[PATCH 3/5] kernel32/tests: Add a IOCTL_DVD_READ_STRUCTURE (DvdPhysicalDescriptor) test (try 2)

Alexandre Goujon ale.goujon at gmail.com
Sun Jun 17 05:11:26 CDT 2012


and fix wine
This one superseeds my previous attempt (#87004)
---
 dlls/kernel32/tests/volume.c |   91 ++++++++++++++++++++++++++++++++++++
 dlls/ntdll/cdrom.c           |  105 ++++++++++++++++++------------------------
 2 files changed, 136 insertions(+), 60 deletions(-)

diff --git a/dlls/kernel32/tests/volume.c b/dlls/kernel32/tests/volume.c
index b459ba6..cf402ad 100644
--- a/dlls/kernel32/tests/volume.c
+++ b/dlls/kernel32/tests/volume.c
@@ -22,6 +22,17 @@
 #include "winbase.h"
 #include "winioctl.h"
 #include <stdio.h>
+#include "ddk/ntddcdvd.h"
+
+#include <pshpack1.h>
+struct COMPLETE_DVD_LAYER_DESCRIPTOR
+{
+    DVD_DESCRIPTOR_HEADER Header;
+    DVD_LAYER_DESCRIPTOR Descriptor;
+    UCHAR Padding;
+};
+#include <poppack.h>
+C_ASSERT(sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR) == 22);
 
 static HINSTANCE hdll;
 static BOOL (WINAPI * pGetVolumeNameForVolumeMountPointA)(LPCSTR, LPSTR, DWORD);
@@ -730,6 +741,85 @@ static void test_GetVolumePathNamesForVolumeNameW(void)
     ok(error == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND got %u\n", error);
 }
 
+static void test_dvd_read_structure(HANDLE handle)
+{
+    int i;
+    DWORD nbBytes;
+    BOOL ret;
+    DVD_READ_STRUCTURE dvdReadStructure;
+    DVD_LAYER_DESCRIPTOR dvdLayerDescriptor;
+    struct COMPLETE_DVD_LAYER_DESCRIPTOR completeDvdLayerDescriptor;
+
+    dvdReadStructure.BlockByteOffset.QuadPart = 0;
+    dvdReadStructure.SessionId = 0;
+    dvdReadStructure.LayerNumber = 0;
+
+
+    /* DvdPhysicalDescriptor */
+    dvdReadStructure.Format = 0;
+
+    SetLastError(0xdeadbeef);
+
+    /* Test whether this ioctl is supported */
+    ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
+        &completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
+    if ((!ret && GetLastError() == ERROR_INVALID_FUNCTION)
+     || (!ret && GetLastError() == ERROR_NOT_SUPPORTED))
+    {
+        skip("IOCTL_DVD_READ_STRUCTURE not supported\n");
+        return;
+    }
+
+    ok(ret || broken(GetLastError() == ERROR_NOT_READY) || broken(GetLastError() == ERROR_INVALID_PARAMETER),
+        "IOCTL_DVD_READ_STRUCTURE (DvdPhysicalDescriptor) failed, last error = %u\n", GetLastError());
+    if(!ret)
+        return;
+
+    /* Confirm there is always a header before the actual data */
+    ok( completeDvdLayerDescriptor.Header.Length == 0x0802, "Length is 0x%04x instead of 0x0802\n", completeDvdLayerDescriptor.Header.Length);
+    ok( completeDvdLayerDescriptor.Header.Reserved[0] == 0, "Reserved[0] is %x instead of 0\n", completeDvdLayerDescriptor.Header.Reserved[0]);
+    ok( completeDvdLayerDescriptor.Header.Reserved[1] == 0, "Reserved[1] is %x instead of 0\n", completeDvdLayerDescriptor.Header.Reserved[1]);
+
+    /* TODO: Also check completeDvdLayerDescriptor.Descriptor content (via IOCTL_SCSI_PASS_THROUGH_DIRECT ?) */
+
+    /* Insufficient output buffer */
+    for(i=0; i<sizeof(DVD_DESCRIPTOR_HEADER); i++)
+    {
+        SetLastError(0xdeadbeef);
+
+        ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
+            &completeDvdLayerDescriptor, i, &nbBytes, NULL);
+        ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,"IOCTL_DVD_READ_STRUCTURE should fail with small buffer\n");
+    }
+
+    SetLastError(0xdeadbeef);
+
+    /* On newer version, an output buffer of sizeof(DVD_READ_STRUCTURE) size fails.
+        I think this is to force developpers to realize that there is a header before the actual content */
+    ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, sizeof(DVD_READ_STRUCTURE),
+        &dvdLayerDescriptor, sizeof(DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
+    ok( (!ret && GetLastError() == ERROR_INVALID_PARAMETER) || broken(ret) /* < Win7 */,
+        "IOCTL_DVD_READ_STRUCTURE should have failed\n");
+
+    SetLastError(0xdeadbeef);
+
+    ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, NULL, sizeof(DVD_READ_STRUCTURE),
+        &completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
+    ok( (!ret && GetLastError() == ERROR_INVALID_PARAMETER),
+        "IOCTL_DVD_READ_STRUCTURE should have failed\n");
+
+    /* Test wrong input parameters */
+    for(i=0; i<sizeof(DVD_READ_STRUCTURE); i++)
+    {
+        SetLastError(0xdeadbeef);
+
+        ret = DeviceIoControl(handle, IOCTL_DVD_READ_STRUCTURE, &dvdReadStructure, i,
+        &completeDvdLayerDescriptor, sizeof(struct COMPLETE_DVD_LAYER_DESCRIPTOR), &nbBytes, NULL);
+        ok( (!ret && GetLastError() == ERROR_INVALID_PARAMETER),
+            "IOCTL_DVD_READ_STRUCTURE should have failed\n");
+    }
+}
+
 static void test_cdrom_ioctl(void)
 {
     char drive_letter, drive_path[] = "A:\\", drive_full_path[] = "\\\\.\\A:";
@@ -766,6 +856,7 @@ static void test_cdrom_ioctl(void)
         }
 
         /* Add your tests here */
+        test_dvd_read_structure(handle);
 
         CloseHandle(handle);
     }
diff --git a/dlls/ntdll/cdrom.c b/dlls/ntdll/cdrom.c
index 53854a8..72157eb 100644
--- a/dlls/ntdll/cdrom.c
+++ b/dlls/ntdll/cdrom.c
@@ -225,25 +225,11 @@ static const char *iocodex(DWORD code)
  */
 typedef struct
 {
-    UCHAR DataLength[2];
-    UCHAR Reserved0[2];
-    UCHAR BookVersion : 4;
-    UCHAR BookType : 4;
-    UCHAR MinimumRate : 4;
-    UCHAR DiskSize : 4;
-    UCHAR LayerType : 4;
-    UCHAR TrackPath : 1;
-    UCHAR NumberOfLayers : 2;
-    UCHAR Reserved1 : 1;
-    UCHAR TrackDensity : 4;
-    UCHAR LinearDensity : 4;
-    ULONG StartingDataSector;
-    ULONG EndDataSector;
-    ULONG EndLayerZeroSector;
-    UCHAR Reserved5 : 7;
-    UCHAR BCAFlag : 1;
-    UCHAR Reserved6;
+    DVD_DESCRIPTOR_HEADER Header;
+    DVD_LAYER_DESCRIPTOR Descriptor;
+    UCHAR Padding;
 } internal_dvd_layer_descriptor;
+C_ASSERT(sizeof(internal_dvd_layer_descriptor) == 22);
 
 
 static NTSTATUS CDROM_ReadTOC(int, int, CDROM_TOC*);
@@ -2503,7 +2489,7 @@ static NTSTATUS DVD_GetRegion(int fd, PDVD_REGION region)
  *
  *
  */
-static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure, PDVD_LAYER_DESCRIPTOR layer)
+static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure, PDVD_LAYER_DESCRIPTOR layer, DWORD outBufferSize)
 {
 #ifdef DVD_READ_STRUCT
     /* dvd_struct is not defined consistently across platforms */
@@ -2551,7 +2537,10 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
     }
 
     if (ioctl(dev, DVD_READ_STRUCT, &s) < 0)
+    {
+       ERR("DVD_READ_STRUCT ioctl failed : %s\n", strerror(errno));
        return STATUS_INVALID_PARAMETER;
+    }
 
     switch (structure->Format)
     {
@@ -2560,26 +2549,24 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
             internal_dvd_layer_descriptor *p = (internal_dvd_layer_descriptor *) layer;
             struct dvd_layer *l = &s.physical.layer[s.physical.layer_num];
 
-            p->DataLength[0] = 2;
-            p->DataLength[1] = 8;
-            p->Reserved0[0] = 0;
-            p->Reserved0[1] = 0;
-            p->BookVersion = l->book_version;
-            p->BookType = l->book_type;
-            p->MinimumRate = l->min_rate;
-            p->DiskSize = l->disc_size;
-            p->LayerType = l->layer_type;
-            p->TrackPath = l->track_path;
-            p->NumberOfLayers = l->nlayers;
-            p->Reserved1 = 0;
-            p->TrackDensity = l->track_density;
-            p->LinearDensity = l->linear_density;
-            p->StartingDataSector = GET_BE_DWORD(l->start_sector);
-            p->EndDataSector = GET_BE_DWORD(l->end_sector);
-            p->EndLayerZeroSector = GET_BE_DWORD(l->end_sector_l0);
-            p->Reserved5 = 0;
-            p->BCAFlag = l->bca;
-            p->Reserved6 = 0;
+            p->Header.Length = 0x0802;
+            p->Header.Reserved[0] = 0;
+            p->Header.Reserved[1] = 0;
+            p->Descriptor.BookVersion = l->book_version;
+            p->Descriptor.BookType = l->book_type;
+            p->Descriptor.MinimumRate = l->min_rate;
+            p->Descriptor.DiskSize = l->disc_size;
+            p->Descriptor.LayerType = l->layer_type;
+            p->Descriptor.TrackPath = l->track_path;
+            p->Descriptor.NumberOfLayers = l->nlayers;
+            p->Descriptor.Reserved1 = 0;
+            p->Descriptor.TrackDensity = l->track_density;
+            p->Descriptor.LinearDensity = l->linear_density;
+            p->Descriptor.StartingDataSector = GET_BE_DWORD(l->start_sector);
+            p->Descriptor.EndDataSector = GET_BE_DWORD(l->end_sector);
+            p->Descriptor.EndLayerZeroSector = GET_BE_DWORD(l->end_sector_l0);
+            p->Descriptor.Reserved5 = 0;
+            p->Descriptor.BCAFlag = l->bca;
         }
         break;
 
@@ -2685,26 +2672,24 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
         switch(structure->Format)
         {
         case DvdPhysicalDescriptor:
-            nt_desc.xlayer->DataLength[0] = 2;
-            nt_desc.xlayer->DataLength[1] = 8;
-            nt_desc.xlayer->Reserved0[0] = 0;
-            nt_desc.xlayer->Reserved0[1] = 0;
-            nt_desc.xlayer->BookVersion = desc.phys.partVersion;
-            nt_desc.xlayer->BookType = desc.phys.bookType;
-            nt_desc.xlayer->MinimumRate = desc.phys.minimumRate;
-            nt_desc.xlayer->DiskSize = desc.phys.discSize;
-            nt_desc.xlayer->LayerType = desc.phys.layerType;
-            nt_desc.xlayer->TrackPath = desc.phys.trackPath;
-            nt_desc.xlayer->NumberOfLayers = desc.phys.numberOfLayers;
-            nt_desc.xlayer->Reserved1 = 0;
-            nt_desc.xlayer->TrackDensity = desc.phys.trackDensity;
-            nt_desc.xlayer->LinearDensity = desc.phys.linearDensity;
-            nt_desc.xlayer->BCAFlag = desc.phys.bcaFlag;
-            nt_desc.xlayer->StartingDataSector = *(DWORD *)&desc.phys.zero1;
-            nt_desc.xlayer->EndDataSector = *(DWORD *)&desc.phys.zero2;
-            nt_desc.xlayer->EndLayerZeroSector = *(DWORD *)&desc.phys.zero3;
-            nt_desc.xlayer->Reserved5 = 0;
-            nt_desc.xlayer->Reserved6 = 0;
+            nt_desc.xlayer->Header.Length = 0x0802;
+            nt_desc.xlayer->Header.Reserved[0] = 0;
+            nt_desc.xlayer->Header.Reserved[1] = 0;
+            nt_desc.xlayer->Descriptor.BookVersion = desc.phys.partVersion;
+            nt_desc.xlayer->Descriptor.BookType = desc.phys.bookType;
+            nt_desc.xlayer->Descriptor.MinimumRate = desc.phys.minimumRate;
+            nt_desc.xlayer->Descriptor.DiskSize = desc.phys.discSize;
+            nt_desc.xlayer->Descriptor.LayerType = desc.phys.layerType;
+            nt_desc.xlayer->Descriptor.TrackPath = desc.phys.trackPath;
+            nt_desc.xlayer->Descriptor.NumberOfLayers = desc.phys.numberOfLayers;
+            nt_desc.xlayer->Descriptor.Reserved1 = 0;
+            nt_desc.xlayer->Descriptor.TrackDensity = desc.phys.trackDensity;
+            nt_desc.xlayer->Descriptor.LinearDensity = desc.phys.linearDensity;
+            nt_desc.xlayer->Descriptor.StartingDataSector = GET_BE_DWORD(*(DWORD *)&desc.phys.zero1);
+            nt_desc.xlayer->Descriptor.EndDataSector = GET_BE_DWORD(*(DWORD *)&desc.phys.zero2);
+            nt_desc.xlayer->Descriptor.EndLayerZeroSector = GET_BE_DWORD(*(DWORD *)&desc.phys.zero3);
+            nt_desc.xlayer->Descriptor.Reserved5 = 0;
+            nt_desc.xlayer->Descriptor.BCAFlag = desc.phys.bcaFlag;
             break;
 
         case DvdCopyrightDescriptor:
@@ -3105,7 +3090,7 @@ NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
         else
         {
             TRACE("doing DVD_READ_STRUCTURE\n");
-            status = DVD_ReadStructure(fd, lpInBuffer, lpOutBuffer);
+            status = DVD_ReadStructure(fd, lpInBuffer, lpOutBuffer, nOutBufferSize);
         }
         break;
 
-- 
1.7.9.5




More information about the wine-patches mailing list