And change skipped test message. It's not really useful and it will fail the tests if the main test summary doesn't match the number of skipped messages.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
In order for the skipped tests to be counted correctly we would need a new winetest_add_skipped helper in wine/test.h and that would cause all tests to be rebuilt.
This is simpler and I don't think driver skipped test count matter so much. It could also be added later.
dlls/dinput8/tests/driver_hid.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/dinput8/tests/driver_hid.h b/dlls/dinput8/tests/driver_hid.h index 8fad343157d..42d12a0cf27 100644 --- a/dlls/dinput8/tests/driver_hid.h +++ b/dlls/dinput8/tests/driver_hid.h @@ -326,7 +326,7 @@ static inline void winetest_vskip( const char *msg, __ms_va_list args ) { if (winetest_add_line() < winetest_mute_threshold) { - winetest_print_context( "Tests skipped: " ); + winetest_print_context( "Driver tests skipped: " ); kvprintf( msg, args ); InterlockedIncrement( &skipped ); } @@ -347,7 +347,7 @@ static inline void WINAPIV winetest_win_skip( const char *msg, ... ) { __ms_va_list args; __ms_va_start( args, msg ); - if (running_under_wine) winetest_vskip( msg, args ); + if (!running_under_wine) winetest_vskip( msg, args ); else winetest_vok( 0, msg, args ); __ms_va_end( args ); }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/driver_hid.c | 165 +++++++++++++++++++++++++++++-- dlls/dinput8/tests/driver_hid.h | 15 +++ dlls/dinput8/tests/hid.c | 170 +++++++++++++++++++++++--------- 3 files changed, 298 insertions(+), 52 deletions(-)
diff --git a/dlls/dinput8/tests/driver_hid.c b/dlls/dinput8/tests/driver_hid.c index b393ddb41cb..9256bb4922e 100644 --- a/dlls/dinput8/tests/driver_hid.c +++ b/dlls/dinput8/tests/driver_hid.c @@ -46,6 +46,114 @@ static HIDP_CAPS caps; static DWORD report_id; static DWORD polled;
+#define EXPECT_QUEUE_BUFFER_SIZE (64 * sizeof(struct hid_expect)) + +struct expect_queue +{ + KSPIN_LOCK lock; + struct hid_expect *pos; + struct hid_expect *end; + struct hid_expect spurious; + struct hid_expect *buffer; +}; + +static void expect_queue_init( struct expect_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; +} + +static void expect_queue_cleanup( struct expect_queue *queue ) +{ + ExFreePool( queue->buffer ); +} + +static void expect_queue_reset( struct expect_queue *queue, void *buffer, unsigned int size ) +{ + struct hid_expect *missing, *missing_end, *tmp; + KIRQL irql; + + missing = ExAllocatePool( PagedPool, EXPECT_QUEUE_BUFFER_SIZE ); + RtlSecureZeroMemory( missing, EXPECT_QUEUE_BUFFER_SIZE ); + missing_end = missing; + + KeAcquireSpinLock( &queue->lock, &irql ); + tmp = queue->pos; + while (tmp < queue->end) *missing_end++ = *tmp++; + + queue->pos = queue->buffer; + queue->end = queue->buffer; + + if (size) memcpy( queue->end, buffer, size ); + queue->end = queue->end + size / sizeof(struct hid_expect); + KeReleaseSpinLock( &queue->lock, irql ); + + tmp = missing; + while (tmp != missing_end) + { + winetest_push_context( "%s expect[%d]", tmp->context, tmp - missing ); + if (tmp->broken) + win_skip( "broken (code %#x id %u len %u)\n", tmp->code, tmp->report_id, tmp->report_len ); + else + ok( 0, "missing (code %#x id %u len %u)\n", tmp->code, tmp->report_id, tmp->report_len ); + winetest_pop_context(); + tmp++; + } + + ExFreePool( missing ); +} + +static void expect_queue_next( struct expect_queue *queue, ULONG code, HID_XFER_PACKET *packet, + LONG *index, struct hid_expect *expect ) +{ + struct hid_expect *missing, *missing_end, *tmp; + ULONG len = packet->reportBufferLen; + BYTE *buf = packet->reportBuffer; + BYTE id = packet->reportId; + KIRQL irql; + + missing = ExAllocatePool( PagedPool, EXPECT_QUEUE_BUFFER_SIZE ); + RtlSecureZeroMemory( missing, EXPECT_QUEUE_BUFFER_SIZE ); + missing_end = missing; + + KeAcquireSpinLock( &queue->lock, &irql ); + tmp = queue->pos; + while (tmp < queue->end) + { + if (!tmp->broken || running_under_wine) break; + if (tmp->code == code && tmp->report_id == id && tmp->report_len == len && + RtlCompareMemory( tmp->report_buf, buf, len ) == len) + break; + *missing_end++ = *tmp++; + } + *index = tmp - queue->buffer; + if (tmp < queue->end) queue->pos = tmp + 1; + else tmp = &queue->spurious; + *expect = *tmp; + KeReleaseSpinLock( &queue->lock, irql ); + + ok( tmp != &queue->spurious, "got spurious packet\n" ); + + tmp = missing; + while (tmp != missing_end) + { + winetest_push_context( "%s expect[%d]", tmp->context, tmp - missing ); + if (tmp->broken) + win_skip( "broken (code %#x id %u len %u)\n", tmp->code, tmp->report_id, tmp->report_len ); + else + ok( 0, "missing (code %#x id %u len %u)\n", tmp->code, tmp->report_id, tmp->report_len ); + winetest_pop_context(); + tmp++; + } + + ExFreePool( missing ); +} + +static struct expect_queue expect_queue; + struct irp_queue { KSPIN_LOCK lock; @@ -169,10 +277,12 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) const ULONG in_size = stack->Parameters.DeviceIoControl.InputBufferLength; const 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; + LONG index;
if (winetest_debug > 1) trace( "ioctl %#x\n", code );
@@ -191,6 +301,8 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) return STATUS_DELETE_PENDING; }
+ winetest_push_context( "id %d%s", report_id, polled ? " poll" : "" ); + switch (code) { case IOCTL_HID_GET_DEVICE_DESCRIPTOR: @@ -345,8 +457,18 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) ok( packet->reportBufferLen >= expected_size, "got len %u\n", packet->reportBufferLen ); ok( !!packet->reportBuffer, "got buffer %p\n", packet->reportBuffer );
- irp->IoStatus.Information = 3; - ret = STATUS_SUCCESS; + expect_queue_next( &expect_queue, code, packet, &index, &expect ); + winetest_push_context( "%s expect[%d]", expect.context, index ); + ok( expect.code == code, "got %#x, expected %#x\n", expect.code, code ); + ok( packet->reportId == expect.report_id, "got id %u\n", packet->reportId ); + todo_wine_if( expect.todo_report_len ) + ok( packet->reportBufferLen == expect.report_len, "got len %u\n", packet->reportBufferLen ); + ok( RtlCompareMemory( packet->reportBuffer, expect.report_buf, expect.report_len ) == expect.report_len, + "unexpected data\n" ); + winetest_pop_context(); + + irp->IoStatus.Information = expect.ret_length; + ret = expect.ret_status; break; }
@@ -364,6 +486,8 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) ret = STATUS_NOT_IMPLEMENTED; }
+ winetest_pop_context(); + if (ret != STATUS_PENDING) { irp->IoStatus.Status = ret; @@ -372,13 +496,23 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) return ret; }
+static NTSTATUS( WINAPI *hidclass_driver_ioctl )(DEVICE_OBJECT *device, IRP *irp); static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp ) { - HID_DEVICE_EXTENSION *ext = device->DeviceExtension; + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + ULONG in_size = stack->Parameters.DeviceIoControl.InputBufferLength; + ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
- ok( 0, "unexpected call\n" ); - IoSkipCurrentIrpStackLocation( irp ); - return IoCallDriver( ext->NextDeviceObject, irp ); + switch (code) + { + case IOCTL_WINETEST_HID_SET_EXPECT: + expect_queue_reset( &expect_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 ); }
static NTSTATUS WINAPI driver_add_device( DRIVER_OBJECT *driver, DEVICE_OBJECT *fdo ) @@ -418,13 +552,13 @@ static NTSTATUS WINAPI driver_close( DEVICE_OBJECT *device, IRP *irp )
static void WINAPI driver_unload( DRIVER_OBJECT *driver ) { + expect_queue_cleanup( &expect_queue ); winetest_cleanup(); }
NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *registry ) { static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ); - char buffer[offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ) + sizeof(report_descriptor_buf)]; HID_MINIDRIVER_REGISTRATION params = { .Revision = HID_REVISION, @@ -435,6 +569,7 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *registry ) UNICODE_STRING name_str; OBJECT_ATTRIBUTES attr; NTSTATUS ret; + char *buffer; HANDLE hkey; DWORD size;
@@ -444,6 +579,10 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *registry ) ret = ZwOpenKey( &hkey, KEY_ALL_ACCESS, &attr ); ok( !ret, "ZwOpenKey returned %#x\n", ret );
+ buffer = ExAllocatePool( PagedPool, info_size + EXPECT_QUEUE_BUFFER_SIZE ); + ok( buffer != NULL, "ExAllocatePool failed\n" ); + if (!buffer) return STATUS_NO_MEMORY; + RtlInitUnicodeString( &name_str, L"ReportID" ); size = info_size + sizeof(report_id); ret = ZwQueryValueKey( hkey, &name_str, KeyValuePartialInformation, buffer, size, &size ); @@ -476,6 +615,13 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *registry ) ok( !ret, "ZwQueryValueKey returned %#x\n", ret ); memcpy( &caps, buffer + info_size, size - info_size );
+ expect_queue_init( &expect_queue ); + RtlInitUnicodeString( &name_str, L"Expect" ); + size = info_size + EXPECT_QUEUE_BUFFER_SIZE; + ret = ZwQueryValueKey( hkey, &name_str, KeyValuePartialInformation, buffer, size, &size ); + ok( !ret, "ZwQueryValueKey returned %#x\n", ret ); + expect_queue_reset( &expect_queue, buffer + info_size, size - info_size ); + driver->DriverExtension->AddDevice = driver_add_device; driver->DriverUnload = driver_unload; driver->MajorFunction[IRP_MJ_PNP] = driver_pnp; @@ -485,8 +631,13 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *registry ) driver->MajorFunction[IRP_MJ_CREATE] = driver_create; driver->MajorFunction[IRP_MJ_CLOSE] = driver_close;
+ ExFreePool( buffer ); + ret = HidRegisterMinidriver( ¶ms ); ok( !ret, "got %#x\n", ret );
+ hidclass_driver_ioctl = driver->MajorFunction[IRP_MJ_DEVICE_CONTROL]; + driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_ioctl; + return STATUS_SUCCESS; } diff --git a/dlls/dinput8/tests/driver_hid.h b/dlls/dinput8/tests/driver_hid.h index 42d12a0cf27..e7202594c25 100644 --- a/dlls/dinput8/tests/driver_hid.h +++ b/dlls/dinput8/tests/driver_hid.h @@ -39,6 +39,21 @@
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) + +struct hid_expect +{ + DWORD code; + DWORD ret_length; + DWORD ret_status; + BYTE broken; /* missing on some win versions */ + BYTE report_id; + BYTE todo_report_len; + BYTE report_len; + BYTE report_buf[128]; + char context[64]; +}; + /* kernel/user shared data */ struct winetest_shared_data { diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 4483a5ec479..4f60c9f2194 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -724,6 +724,127 @@ static BOOL sync_ioctl( HANDLE file, DWORD code, void *in_buf, DWORD in_len, voi return ret; }
+#define set_hid_expect( a, b, c ) set_hid_expect_( __LINE__, a, b, c ) +static void set_hid_expect_( 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_SET_EXPECT, expect, expect_size, NULL, 0 ); + ok( ret, "IOCTL_WINETEST_HID_SET_EXPECT failed, last error %u\n", GetLastError() ); +} + +static void test_hidp_set_feature( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed ) +{ + struct hid_expect expect[] = + { + { + .code = IOCTL_HID_SET_FEATURE, + .report_id = report_id, + .report_len = report_len - (report_id ? 0 : 1), + .report_buf = {report_id}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + { + .code = IOCTL_HID_SET_FEATURE, + .report_id = report_id, + .todo_report_len = TRUE, + .report_len = report_len - (report_id ? 0 : 1), + .report_buf = + { + report_id,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd, + 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd, + }, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + }; + char buffer[200], report[200]; + NTSTATUS status; + ULONG length; + BOOL ret; + + memset( report, 0xcd, sizeof(report) ); + status = HidP_InitializeReportForID( HidP_Feature, report_id, preparsed, report, report_len ); + ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status ); + + SetLastError( 0xdeadbeef ); + ret = HidD_SetFeature( file, report, 0 ); + ok( !ret, "HidD_SetFeature succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_SetFeature returned error %u\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = HidD_SetFeature( file, report, report_len - 1 ); + ok( !ret, "HidD_SetFeature succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), + "HidD_SetFeature returned error %u\n", GetLastError() ); + + if (!report_id) + { + struct hid_expect broken_expect = + { + .code = IOCTL_HID_SET_FEATURE, + .broken = TRUE, + .report_len = report_len - 1, + .report_buf = + { + 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, + 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, + 0x5a,0x5a,0x5a,0x5a,0x5a, + }, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }; + + set_hid_expect( file, &broken_expect, sizeof(broken_expect) ); + } + + SetLastError( 0xdeadbeef ); + memset( buffer, 0x5a, sizeof(buffer) ); + ret = HidD_SetFeature( file, buffer, report_len ); + if (report_id || broken( !ret )) + { + ok( !ret, "HidD_SetFeature succeeded, last error %u\n", GetLastError() ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), + "HidD_SetFeature returned error %u\n", GetLastError() ); + } + else + { + ok( ret, "HidD_SetFeature failed, last error %u\n", GetLastError() ); + } + + set_hid_expect( file, expect, sizeof(expect) ); + + SetLastError( 0xdeadbeef ); + ret = HidD_SetFeature( file, report, report_len ); + ok( ret, "HidD_SetFeature failed, last error %u\n", GetLastError() ); + + length = report_len * 2; + SetLastError( 0xdeadbeef ); + ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, NULL, 0, report, &length ); + ok( !ret, "IOCTL_HID_SET_FEATURE succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "IOCTL_HID_SET_FEATURE returned error %u\n", + GetLastError() ); + length = 0; + SetLastError( 0xdeadbeef ); + ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, report, report_len * 2, NULL, &length ); + ok( ret, "IOCTL_HID_SET_FEATURE failed, last error %u\n", GetLastError() ); + ok( length == 3, "got length %u, expected 3\n", length ); + + set_hid_expect( file, NULL, 0 ); +} + static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polled, const HIDP_CAPS *expect_caps ) { const HIDP_BUTTON_CAPS expect_button_caps[] = @@ -1653,51 +1774,7 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle 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 );
- memset( report, 0xcd, sizeof(report) ); - status = HidP_InitializeReportForID( HidP_Feature, report_id, preparsed_data, report, - caps.FeatureReportByteLength ); - ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status ); - - SetLastError( 0xdeadbeef ); - ret = HidD_SetFeature( file, report, 0 ); - ok( !ret, "HidD_SetFeature succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_SetFeature returned error %u\n", GetLastError() ); - - SetLastError( 0xdeadbeef ); - ret = HidD_SetFeature( file, report, caps.FeatureReportByteLength - 1 ); - ok( !ret, "HidD_SetFeature succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), - "HidD_SetFeature returned error %u\n", GetLastError() ); - - SetLastError( 0xdeadbeef ); - memset( buffer, 0x5a, sizeof(buffer) ); - ret = HidD_SetFeature( file, buffer, caps.FeatureReportByteLength ); - if (report_id || broken( !ret )) - { - ok( !ret, "HidD_SetFeature succeeded, last error %u\n", GetLastError() ); - ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), - "HidD_SetFeature returned error %u\n", GetLastError() ); - } - else - { - ok( ret, "HidD_SetFeature failed, last error %u\n", GetLastError() ); - } - - SetLastError( 0xdeadbeef ); - ret = HidD_SetFeature( file, report, caps.FeatureReportByteLength ); - ok( ret, "HidD_SetFeature failed, last error %u\n", GetLastError() ); - - value = caps.FeatureReportByteLength * 2; - SetLastError( 0xdeadbeef ); - ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, NULL, 0, report, &value ); - ok( !ret, "IOCTL_HID_SET_FEATURE succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "IOCTL_HID_SET_FEATURE returned error %u\n", - GetLastError() ); - value = 0; - SetLastError( 0xdeadbeef ); - ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, report, caps.FeatureReportByteLength * 2, NULL, &value ); - ok( ret, "IOCTL_HID_SET_FEATURE failed, last error %u\n", GetLastError() ); - ok( value == 3, "got length %u, expected 3\n", value ); + test_hidp_set_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data );
memset( report, 0xcd, sizeof(report) ); status = HidP_InitializeReportForID( HidP_Output, report_id, preparsed_data, report, caps.OutputReportByteLength ); @@ -2318,6 +2395,9 @@ static void test_hid_driver( DWORD report_id, DWORD polled ) status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)&caps, sizeof(caps) ); ok( !status, "RegSetValueExW returned %#x\n", status );
+ status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, NULL, 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();
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/driver_hid.c | 20 +++-- dlls/dinput8/tests/hid.c | 138 ++++++++++++++++++++++---------- 2 files changed, 108 insertions(+), 50 deletions(-)
diff --git a/dlls/dinput8/tests/driver_hid.c b/dlls/dinput8/tests/driver_hid.c index 9256bb4922e..043a1555dbd 100644 --- a/dlls/dinput8/tests/driver_hid.c +++ b/dlls/dinput8/tests/driver_hid.c @@ -107,7 +107,7 @@ static void expect_queue_reset( struct expect_queue *queue, void *buffer, unsign }
static void expect_queue_next( struct expect_queue *queue, ULONG code, HID_XFER_PACKET *packet, - LONG *index, struct hid_expect *expect ) + LONG *index, struct hid_expect *expect, BOOL compare_buf ) { struct hid_expect *missing, *missing_end, *tmp; ULONG len = packet->reportBufferLen; @@ -125,7 +125,7 @@ static void expect_queue_next( struct expect_queue *queue, ULONG code, HID_XFER_ { if (!tmp->broken || running_under_wine) break; if (tmp->code == code && tmp->report_id == id && tmp->report_len == len && - RtlCompareMemory( tmp->report_buf, buf, len ) == len) + (!compare_buf || RtlCompareMemory( tmp->report_buf, buf, len ) == len)) break; *missing_end++ = *tmp++; } @@ -439,10 +439,16 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) ok( packet->reportBufferLen >= expected_size, "got len %u\n", packet->reportBufferLen ); ok( !!packet->reportBuffer, "got buffer %p\n", packet->reportBuffer );
- memset( packet->reportBuffer, 0xa5, 3 ); - if (report_id) ((char *)packet->reportBuffer)[0] = report_id; - irp->IoStatus.Information = 3; - ret = STATUS_SUCCESS; + expect_queue_next( &expect_queue, code, packet, &index, &expect, FALSE ); + winetest_push_context( "%s expect[%d]", expect.context, index ); + ok( expect.code == code, "got %#x, expected %#x\n", expect.code, code ); + ok( packet->reportId == expect.report_id, "got id %u\n", packet->reportId ); + ok( packet->reportBufferLen == expect.report_len, "got len %u\n", packet->reportBufferLen ); + winetest_pop_context(); + + memcpy( packet->reportBuffer, expect.report_buf, expect.ret_length ); + irp->IoStatus.Information = expect.ret_length; + ret = expect.ret_status; break; }
@@ -457,7 +463,7 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) ok( packet->reportBufferLen >= expected_size, "got len %u\n", packet->reportBufferLen ); ok( !!packet->reportBuffer, "got buffer %p\n", packet->reportBuffer );
- expect_queue_next( &expect_queue, code, packet, &index, &expect ); + expect_queue_next( &expect_queue, code, packet, &index, &expect, TRUE ); winetest_push_context( "%s expect[%d]", expect.context, index ); ok( expect.code == code, "got %#x, expected %#x\n", expect.code, code ); ok( packet->reportId == expect.report_id, "got id %u\n", packet->reportId ); diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 4f60c9f2194..98366c878e6 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -743,6 +743,100 @@ 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() ); }
+static void test_hidp_get_feature( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed ) +{ + struct hid_expect expect[] = + { + { + .code = IOCTL_HID_GET_FEATURE, + .report_id = report_id, + .report_len = report_len - (report_id ? 0 : 1), + .report_buf = {report_id ? report_id : 0xa5,0xa5,0xa5}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + { + .code = IOCTL_HID_GET_FEATURE, + .report_id = report_id, + .report_len = 2 * report_len - (report_id ? 0 : 1), + .report_buf = {report_id ? report_id : 0xa5,0xa5,0xa5}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + }; + + char buffer[200], report[200]; + NTSTATUS status; + ULONG length; + BOOL ret; + + memset( report, 0xcd, sizeof(report) ); + status = HidP_InitializeReportForID( HidP_Feature, report_id, preparsed, report, report_len ); + ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status ); + + SetLastError( 0xdeadbeef ); + ret = HidD_GetFeature( file, report, 0 ); + ok( !ret, "HidD_GetFeature succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetFeature returned error %u\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = HidD_GetFeature( file, report, report_len - 1 ); + ok( !ret, "HidD_GetFeature succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), + "HidD_GetFeature returned error %u\n", GetLastError() ); + + if (!report_id) + { + struct hid_expect broken_expect = + { + .code = IOCTL_HID_GET_FEATURE, + .broken = TRUE, + .report_len = report_len - 1, + .report_buf = + { + 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, + 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, + 0x5a,0x5a,0x5a,0x5a,0x5a, + }, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }; + + set_hid_expect( file, &broken_expect, sizeof(broken_expect) ); + } + + SetLastError( 0xdeadbeef ); + memset( buffer, 0x5a, sizeof(buffer) ); + ret = HidD_GetFeature( file, buffer, report_len ); + if (report_id || broken( !ret )) + { + ok( !ret, "HidD_GetFeature succeeded, last error %u\n", GetLastError() ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), + "HidD_GetFeature returned error %u\n", GetLastError() ); + } + else + { + ok( ret, "HidD_GetFeature failed, last error %u\n", GetLastError() ); + ok( buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0] ); + } + + set_hid_expect( file, expect, sizeof(expect) ); + + SetLastError( 0xdeadbeef ); + ret = HidD_GetFeature( file, report, report_len ); + ok( ret, "HidD_GetFeature failed, last error %u\n", GetLastError() ); + ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id ); + + length = report_len * 2; + SetLastError( 0xdeadbeef ); + ret = sync_ioctl( file, IOCTL_HID_GET_FEATURE, NULL, 0, report, &length ); + ok( ret, "IOCTL_HID_GET_FEATURE failed, last error %u\n", GetLastError() ); + ok( length == 3, "got length %u, expected 3\n", length ); + ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id ); + + set_hid_expect( file, NULL, 0 ); +} + static void test_hidp_set_feature( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed ) { struct hid_expect expect[] = @@ -1731,49 +1825,7 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle 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 );
- memset( report, 0xcd, sizeof(report) ); - status = HidP_InitializeReportForID( HidP_Feature, report_id, preparsed_data, report, - caps.FeatureReportByteLength ); - ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status ); - - SetLastError( 0xdeadbeef ); - ret = HidD_GetFeature( file, report, 0 ); - ok( !ret, "HidD_GetFeature succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetFeature returned error %u\n", GetLastError() ); - - SetLastError( 0xdeadbeef ); - ret = HidD_GetFeature( file, report, caps.FeatureReportByteLength - 1 ); - ok( !ret, "HidD_GetFeature succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), - "HidD_GetFeature returned error %u\n", GetLastError() ); - - SetLastError( 0xdeadbeef ); - memset( buffer, 0x5a, sizeof(buffer) ); - ret = HidD_GetFeature( file, buffer, caps.FeatureReportByteLength ); - if (report_id || broken( !ret )) - { - ok( !ret, "HidD_GetFeature succeeded, last error %u\n", GetLastError() ); - ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), - "HidD_GetFeature returned error %u\n", GetLastError() ); - } - else - { - ok( ret, "HidD_GetFeature failed, last error %u\n", GetLastError() ); - 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() ); - 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() ); - 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 ); - + test_hidp_get_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data ); test_hidp_set_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data );
memset( report, 0xcd, sizeof(report) );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/driver_hid.c | 14 ++- dlls/dinput8/tests/hid.c | 145 +++++++++++++++++++++----------- 2 files changed, 109 insertions(+), 50 deletions(-)
diff --git a/dlls/dinput8/tests/driver_hid.c b/dlls/dinput8/tests/driver_hid.c index 043a1555dbd..fea826c8b63 100644 --- a/dlls/dinput8/tests/driver_hid.c +++ b/dlls/dinput8/tests/driver_hid.c @@ -423,8 +423,18 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) ok( packet->reportBufferLen >= expected_size, "got len %u\n", packet->reportBufferLen ); ok( !!packet->reportBuffer, "got buffer %p\n", packet->reportBuffer );
- irp->IoStatus.Information = 3; - ret = STATUS_SUCCESS; + expect_queue_next( &expect_queue, code, packet, &index, &expect, TRUE ); + winetest_push_context( "%s expect[%d]", expect.context, index ); + ok( expect.code == code, "got %#x, expected %#x\n", expect.code, code ); + ok( packet->reportId == expect.report_id, "got id %u\n", packet->reportId ); + todo_wine_if( expect.todo_report_len ) + ok( packet->reportBufferLen == expect.report_len, "got len %u\n", packet->reportBufferLen ); + ok( RtlCompareMemory( packet->reportBuffer, expect.report_buf, expect.report_len ) == expect.report_len, + "unexpected data\n" ); + winetest_pop_context(); + + irp->IoStatus.Information = expect.ret_length; + ret = expect.ret_status; break; }
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 98366c878e6..f7efdad25ee 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -939,6 +939,102 @@ static void test_hidp_set_feature( HANDLE file, int report_id, ULONG report_len, set_hid_expect( file, NULL, 0 ); }
+static void test_hidp_set_output( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed ) +{ + struct hid_expect expect[] = + { + { + .code = IOCTL_HID_SET_OUTPUT_REPORT, + .report_id = report_id, + .report_len = report_len - (report_id ? 0 : 1), + .report_buf = {report_id}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + { + .code = IOCTL_HID_SET_OUTPUT_REPORT, + .report_id = report_id, + .todo_report_len = TRUE, + .report_len = report_len - (report_id ? 0 : 1), + .report_buf = {report_id,0,0xcd,0xcd,0xcd}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + }; + + char buffer[200], report[200]; + NTSTATUS status; + ULONG length; + BOOL ret; + + memset( report, 0xcd, sizeof(report) ); + status = HidP_InitializeReportForID( HidP_Output, report_id, preparsed, report, report_len ); + ok( status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status ); + memset( report, 0, report_len ); + report[0] = report_id; + + SetLastError( 0xdeadbeef ); + ret = HidD_SetOutputReport( file, report, 0 ); + ok( !ret, "HidD_SetOutputReport succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_SetOutputReport returned error %u\n", + GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = HidD_SetOutputReport( file, report, report_len - 1 ); + ok( !ret, "HidD_SetOutputReport succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), + "HidD_SetOutputReport returned error %u\n", GetLastError() ); + + if (!report_id) + { + struct hid_expect broken_expect = + { + .code = IOCTL_HID_SET_OUTPUT_REPORT, + .broken = TRUE, + .report_len = report_len - 1, + .report_buf = {0x5a,0x5a}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }; + + set_hid_expect( file, &broken_expect, sizeof(broken_expect) ); + } + + SetLastError( 0xdeadbeef ); + memset( buffer, 0x5a, sizeof(buffer) ); + ret = HidD_SetOutputReport( file, buffer, report_len ); + if (report_id || broken( !ret )) + { + ok( !ret, "HidD_SetOutputReport succeeded, last error %u\n", GetLastError() ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), + "HidD_SetOutputReport returned error %u\n", GetLastError() ); + } + else + { + ok( ret, "HidD_SetOutputReport failed, last error %u\n", GetLastError() ); + } + + set_hid_expect( file, expect, sizeof(expect) ); + + SetLastError( 0xdeadbeef ); + ret = HidD_SetOutputReport( file, report, report_len ); + ok( ret, "HidD_SetOutputReport failed, last error %u\n", GetLastError() ); + + length = report_len * 2; + SetLastError( 0xdeadbeef ); + ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, NULL, 0, report, &length ); + ok( !ret, "IOCTL_HID_SET_OUTPUT_REPORT succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_USER_BUFFER, + "IOCTL_HID_SET_OUTPUT_REPORT returned error %u\n", GetLastError() ); + length = 0; + SetLastError( 0xdeadbeef ); + ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, report, report_len * 2, NULL, &length ); + ok( ret, "IOCTL_HID_SET_OUTPUT_REPORT failed, last error %u\n", GetLastError() ); + ok( length == 3, "got length %u, expected 3\n", length ); + + set_hid_expect( file, NULL, 0 ); +} + static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polled, const HIDP_CAPS *expect_caps ) { const HIDP_BUTTON_CAPS expect_button_caps[] = @@ -1827,54 +1923,7 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle
test_hidp_get_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data ); test_hidp_set_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data ); - - memset( report, 0xcd, sizeof(report) ); - status = HidP_InitializeReportForID( HidP_Output, report_id, preparsed_data, report, caps.OutputReportByteLength ); - ok( status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status ); - memset( report, 0, caps.OutputReportByteLength ); - report[0] = report_id; - - SetLastError( 0xdeadbeef ); - ret = HidD_SetOutputReport( file, report, 0 ); - ok( !ret, "HidD_SetOutputReport succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_SetOutputReport returned error %u\n", - GetLastError() ); - - SetLastError( 0xdeadbeef ); - ret = HidD_SetOutputReport( file, report, caps.OutputReportByteLength - 1 ); - ok( !ret, "HidD_SetOutputReport succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), - "HidD_SetOutputReport returned error %u\n", GetLastError() ); - - SetLastError( 0xdeadbeef ); - memset( buffer, 0x5a, sizeof(buffer) ); - ret = HidD_SetOutputReport( file, buffer, caps.OutputReportByteLength ); - if (report_id || broken( !ret )) - { - ok( !ret, "HidD_SetOutputReport succeeded, last error %u\n", GetLastError() ); - ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), - "HidD_SetOutputReport returned error %u\n", GetLastError() ); - } - else - { - ok( ret, "HidD_SetOutputReport failed, last error %u\n", GetLastError() ); - } - - SetLastError( 0xdeadbeef ); - ret = HidD_SetOutputReport( file, report, caps.OutputReportByteLength ); - ok( ret, "HidD_SetOutputReport failed, last error %u\n", GetLastError() ); - - value = caps.OutputReportByteLength * 2; - SetLastError( 0xdeadbeef ); - ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, NULL, 0, report, &value ); - ok( !ret, "IOCTL_HID_SET_OUTPUT_REPORT succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_USER_BUFFER, - "IOCTL_HID_SET_OUTPUT_REPORT returned error %u\n", GetLastError() ); - value = 0; - SetLastError( 0xdeadbeef ); - ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, report, caps.OutputReportByteLength * 2, NULL, &value ); - ok( ret, "IOCTL_HID_SET_OUTPUT_REPORT failed, last error %u\n", GetLastError() ); - ok( value == 3, "got length %u, expected 3\n", value ); + test_hidp_set_output( file, report_id, caps.OutputReportByteLength, preparsed_data );
SetLastError( 0xdeadbeef ); ret = WriteFile( file, report, 0, &value, NULL );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/driver_hid.c | 16 ++++-- dlls/dinput8/tests/hid.c | 97 ++++++++++++++++++++------------- 2 files changed, 71 insertions(+), 42 deletions(-)
diff --git a/dlls/dinput8/tests/driver_hid.c b/dlls/dinput8/tests/driver_hid.c index fea826c8b63..528f4af9939 100644 --- a/dlls/dinput8/tests/driver_hid.c +++ b/dlls/dinput8/tests/driver_hid.c @@ -385,12 +385,18 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) ok( !out_size, "got output size %u\n", out_size ); ok( packet->reportBufferLen >= expected_size, "got report size %u\n", packet->reportBufferLen );
- if (report_id) - ok( packet->reportBuffer[0] == report_id, "got report id %x\n", packet->reportBuffer[0] ); - else ok( packet->reportBuffer[0] == 0xcd, "got first byte %x\n", packet->reportBuffer[0] ); + expect_queue_next( &expect_queue, code, packet, &index, &expect, TRUE ); + winetest_push_context( "%s expect[%d]", expect.context, index ); + ok( expect.code == code, "got %#x, expected %#x\n", expect.code, code ); + ok( packet->reportId == expect.report_id, "got id %u\n", packet->reportId ); + todo_wine_if( expect.todo_report_len ) + ok( packet->reportBufferLen == expect.report_len, "got len %u\n", packet->reportBufferLen ); + ok( RtlCompareMemory( packet->reportBuffer, expect.report_buf, expect.report_len ) == expect.report_len, + "unexpected data\n" ); + winetest_pop_context();
- irp->IoStatus.Information = 3; - ret = STATUS_SUCCESS; + irp->IoStatus.Information = expect.ret_length; + ret = expect.ret_status; break; }
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index f7efdad25ee..b8188690c1d 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -1035,6 +1035,65 @@ static void test_hidp_set_output( HANDLE file, int report_id, ULONG report_len, set_hid_expect( file, NULL, 0 ); }
+static void test_write_file( HANDLE file, int report_id, ULONG report_len ) +{ + struct hid_expect expect = + { + .code = IOCTL_HID_WRITE_REPORT, + .report_id = report_id, + .todo_report_len = report_id == 0, + .report_len = report_len - (report_id ? 0 : 1), + .report_buf = {report_id ? report_id : 0xcd,0xcd,0xcd,0xcd,0xcd}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }; + + char report[200]; + ULONG length; + BOOL ret; + + SetLastError( 0xdeadbeef ); + ret = WriteFile( file, report, 0, &length, NULL ); + ok( !ret, "WriteFile succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "WriteFile returned error %u\n", GetLastError() ); + ok( length == 0, "WriteFile returned %x\n", length ); + SetLastError( 0xdeadbeef ); + ret = WriteFile( file, report, report_len - 1, &length, NULL ); + ok( !ret, "WriteFile succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_USER_BUFFER, + "WriteFile returned error %u\n", GetLastError() ); + ok( length == 0, "WriteFile returned %x\n", length ); + + set_hid_expect( file, &expect, sizeof(expect) ); + + memset( report, 0xcd, sizeof(report) ); + report[0] = 0xa5; + SetLastError( 0xdeadbeef ); + ret = WriteFile( file, report, report_len * 2, &length, NULL ); + if (report_id || broken( !ret ) /* w7u */) + { + ok( !ret, "WriteFile succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "WriteFile returned error %u\n", GetLastError() ); + ok( length == 0, "WriteFile wrote %u\n", length ); + SetLastError( 0xdeadbeef ); + report[0] = report_id; + ret = WriteFile( file, report, report_len, &length, NULL ); + } + + if (report_id) + { + ok( ret, "WriteFile failed, last error %u\n", GetLastError() ); + ok( length == 2, "WriteFile wrote %u\n", length ); + } + else + { + ok( ret, "WriteFile failed, last error %u\n", GetLastError() ); + ok( length == 3, "WriteFile wrote %u\n", length ); + } + + set_hid_expect( file, NULL, 0 ); +} + static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polled, const HIDP_CAPS *expect_caps ) { const HIDP_BUTTON_CAPS expect_button_caps[] = @@ -1924,43 +1983,7 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle test_hidp_get_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data ); test_hidp_set_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data ); test_hidp_set_output( file, report_id, caps.OutputReportByteLength, preparsed_data ); - - SetLastError( 0xdeadbeef ); - ret = WriteFile( file, report, 0, &value, NULL ); - ok( !ret, "WriteFile succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "WriteFile returned error %u\n", GetLastError() ); - ok( value == 0, "WriteFile returned %x\n", value ); - SetLastError( 0xdeadbeef ); - ret = WriteFile( file, report, caps.OutputReportByteLength - 1, &value, NULL ); - ok( !ret, "WriteFile succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_USER_BUFFER, - "WriteFile returned error %u\n", GetLastError() ); - ok( value == 0, "WriteFile returned %x\n", value ); - - memset( report, 0xcd, sizeof(report) ); - report[0] = 0xa5; - SetLastError( 0xdeadbeef ); - ret = WriteFile( file, report, caps.OutputReportByteLength * 2, &value, NULL ); - if (report_id || broken( !ret ) /* w7u */) - { - ok( !ret, "WriteFile succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_PARAMETER, "WriteFile returned error %u\n", GetLastError() ); - ok( value == 0, "WriteFile wrote %u\n", value ); - SetLastError( 0xdeadbeef ); - report[0] = report_id; - ret = WriteFile( file, report, caps.OutputReportByteLength, &value, NULL ); - } - - if (report_id) - { - ok( ret, "WriteFile failed, last error %u\n", GetLastError() ); - ok( value == 2, "WriteFile wrote %u\n", value ); - } - else - { - ok( ret, "WriteFile failed, last error %u\n", GetLastError() ); - ok( value == 3, "WriteFile wrote %u\n", value ); - } + test_write_file( file, report_id, caps.OutputReportByteLength );
memset( report, 0xcd, sizeof(report) ); SetLastError( 0xdeadbeef );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/driver_hid.c | 14 +++- dlls/dinput8/tests/hid.c | 137 ++++++++++++++++++++++---------- 2 files changed, 105 insertions(+), 46 deletions(-)
diff --git a/dlls/dinput8/tests/driver_hid.c b/dlls/dinput8/tests/driver_hid.c index 528f4af9939..7d613f1d92c 100644 --- a/dlls/dinput8/tests/driver_hid.c +++ b/dlls/dinput8/tests/driver_hid.c @@ -411,10 +411,16 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) ok( packet->reportBufferLen >= expected_size, "got len %u\n", packet->reportBufferLen ); ok( !!packet->reportBuffer, "got buffer %p\n", packet->reportBuffer );
- memset( packet->reportBuffer, 0xa5, 3 ); - if (report_id) ((char *)packet->reportBuffer)[0] = report_id; - irp->IoStatus.Information = 3; - ret = STATUS_SUCCESS; + expect_queue_next( &expect_queue, code, packet, &index, &expect, FALSE ); + winetest_push_context( "%s expect[%d]", expect.context, index ); + ok( expect.code == code, "got %#x, expected %#x\n", expect.code, code ); + ok( packet->reportId == expect.report_id, "got id %u\n", packet->reportId ); + ok( packet->reportBufferLen == expect.report_len, "got len %u\n", packet->reportBufferLen ); + winetest_pop_context(); + + memcpy( packet->reportBuffer, expect.report_buf, expect.ret_length ); + irp->IoStatus.Information = expect.ret_length; + ret = expect.ret_status; break; }
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index b8188690c1d..5bcfc5b9f83 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -743,6 +743,100 @@ 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() ); }
+static void test_hidp_get_input( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed ) +{ + struct hid_expect expect[] = + { + { + .code = IOCTL_HID_GET_INPUT_REPORT, + .report_id = report_id, + .report_len = report_len - (report_id ? 0 : 1), + .report_buf = {report_id ? report_id : 0xa5,0xa5,2}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + { + .code = IOCTL_HID_GET_INPUT_REPORT, + .report_id = report_id, + .report_len = 2 * report_len - (report_id ? 0 : 1), + .report_buf = {report_id ? report_id : 0xa5,0xa5,1}, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }, + }; + + char buffer[200], report[200]; + NTSTATUS status; + ULONG length; + BOOL ret; + + memset( report, 0xcd, sizeof(report) ); + status = HidP_InitializeReportForID( HidP_Input, report_id, preparsed, report, report_len ); + ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status ); + + SetLastError( 0xdeadbeef ); + ret = HidD_GetInputReport( file, report, 0 ); + ok( !ret, "HidD_GetInputReport succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetInputReport returned error %u\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = HidD_GetInputReport( file, report, report_len - 1 ); + ok( !ret, "HidD_GetInputReport succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), + "HidD_GetInputReport returned error %u\n", GetLastError() ); + + if (!report_id) + { + struct hid_expect broken_expect = + { + .code = IOCTL_HID_GET_INPUT_REPORT, + .broken = TRUE, + .report_len = report_len - 1, + .report_buf = + { + 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, + 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, + 0x5a,0x5a,0x5a,0x5a,0x5a, + }, + .ret_length = 3, + .ret_status = STATUS_SUCCESS, + }; + + set_hid_expect( file, &broken_expect, sizeof(broken_expect) ); + } + + SetLastError( 0xdeadbeef ); + memset( buffer, 0x5a, sizeof(buffer) ); + ret = HidD_GetInputReport( file, buffer, report_len ); + if (report_id || broken( !ret ) /* w7u */) + { + ok( !ret, "HidD_GetInputReport succeeded, last error %u\n", GetLastError() ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), + "HidD_GetInputReport returned error %u\n", GetLastError() ); + } + else + { + ok( ret, "HidD_GetInputReport failed, last error %u\n", GetLastError() ); + ok( buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0] ); + } + + set_hid_expect( file, expect, sizeof(expect) ); + + SetLastError( 0xdeadbeef ); + ret = HidD_GetInputReport( file, report, report_len ); + ok( ret, "HidD_GetInputReport failed, last error %u\n", GetLastError() ); + ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id ); + + SetLastError( 0xdeadbeef ); + length = report_len * 2; + ret = sync_ioctl( file, IOCTL_HID_GET_INPUT_REPORT, NULL, 0, report, &length ); + ok( ret, "IOCTL_HID_GET_INPUT_REPORT failed, last error %u\n", GetLastError() ); + ok( length == 3, "got length %u, expected 3\n", length ); + ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id ); + + set_hid_expect( file, NULL, 0 ); +} + static void test_hidp_get_feature( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed ) { struct hid_expect expect[] = @@ -1938,48 +2032,7 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status ); ok( value == 0xfffffd0b, "got value %x, expected %#x\n", value, 0xfffffd0b );
- memset( report, 0xcd, sizeof(report) ); - status = HidP_InitializeReportForID( HidP_Input, report_id, preparsed_data, report, caps.InputReportByteLength ); - ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status ); - - SetLastError( 0xdeadbeef ); - ret = HidD_GetInputReport( file, report, 0 ); - ok( !ret, "HidD_GetInputReport succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetInputReport returned error %u\n", GetLastError() ); - - SetLastError( 0xdeadbeef ); - ret = HidD_GetInputReport( file, report, caps.InputReportByteLength - 1 ); - ok( !ret, "HidD_GetInputReport succeeded\n" ); - ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), - "HidD_GetInputReport returned error %u\n", GetLastError() ); - - SetLastError( 0xdeadbeef ); - memset( buffer, 0x5a, sizeof(buffer) ); - ret = HidD_GetInputReport( file, buffer, caps.InputReportByteLength ); - if (report_id || broken( !ret ) /* w7u */) - { - ok( !ret, "HidD_GetInputReport succeeded, last error %u\n", GetLastError() ); - ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ), - "HidD_GetInputReport returned error %u\n", GetLastError() ); - } - else - { - ok( ret, "HidD_GetInputReport failed, last error %u\n", GetLastError() ); - ok( buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0] ); - } - - SetLastError( 0xdeadbeef ); - ret = HidD_GetInputReport( file, report, caps.InputReportByteLength ); - ok( ret, "HidD_GetInputReport failed, last error %u\n", GetLastError() ); - ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id ); - - SetLastError( 0xdeadbeef ); - value = caps.InputReportByteLength * 2; - ret = sync_ioctl( file, IOCTL_HID_GET_INPUT_REPORT, NULL, 0, report, &value ); - ok( ret, "IOCTL_HID_GET_INPUT_REPORT failed, last error %u\n", GetLastError() ); - 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 ); - + test_hidp_get_input( file, report_id, caps.InputReportByteLength, preparsed_data ); test_hidp_get_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data ); test_hidp_set_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data ); test_hidp_set_output( file, report_id, caps.OutputReportByteLength, preparsed_data );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/driver_hid.c | 3 --- dlls/dinput8/tests/driver_hid.h | 1 - dlls/dinput8/tests/hid.c | 3 --- dlls/hidclass.sys/device.c | 17 ++++++----------- 4 files changed, 6 insertions(+), 18 deletions(-)
diff --git a/dlls/dinput8/tests/driver_hid.c b/dlls/dinput8/tests/driver_hid.c index 7d613f1d92c..91f420d7bf6 100644 --- a/dlls/dinput8/tests/driver_hid.c +++ b/dlls/dinput8/tests/driver_hid.c @@ -389,7 +389,6 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) winetest_push_context( "%s expect[%d]", expect.context, index ); ok( expect.code == code, "got %#x, expected %#x\n", expect.code, code ); ok( packet->reportId == expect.report_id, "got id %u\n", packet->reportId ); - todo_wine_if( expect.todo_report_len ) ok( packet->reportBufferLen == expect.report_len, "got len %u\n", packet->reportBufferLen ); ok( RtlCompareMemory( packet->reportBuffer, expect.report_buf, expect.report_len ) == expect.report_len, "unexpected data\n" ); @@ -439,7 +438,6 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) winetest_push_context( "%s expect[%d]", expect.context, index ); ok( expect.code == code, "got %#x, expected %#x\n", expect.code, code ); ok( packet->reportId == expect.report_id, "got id %u\n", packet->reportId ); - todo_wine_if( expect.todo_report_len ) ok( packet->reportBufferLen == expect.report_len, "got len %u\n", packet->reportBufferLen ); ok( RtlCompareMemory( packet->reportBuffer, expect.report_buf, expect.report_len ) == expect.report_len, "unexpected data\n" ); @@ -489,7 +487,6 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) winetest_push_context( "%s expect[%d]", expect.context, index ); ok( expect.code == code, "got %#x, expected %#x\n", expect.code, code ); ok( packet->reportId == expect.report_id, "got id %u\n", packet->reportId ); - todo_wine_if( expect.todo_report_len ) ok( packet->reportBufferLen == expect.report_len, "got len %u\n", packet->reportBufferLen ); ok( RtlCompareMemory( packet->reportBuffer, expect.report_buf, expect.report_len ) == expect.report_len, "unexpected data\n" ); diff --git a/dlls/dinput8/tests/driver_hid.h b/dlls/dinput8/tests/driver_hid.h index e7202594c25..c9c75c6d081 100644 --- a/dlls/dinput8/tests/driver_hid.h +++ b/dlls/dinput8/tests/driver_hid.h @@ -48,7 +48,6 @@ struct hid_expect DWORD ret_status; BYTE broken; /* missing on some win versions */ BYTE report_id; - BYTE todo_report_len; BYTE report_len; BYTE report_buf[128]; char context[64]; diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 5bcfc5b9f83..85ccc2a05df 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -946,7 +946,6 @@ static void test_hidp_set_feature( HANDLE file, int report_id, ULONG report_len, { .code = IOCTL_HID_SET_FEATURE, .report_id = report_id, - .todo_report_len = TRUE, .report_len = report_len - (report_id ? 0 : 1), .report_buf = { @@ -1048,7 +1047,6 @@ static void test_hidp_set_output( HANDLE file, int report_id, ULONG report_len, { .code = IOCTL_HID_SET_OUTPUT_REPORT, .report_id = report_id, - .todo_report_len = TRUE, .report_len = report_len - (report_id ? 0 : 1), .report_buf = {report_id,0,0xcd,0xcd,0xcd}, .ret_length = 3, @@ -1135,7 +1133,6 @@ static void test_write_file( HANDLE file, int report_id, ULONG report_len ) { .code = IOCTL_HID_WRITE_REPORT, .report_id = report_id, - .todo_report_len = report_id == 0, .report_len = report_len - (report_id ? 0 : 1), .report_buf = {report_id ? report_id : 0xcd,0xcd,0xcd,0xcd,0xcd}, .ret_length = 3, diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 9b91834267e..71fb4a366db 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -365,7 +365,7 @@ static void hid_device_xfer_report( BASE_DEVICE_EXTENSION *ext, ULONG code, IRP HIDP_REPORT_IDS *reports = ext->u.pdo.device_desc.ReportIDs; ULONG report_count = ext->u.pdo.device_desc.ReportIDsLength; IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); - ULONG i, report_len = 0, buffer_len = 0; + ULONG i, offset = 0, report_len = 0, buffer_len = 0; HID_XFER_PACKET packet; BYTE *buffer = NULL;
@@ -402,6 +402,7 @@ static void hid_device_xfer_report( BASE_DEVICE_EXTENSION *ext, ULONG code, IRP irp->IoStatus.Status = STATUS_INVALID_PARAMETER; return; } + if (!reports[i].ReportID) offset = 1;
switch (code) { @@ -423,26 +424,20 @@ static void hid_device_xfer_report( BASE_DEVICE_EXTENSION *ext, ULONG code, IRP return; }
- packet.reportId = buffer[0]; - packet.reportBuffer = buffer; - packet.reportBufferLen = buffer_len; - - if (!reports[i].ReportID) - { - packet.reportId = 0; - packet.reportBuffer++; - packet.reportBufferLen--; - } + packet.reportId = reports[i].ReportID; + packet.reportBuffer = buffer + offset;
switch (code) { case IOCTL_HID_GET_FEATURE: case IOCTL_HID_GET_INPUT_REPORT: + packet.reportBufferLen = buffer_len - offset; call_minidriver( code, ext->u.pdo.parent_fdo, NULL, 0, &packet, sizeof(packet), &irp->IoStatus ); break; case IOCTL_HID_SET_FEATURE: case IOCTL_HID_SET_OUTPUT_REPORT: case IOCTL_HID_WRITE_REPORT: + packet.reportBufferLen = report_len - offset; call_minidriver( code, ext->u.pdo.parent_fdo, NULL, sizeof(packet), &packet, 0, &irp->IoStatus ); if (code == IOCTL_HID_WRITE_REPORT && packet.reportId) irp->IoStatus.Information--; break;
And change skipped test message. It's not really useful and it will fail the tests if the main test summary doesn't match the number of skipped messages.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntoskrnl.exe/tests/utils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/utils.h b/dlls/ntoskrnl.exe/tests/utils.h index f73f6f938ca..98fe3f97864 100644 --- a/dlls/ntoskrnl.exe/tests/utils.h +++ b/dlls/ntoskrnl.exe/tests/utils.h @@ -306,7 +306,7 @@ static inline void winetest_vskip( const char *msg, __ms_va_list args ) { if (winetest_add_line() < winetest_mute_threshold) { - winetest_print_context( "Tests skipped: " ); + winetest_print_context( "Driver tests skipped: " ); kvprintf(msg, args); InterlockedIncrement(&skipped); } @@ -328,7 +328,7 @@ static inline void WINAPIV winetest_win_skip( const char *msg, ... ) { __ms_va_list args; __ms_va_start(args, msg); - if (running_under_wine) + if (!running_under_wine) winetest_vskip(msg, args); else winetest_vok(0, msg, args);