Commit e8c6f130 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

hidclass.sys: Always copy InputReportByteLength bytes into read buffer.

parent 88bc48fb
...@@ -77,32 +77,6 @@ static void WINAPI read_cancel_routine(DEVICE_OBJECT *device, IRP *irp) ...@@ -77,32 +77,6 @@ static void WINAPI read_cancel_routine(DEVICE_OBJECT *device, IRP *irp)
IoCompleteRequest(irp, IO_NO_INCREMENT); IoCompleteRequest(irp, IO_NO_INCREMENT);
} }
static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, ULONG buffer_length, ULONG *out_length)
{
BOOL zero_id = (packet->reportId == 0);
*out_length = 0;
if ((zero_id && buffer_length > packet->reportBufferLen) ||
(!zero_id && buffer_length >= packet->reportBufferLen))
{
if (packet->reportId != 0)
{
memcpy(buffer, packet->reportBuffer, packet->reportBufferLen);
*out_length = packet->reportBufferLen;
}
else
{
buffer[0] = 0;
memcpy(&buffer[1], packet->reportBuffer, packet->reportBufferLen);
*out_length = packet->reportBufferLen + 1;
}
return STATUS_SUCCESS;
}
else
return STATUS_BUFFER_OVERFLOW;
}
static void hid_device_send_input(DEVICE_OBJECT *device, HID_XFER_PACKET *packet) static void hid_device_send_input(DEVICE_OBJECT *device, HID_XFER_PACKET *packet)
{ {
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
...@@ -145,24 +119,24 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device) ...@@ -145,24 +119,24 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device)
IRP *irp; IRP *irp;
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
UINT buffer_size = RingBuffer_GetBufferSize(ext->u.pdo.ring_buffer); UINT buffer_size = RingBuffer_GetBufferSize(ext->u.pdo.ring_buffer);
const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data;
HID_XFER_PACKET *packet; HID_XFER_PACKET *packet;
packet = malloc(buffer_size); packet = malloc(buffer_size);
while((irp = pop_irp_from_queue(ext))) while((irp = pop_irp_from_queue(ext)))
{ {
int ptr; BYTE *buffer = irp->AssociatedIrp.SystemBuffer, *dst = buffer;
ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext ); int ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext );
RingBuffer_Read(ext->u.pdo.ring_buffer, ptr, packet, &buffer_size); RingBuffer_Read(ext->u.pdo.ring_buffer, ptr, packet, &buffer_size);
if (buffer_size) if (buffer_size)
{ {
ULONG out_length;
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
packet->reportBuffer = (BYTE *)packet + sizeof(*packet);
TRACE_(hid_report)("Processing Request (%i)\n",ptr); TRACE_(hid_report)("Processing Request (%i)\n",ptr);
irp->IoStatus.Status = copy_packet_into_buffer( packet, irp->AssociatedIrp.SystemBuffer, irpsp->Parameters.Read.Length, &out_length ); if (!data->reports[0].reportID) *dst++ = 0;
irp->IoStatus.Information = out_length; memcpy( dst, packet + 1, data->caps.InputReportByteLength - (dst - buffer) );
irp->IoStatus.Information = packet->reportBufferLen;
irp->IoStatus.Status = STATUS_SUCCESS;
} }
else else
{ {
...@@ -483,8 +457,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) ...@@ -483,8 +457,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp)
HID_XFER_PACKET *packet; HID_XFER_PACKET *packet;
ULONG buffer_len = irpsp->Parameters.DeviceIoControl.OutputBufferLength; ULONG buffer_len = irpsp->Parameters.DeviceIoControl.OutputBufferLength;
UINT packet_size = sizeof(*packet) + buffer_len; UINT packet_size = sizeof(*packet) + buffer_len;
BYTE *buffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); BYTE *buffer = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority ), *dst = buffer;
ULONG out_length;
if (!buffer) if (!buffer)
{ {
...@@ -510,7 +483,10 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) ...@@ -510,7 +483,10 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp)
sizeof(*packet), &irp->IoStatus ); sizeof(*packet), &irp->IoStatus );
if (irp->IoStatus.Status == STATUS_SUCCESS) if (irp->IoStatus.Status == STATUS_SUCCESS)
irp->IoStatus.Status = copy_packet_into_buffer( packet, buffer, buffer_len, &out_length ); {
if (!data->reports[0].reportID) *dst++ = 0;
memcpy( dst, packet + 1, data->caps.InputReportByteLength - (dst - buffer) );
}
free(packet); free(packet);
break; break;
} }
...@@ -568,6 +544,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) ...@@ -568,6 +544,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp)
const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data; const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data;
UINT buffer_size = RingBuffer_GetBufferSize(ext->u.pdo.ring_buffer); UINT buffer_size = RingBuffer_GetBufferSize(ext->u.pdo.ring_buffer);
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp);
BYTE *buffer = irp->AssociatedIrp.SystemBuffer, *dst = buffer;
NTSTATUS status; NTSTATUS status;
int ptr = -1; int ptr = -1;
BOOL removed; BOOL removed;
...@@ -599,13 +576,10 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) ...@@ -599,13 +576,10 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp)
if (buffer_size) if (buffer_size)
{ {
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); if (!data->reports[0].reportID) *dst++ = 0;
ULONG out_length; memcpy( dst, packet + 1, data->caps.InputReportByteLength - (dst - buffer) );
packet->reportBuffer = (BYTE *)packet + sizeof(*packet); irp->IoStatus.Information = packet->reportBufferLen;
TRACE_(hid_report)("Got Packet %p %i\n", packet->reportBuffer, packet->reportBufferLen); irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Status = copy_packet_into_buffer( packet, irp->AssociatedIrp.SystemBuffer, irpsp->Parameters.Read.Length, &out_length );
irp->IoStatus.Information = out_length;
} }
else else
{ {
......
...@@ -2684,9 +2684,9 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled ...@@ -2684,9 +2684,9 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
memset(report, 0xcd, sizeof(report)); memset(report, 0xcd, sizeof(report));
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ret = ReadFile(file, report, caps.InputReportByteLength, &value, NULL); ret = ReadFile(file, report, caps.InputReportByteLength, &value, NULL);
todo_wine ok(ret, "ReadFile failed, last error %u\n", GetLastError()); ok(ret, "ReadFile failed, last error %u\n", GetLastError());
todo_wine ok(value == (report_id ? 3 : 4), "ReadFile returned %x\n", value); todo_wine ok(value == (report_id ? 3 : 4), "ReadFile returned %x\n", value);
todo_wine ok(report[0] == report_id, "unexpected report data\n"); ok(report[0] == report_id, "unexpected report data\n");
overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
overlapped2.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); overlapped2.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
...@@ -2695,9 +2695,9 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled ...@@ -2695,9 +2695,9 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
while (ReadFile(async_file, report, caps.InputReportByteLength, NULL, &overlapped)) while (ReadFile(async_file, report, caps.InputReportByteLength, NULL, &overlapped))
ResetEvent(overlapped.hEvent); ResetEvent(overlapped.hEvent);
todo_wine ok(GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError()); ok(GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError());
ret = GetOverlappedResult(async_file, &overlapped, &value, TRUE); ret = GetOverlappedResult(async_file, &overlapped, &value, TRUE);
todo_wine ok(ret, "GetOverlappedResult failed, last error %u\n", GetLastError()); ok(ret, "GetOverlappedResult failed, last error %u\n", GetLastError());
todo_wine ok(value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected 3\n", value); todo_wine ok(value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected 3\n", value);
ResetEvent(overlapped.hEvent); ResetEvent(overlapped.hEvent);
...@@ -2716,13 +2716,14 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled ...@@ -2716,13 +2716,14 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
/* wait for first report to be ready */ /* wait for first report to be ready */
ret = GetOverlappedResult(async_file, &overlapped, &value, TRUE); ret = GetOverlappedResult(async_file, &overlapped, &value, TRUE);
todo_wine ok(ret, "GetOverlappedResult failed, last error %u\n", GetLastError()); ok(ret, "GetOverlappedResult failed, last error %u\n", GetLastError());
todo_wine ok(value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected 3\n", value); todo_wine ok(value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected 3\n", value);
/* second report should be ready and the same */ /* second report should be ready and the same */
ret = GetOverlappedResult(async_file, &overlapped2, &value, FALSE); ret = GetOverlappedResult(async_file, &overlapped2, &value, FALSE);
todo_wine ok(ret, "GetOverlappedResult failed, last error %u\n", GetLastError()); ok(ret, "GetOverlappedResult failed, last error %u\n", GetLastError());
todo_wine ok(value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected 3\n", value); todo_wine ok(value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected 3\n", value);
todo_wine ok(memcmp(report, buffer + caps.InputReportByteLength, caps.InputReportByteLength), "expected different report\n"); ok(memcmp(report, buffer + caps.InputReportByteLength, caps.InputReportByteLength),
"expected different report\n");
ok(!memcmp(report, buffer, caps.InputReportByteLength), "expected identical reports\n"); ok(!memcmp(report, buffer, caps.InputReportByteLength), "expected identical reports\n");
CloseHandle(overlapped.hEvent); CloseHandle(overlapped.hEvent);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment