[PATCH 7/7] ntdll: Fix IOCTL_DVD_READ_STRUCTURE parameter checking, returned byte count, and output format (try 2)
Dan Kegel
dank at kegel.com
Fri Feb 10 14:30:33 CST 2012
The output buffer always starts with _DVD_DESCRIPTOR_HEADER,
partial output buffers are allowed, and
overly long output buffers are zero-filled on the end up to offset 2052.
Changes since yesterday:
- fixed a typo in test case (OSIZE-1 should have been OSIZE+1)
- moved odd-sized buffer check change into own patch
---
dlls/kernel32/tests/cdrom.c | 118 ++++++++++++++++++++++++++-
dlls/ntdll/cdrom.c | 191 +++++++++++++++++++++++++------------------
2 files changed, 228 insertions(+), 81 deletions(-)
diff --git a/dlls/kernel32/tests/cdrom.c b/dlls/kernel32/tests/cdrom.c
index 3b997f5..cb91ba8 100644
--- a/dlls/kernel32/tests/cdrom.c
+++ b/dlls/kernel32/tests/cdrom.c
@@ -26,6 +26,12 @@
#include "wine/test.h"
+#ifdef WORDS_BIGENDIAN
+#define GET_BE_SHORT(x) (x)
+#else
+static unsigned short GET_BE_SHORT(unsigned short x) { return ((x & 0xff) << 8) | ((x & 0xff00) >> 8); }
+#endif
+
#include <pshpack1.h>
typedef struct xDVD_LAYER_DESCRIPTOR {
@@ -39,6 +45,16 @@ typedef struct xDVD_LAYER_DESCRIPTOR {
char reserved1;
} xDVD_LAYER_DESCRIPTOR;
+struct xDVD_MANUFACTURER_DESCRIPTOR {
+ struct _DVD_DESCRIPTOR_HEADER h;
+ struct _DVD_MANUFACTURER_DESCRIPTOR manufacturer;
+};
+
+struct xDVD_COPYRIGHT_DESCRIPTOR {
+ struct _DVD_DESCRIPTOR_HEADER h;
+ struct _DVD_COPYRIGHT_DESCRIPTOR copyright;
+};
+
#include <poppack.h>
#define HUGEBUF 8192 /* Larger than ever needed */
@@ -80,20 +96,42 @@ static void test_readStruct_input(HANDLE hdevice)
}
}
+#define BACKGROUND_VAL 0x77
+
+/* Returns true if all bytes are zero */
+static int all_zeroes(char *buf, int len)
+{
+ while (len-- > 0)
+ if (*buf++) return FALSE;
+ return TRUE;
+}
+
/* Try IOCTL_DVD_READ_STRUCTURE.DvdPhysicalDescriptor
* with various size output buffers
*/
+#define OSIZE sizeof(xDVD_LAYER_DESCRIPTOR)
static void test_readStruct_layer(HANDLE hdevice)
{
static struct {
int olen;
BOOL ret;
+ DWORD nread;
DWORD err;
} cases[] = {
- {3, FALSE, ERROR_INSUFFICIENT_BUFFER },
- {sizeof(xDVD_LAYER_DESCRIPTOR), TRUE, 0 },
- {sizeof(xDVD_LAYER_DESCRIPTOR)+1, FALSE, ERROR_INVALID_PARAMETER },
+ {3, FALSE, 0, ERROR_INSUFFICIENT_BUFFER },
+ {4, TRUE, 4, 0, },
+ {5, FALSE, 0, ERROR_INVALID_PARAMETER, },
+ {6, TRUE, 6, 0, },
+ {OSIZE-2, TRUE, OSIZE-2, 0, },
+ {OSIZE-1, FALSE, 0, ERROR_INVALID_PARAMETER, },
+ {OSIZE, TRUE, OSIZE, 0, },
+ {OSIZE+1, FALSE, 0, ERROR_INVALID_PARAMETER, },
+ {OSIZE+2, TRUE, OSIZE+2, 0, },
+ {2052, TRUE, 2052, 0, },
+ {2054, TRUE, 2054, 0, },
+ {4096, TRUE, 4096, 0, },
+ {4098, TRUE, 4098, 0, },
{0}
};
DVD_READ_STRUCTURE ibuf;
@@ -106,13 +144,23 @@ static void test_readStruct_layer(HANDLE hdevice)
char obuf[HUGEBUF];
DWORD bytes_read = 0;
BOOL bResult;
+ int all_clear;
+ memset(obuf, BACKGROUND_VAL, sizeof(obuf));
bResult = DeviceIoControl(hdevice, IOCTL_DVD_READ_STRUCTURE,
&ibuf, sizeof(ibuf),
obuf, cases[i].olen, &bytes_read, 0);
ok(bResult == cases[i].ret,
"case %d: DeviceIoControl returned %d, expected %d\n",
i, bResult, cases[i].ret);
+ ok(bytes_read == cases[i].nread,
+ "case %d: DeviceIoControl read %d bytes, expected %d\n",
+ i, bytes_read, cases[i].nread);
+ /* Windows zeroes out all bytes [OSIZE..2052). Bytes past 2052 are set to undefined values. */
+ if (cases[i].olen > OSIZE) {
+ all_clear = all_zeroes(obuf + OSIZE, min(2052, bytes_read) - OSIZE);
+ ok(all_clear, "case %d: not all trailing bytes zero\n", i);
+ }
if (cases[i].err) {
DWORD err = GetLastError();
ok(err == cases[i].err,
@@ -121,6 +169,7 @@ static void test_readStruct_layer(HANDLE hdevice)
}
}
}
+#undef OSIZE
/* Backdoor way to do the same thing as IOCTL_DVD_READ_STRUCTURE */
DWORD read_discStructure(HANDLE device, int format, void *obuf, int obuflen)
@@ -176,6 +225,67 @@ static void test_readStruct_layer_vs_passthrough(HANDLE hdevice)
ok(memcmp(&xlayer1.layer, &xlayer2.layer, sizeof(xlayer1.layer)) == 0,
"SCSI_PASS_THROUGH_DIRECT and IOCTL_DVD_READ_STRUCTURE report different results for DvdPhysicalDescriptor\n");
+
+ ok(GET_BE_SHORT(xlayer1.h.Length) == xlayer2.h.Length,
+ "SCSI_PASS_THROUGH_DIRECT reports length %d, IOCTL_DVD_READ_STRUCTURE report length %d for DvdPhysicalDescriptor\n",
+ GET_BE_SHORT(xlayer1.h.Length), xlayer2.h.Length);
+}
+
+/* Compare dvd manufacturer descriptor as read via two different APIs */
+static void test_readStruct_manufacturer_vs_passthrough(HANDLE hdevice)
+{
+ struct xDVD_MANUFACTURER_DESCRIPTOR xmanufacturer1;
+ struct xDVD_MANUFACTURER_DESCRIPTOR xmanufacturer2;
+ DVD_READ_STRUCTURE ibuf;
+ DWORD bytes_read;
+ BOOL bRet;
+
+ bRet = read_discStructure(hdevice, DvdManufacturerDescriptor, &xmanufacturer1, sizeof(xmanufacturer1));
+ ok(bRet, "can't read manufacturer via SCSI_PASS_THROUGH_DIRECT\n");
+
+ /* Linux 3.0 and earlier fail IOCTL_DVD_READ_STRUCTURE
+ * See https://bugzilla.kernel.org/show_bug.cgi?id=39062
+ */
+ ZeroMemory(&ibuf, sizeof(ibuf));
+ ibuf.Format = DvdManufacturerDescriptor;
+ bRet = DeviceIoControl(hdevice, IOCTL_DVD_READ_STRUCTURE,
+ &ibuf, sizeof(ibuf),
+ &xmanufacturer2, sizeof(xmanufacturer2), &bytes_read, 0);
+ ok(bRet, "can't read manufacturer via IOCTL_DVD_READ_STRUCTURE\n");
+
+ ok(memcmp(&xmanufacturer1.manufacturer, &xmanufacturer2.manufacturer, sizeof(xmanufacturer1.manufacturer)) == 0,
+ "SCSI_PASS_THROUGH_DIRECT and IOCTL_DVD_READ_STRUCTURE report different results for DvdManufacturerDescriptor\n");
+
+ ok(GET_BE_SHORT(xmanufacturer1.h.Length) == xmanufacturer2.h.Length,
+ "SCSI_PASS_THROUGH_DIRECT reports length %d, IOCTL_DVD_READ_STRUCTURE report length %d for DvdManufacturerDescriptor\n",
+ GET_BE_SHORT(xmanufacturer1.h.Length), xmanufacturer2.h.Length);
+}
+
+/* Compare dvd copyright descriptor as read via two different APIs */
+static void test_readStruct_copyright_vs_passthrough(HANDLE hdevice)
+{
+ struct xDVD_COPYRIGHT_DESCRIPTOR xcopyright1;
+ struct xDVD_COPYRIGHT_DESCRIPTOR xcopyright2;
+ DVD_READ_STRUCTURE ibuf;
+ DWORD bytes_read;
+ BOOL bRet;
+
+ bRet = read_discStructure(hdevice, DvdCopyrightDescriptor, &xcopyright1, sizeof(xcopyright1));
+ ok(bRet, "can't read copyright via SCSI_PASS_THROUGH_DIRECT\n");
+
+ ZeroMemory(&ibuf, sizeof(ibuf));
+ ibuf.Format = DvdCopyrightDescriptor;
+ bRet = DeviceIoControl(hdevice, IOCTL_DVD_READ_STRUCTURE,
+ &ibuf, sizeof(ibuf),
+ &xcopyright2, sizeof(xcopyright2), &bytes_read, 0);
+ ok(bRet, "can't read copyright via IOCTL_DVD_READ_STRUCTURE, err %d\n", GetLastError());
+
+ ok(memcmp(&xcopyright1.copyright, &xcopyright2.copyright, sizeof(xcopyright1.copyright)) == 0,
+ "SCSI_PASS_THROUGH_DIRECT and IOCTL_DVD_READ_STRUCTURE report different results for DvdCopyrightDescriptor\n");
+
+ ok(GET_BE_SHORT(xcopyright1.h.Length) == xcopyright2.h.Length,
+ "SCSI_PASS_THROUGH_DIRECT reports length %d, IOCTL_DVD_READ_STRUCTURE report length %d for DvdCopyrightDescriptor\n",
+ GET_BE_SHORT(xcopyright1.h.Length), xcopyright2.h.Length);
}
static BOOL isDvd(HANDLE hdevice)
@@ -234,6 +344,8 @@ START_TEST(cdrom)
test_readStruct_input(hdevice);
test_readStruct_layer(hdevice);
test_readStruct_layer_vs_passthrough(hdevice);
+ test_readStruct_manufacturer_vs_passthrough(hdevice);
+ test_readStruct_copyright_vs_passthrough(hdevice);
}
CloseHandle(hdevice);
}
diff --git a/dlls/ntdll/cdrom.c b/dlls/ntdll/cdrom.c
index 61c7db9..9820ce0 100644
--- a/dlls/ntdll/cdrom.c
+++ b/dlls/ntdll/cdrom.c
@@ -218,33 +218,59 @@ static const char *iocodex(DWORD code)
#define FRAME_OF_TOC(toc, idx) FRAME_OF_ADDR((toc).TrackData[idx - (toc).FirstTrack].Address)
#define MSF_OF_FRAME(m,fr) {int f=(fr); ((UCHAR *)&(m))[2]=f%CD_FRAMES;f/=CD_FRAMES;((UCHAR *)&(m))[1]=f%CD_SECS;((UCHAR *)&(m))[0]=f/CD_SECS;}
-/* The documented format of DVD_LAYER_DESCRIPTOR is wrong. Even the format in the
- * DDK's header is wrong. There are four bytes at the start defined by
- * MMC-5. The first two are the size of the structure in big-endian order as
- * defined by MMC-5. The other two are reserved.
+/* The results from DVD_READ_STRUCTURE are
+ * DVD_DESCRIPTOR_HEADER followed by a DVD_*_DESCRIPTOR.
+ * The Length field of DVD_DESCRIPTOR_HEADER
+ * appears to mean "number of bytes following this Length field,
+ * including the remaining two bytes of DVD_DESCRIPTOR_HEADER".
+ * There are two ioctls that can handle DVD_READ_STRUCTURE requests:
+ * IOCTL_DVD_READ_STRUCTURE which sets Length in host byte order, and
+ * SCSI_PASS_THROUGH_DIRECT which sets Length in big-endian byte order.
*/
-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;
-} internal_dvd_layer_descriptor;
+#include <pshpack1.h>
+
+typedef struct xDVD_LAYER_DESCRIPTOR {
+ struct _DVD_DESCRIPTOR_HEADER h;
+ struct _DVD_LAYER_DESCRIPTOR layer;
+ /* On Windows, _DVD_LAYER_DESCRIPTOR is 17 bytes, but
+ * IOCTL_DVD_READ_STRUCTURE wants 22 bytes, so it needs
+ * the header plus at least one byte of padding.
+ */
+ char Reserved;
+} xDVD_LAYER_DESCRIPTOR;
+
+struct xDVD_MANUFACTURER_DESCRIPTOR {
+ struct _DVD_DESCRIPTOR_HEADER h;
+ struct _DVD_MANUFACTURER_DESCRIPTOR manufacturer;
+};
+
+struct xDVD_COPYRIGHT_DESCRIPTOR {
+ struct _DVD_DESCRIPTOR_HEADER h;
+ struct _DVD_COPYRIGHT_DESCRIPTOR copyright;
+};
+
+struct xDVD_DISK_KEY_DESCRIPTOR {
+ struct _DVD_DESCRIPTOR_HEADER h;
+ struct _DVD_DISK_KEY_DESCRIPTOR disk_key;
+};
+
+struct xDVD_BCA_DESCRIPTOR {
+ struct _DVD_DESCRIPTOR_HEADER h;
+ struct _DVD_BCA_DESCRIPTOR bca;
+};
+
+#include <poppack.h>
+
+union xDVD_DESCRIPTOR {
+ struct _DVD_DESCRIPTOR_HEADER h;
+ struct xDVD_LAYER_DESCRIPTOR xlayer;
+ struct xDVD_MANUFACTURER_DESCRIPTOR xmanufacturer;
+ struct xDVD_COPYRIGHT_DESCRIPTOR xcopyright;
+ struct xDVD_DISK_KEY_DESCRIPTOR xdisk_key;
+ struct xDVD_BCA_DESCRIPTOR xbca;
+ char size[2052];
+};
static NTSTATUS CDROM_ReadTOC(int, int, CDROM_TOC*);
static NTSTATUS CDROM_GetStatusCode(int);
@@ -2503,8 +2529,10 @@ 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, union xDVD_DESCRIPTOR *obuf, DWORD obuflen)
{
+ union xDVD_DESCRIPTOR tmp;
+
#ifdef DVD_READ_STRUCT
/* dvd_struct is not defined consistently across platforms */
union
@@ -2553,17 +2581,16 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
if (ioctl(dev, DVD_READ_STRUCT, &s) < 0)
return STATUS_INVALID_PARAMETER;
+ ZeroMemory(&tmp, sizeof(tmp));
+
switch (structure->Format)
{
case DvdPhysicalDescriptor:
{
- internal_dvd_layer_descriptor *p = (internal_dvd_layer_descriptor *) layer;
+ DVD_LAYER_DESCRIPTOR *p = &tmp.xlayer.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;
+ tmp.h.Length = 2050;
p->BookVersion = l->book_version;
p->BookType = l->book_type;
p->MinimumRate = l->min_rate;
@@ -2579,13 +2606,13 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
p->EndLayerZeroSector = GET_BE_DWORD(l->end_sector_l0);
p->Reserved5 = 0;
p->BCAFlag = l->bca;
- p->Reserved6 = 0;
}
break;
case DvdCopyrightDescriptor:
{
- PDVD_COPYRIGHT_DESCRIPTOR p = (PDVD_COPYRIGHT_DESCRIPTOR) layer;
+ PDVD_COPYRIGHT_DESCRIPTOR p = &tmp.xcopyright.copyright;
+ tmp.h.Length = 6;
p->CopyrightProtectionType = s.copyright.cpst;
p->RegionManagementInformation = s.copyright.rmi;
@@ -2595,7 +2622,8 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
case DvdDiskKeyDescriptor:
{
- PDVD_DISK_KEY_DESCRIPTOR p = (PDVD_DISK_KEY_DESCRIPTOR) layer;
+ PDVD_DISK_KEY_DESCRIPTOR p = &tmp.xdisk_key.disk_key;
+ tmp.h.Length = 2050;
memcpy(p->DiskKeyData, s.disckey.value, 2048);
}
@@ -2603,7 +2631,8 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
case DvdBCADescriptor:
{
- PDVD_BCA_DESCRIPTOR p = (PDVD_BCA_DESCRIPTOR) layer;
+ PDVD_BCA_DESCRIPTOR p = &tmp.xbca.bca;
+ tmp.h.Length = s.bca.len + sizeof(tmp.h.Length); /* ? */
memcpy(p->BCAInformation, s.bca.value, s.bca.len);
}
@@ -2611,7 +2640,8 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
case DvdManufacturerDescriptor:
{
- PDVD_MANUFACTURER_DESCRIPTOR p = (PDVD_MANUFACTURER_DESCRIPTOR) layer;
+ PDVD_MANUFACTURER_DESCRIPTOR p = &tmp.xmanufacturer.manufacturer;
+ tmp.h.Length = 2050;
memcpy(p->ManufacturingInformation, s.manufact.value, 2048);
}
@@ -2621,7 +2651,7 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
break;
}
#elif defined(__APPLE__)
- NTSTATUS ret = STATUS_NOT_SUPPORTED;
+ NTSTATUS ret;
dk_dvd_read_structure_t dvdrs;
union
{
@@ -2630,14 +2660,6 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
DVDDiscKeyInfo disk_key;
DVDManufacturingInfo manf;
} desc;
- union
- {
- PDVD_LAYER_DESCRIPTOR layer;
- internal_dvd_layer_descriptor *xlayer;
- PDVD_COPYRIGHT_DESCRIPTOR copy;
- PDVD_DISK_KEY_DESCRIPTOR disk_key;
- PDVD_MANUFACTURER_DESCRIPTOR manf;
- } nt_desc;
nt_desc.layer = layer;
dvdrs.address = (uint32_t)(structure->BlockByteOffset.QuadPart>>11);
@@ -2679,66 +2701,78 @@ static NTSTATUS DVD_ReadStructure(int dev, const DVD_READ_STRUCTURE *structure,
return STATUS_NOT_SUPPORTED;
}
ret = CDROM_GetStatusCode(ioctl(dev, DKIOCDVDREADSTRUCTURE, &dvdrs));
- if(ret == STATUS_SUCCESS)
+ if (ret != STATUS_SUCCESS)
+ return ret;
+ ZeroMemory(&tmp, sizeof(tmp));
+ switch(structure->Format)
{
- 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 = OSReadBigInt32(&desc.phys.zero1, 0);
- nt_desc.xlayer->EndDataSector = OSReadBigInt32(&desc.phys.zero2, 0);
- nt_desc.xlayer->EndLayerZeroSector = OSReadBigInt32(&desc.phys.zero3, 0);
- nt_desc.xlayer->Reserved5 = 0;
- nt_desc.xlayer->Reserved6 = 0;
+ {
+ DVD_LAYER_DESCRIPTOR *p = &tmp.xlayer.layer;
+ tmp.h.Length = 2050;
+ p->BookVersion = desc.phys.partVersion;
+ p->BookType = desc.phys.bookType;
+ p->MinimumRate = desc.phys.minimumRate;
+ p->DiskSize = desc.phys.discSize;
+ p->LayerType = desc.phys.layerType;
+ p->TrackPath = desc.phys.trackPath;
+ p->NumberOfLayers = desc.phys.numberOfLayers;
+ p->Reserved1 = 0;
+ p->TrackDensity = desc.phys.trackDensity;
+ p->LinearDensity = desc.phys.linearDensity;
+ p->BCAFlag = desc.phys.bcaFlag;
+ p->StartingDataSector = OSReadBigInt32(&desc.phys.zero1, 0);
+ p->EndDataSector = OSReadBigInt32(&desc.phys.zero2, 0);
+ p->EndLayerZeroSector = OSReadBigInt32(&desc.phys.zero3, 0);
+ p->Reserved5 = 0;
break;
+ }
case DvdCopyrightDescriptor:
- nt_desc.copy->CopyrightProtectionType =
+ {
+ PDVD_COPYRIGHT_DESCRIPTOR p = &tmp.xcopyright.copyright;
+ tmp.h.Length = 6;
+ p->CopyrightProtectionType =
desc.copy.copyrightProtectionSystemType;
- nt_desc.copy->RegionManagementInformation =
+ p->RegionManagementInformation =
desc.copy.regionMask;
- nt_desc.copy->Reserved = 0;
+ p->Reserved = 0;
break;
+ }
case DvdDiskKeyDescriptor:
+ {
+ PDVD_DISK_KEY_DESCRIPTOR p = &tmp.xdisk_key.disk_key;
+ tmp.h.Length = 2050;
memcpy(
- nt_desc.disk_key->DiskKeyData,
+ p->DiskKeyData,
desc.disk_key.discKeyStructures,
2048);
break;
+ }
case DvdManufacturerDescriptor:
+ {
+ PDVD_MANUFACTURER_DESCRIPTOR p = &tmp.xmanufacturer.manufacturer;
+ tmp.h.Length = 2050;
memcpy(
- nt_desc.manf->ManufacturingInformation,
+ p->ManufacturingInformation,
desc.manf.discManufacturingInfo,
2048);
break;
+ }
case DvdBCADescriptor:
case DvdMaxDescriptor:
default:
/* Silence warning */
break;
- }
}
- return ret;
#else
+ tmp.h.Length = 4;
FIXME("\n");
#endif
+ memcpy(obuf, &tmp, min(obuflen, sizeof(tmp)));
return STATUS_SUCCESS;
}
@@ -3098,14 +3132,15 @@ NTSTATUS CDROM_DeviceIoControl(HANDLE hDevice,
status = DVD_GetRegion(fd, lpOutBuffer);
break;
case IOCTL_DVD_READ_STRUCTURE:
- sz = sizeof(DVD_LAYER_DESCRIPTOR);
if (lpInBuffer == NULL || nInBufferSize < sizeof(DVD_READ_STRUCTURE)) status = STATUS_INVALID_PARAMETER;
- else if (nOutBufferSize < sz) status = STATUS_BUFFER_TOO_SMALL;
+ else if (nOutBufferSize < sizeof(DVD_DESCRIPTOR_HEADER)) status = STATUS_BUFFER_TOO_SMALL;
else if (nOutBufferSize & 1) status = STATUS_INVALID_PARAMETER;
else
{
TRACE("doing DVD_READ_STRUCTURE\n");
- status = DVD_ReadStructure(fd, lpInBuffer, lpOutBuffer);
+ status = DVD_ReadStructure(fd, lpInBuffer, lpOutBuffer, nOutBufferSize);
+ if (status == STATUS_SUCCESS)
+ sz = nOutBufferSize;
}
break;
--
1.7.9
More information about the wine-patches
mailing list