Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/driver_hid.c | 125 ++++++++++++++++++++++++++------ dlls/dinput8/tests/driver_hid.h | 1 + dlls/dinput8/tests/hid.c | 50 +++++++++++++ 3 files changed, 155 insertions(+), 21 deletions(-)
diff --git a/dlls/dinput8/tests/driver_hid.c b/dlls/dinput8/tests/driver_hid.c index 91f420d7bf6..cbaa1e89959 100644 --- a/dlls/dinput8/tests/driver_hid.c +++ b/dlls/dinput8/tests/driver_hid.c @@ -199,11 +199,97 @@ static void irp_queue_init( struct irp_queue *queue ) InitializeListHead( &queue->list ); }
+struct input_queue +{ + KSPIN_LOCK lock; + struct hid_expect *pos; + struct hid_expect *end; + struct hid_expect *buffer; + struct irp_queue pending; +}; + +static void input_queue_init( struct input_queue *queue ) +{ + KeInitializeSpinLock( &queue->lock ); + queue->buffer = ExAllocatePool( PagedPool, EXPECT_QUEUE_BUFFER_SIZE ); + RtlSecureZeroMemory( queue->buffer, EXPECT_QUEUE_BUFFER_SIZE ); + queue->pos = queue->buffer; + queue->end = queue->buffer; + irp_queue_init( &queue->pending ); +} + +static void input_queue_cleanup( struct input_queue *queue ) +{ + ExFreePool( queue->buffer ); +} + +static BOOL input_queue_read_locked( struct input_queue *queue, IRP *irp ) +{ + struct hid_expect *tmp = queue->pos; + if (tmp >= queue->end) return FALSE; + + memcpy( irp->UserBuffer, tmp->report_buf, tmp->ret_length ); + irp->IoStatus.Information = tmp->ret_length; + irp->IoStatus.Status = tmp->ret_status; + if (tmp < queue->end) queue->pos = tmp + 1; + + /* loop on the queue data in polled mode */ + if (polled && queue->pos == queue->end) queue->pos = queue->buffer; + return TRUE; +} + +static NTSTATUS input_queue_read( struct input_queue *queue, IRP *irp ) +{ + NTSTATUS status; + KIRQL irql; + + KeAcquireSpinLock( &queue->lock, &irql ); + if (input_queue_read_locked( queue, irp )) status = STATUS_SUCCESS; + else + { + IoMarkIrpPending( irp ); + irp_queue_push( &queue->pending, irp ); + status = STATUS_PENDING; + } + KeReleaseSpinLock( &queue->lock, irql ); + + return status; +} + +static void input_queue_reset( struct input_queue *queue, void *in_buf, ULONG in_size ) +{ + struct irp_queue completed; + ULONG remaining; + KIRQL irql; + IRP *irp; + + irp_queue_init( &completed ); + + KeAcquireSpinLock( &queue->lock, &irql ); + remaining = queue->end - queue->pos; + queue->pos = queue->buffer; + queue->end = queue->buffer; + memcpy( queue->end, in_buf, in_size ); + queue->end += in_size / sizeof(struct hid_expect); + + while (!polled && queue->pos < queue->end && (irp = irp_queue_pop( &queue->pending ))) + { + input_queue_read_locked( queue, irp ); + irp_queue_push( &completed, irp ); + } + KeReleaseSpinLock( &queue->lock, irql ); + + if (!polled) ok( !remaining, "unread input\n" ); + + while ((irp = irp_queue_pop( &completed ))) IoCompleteRequest( irp, IO_NO_INCREMENT ); +} + +static struct input_queue input_queue; + struct hid_device { BOOL removed; KSPIN_LOCK lock; - struct irp_queue irp_queue; };
static NTSTATUS WINAPI driver_pnp( DEVICE_OBJECT *device, IRP *irp ) @@ -221,7 +307,6 @@ static NTSTATUS WINAPI driver_pnp( DEVICE_OBJECT *device, IRP *irp ) ++got_start_device; impl->removed = FALSE; KeInitializeSpinLock( &impl->lock ); - irp_queue_init( &impl->irp_queue ); IoSetDeviceInterfaceState( &control_symlink, TRUE ); irp->IoStatus.Status = STATUS_SUCCESS; break; @@ -231,7 +316,7 @@ static NTSTATUS WINAPI driver_pnp( DEVICE_OBJECT *device, IRP *irp ) KeAcquireSpinLock( &impl->lock, &irql ); impl->removed = TRUE; KeReleaseSpinLock( &impl->lock, irql ); - irp_queue_clear( &impl->irp_queue ); + irp_queue_clear( &input_queue.pending ); irp->IoStatus.Status = STATUS_SUCCESS; break;
@@ -247,7 +332,7 @@ static NTSTATUS WINAPI driver_pnp( DEVICE_OBJECT *device, IRP *irp ) break;
case IRP_MN_REMOVE_DEVICE: - irp_queue_clear( &impl->irp_queue ); + irp_queue_clear( &input_queue.pending ); IoSetDeviceInterfaceState( &control_symlink, FALSE ); irp->IoStatus.Status = STATUS_SUCCESS; break; @@ -275,10 +360,9 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) HID_DEVICE_EXTENSION *ext = device->DeviceExtension; struct hid_device *impl = ext->MiniDeviceExtension; const ULONG in_size = stack->Parameters.DeviceIoControl.InputBufferLength; - const ULONG out_size = stack->Parameters.DeviceIoControl.OutputBufferLength; + ULONG out_size = stack->Parameters.DeviceIoControl.OutputBufferLength; const ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; struct hid_expect expect = {0}; - static BYTE seq = 0; NTSTATUS ret; BOOL removed; KIRQL irql; @@ -358,21 +442,7 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) ULONG expected_size = caps.InputReportByteLength - (report_id ? 0 : 1); ok( !in_size, "got input size %u\n", in_size ); ok( out_size == expected_size, "got output size %u\n", out_size ); - - if (polled) - { - memset( irp->UserBuffer, 0xa5, expected_size ); - if (report_id) ((char *)irp->UserBuffer)[0] = report_id; - ((char *)irp->UserBuffer)[1] = seq++; - irp->IoStatus.Information = 3; - ret = STATUS_SUCCESS; - } - else - { - IoMarkIrpPending( irp ); - irp_queue_push( &impl->irp_queue, irp ); - ret = STATUS_PENDING; - } + ret = input_queue_read( &input_queue, irp ); break; }
@@ -535,6 +605,11 @@ static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp ) irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( irp, IO_NO_INCREMENT ); return STATUS_SUCCESS; + case IOCTL_WINETEST_HID_SEND_INPUT: + input_queue_reset( &input_queue, irp->AssociatedIrp.SystemBuffer, in_size ); + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return STATUS_SUCCESS; }
return hidclass_driver_ioctl( device, irp ); @@ -577,6 +652,7 @@ static NTSTATUS WINAPI driver_close( DEVICE_OBJECT *device, IRP *irp )
static void WINAPI driver_unload( DRIVER_OBJECT *driver ) { + input_queue_cleanup( &input_queue ); expect_queue_cleanup( &expect_queue ); winetest_cleanup(); } @@ -647,6 +723,13 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *registry ) ok( !ret, "ZwQueryValueKey returned %#x\n", ret ); expect_queue_reset( &expect_queue, buffer + info_size, size - info_size );
+ input_queue_init( &input_queue ); + RtlInitUnicodeString( &name_str, L"Input" ); + size = info_size + EXPECT_QUEUE_BUFFER_SIZE; + ret = ZwQueryValueKey( hkey, &name_str, KeyValuePartialInformation, buffer, size, &size ); + ok( !ret, "ZwQueryValueKey returned %#x\n", ret ); + input_queue_reset( &input_queue, buffer + info_size, size - info_size ); + driver->DriverExtension->AddDevice = driver_add_device; driver->DriverUnload = driver_unload; driver->MajorFunction[IRP_MJ_PNP] = driver_pnp; diff --git a/dlls/dinput8/tests/driver_hid.h b/dlls/dinput8/tests/driver_hid.h index c9c75c6d081..538d6205ab9 100644 --- a/dlls/dinput8/tests/driver_hid.h +++ b/dlls/dinput8/tests/driver_hid.h @@ -40,6 +40,7 @@ DEFINE_GUID(control_class,0xdeadbeef,0x29ef,0x4538,0xa5,0xfd,0xb6,0x95,0x73,0xa3,0x62,0xc0);
#define IOCTL_WINETEST_HID_SET_EXPECT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x800, METHOD_IN_DIRECT, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_HID_SEND_INPUT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x801, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
struct hid_expect { diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 85ccc2a05df..0623ad9ae50 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -743,6 +743,25 @@ static void set_hid_expect_( int line, HANDLE file, struct hid_expect *expect, D ok( ret, "IOCTL_WINETEST_HID_SET_EXPECT failed, last error %u\n", GetLastError() ); }
+#define send_hid_input( a, b, c ) send_hid_input_( __LINE__, a, b, c ) +static void send_hid_input_( int line, HANDLE file, struct hid_expect *expect, DWORD expect_size ) +{ + const char *source_file; + BOOL ret; + int i; + + source_file = strrchr( __FILE__, '/' ); + if (!source_file) source_file = strrchr( __FILE__, '\' ); + if (!source_file) source_file = __FILE__; + else source_file++; + + for (i = 0; i < expect_size / sizeof(struct hid_expect); ++i) + snprintf( expect[i].context, ARRAY_SIZE(expect[i].context), "%s:%d", source_file, line ); + + ret = sync_ioctl( file, IOCTL_WINETEST_HID_SEND_INPUT, expect, expect_size, NULL, 0 ); + ok( ret, "IOCTL_WINETEST_HID_SEND_INPUT failed, last error %u\n", GetLastError() ); +} + static void test_hidp_get_input( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed ) { struct hid_expect expect[] = @@ -2049,6 +2068,26 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle
if (polled) { + struct hid_expect expect[] = + { + { + .code = IOCTL_HID_READ_REPORT, + .report_len = caps.InputReportByteLength - (report_id ? 0 : 1), + .report_buf = {report_id ? report_id : 0x5a,0x5a,0}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + { + .code = IOCTL_HID_READ_REPORT, + .report_len = caps.InputReportByteLength - (report_id ? 0 : 1), + .report_buf = {report_id ? report_id : 0x5a,0x5a,1}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + }; + + send_hid_input( file, expect, sizeof(expect) ); + memset( report, 0xcd, sizeof(report) ); SetLastError( 0xdeadbeef ); ret = ReadFile( file, report, caps.InputReportByteLength, &value, NULL ); @@ -2541,6 +2580,14 @@ static void test_hid_driver( DWORD report_id, DWORD polled ) .NumberFeatureValueCaps = 6, .NumberFeatureDataIndices = 8, }; + const struct hid_expect expect_in = + { + .code = IOCTL_HID_READ_REPORT, + .report_len = caps.InputReportByteLength - (report_id ? 0 : 1), + .report_buf = {report_id ? report_id : 0x5a,0x5a,0x5a}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + };
WCHAR cwd[MAX_PATH], tempdir[MAX_PATH]; LSTATUS status; @@ -2572,6 +2619,9 @@ static void test_hid_driver( DWORD report_id, DWORD polled ) status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, NULL, 0 ); ok( !status, "RegSetValueExW returned %#x\n", status );
+ status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, (void *)&expect_in, polled ? sizeof(expect_in) : 0 ); + ok( !status, "RegSetValueExW returned %#x\n", status ); + if (pnp_driver_start( L"driver_hid.dll" )) test_hid_device( report_id, polled, &caps );
pnp_driver_stop();
Using the new custom IOCTL to complete reads on demand.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 88 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 0623ad9ae50..0d0e528bf40 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -1374,11 +1374,11 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle DWORD waveform_list; HIDP_DATA data[64]; USAGE usages[16]; + ULONG off, value; NTSTATUS status; HIDP_CAPS caps; unsigned int i; USHORT count; - ULONG value; BOOL ret;
ret = HidD_GetPreparsedData( file, &preparsed_data ); @@ -2136,6 +2136,92 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle CloseHandle( overlapped.hEvent ); CloseHandle( overlapped2.hEvent ); } + else + { + struct hid_expect expect[] = + { + { + .code = IOCTL_HID_READ_REPORT, + .report_len = caps.InputReportByteLength - (report_id ? 0 : 1), + .report_buf = {report_id ? report_id : 0x5a,0x5a,0x5a}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + { + .code = IOCTL_HID_READ_REPORT, + .report_len = caps.InputReportByteLength - (report_id ? 0 : 1), + .report_buf = {report_id ? report_id : 0xa5,0xa5,0xa5,0xa5,0xa5}, + .ret_length = caps.InputReportByteLength - (report_id ? 0 : 1), + .ret_status = STATUS_SUCCESS, + }, + }; + + overlapped.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL ); + overlapped2.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL ); + + SetLastError( 0xdeadbeef ); + memset( report, 0, sizeof(report) ); + ret = ReadFile( async_file, report, caps.InputReportByteLength, NULL, &overlapped ); + ok( !ret, "ReadFile succeeded\n" ); + ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() ); + Sleep( 50 ); + ret = GetOverlappedResult( async_file, &overlapped, &value, FALSE ); + ok( !ret, "GetOverlappedResult succeeded\n" ); + ok( GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult returned error %u\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + memset( buffer, 0, sizeof(buffer) ); + ret = ReadFile( async_file, buffer, caps.InputReportByteLength, NULL, &overlapped2 ); + ok( !ret, "ReadFile succeeded\n" ); + ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() ); + Sleep( 50 ); + ret = GetOverlappedResult( async_file, &overlapped2, &value, FALSE ); + ok( !ret, "GetOverlappedResult succeeded\n" ); + ok( GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult returned error %u\n", GetLastError() ); + + memset( report + caps.InputReportByteLength, 0xa5, 5 ); + if (report_id) report[caps.InputReportByteLength] = report_id; + + send_hid_input( file, expect, sizeof(expect) ); + + /* first read should be completed */ + ret = GetOverlappedResult( async_file, &overlapped, &value, TRUE ); + ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() ); + todo_wine + ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength ); + /* second read should still be pending */ + Sleep( 50 ); + ret = GetOverlappedResult( async_file, &overlapped2, &value, FALSE ); + todo_wine + ok( !ret, "GetOverlappedResult succeeded\n" ); + todo_wine + ok( GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult returned error %u\n", GetLastError() ); + + memset( buffer + caps.InputReportByteLength, 0x3b, 5 ); + if (report_id) buffer[caps.InputReportByteLength] = report_id; + memset( expect[1].report_buf, 0x3b, 5 ); + if (report_id) expect[1].report_buf[0] = report_id; + + send_hid_input( file, expect, sizeof(expect) ); + + ret = GetOverlappedResult( async_file, &overlapped2, &value, TRUE ); + ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() ); + todo_wine + ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength ); + + off = report_id ? 0 : 1; + todo_wine + ok( memcmp( report, buffer, caps.InputReportByteLength ), "expected different report\n" ); + todo_wine + ok( !memcmp( report + off, report + caps.InputReportByteLength, caps.InputReportByteLength - off ), + "expected identical reports\n" ); + todo_wine + ok( !memcmp( buffer + off, buffer + caps.InputReportByteLength, caps.InputReportByteLength - off ), + "expected identical reports\n" ); + + CloseHandle( overlapped.hEvent ); + CloseHandle( overlapped2.hEvent ); + }
HidD_FreePreparsedData( preparsed_data ); }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/driver_hid.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/dinput8/tests/driver_hid.c b/dlls/dinput8/tests/driver_hid.c index cbaa1e89959..28694e5a4c6 100644 --- a/dlls/dinput8/tests/driver_hid.c +++ b/dlls/dinput8/tests/driver_hid.c @@ -568,9 +568,8 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) }
case IOCTL_HID_GET_STRING: - ok( !in_size, "got input size %u\n", in_size ); - ok( out_size == 128, "got output size %u\n", out_size ); - + todo_wine + ok( 0, "unexpected IOCTL_HID_GET_STRING\n" ); memcpy( irp->UserBuffer, L"Wine Test", sizeof(L"Wine Test") ); irp->IoStatus.Information = sizeof(L"Wine Test"); ret = STATUS_SUCCESS;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 3 --- dlls/hidclass.sys/device.c | 10 ++++++---- 2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 0d0e528bf40..40d40b6fcdf 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -2187,7 +2187,6 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle /* first read should be completed */ ret = GetOverlappedResult( async_file, &overlapped, &value, TRUE ); ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() ); - todo_wine ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength ); /* second read should still be pending */ Sleep( 50 ); @@ -2206,13 +2205,11 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle
ret = GetOverlappedResult( async_file, &overlapped2, &value, TRUE ); ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() ); - todo_wine ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength );
off = report_id ? 0 : 1; todo_wine ok( memcmp( report, buffer, caps.InputReportByteLength ), "expected different report\n" ); - todo_wine ok( !memcmp( report + off, report + caps.InputReportByteLength, caps.InputReportByteLength - off ), "expected identical reports\n" ); todo_wine diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 71fb4a366db..b9b31045297 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -246,7 +246,8 @@ static DWORD CALLBACK hid_device_thread(void *args) HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; HIDP_REPORT_IDS *reports = ext->u.pdo.device_desc.ReportIDs; ULONG report_count = ext->u.pdo.device_desc.ReportIDsLength; - ULONG i, report_id = 0, poll_interval = 0; + BOOL polled = ext->u.pdo.information.Polled; + ULONG i, report_id = 0, timeout = 0; HID_XFER_PACKET *packet; IO_STATUS_BLOCK io; BYTE *buffer; @@ -256,7 +257,7 @@ static DWORD CALLBACK hid_device_thread(void *args) buffer = (BYTE *)(packet + 1); packet->reportBuffer = buffer;
- if (ext->u.pdo.information.Polled) poll_interval = ext->u.pdo.poll_interval; + if (polled) timeout = ext->u.pdo.poll_interval;
for (i = 0; i < report_count; ++i) { @@ -288,10 +289,11 @@ static DWORD CALLBACK hid_device_thread(void *args) packet->reportBuffer = buffer; packet->reportBufferLen = io.Information;
- hid_device_queue_input( device, packet ); + if (polled || io.Information == desc->InputLength) + hid_device_queue_input( device, packet ); }
- res = WaitForSingleObject(ext->u.pdo.halt_event, poll_interval); + res = WaitForSingleObject(ext->u.pdo.halt_event, timeout); } while (res == WAIT_TIMEOUT);
TRACE("device thread exiting, res %#x\n", res);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 40d40b6fcdf..5745fcedad3 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -2105,7 +2105,8 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle 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() ); - 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 %u\n", + value, (report_id ? 3 : 4) ); ResetEvent( overlapped.hEvent );
memcpy( buffer, report, caps.InputReportByteLength ); @@ -2124,11 +2125,13 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle /* wait for second report to be ready */ ret = GetOverlappedResult( async_file, &overlapped2, &value, TRUE ); ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() ); - 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 %u\n", + value, (report_id ? 3 : 4) ); /* first report should be ready and the same */ ret = GetOverlappedResult( async_file, &overlapped, &value, FALSE ); ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() ); - 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 %u\n", + value, (report_id ? 3 : 4) ); ok( memcmp( report, buffer + caps.InputReportByteLength, caps.InputReportByteLength ), "expected different report\n" ); ok( !memcmp( report, buffer, caps.InputReportByteLength ), "expected identical reports\n" );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/hid.c | 4 ---- dlls/hidclass.sys/device.c | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 5745fcedad3..86e878d5ecb 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -2194,9 +2194,7 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle /* second read should still be pending */ Sleep( 50 ); ret = GetOverlappedResult( async_file, &overlapped2, &value, FALSE ); - todo_wine ok( !ret, "GetOverlappedResult succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult returned error %u\n", GetLastError() );
memset( buffer + caps.InputReportByteLength, 0x3b, 5 ); @@ -2211,11 +2209,9 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength );
off = report_id ? 0 : 1; - todo_wine ok( memcmp( report, buffer, caps.InputReportByteLength ), "expected different report\n" ); ok( !memcmp( report + off, report + caps.InputReportByteLength, caps.InputReportByteLength - off ), "expected identical reports\n" ); - todo_wine ok( !memcmp( buffer + off, buffer + caps.InputReportByteLength, caps.InputReportByteLength - off ), "expected identical reports\n" );
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index b9b31045297..8e998bd71be 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -182,6 +182,7 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + const BOOL polled = ext->u.pdo.information.Polled; struct hid_report *last_report, *report; struct hid_report_queue *queue; RAWINPUT *rawinput; @@ -223,8 +224,9 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack hid_report_queue_push( queue, last_report ); KeReleaseSpinLock( &ext->u.pdo.report_queues_lock, irql );
- while ((irp = pop_irp_from_queue( ext ))) + do { + if (!(irp = pop_irp_from_queue( ext ))) break; queue = irp->Tail.Overlay.OriginalFileObject->FsContext;
if (!(report = hid_report_queue_pop( queue ))) hid_report_incref( (report = last_report) ); @@ -235,6 +237,7 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack
IoCompleteRequest( irp, IO_NO_INCREMENT ); } + while (polled);
hid_report_decref( last_report ); }