Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/device.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 61126571ac6..3a577aabfbd 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -193,18 +193,11 @@ static DWORD CALLBACK hid_device_thread(void *args) { while(1) { - KEVENT event; - - KeInitializeEvent(&event, NotificationEvent, FALSE); - packet->reportBufferLen = report_size; packet->reportId = 0;
- irp = IoBuildDeviceIoControlRequest(IOCTL_HID_GET_INPUT_REPORT, ext->u.pdo.parent_fdo, - NULL, 0, packet, sizeof(*packet), TRUE, &event, &irp_status); - - if (IoCallDriver(ext->u.pdo.parent_fdo, irp) == STATUS_PENDING) - KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); + call_minidriver( IOCTL_HID_GET_INPUT_REPORT, ext->u.pdo.parent_fdo, NULL, 0, packet, + sizeof(*packet), &irp_status );
if (irp_status.Status == STATUS_SUCCESS) {
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/device.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 3a577aabfbd..ab449b9b0d9 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -178,7 +178,6 @@ static DWORD CALLBACK hid_device_thread(void *args) { DEVICE_OBJECT *device = (DEVICE_OBJECT*)args;
- IRP *irp; IO_STATUS_BLOCK irp_status; HID_XFER_PACKET *packet; DWORD rc; @@ -221,15 +220,8 @@ static DWORD CALLBACK hid_device_thread(void *args)
while(1) { - KEVENT event; - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - irp = IoBuildDeviceIoControlRequest(IOCTL_HID_READ_REPORT, ext->u.pdo.parent_fdo, - NULL, 0, packet->reportBuffer, report_size, TRUE, &event, &irp_status); - - if (IoCallDriver(ext->u.pdo.parent_fdo, irp) == STATUS_PENDING) - KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); + call_minidriver( IOCTL_HID_READ_REPORT, ext->u.pdo.parent_fdo, NULL, 0, + packet->reportBuffer, report_size, &irp_status );
rc = WaitForSingleObject(ext->u.pdo.halt_event, 0); if (rc == WAIT_OBJECT_0)
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/device.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index ab449b9b0d9..f1b0083fffd 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -177,9 +177,8 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device) static DWORD CALLBACK hid_device_thread(void *args) { DEVICE_OBJECT *device = (DEVICE_OBJECT*)args; - - IO_STATUS_BLOCK irp_status; HID_XFER_PACKET *packet; + IO_STATUS_BLOCK io; DWORD rc;
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; @@ -196,9 +195,9 @@ static DWORD CALLBACK hid_device_thread(void *args) packet->reportId = 0;
call_minidriver( IOCTL_HID_GET_INPUT_REPORT, ext->u.pdo.parent_fdo, NULL, 0, packet, - sizeof(*packet), &irp_status ); + sizeof(*packet), &io );
- if (irp_status.Status == STATUS_SUCCESS) + if (io.Status == STATUS_SUCCESS) { RingBuffer_Write(ext->u.pdo.ring_buffer, packet); hid_device_send_input(device, packet); @@ -221,15 +220,15 @@ static DWORD CALLBACK hid_device_thread(void *args) while(1) { call_minidriver( IOCTL_HID_READ_REPORT, ext->u.pdo.parent_fdo, NULL, 0, - packet->reportBuffer, report_size, &irp_status ); + packet->reportBuffer, report_size, &io );
rc = WaitForSingleObject(ext->u.pdo.halt_event, 0); if (rc == WAIT_OBJECT_0) exit_now = TRUE;
- if (!exit_now && irp_status.Status == STATUS_SUCCESS) + if (!exit_now && io.Status == STATUS_SUCCESS) { - packet->reportBufferLen = irp_status.Information; + packet->reportBufferLen = io.Information; if (ext->u.pdo.preparsed_data->reports[0].reportID) packet->reportId = packet->reportBuffer[0]; else
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/device.c | 60 +++++++++--------------------- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 15 ++++---- 2 files changed, 25 insertions(+), 50 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index f1b0083fffd..a465cc53369 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -77,32 +77,6 @@ static void WINAPI read_cancel_routine(DEVICE_OBJECT *device, IRP *irp) 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) { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; @@ -145,24 +119,24 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device) IRP *irp; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; 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;
packet = malloc(buffer_size);
while((irp = pop_irp_from_queue(ext))) { - int ptr; - ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext ); + BYTE *buffer = irp->AssociatedIrp.SystemBuffer, *dst = buffer; + int ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext );
RingBuffer_Read(ext->u.pdo.ring_buffer, ptr, packet, &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); - irp->IoStatus.Status = copy_packet_into_buffer( packet, irp->AssociatedIrp.SystemBuffer, irpsp->Parameters.Read.Length, &out_length ); - irp->IoStatus.Information = out_length; + if (!data->reports[0].reportID) *dst++ = 0; + memcpy( dst, packet + 1, data->caps.InputReportByteLength - (dst - buffer) ); + irp->IoStatus.Information = packet->reportBufferLen; + irp->IoStatus.Status = STATUS_SUCCESS; } else { @@ -483,8 +457,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) HID_XFER_PACKET *packet; ULONG buffer_len = irpsp->Parameters.DeviceIoControl.OutputBufferLength; UINT packet_size = sizeof(*packet) + buffer_len; - BYTE *buffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); - ULONG out_length; + BYTE *buffer = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority ), *dst = buffer;
if (!buffer) { @@ -510,7 +483,10 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) sizeof(*packet), &irp->IoStatus );
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); break; } @@ -568,6 +544,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data; UINT buffer_size = RingBuffer_GetBufferSize(ext->u.pdo.ring_buffer); IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); + BYTE *buffer = irp->AssociatedIrp.SystemBuffer, *dst = buffer; NTSTATUS status; int ptr = -1; BOOL removed; @@ -599,13 +576,10 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp)
if (buffer_size) { - IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); - ULONG out_length; - packet->reportBuffer = (BYTE *)packet + sizeof(*packet); - TRACE_(hid_report)("Got Packet %p %i\n", packet->reportBuffer, packet->reportBufferLen); - - irp->IoStatus.Status = copy_packet_into_buffer( packet, irp->AssociatedIrp.SystemBuffer, irpsp->Parameters.Read.Length, &out_length ); - irp->IoStatus.Information = out_length; + if (!data->reports[0].reportID) *dst++ = 0; + memcpy( dst, packet + 1, data->caps.InputReportByteLength - (dst - buffer) ); + irp->IoStatus.Information = packet->reportBufferLen; + irp->IoStatus.Status = STATUS_SUCCESS; } else { diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 02f37773c67..aa22d72828c 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2684,9 +2684,9 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled memset(report, 0xcd, sizeof(report)); SetLastError(0xdeadbeef); 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(report[0] == report_id, "unexpected report data\n"); + ok(report[0] == report_id, "unexpected report data\n");
overlapped.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 SetLastError(0xdeadbeef); while (ReadFile(async_file, report, caps.InputReportByteLength, NULL, &overlapped)) 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); - 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); ResetEvent(overlapped.hEvent);
@@ -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 */ 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); /* second report should be ready and the same */ 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(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");
CloseHandle(overlapped.hEvent);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/device.c | 117 +++++++++++++++------------ dlls/ntoskrnl.exe/tests/driver_hid.c | 4 +- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 10 +-- 3 files changed, 72 insertions(+), 59 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index a465cc53369..a7cb6a843e0 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -81,12 +81,10 @@ static void hid_device_send_input(DEVICE_OBJECT *device, HID_XFER_PACKET *packet { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; RAWINPUT *rawinput; - UCHAR *report, id; ULONG data_size; INPUT input;
data_size = offsetof(RAWINPUT, data.hid.bRawData) + packet->reportBufferLen; - if (!(id = ext->u.pdo.preparsed_data->reports[0].reportID)) data_size += 1;
if (!(rawinput = malloc(data_size))) { @@ -100,10 +98,7 @@ static void hid_device_send_input(DEVICE_OBJECT *device, HID_XFER_PACKET *packet rawinput->header.wParam = RIM_INPUT; rawinput->data.hid.dwCount = 1; rawinput->data.hid.dwSizeHid = data_size - offsetof(RAWINPUT, data.hid.bRawData); - - report = rawinput->data.hid.bRawData; - if (!id) *report++ = 0; - memcpy(report, packet->reportBuffer, packet->reportBufferLen); + memcpy( rawinput->data.hid.bRawData, packet->reportBuffer, packet->reportBufferLen );
input.type = INPUT_HARDWARE; input.hi.uMsg = WM_INPUT; @@ -126,15 +121,13 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device)
while((irp = pop_irp_from_queue(ext))) { - BYTE *buffer = irp->AssociatedIrp.SystemBuffer, *dst = buffer; int ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext );
RingBuffer_Read(ext->u.pdo.ring_buffer, ptr, packet, &buffer_size); if (buffer_size) { TRACE_(hid_report)("Processing Request (%i)\n",ptr); - if (!data->reports[0].reportID) *dst++ = 0; - memcpy( dst, packet + 1, data->caps.InputReportByteLength - (dst - buffer) ); + memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, data->caps.InputReportByteLength ); irp->IoStatus.Information = packet->reportBufferLen; irp->IoStatus.Status = STATUS_SUCCESS; } @@ -151,28 +144,42 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device) static DWORD CALLBACK hid_device_thread(void *args) { DEVICE_OBJECT *device = (DEVICE_OBJECT*)args; - HID_XFER_PACKET *packet; + BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data; + BYTE report_id = HID_INPUT_VALUE_CAPS( data )->report_id; + ULONG buffer_len = data->caps.InputReportByteLength; IO_STATUS_BLOCK io; + HID_XFER_PACKET *packet; + BYTE *buffer; DWORD rc;
- BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - USHORT report_size = ext->u.pdo.preparsed_data->caps.InputReportByteLength; - - packet = malloc(sizeof(*packet) + report_size); - packet->reportBuffer = (BYTE *)packet + sizeof(*packet); + packet = malloc( sizeof(*packet) + buffer_len ); + buffer = (BYTE *)(packet + 1); + packet->reportBuffer = buffer;
if (ext->u.pdo.information.Polled) { while(1) { - packet->reportBufferLen = report_size; - packet->reportId = 0; + packet->reportId = buffer[0] = report_id; + packet->reportBufferLen = buffer_len; + + if (!report_id) + { + packet->reportBuffer++; + packet->reportBufferLen--; + }
call_minidriver( IOCTL_HID_GET_INPUT_REPORT, ext->u.pdo.parent_fdo, NULL, 0, packet, sizeof(*packet), &io );
if (io.Status == STATUS_SUCCESS) { + if (!report_id) io.Information++; + packet->reportId = buffer[0]; + packet->reportBuffer = buffer; + packet->reportBufferLen = io.Information; + RingBuffer_Write(ext->u.pdo.ring_buffer, packet); hid_device_send_input(device, packet); HID_Device_processQueue(device); @@ -193,8 +200,17 @@ static DWORD CALLBACK hid_device_thread(void *args)
while(1) { + packet->reportId = buffer[0] = report_id; + packet->reportBufferLen = buffer_len; + + if (!report_id) + { + packet->reportBuffer++; + packet->reportBufferLen--; + } + call_minidriver( IOCTL_HID_READ_REPORT, ext->u.pdo.parent_fdo, NULL, 0, - packet->reportBuffer, report_size, &io ); + packet->reportBuffer, packet->reportBufferLen, &io );
rc = WaitForSingleObject(ext->u.pdo.halt_event, 0); if (rc == WAIT_OBJECT_0) @@ -202,11 +218,11 @@ static DWORD CALLBACK hid_device_thread(void *args)
if (!exit_now && io.Status == STATUS_SUCCESS) { + if (!report_id) io.Information++; + packet->reportId = buffer[0]; + packet->reportBuffer = buffer; packet->reportBufferLen = io.Information; - if (ext->u.pdo.preparsed_data->reports[0].reportID) - packet->reportId = packet->reportBuffer[0]; - else - packet->reportId = 0; + RingBuffer_Write(ext->u.pdo.ring_buffer, packet); hid_device_send_input(device, packet); HID_Device_processQueue(device); @@ -375,6 +391,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data; + BYTE report_id = HID_INPUT_VALUE_CAPS( data )->report_id; NTSTATUS status; BOOL removed; KIRQL irql; @@ -454,10 +471,9 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) } case IOCTL_HID_GET_INPUT_REPORT: { - HID_XFER_PACKET *packet; + HID_XFER_PACKET packet; ULONG buffer_len = irpsp->Parameters.DeviceIoControl.OutputBufferLength; - UINT packet_size = sizeof(*packet) + buffer_len; - BYTE *buffer = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority ), *dst = buffer; + BYTE *buffer = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority );
if (!buffer) { @@ -470,24 +486,19 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) break; }
- packet = malloc(packet_size); + packet.reportId = buffer[0]; + packet.reportBuffer = buffer; + packet.reportBufferLen = buffer_len;
- if (ext->u.pdo.preparsed_data->reports[0].reportID) - packet->reportId = buffer[0]; - else - packet->reportId = 0; - packet->reportBuffer = (BYTE *)packet + sizeof(*packet); - packet->reportBufferLen = buffer_len - 1; - - call_minidriver( IOCTL_HID_GET_INPUT_REPORT, ext->u.pdo.parent_fdo, NULL, 0, packet, - sizeof(*packet), &irp->IoStatus ); - - if (irp->IoStatus.Status == STATUS_SUCCESS) + if (!report_id) { - if (!data->reports[0].reportID) *dst++ = 0; - memcpy( dst, packet + 1, data->caps.InputReportByteLength - (dst - buffer) ); + packet.reportId = 0; + packet.reportBuffer++; + packet.reportBufferLen--; } - free(packet); + + call_minidriver( IOCTL_HID_GET_INPUT_REPORT, ext->u.pdo.parent_fdo, NULL, 0, &packet, + sizeof(packet), &irp->IoStatus ); break; } case IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS: @@ -544,7 +555,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data; UINT buffer_size = RingBuffer_GetBufferSize(ext->u.pdo.ring_buffer); IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); - BYTE *buffer = irp->AssociatedIrp.SystemBuffer, *dst = buffer; + BYTE report_id = HID_INPUT_VALUE_CAPS( data )->report_id; NTSTATUS status; int ptr = -1; BOOL removed; @@ -576,8 +587,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp)
if (buffer_size) { - if (!data->reports[0].reportID) *dst++ = 0; - memcpy( dst, packet + 1, data->caps.InputReportByteLength - (dst - buffer) ); + memcpy( irp->AssociatedIrp.SystemBuffer, packet + 1, data->caps.InputReportByteLength ); irp->IoStatus.Information = packet->reportBufferLen; irp->IoStatus.Status = STATUS_SUCCESS; } @@ -608,19 +618,24 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) else { HID_XFER_PACKET packet; + BYTE *buffer = irp->AssociatedIrp.SystemBuffer; + ULONG buffer_len = irpsp->Parameters.Read.Length; + TRACE("No packet, but opportunistic reads enabled\n"); - packet.reportId = ((BYTE*)irp->AssociatedIrp.SystemBuffer)[0]; - packet.reportBuffer = &((BYTE*)irp->AssociatedIrp.SystemBuffer)[1]; - packet.reportBufferLen = irpsp->Parameters.Read.Length - 1;
- call_minidriver( IOCTL_HID_GET_INPUT_REPORT, ext->u.pdo.parent_fdo, NULL, 0, &packet, - sizeof(packet), &irp->IoStatus ); + packet.reportId = buffer[0]; + packet.reportBuffer = buffer; + packet.reportBufferLen = buffer_len;
- if (irp->IoStatus.Status == STATUS_SUCCESS) + if (!report_id) { - ((BYTE*)irp->AssociatedIrp.SystemBuffer)[0] = packet.reportId; - irp->IoStatus.Information = packet.reportBufferLen + 1; + packet.reportId = 0; + packet.reportBuffer++; + packet.reportBufferLen--; } + + call_minidriver( IOCTL_HID_GET_INPUT_REPORT, ext->u.pdo.parent_fdo, NULL, 0, &packet, + sizeof(packet), &irp->IoStatus ); } } free(packet); diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c index a45e5f56928..831b08c5c97 100644 --- a/dlls/ntoskrnl.exe/tests/driver_hid.c +++ b/dlls/ntoskrnl.exe/tests/driver_hid.c @@ -479,7 +479,6 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) { ULONG expected_size = 23; ok(!in_size, "got input size %u\n", in_size); - todo_wine_if(!report_id) ok(out_size == expected_size, "got output size %u\n", out_size);
if (polled) @@ -533,9 +532,8 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) ok(!in_size, "got input size %u\n", in_size); ok(out_size == sizeof(*packet), "got output size %u\n", out_size);
- todo_wine_if(packet->reportId == 0x5a || (polled && report_id && packet->reportId == 0)) + todo_wine_if(packet->reportId == 0x5a) ok(packet->reportId == report_id, "got id %u\n", packet->reportId); - todo_wine_if(packet->reportBufferLen == 22) ok(packet->reportBufferLen >= expected_size, "got len %u\n", packet->reportBufferLen); ok(!!packet->reportBuffer, "got buffer %p\n", packet->reportBuffer);
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index aa22d72828c..17d82fa3482 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2463,7 +2463,7 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled else { ok(ret, "HidD_GetInputReport failed, last error %u\n", GetLastError()); - todo_wine ok(buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0]); + ok(buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0]); }
SetLastError(0xdeadbeef); @@ -2685,7 +2685,7 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled SetLastError(0xdeadbeef); ret = ReadFile(file, report, caps.InputReportByteLength, &value, NULL); ok(ret, "ReadFile failed, last error %u\n", GetLastError()); - todo_wine ok(value == (report_id ? 3 : 4), "ReadFile returned %x\n", value); + ok(value == (report_id ? 3 : 4), "ReadFile returned %x\n", value); ok(report[0] == report_id, "unexpected report data\n");
overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); @@ -2698,7 +2698,7 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled ok(GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError()); ret = GetOverlappedResult(async_file, &overlapped, &value, TRUE); 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); + ok(value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected 3\n", value); ResetEvent(overlapped.hEvent);
memcpy(buffer, report, caps.InputReportByteLength); @@ -2717,11 +2717,11 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled /* wait for first report to be ready */ ret = GetOverlappedResult(async_file, &overlapped, &value, TRUE); 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); + ok(value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected 3\n", value); /* second report should be ready and the same */ ret = GetOverlappedResult(async_file, &overlapped2, &value, FALSE); 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); + ok(value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected 3\n", value); ok(memcmp(report, buffer + caps.InputReportByteLength, caps.InputReportByteLength), "expected different report\n"); ok(!memcmp(report, buffer, caps.InputReportByteLength), "expected identical reports\n");
From HID_IOCTL_GET_INPUT_REPORT code, to factor report buffer transfer,
and use it for HID_IOCTL_GET_FEATURE.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/device.c | 100 ++++++++++----------------- dlls/ntoskrnl.exe/tests/driver_hid.c | 3 +- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 10 +-- 3 files changed, 39 insertions(+), 74 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index a7cb6a843e0..81ddd7e6d7e 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -299,46 +299,48 @@ static void handle_minidriver_string( BASE_DEVICE_EXTENSION *ext, IRP *irp, SHOR } }
-static void HID_get_feature( BASE_DEVICE_EXTENSION *ext, IRP *irp ) +static void hid_device_xfer_report( BASE_DEVICE_EXTENSION *ext, ULONG code, IRP *irp ) { - IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); - HID_XFER_PACKET *packet; - DWORD len; - BYTE *out_buffer; - - irp->IoStatus.Information = 0; + const WINE_HIDP_PREPARSED_DATA *preparsed = ext->u.pdo.preparsed_data; + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + ULONG report_len = 0, buffer_len = stack->Parameters.DeviceIoControl.OutputBufferLength; + BYTE *buffer = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority ); + BYTE report_id = HID_INPUT_VALUE_CAPS( preparsed )->report_id; + HID_XFER_PACKET packet;
- out_buffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); - TRACE_(hid_report)("Device %p Buffer length %i Buffer %p\n", ext, irpsp->Parameters.DeviceIoControl.OutputBufferLength, out_buffer); + switch (code) + { + case IOCTL_HID_GET_INPUT_REPORT: + report_len = preparsed->caps.InputReportByteLength; + break; + case IOCTL_HID_GET_FEATURE: + report_len = preparsed->caps.FeatureReportByteLength; + break; + }
- if (!irpsp->Parameters.DeviceIoControl.OutputBufferLength || !out_buffer) + if (!buffer) { - irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER; + return; + } + if (buffer_len < report_len) + { + irp->IoStatus.Status = STATUS_INVALID_PARAMETER; return; }
- len = sizeof(*packet) + irpsp->Parameters.DeviceIoControl.OutputBufferLength; - packet = malloc(len); - packet->reportBufferLen = irpsp->Parameters.DeviceIoControl.OutputBufferLength; - packet->reportBuffer = ((BYTE*)packet) + sizeof(*packet); - packet->reportId = out_buffer[0]; - - TRACE_(hid_report)("(id %i, len %i buffer %p)\n", packet->reportId, packet->reportBufferLen, packet->reportBuffer); - - call_minidriver( IOCTL_HID_GET_FEATURE, ext->u.pdo.parent_fdo, NULL, 0, packet, sizeof(*packet), - &irp->IoStatus ); + packet.reportId = buffer[0]; + packet.reportBuffer = buffer; + packet.reportBufferLen = buffer_len;
- if (irp->IoStatus.Status == STATUS_SUCCESS) + if (!report_id) { - irp->IoStatus.Information = packet->reportBufferLen; - memcpy(out_buffer, packet->reportBuffer, packet->reportBufferLen); + packet.reportId = 0; + packet.reportBuffer++; + packet.reportBufferLen--; } - else - irp->IoStatus.Information = 0; - - TRACE_(hid_report)( "Result 0x%x get %li bytes\n", irp->IoStatus.Status, irp->IoStatus.Information );
- free(packet); + call_minidriver( code, ext->u.pdo.parent_fdo, NULL, 0, &packet, sizeof(packet), &irp->IoStatus ); }
static void HID_set_to_device( DEVICE_OBJECT *device, IRP *irp ) @@ -390,10 +392,9 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) { IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - const WINE_HIDP_PREPARSED_DATA *data = ext->u.pdo.preparsed_data; - BYTE report_id = HID_INPUT_VALUE_CAPS( data )->report_id; NTSTATUS status; BOOL removed; + ULONG code; KIRQL irql;
irp->IoStatus.Information = 0; @@ -411,7 +412,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) return STATUS_DELETE_PENDING; }
- switch (irpsp->Parameters.DeviceIoControl.IoControlCode) + switch ((code = irpsp->Parameters.DeviceIoControl.IoControlCode)) { case IOCTL_HID_GET_POLL_FREQUENCY_MSEC: TRACE("IOCTL_HID_GET_POLL_FREQUENCY_MSEC\n"); @@ -469,38 +470,6 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) handle_IOCTL_HID_GET_COLLECTION_DESCRIPTOR( irp, ext ); break; } - case IOCTL_HID_GET_INPUT_REPORT: - { - HID_XFER_PACKET packet; - ULONG buffer_len = irpsp->Parameters.DeviceIoControl.OutputBufferLength; - BYTE *buffer = MmGetSystemAddressForMdlSafe( irp->MdlAddress, NormalPagePriority ); - - if (!buffer) - { - irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER; - break; - } - if (buffer_len < data->caps.InputReportByteLength) - { - irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - break; - } - - packet.reportId = buffer[0]; - packet.reportBuffer = buffer; - packet.reportBufferLen = buffer_len; - - if (!report_id) - { - packet.reportId = 0; - packet.reportBuffer++; - packet.reportBufferLen--; - } - - call_minidriver( IOCTL_HID_GET_INPUT_REPORT, ext->u.pdo.parent_fdo, NULL, 0, &packet, - sizeof(packet), &irp->IoStatus ); - break; - } case IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS: { irp->IoStatus.Information = 0; @@ -527,7 +496,8 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) break; } case IOCTL_HID_GET_FEATURE: - HID_get_feature( ext, irp ); + case IOCTL_HID_GET_INPUT_REPORT: + hid_device_xfer_report( ext, code, irp ); break; case IOCTL_HID_SET_FEATURE: case IOCTL_HID_SET_OUTPUT_REPORT: diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c index 831b08c5c97..d268b62d288 100644 --- a/dlls/ntoskrnl.exe/tests/driver_hid.c +++ b/dlls/ntoskrnl.exe/tests/driver_hid.c @@ -570,9 +570,8 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) ok(!in_size, "got input size %u\n", in_size); ok(out_size == sizeof(*packet), "got output size %u\n", out_size);
- todo_wine_if(packet->reportId == 0x5a || packet->reportId == 0xa5) + todo_wine_if(packet->reportId == 0x5a) ok(packet->reportId == report_id, "got id %u\n", packet->reportId); - todo_wine_if(packet->reportBufferLen == 16) ok(packet->reportBufferLen >= expected_size, "got len %u\n", packet->reportBufferLen); ok(!!packet->reportBuffer, "got buffer %p\n", packet->reportBuffer);
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 17d82fa3482..f5ebf21b7f9 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2486,13 +2486,11 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled SetLastError(0xdeadbeef); ret = HidD_GetFeature(file, report, 0); ok(!ret, "HidD_GetFeature succeeded\n"); - todo_wine ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetFeature returned error %u\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetFeature returned error %u\n", GetLastError());
SetLastError(0xdeadbeef); ret = HidD_GetFeature(file, report, caps.FeatureReportByteLength - 1); - todo_wine ok(!ret, "HidD_GetFeature succeeded\n"); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER || broken(GetLastError() == ERROR_CRC), "HidD_GetFeature returned error %u\n", GetLastError());
@@ -2510,21 +2508,19 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled else { ok(ret, "HidD_GetFeature failed, last error %u\n", GetLastError()); - todo_wine ok(buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0]); + ok(buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0]); }
SetLastError(0xdeadbeef); ret = HidD_GetFeature(file, report, caps.FeatureReportByteLength); ok(ret, "HidD_GetFeature failed, last error %u\n", GetLastError()); - todo_wine_if(!report_id) ok(report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id);
value = caps.FeatureReportByteLength * 2; SetLastError(0xdeadbeef); ret = sync_ioctl(file, IOCTL_HID_GET_FEATURE, NULL, 0, report, &value); ok(ret, "IOCTL_HID_GET_FEATURE failed, last error %u\n", GetLastError()); - todo_wine ok(value == 3, "got length %u, expected 3\n", value); - todo_wine_if(!report_id) + ok(value == 3, "got length %u, expected 3\n", value); ok(report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id);