[PATCH 0/6] MR10538: dinput/tests: Add tests for dinput joystick guidInstance values.
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/dinput/tests/driver_hid.h | 1 + dlls/dinput/tests/hid.c | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/dlls/dinput/tests/driver_hid.h b/dlls/dinput/tests/driver_hid.h index 1ae8fd90e43..941e7296719 100644 --- a/dlls/dinput/tests/driver_hid.h +++ b/dlls/dinput/tests/driver_hid.h @@ -79,6 +79,7 @@ struct hid_device_desc { BOOL is_polled; BOOL use_report_id; + UINT tlc_count; DWORD report_descriptor_len; char report_descriptor_buf[MAX_HID_DESCRIPTOR_LEN]; diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index 273e94e82bb..99f4567e25f 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -714,7 +714,7 @@ BOOL bus_device_start(void) void hid_device_stop( struct hid_device_desc *desc, UINT count ) { HANDLE control; - DWORD ret, i; + DWORD ret; control = CreateFileW( L"\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, NULL, OPEN_EXISTING, 0, NULL ); @@ -728,9 +728,9 @@ void hid_device_stop( struct hid_device_desc *desc, UINT count ) ret = WaitForSingleObject( device_removed, 5000 ); ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); - for (i = 0; i < count; ++i) + for (UINT j = 0; j < (desc->tlc_count ? desc->tlc_count : 1); ++j) { - ret = WaitForSingleObject( device_removed, i > 0 ? 500 : 5000 ); + ret = WaitForSingleObject( device_removed, j > 0 ? 500 : 5000 ); ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); } } @@ -738,7 +738,7 @@ void hid_device_stop( struct hid_device_desc *desc, UINT count ) BOOL hid_device_start_( struct hid_device_desc *desc, UINT count, DWORD timeout ) { HANDLE control; - DWORD ret, i; + DWORD ret; control = CreateFileW( L"\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, NULL, OPEN_EXISTING, 0, NULL ); @@ -752,7 +752,7 @@ BOOL hid_device_start_( struct hid_device_desc *desc, UINT count, DWORD timeout if (ret) return FALSE; - for (i = 0; i < count; ++i) + for (UINT j = 0; j < (desc->tlc_count ? desc->tlc_count : 1); ++j) { ret = WaitForSingleObject( device_added, timeout ); ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); @@ -4038,6 +4038,7 @@ static void test_hid_multiple_tlc(void) struct hid_device_desc desc = { + .tlc_count = 2, .caps = { .InputReportByteLength = 7 }, .attributes = default_attributes, }; @@ -4154,7 +4155,7 @@ static void test_hid_multiple_tlc(void) memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); fill_context( desc.context, ARRAY_SIZE(desc.context) ); - if (!hid_device_start( &desc, 2 )) goto done; + if (!hid_device_start( &desc, 1 )) goto done; swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x&col01", desc.attributes.VendorID, desc.attributes.ProductID ); @@ -4208,7 +4209,7 @@ static void test_hid_multiple_tlc(void) ok( !ret, "Failed to find HID device matching %s\n", debugstr_w( device_path ) ); done: - hid_device_stop( &desc, 2 ); + hid_device_stop( &desc, 1 ); } START_TEST( hid ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10538
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/dinput/tests/driver_hid.c | 2 - dlls/dinput/tests/hid.c | 70 ++++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/dlls/dinput/tests/driver_hid.c b/dlls/dinput/tests/driver_hid.c index 7b20af07493..5d92c8b230a 100644 --- a/dlls/dinput/tests/driver_hid.c +++ b/dlls/dinput/tests/driver_hid.c @@ -57,8 +57,6 @@ static void check_device( DEVICE_OBJECT *device ) ok( device == impl->expect_hid_fdo, "got device %p\n", device ); ok( device->DriverObject == expect_driver, "got DriverObject %p\n", device->DriverObject ); - if (!device->NextDevice) ok( device == impl->expect_hid_fdo, "got device %p\n", device ); - else ok( device->NextDevice == impl->expect_hid_fdo, "got NextDevice %p\n", device->NextDevice ); ok( !device->AttachedDevice, "got AttachedDevice %p\n", device->AttachedDevice ); ok( ext->MiniDeviceExtension == impl->expect_hid_ext, "got MiniDeviceExtension %p\n", ext->MiniDeviceExtension ); diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index 99f4567e25f..4dcbba7ab26 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -711,54 +711,68 @@ BOOL bus_device_start(void) return ret || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING; } -void hid_device_stop( struct hid_device_desc *desc, UINT count ) +static void hid_device_remove( HANDLE control, struct hid_device_desc *desc, UINT count ) { - HANDLE control; DWORD ret; - control = CreateFileW( L"\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, - NULL, OPEN_EXISTING, 0, NULL ); - ok( control != INVALID_HANDLE_VALUE, "CreateFile failed, error %lu\n", GetLastError() ); - ret = sync_ioctl( control, IOCTL_WINETEST_REMOVE_DEVICE, desc, sizeof(*desc), NULL, 0, 5000 ); - ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "IOCTL_WINETEST_REMOVE_DEVICE failed, last error %lu\n", GetLastError() ); - CloseHandle( control ); - - if (!ret) return; - - ret = WaitForSingleObject( device_removed, 5000 ); - ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); - - for (UINT j = 0; j < (desc->tlc_count ? desc->tlc_count : 1); ++j) + for (UINT i = 0; i < count; i++) { - ret = WaitForSingleObject( device_removed, j > 0 ? 500 : 5000 ); + ret = sync_ioctl( control, IOCTL_WINETEST_REMOVE_DEVICE, desc + i, sizeof(*desc), NULL, 0, 5000 ); + ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "IOCTL_WINETEST_REMOVE_DEVICE failed, last error %lu\n", GetLastError() ); + if (!ret) continue; + + ret = WaitForSingleObject( device_removed, 5000 ); ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); + + for (UINT j = 0; j < (desc->tlc_count ? desc->tlc_count : 1); ++j) + { + ret = WaitForSingleObject( device_removed, j > 0 ? 500 : 5000 ); + ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); + } } } +void hid_device_stop( struct hid_device_desc *desc, UINT count ) +{ + HANDLE control = CreateFileW( L"\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, + NULL, OPEN_EXISTING, 0, NULL ); + ok( control != INVALID_HANDLE_VALUE, "CreateFile failed, error %lu\n", GetLastError() ); + hid_device_remove( control, desc, count ); + CloseHandle( control ); +} + BOOL hid_device_start_( struct hid_device_desc *desc, UINT count, DWORD timeout ) { HANDLE control; - DWORD ret; + DWORD ret = 0; control = CreateFileW( L"\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, NULL, OPEN_EXISTING, 0, NULL ); ok( control != INVALID_HANDLE_VALUE, "CreateFile failed, error %lu\n", GetLastError() ); - ret = sync_ioctl( control, IOCTL_WINETEST_CREATE_DEVICE, desc, sizeof(*desc), NULL, 0, 5000 ); - ok( ret, "IOCTL_WINETEST_CREATE_DEVICE failed, last error %lu\n", GetLastError() ); - CloseHandle( control ); - - ret = WaitForSingleObject( device_added, 5000 ); - ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); - - if (ret) return FALSE; - for (UINT j = 0; j < (desc->tlc_count ? desc->tlc_count : 1); ++j) + for (UINT i = 0; i < count; i++) { - ret = WaitForSingleObject( device_added, timeout ); + ret = sync_ioctl( control, IOCTL_WINETEST_CREATE_DEVICE, desc + i, sizeof(*desc), NULL, 0, 5000 ); + ok( ret, "IOCTL_WINETEST_CREATE_DEVICE failed, last error %lu\n", GetLastError() ); + + ret = WaitForSingleObject( device_added, 5000 ); ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); + + if (ret) + { + hid_device_remove( control, desc, i ); + break; + } + + for (UINT j = 0; j < (desc->tlc_count ? desc->tlc_count : 1); ++j) + { + ret = WaitForSingleObject( device_added, timeout ); + ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); + } } - return TRUE; + CloseHandle( control ); + return !ret; } #define check_hidp_caps( a, b ) check_hidp_caps_( __LINE__, a, b ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10538
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/dinput/tests/device8.c | 8 ++------ dlls/dinput/tests/dinput_test.h | 7 ++----- dlls/dinput/tests/force_feedback.c | 4 ---- dlls/dinput/tests/hid.c | 32 ++++++++++++++---------------- dlls/dinput/tests/hotplug.c | 2 -- dlls/dinput/tests/joystick8.c | 8 -------- 6 files changed, 19 insertions(+), 42 deletions(-) diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index 85c0b79d70e..ceed0573510 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -1704,9 +1704,8 @@ static void test_hid_mouse(void) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); - if (!hid_device_start_( &desc, 1, 5000 /* needs a long timeout on Win7 */ )) goto done; + if (!hid_device_start( &desc, 1 )) goto done; swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x", desc.attributes.VendorID, desc.attributes.ProductID ); @@ -1950,7 +1949,6 @@ static void test_hid_touch_screen(void) memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); desc.expect_size = sizeof(expect_max_count); memcpy( desc.expect, &expect_max_count, sizeof(expect_max_count) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; @@ -2124,7 +2122,6 @@ static void test_hid_touch_screen(void) desc.is_polled = TRUE; desc.input_size = sizeof(touch_release); memcpy( desc.input, &touch_release, sizeof(touch_release) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; @@ -3201,9 +3198,8 @@ static void test_hid_keyboard(void) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); - if (!hid_device_start_( &desc, 1, 5000 /* needs a long timeout on Win7 */ )) goto done; + if (!hid_device_start( &desc, 1 )) goto done; swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x", desc.attributes.VendorID, desc.attributes.ProductID ); diff --git a/dlls/dinput/tests/dinput_test.h b/dlls/dinput/tests/dinput_test.h index d19e1868d76..26842aa119b 100644 --- a/dlls/dinput/tests/dinput_test.h +++ b/dlls/dinput/tests/dinput_test.h @@ -51,8 +51,8 @@ extern const WCHAR expect_path_end[]; extern HINSTANCE instance; extern BOOL localized; /* object names get translated */ -#define hid_device_start( a, b ) hid_device_start_( a, b, 1000 ) -BOOL hid_device_start_( struct hid_device_desc *desc, UINT count, DWORD timeout ); +#define hid_device_start( a, b ) hid_device_start_( __FILE__, __LINE__, a, b, 1000 ) +BOOL hid_device_start_( const char *file, int line, struct hid_device_desc *desc, UINT count, DWORD timeout ); void hid_device_stop( struct hid_device_desc *desc, UINT count ); BOOL bus_device_start(void); void bus_device_stop(void); @@ -67,9 +67,6 @@ void dinput_test_exit(void); HRESULT dinput_test_create_device( DWORD version, DIDEVICEINSTANCEW *devinst, IDirectInputDevice8W **device ); DWORD WINAPI dinput_test_device_thread( void *stop_event ); -#define fill_context( a, b ) fill_context_( __FILE__, __LINE__, a, b ) -void fill_context_( const char *file, int line, char *buffer, SIZE_T size ); - #define check_member_( file, line, val, exp, fmt, member ) \ ok_(file, line)( (val).member == (exp).member, "got " #member " " fmt "\n", (val).member ) #define check_member( val, exp, fmt, member ) \ diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c index 69a521b0e47..1de2321fcc5 100644 --- a/dlls/dinput/tests/force_feedback.c +++ b/dlls/dinput/tests/force_feedback.c @@ -3424,7 +3424,6 @@ static BOOL test_force_feedback_joystick( DWORD version ) desc.report_descriptor_len = sizeof(report_descriptor); memcpy( desc.report_descriptor_buf, report_descriptor, sizeof(report_descriptor) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; if (FAILED(hr = dinput_test_create_device( version, &devinst, &device ))) goto done; @@ -4321,7 +4320,6 @@ static BOOL test_force_feedback_six_axes(void) desc.report_descriptor_len = sizeof(report_descriptor); memcpy( desc.report_descriptor_buf, report_descriptor, sizeof(report_descriptor) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; if (FAILED(hr = dinput_test_create_device( version, &devinst, &device ))) goto done; @@ -5310,7 +5308,6 @@ static void test_device_managed_effect(void) memcpy( desc.report_descriptor_buf, report_descriptor, sizeof(report_descriptor) ); desc.expect_size = sizeof(expect_pool); memcpy( desc.expect, expect_pool, sizeof(expect_pool) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; if (FAILED(hr = dinput_test_create_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done; @@ -7268,7 +7265,6 @@ static void test_windows_gaming_input(void) memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); desc.expect_size = sizeof(expect_init); memcpy( desc.expect, expect_init, sizeof(expect_init) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; ret = WaitForSingleObject( controller_added.event, 5000 ); diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index 4dcbba7ab26..2bb79b6212d 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -711,6 +711,16 @@ BOOL bus_device_start(void) return ret || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING; } +static void fill_context( const char *file, int line, char *buffer, SIZE_T size ) +{ + const char *source_file; + source_file = strrchr( file, '/' ); + if (!source_file) source_file = strrchr( file, '\\' ); + if (!source_file) source_file = file; + else source_file++; + snprintf( buffer, size, "%s:%d", source_file, line ); +} + static void hid_device_remove( HANDLE control, struct hid_device_desc *desc, UINT count ) { DWORD ret; @@ -741,7 +751,7 @@ void hid_device_stop( struct hid_device_desc *desc, UINT count ) CloseHandle( control ); } -BOOL hid_device_start_( struct hid_device_desc *desc, UINT count, DWORD timeout ) +BOOL hid_device_start_( const char *file, int line, struct hid_device_desc *desc, UINT count, DWORD timeout ) { HANDLE control; DWORD ret = 0; @@ -752,6 +762,8 @@ BOOL hid_device_start_( struct hid_device_desc *desc, UINT count, DWORD timeout for (UINT i = 0; i < count; i++) { + fill_context( file, line, desc[i].context, ARRAY_SIZE(desc[i].context) ); + ret = sync_ioctl( control, IOCTL_WINETEST_CREATE_DEVICE, desc + i, sizeof(*desc), NULL, 0, 5000 ); ok( ret, "IOCTL_WINETEST_CREATE_DEVICE failed, last error %lu\n", GetLastError() ); @@ -937,16 +949,6 @@ BOOL sync_ioctl_( const char *file, int line, HANDLE device, DWORD code, void *i return ret; } -void fill_context_( const char *file, int line, char *buffer, SIZE_T size ) -{ - const char *source_file; - source_file = strrchr( file, '/' ); - if (!source_file) source_file = strrchr( file, '\\' ); - if (!source_file) source_file = file; - else source_file++; - snprintf( buffer, size, "%s:%d", source_file, line ); -} - void set_hid_expect_( const char *file, int line, HANDLE device, struct hid_device_desc *desc, struct hid_expect *expect, DWORD expect_size ) { @@ -957,7 +959,7 @@ void set_hid_expect_( const char *file, int line, HANDLE device, struct hid_devi if (desc) memcpy( buffer, desc, sizeof(*desc) ); else memset( buffer, 0, sizeof(*desc) ); - fill_context_( file, line, buffer + sizeof(*desc), ARRAY_SIZE(buffer) - sizeof(*desc) ); + fill_context( file, line, buffer + sizeof(*desc), ARRAY_SIZE(buffer) - sizeof(*desc) ); size = sizeof(*desc) + strlen( buffer + sizeof(*desc) ) + 1; ret = sync_ioctl_( file, line, device, IOCTL_WINETEST_HID_SET_CONTEXT, buffer, size, NULL, 0, 5000 ); ok_(file, line)( ret, "IOCTL_WINETEST_HID_SET_CONTEXT failed, last error %lu\n", GetLastError() ); @@ -1001,7 +1003,7 @@ void send_hid_input_( const char *file, int line, HANDLE device, struct hid_devi if (desc) memcpy( buffer, desc, sizeof(*desc) ); else memset( buffer, 0, sizeof(*desc) ); - fill_context_( file, line, buffer + sizeof(*desc), ARRAY_SIZE(buffer) - sizeof(*desc) ); + fill_context( file, line, buffer + sizeof(*desc), ARRAY_SIZE(buffer) - sizeof(*desc) ); size = sizeof(*desc) + strlen( buffer + sizeof(*desc) ) + 1; ret = sync_ioctl_( file, line, device, IOCTL_WINETEST_HID_SET_CONTEXT, buffer, size, NULL, 0, 5000 ); ok_(file, line)( ret, "IOCTL_WINETEST_HID_SET_CONTEXT failed, last error %lu\n", GetLastError() ); @@ -3183,7 +3185,6 @@ static void test_hid_driver( DWORD report_id, DWORD polled ) memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); desc.input_size = polled ? sizeof(expect_in) : 0; memcpy( desc.input, &expect_in, sizeof(expect_in) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (hid_device_start( &desc, 1 )) test_hid_device( report_id, polled, &caps, &desc ); hid_device_stop( &desc, 1 ); @@ -3592,7 +3593,6 @@ static void test_hidp_kdr(void) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; @@ -3902,7 +3902,6 @@ DWORD WINAPI dinput_test_device_thread( void *stop_event ) desc.report_descriptor_len = sizeof(gamepad_desc); memcpy( desc.report_descriptor_buf, gamepad_desc, sizeof(gamepad_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); hid_device_start( &desc, 1 ); ret = WaitForSingleObject( stop_event, 5000 ); @@ -4167,7 +4166,6 @@ static void test_hid_multiple_tlc(void) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; diff --git a/dlls/dinput/tests/hotplug.c b/dlls/dinput/tests/hotplug.c index ce44bae754c..9bea45202ff 100644 --- a/dlls/dinput/tests/hotplug.c +++ b/dlls/dinput/tests/hotplug.c @@ -167,7 +167,6 @@ static BOOL test_input_lost( DWORD version ) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; if (FAILED(hr = dinput_test_create_device( version, &devinst, &device ))) goto done; @@ -209,7 +208,6 @@ static BOOL test_input_lost( DWORD version ) hr = IDirectInputDevice8_Unacquire( device ); ok( hr == DI_NOEFFECT, "Unacquire returned: %#lx\n", hr ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); hid_device_start( &desc, 1 ); hr = IDirectInputDevice8_Acquire( device ); diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index d267aff724f..f1da7a57df0 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -1918,7 +1918,6 @@ static void test_simple_joystick( DWORD version ) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; if (FAILED(hr = dinput_test_create_device( version, &devinst, &device ))) goto done; @@ -3742,7 +3741,6 @@ static BOOL test_device_types( DWORD version ) desc.caps = device_desc[i].hid_caps; desc.report_descriptor_len = device_desc[i].report_desc_len; memcpy( desc.report_descriptor_buf, device_desc[i].report_desc_buf, device_desc[i].report_desc_len ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) { @@ -4212,7 +4210,6 @@ static void test_many_axes_joystick(void) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; if (FAILED(hr = dinput_test_create_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done; @@ -4480,7 +4477,6 @@ static void test_driving_wheel_axes(void) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; if (FAILED(hr = dinput_test_create_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done; @@ -4715,7 +4711,6 @@ static void test_winmm_joystick(void) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; @@ -5139,7 +5134,6 @@ static void test_windows_gaming_input(void) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); if (!hid_device_start( &desc, 1 )) goto done; res = WaitForSingleObject( controller_added.event, 5000 ); @@ -5250,7 +5244,6 @@ static void test_windows_gaming_input(void) desc.report_descriptor_len = sizeof(wheel_threepedals_desc); memcpy( desc.report_descriptor_buf, wheel_threepedals_desc, sizeof(wheel_threepedals_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); controller_added.event = CreateEventW( NULL, FALSE, FALSE, NULL ); ok( !!controller_added.event, "CreateEventW failed, error %lu\n", GetLastError() ); @@ -5469,7 +5462,6 @@ static void test_rawinput( char **argv ) desc.report_descriptor_len = sizeof(report_desc); memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) ); - fill_context( desc.context, ARRAY_SIZE(desc.context) ); rawinput_device_added = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL ); ok( !!rawinput_device_added, "CreateSemaphoreW failed, error %lu\n", GetLastError() ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10538
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/dinput/tests/hid.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index 2bb79b6212d..7c42ac54f74 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -3614,13 +3614,27 @@ done: hid_device_stop( &desc, 1 ); } +static void cleanup_registry_tree( HKEY root, const WCHAR *path ) +{ + WCHAR buf[MAX_PATH]; + HKEY hkey; + + RegCreateKeyExW( root, path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL ); + for (ULONG i = 0, size = ARRAY_SIZE(buf); !RegEnumKeyExW( hkey, i, buf, &size, NULL, NULL, NULL, NULL ); i++, size = ARRAY_SIZE(buf)) + { + if (wcsnicmp( buf, L"VID_1209", 8 )) continue; + RegDeleteTreeW( hkey, buf ); + i = -1; + } + RegCloseKey( hkey ); +} + void cleanup_registry_keys(void) { static const WCHAR joystick_oem_path[] = L"System\\CurrentControlSet\\Control\\MediaProperties\\" "PrivateProperties\\Joystick\\OEM"; static const WCHAR dinput_path[] = L"System\\CurrentControlSet\\Control\\MediaProperties\\" "PrivateProperties\\DirectInput"; - HKEY root_key; /* These keys are automatically created by DInput and they store the list of supported force-feedback effects. OEM drivers are supposed @@ -3630,21 +3644,10 @@ void cleanup_registry_keys(void) We need to clean them up, or DInput will not refresh the list of effects from the PID report changes. */ - RegCreateKeyExW( HKEY_CURRENT_USER, joystick_oem_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL ); - RegDeleteTreeW( root_key, expect_vidpid_str ); - RegCloseKey( root_key ); - - RegCreateKeyExW( HKEY_CURRENT_USER, dinput_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL ); - RegDeleteTreeW( root_key, expect_vidpid_str ); - RegCloseKey( root_key ); - - RegCreateKeyExW( HKEY_LOCAL_MACHINE, joystick_oem_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL ); - RegDeleteTreeW( root_key, expect_vidpid_str ); - RegCloseKey( root_key ); - - RegCreateKeyExW( HKEY_LOCAL_MACHINE, dinput_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL ); - RegDeleteTreeW( root_key, expect_vidpid_str ); - RegCloseKey( root_key ); + cleanup_registry_tree( HKEY_CURRENT_USER, joystick_oem_path ); + cleanup_registry_tree( HKEY_CURRENT_USER, dinput_path ); + cleanup_registry_tree( HKEY_LOCAL_MACHINE, joystick_oem_path ); + cleanup_registry_tree( HKEY_LOCAL_MACHINE, dinput_path ); } static LRESULT CALLBACK monitor_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10538
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/dinput/tests/hotplug.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/dlls/dinput/tests/hotplug.c b/dlls/dinput/tests/hotplug.c index 9bea45202ff..10a3051e8ce 100644 --- a/dlls/dinput/tests/hotplug.c +++ b/dlls/dinput/tests/hotplug.c @@ -154,9 +154,9 @@ static BOOL test_input_lost( DWORD version ) .dwData = UINT_MAX, }; - DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)}; + DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)}, devinst2 = devinst; + IDirectInputDevice8W *device = NULL, *device2; DIDEVICEOBJECTDATA objdata[32] = {{0}}; - IDirectInputDevice8W *device = NULL; ULONG ref, count, size; DIJOYSTATE2 state; HRESULT hr; @@ -218,6 +218,15 @@ static BOOL test_input_lost( DWORD version ) ref = IDirectInputDevice8_Release( device ); ok( ref == 0, "Release returned %ld\n", ref ); + /* Test guidInstance across hotplugs. It should remain the same. */ + hr = dinput_test_create_device( version, &devinst2, &device2 ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( !!device2, "device2 is NULL.\n" ); + todo_wine ok( !memcmp( &devinst.guidInstance, &devinst2.guidInstance, sizeof(GUID) ), + "Unexpected guidInstance.\n" ); + ref = IDirectInputDevice8_Release( device2 ); + ok( ref == 0, "Release returned %ld\n", ref ); + done: hid_device_stop( &desc, 1 ); cleanup_registry_keys(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10538
From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/dinput/tests/dinput_test.h | 1 + dlls/dinput/tests/joystick8.c | 515 ++++++++++++++++++++++++++++++++ 2 files changed, 516 insertions(+) diff --git a/dlls/dinput/tests/dinput_test.h b/dlls/dinput/tests/dinput_test.h index 26842aa119b..ae3416c4ba7 100644 --- a/dlls/dinput/tests/dinput_test.h +++ b/dlls/dinput/tests/dinput_test.h @@ -64,6 +64,7 @@ void cleanup_registry_keys(void); void dinput_test_init_( const char *file, int line ); void dinput_test_exit(void); +HRESULT dinput_test_create_device_instance( DWORD version, const GUID *guid_inst, IDirectInputDevice8W **device ); HRESULT dinput_test_create_device( DWORD version, DIDEVICEINSTANCEW *devinst, IDirectInputDevice8W **device ); DWORD WINAPI dinput_test_device_thread( void *stop_event ); diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index f1da7a57df0..5b2ca8fe66d 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -302,6 +302,39 @@ static BOOL CALLBACK enum_device_count( const DIDEVICEINSTANCEW *devinst, void * return DIENUM_CONTINUE; } +struct dinput +{ + DWORD version; + union + { + IDirectInput8W *di8; + IDirectInputW *di; + }; +}; + +static HRESULT dinput_create( struct dinput *di ) +{ + return di->version < 0x0800 ? DirectInputCreateEx( instance, di->version, &IID_IDirectInput2W, (void **)&di->di, NULL ) + : DirectInput8Create( instance, di->version, &IID_IDirectInput8W, (void **)&di->di, NULL ); +} + +static ULONG dinput_release( struct dinput *di ) +{ + return di->version < 0x0800 ? IDirectInput_Release( di->di ) : IDirectInput8_Release( di->di8 ); +} + +static HRESULT dinput_enum_devices( struct dinput *di, LPDIENUMDEVICESCALLBACKW callback, void *context ) +{ + return di->version < 0x0800 ? IDirectInput_EnumDevices( di->di, 0, callback, context, DIEDFL_ALLDEVICES ) + : IDirectInput8_EnumDevices( di->di8, DI8DEVCLASS_ALL, callback, context, DIEDFL_ALLDEVICES ); +} + +static HRESULT dinput_create_device( struct dinput *di, const GUID *guid, IDirectInputDevice8W **device ) +{ + return di->version < 0x0800 ? IDirectInput_CreateDevice( di->di, guid, (IDirectInputDeviceW **)device, NULL ) + : IDirectInput8_CreateDevice( di->di8, guid, device, NULL ); +} + static void check_dinput_devices( DWORD version, DIDEVICEINSTANCEW *devinst ) { DIPROPDWORD prop_dword = @@ -5973,6 +6006,484 @@ static void test_rawinput_desktop( const char *path, BOOL input ) DestroyWindow( hwnd ); } +static BOOL CALLBACK find_test_device_instances( const DIDEVICEINSTANCEW *devinst, void *context ) +{ + GUID **instance = context; + + if (LOWORD(devinst->guidProduct.Data1) == LOWORD(EXPECT_VIDPID)) + { + **instance = devinst->guidInstance; + (*instance)++; + } + + return DIENUM_CONTINUE; +} + +#define check_device_hid_serial( a, b ) check_device_hid_serial_( __LINE__, a, b ) +static void check_device_hid_serial_( int line, IDirectInputDevice8W *device, const WCHAR *expect ) +{ + DIPROPGUIDANDPATH prop_guid_path = + { + .diph = + { + .dwSize = sizeof(DIPROPGUIDANDPATH), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_DEVICE, + }, + }; + WCHAR device_id[MAX_PATH] = {0}; + HANDLE file_handle; + HRESULT hr; + BOOL ret; + + hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph ); + ok_(__FILE__, line)( hr == S_OK, "Unexpected hr %#lx.\n", hr ); + + file_handle = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); + ok_(__FILE__, line)( file_handle != INVALID_HANDLE_VALUE, "Got error %lu.\n", GetLastError() ); + + ret = HidD_GetSerialNumberString( file_handle, device_id, ARRAY_SIZE(device_id) ); + ok_(__FILE__, line)( ret, "Failed to get HID serial number string.\n" ); + ok_(__FILE__, line)( !wcscmp( expect, device_id ), "Unexpected device serial %s.\n", debugstr_w(device_id) ); + + CloseHandle( file_handle ); +} + +static void test_joystick_instance_guid( DWORD version ) +{ +#include "psh_hid_macros.h" + static const unsigned char report_desc[] = + { + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Application), + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Physical), + USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON), + USAGE_MINIMUM(1, 1), + USAGE_MAXIMUM(1, 6), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 1), + REPORT_SIZE(1, 1), + REPORT_COUNT(1, 8), + INPUT(1, Data|Var|Abs), + END_COLLECTION, + END_COLLECTION, + }; + C_ASSERT( sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN ); +#include "pop_hid_macros.h" + struct hid_device_desc descs[4] = + { +#define MAKE_ATTR( pid) { sizeof(HID_DEVICE_ATTRIBUTES), LOWORD(EXPECT_VIDPID), pid, 0x0100 } +#define MAKE_DESC( pid, serial ) {.use_report_id = TRUE, .caps = {.InputReportByteLength = 1}, .attributes = MAKE_ATTR( pid ), .serial_str = serial} + MAKE_DESC( 0x0001, L"1&2345&6" ), + MAKE_DESC( 0x0001, L"2&7812&1" ), + MAKE_DESC( 0x0002, L"3&4580&7" ), + MAKE_DESC( 0x0002, L"4&5880&3" ), +#undef MAKE_DESC +#undef MAKE_ATTR + }; + const GUID instance_uuid_init = {0x00000000, 0x0000, 0x1000, {0x80, 0x00, 0x00, 0x00, 'D', 'E', 'S', 'T'}}; + struct dinput di = {.version = version}, di2 = {.version = version}; + GUID expect_instances[4], instances[64], *instances_end; + IDirectInputDevice8W *device; + HRESULT hr; + ULONG ref; + + winetest_push_context( "%#lx", version ); + cleanup_registry_keys(); + + if (FAILED(hr = dinput_create( &di ))) + { + win_skip( "DirectInput8Create returned %#lx\n", hr ); + return; + } + + for (UINT i = 0; i < ARRAY_SIZE(descs); i++) + { + descs[i].report_descriptor_len = sizeof(report_desc); + memcpy( descs[i].report_descriptor_buf, report_desc, sizeof(report_desc) ); + } + + if (!hid_device_start( descs, ARRAY_SIZE(descs) )) goto done; + + /* Enumerate all devices, each with a unique guidInstance. */ + instances_end = instances; + hr = dinput_enum_devices( &di, find_test_device_instances, &instances_end ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( instances_end == instances + 4, "Unexpected count %Iu.\n", instances_end - instances ); + + for (UINT i = 0; i < instances_end - instances; i++) + { + winetest_push_context( "device %d", i ); + + hr = dinput_create_device( &di, &instances[i], &device ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + expect_instances[i] = instances[i]; + + check_device_hid_serial( device, descs[i].serial_str ); + + IDirectInputDevice8_Release( device ); + winetest_pop_context(); + } + + /* + * Delete the existing registry keys, this will result in a new set of + * guidInstance values being generated on the next call to EnumDevices(). + */ + cleanup_registry_keys(); + + /* + * EnumDevices() hasn't been called yet, guidInstance values are still + * valid. + */ + for (UINT i = 0; i < instances_end - instances; i++) + { + winetest_push_context( "device %d", i ); + + hr = dinput_create_device( &di, &expect_instances[i], &device ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + + check_device_hid_serial( device, descs[i].serial_str ); + + IDirectInputDevice8_Release( device ); + winetest_pop_context(); + } + + /* The cache is module-local, other dinput version will fail to find + * the devices, but it doesn't cause the list to be refreshed. + */ + di2.version = 0x0500; + hr = dinput_create( &di2 ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + + hr = dinput_create_device( &di2, &expect_instances[0], &device ); + if (version == 0x800) todo_wine ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); + else ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) + { + check_device_hid_serial( device, descs[0].serial_str ); + IDirectInputDevice8_Release( device ); + } + + ref = dinput_release( &di2 ); + ok( ref == 0, "Release returned %ld\n", ref ); + + hr = dinput_create_device( &di, &expect_instances[0], &device ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + check_device_hid_serial( device, descs[0].serial_str ); + IDirectInputDevice8_Release( device ); + + + /* + * Call EnumDevices(), a new set of guidInstance values and registry entries + * will be created. + */ + instances_end = instances; + hr = dinput_enum_devices( &di, find_test_device_instances, &instances_end ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( instances_end == instances + 4, "Unexpected count %Iu.\n", instances_end - instances ); + + for (UINT i = 0; i < instances_end - instances; i++) + { + winetest_push_context( "device %d", i ); + + todo_wine ok( !IsEqualGUID( &expect_instances[i], &instances[i] ), + "Unexpected instance %s.\n", debugstr_guid( &instances[i] ) ); + + /* Old guidInstance no longer works. */ + hr = dinput_create_device( &di, &expect_instances[i], &device ); + todo_wine ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) IDirectInputDevice8_Release( device ); + expect_instances[i] = instances[i]; + + /* New guidInstance, same device. */ + hr = dinput_create_device( &di, &instances[i], &device ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + + check_device_hid_serial( device, descs[i].serial_str ); + + IDirectInputDevice8_Release( device ); + winetest_pop_context(); + } + + + /* Opening a device with an unknown instance GUID will cause a refresh + * of the device list, the same was as calling EnumDevices. + */ + cleanup_registry_keys(); + + instances[0] = instance_uuid_init; + instances[0].Data1 = 0xdeadbeef; + instances[0].Data2 = 0xdead; + instances[0].Data3 = 0xbeef; + hr = dinput_create_device( &di, &instances[0], &device ); + ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); + + hr = dinput_create_device( &di, &expect_instances[0], &device ); + todo_wine ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) IDirectInputDevice8_Release( device ); + + instances_end = instances; + hr = dinput_enum_devices( &di, find_test_device_instances, &instances_end ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( instances_end == instances + 4, "Unexpected count %Iu.\n", instances_end - instances ); + memcpy( expect_instances, instances, 4 * sizeof(*instances) ); + + + /* Opening a device with an unknown product GUID will cause a refresh + * of the device list, the same was as calling EnumDevices. + */ + cleanup_registry_keys(); + + instances[0] = expect_guid_product; + instances[0].Data1 = MAKELONG( LOWORD(EXPECT_VIDPID), 0x0003 ); + hr = dinput_create_device( &di, &instances[0], &device ); + ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); + + hr = dinput_create_device( &di, &expect_instances[0], &device ); + todo_wine ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) IDirectInputDevice8_Release( device ); + + instances_end = instances; + hr = dinput_enum_devices( &di, find_test_device_instances, &instances_end ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( instances_end == instances + 4, "Unexpected count %Iu.\n", instances_end - instances ); + memcpy( expect_instances, instances, 4 * sizeof(*instances) ); + + + /* Opening a cached device that has been unplugged fails but does + * not invalidate the cache, and other cached devices stay valid. + */ + cleanup_registry_keys(); + hid_device_stop( &descs[0], 1 ); + + hr = dinput_create_device( &di, &instances[1], &device ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + check_device_hid_serial( device, descs[1].serial_str ); + IDirectInputDevice8_Release( device ); + + hr = dinput_create_device( &di, &expect_instances[0], &device ); + todo_wine ok( hr == E_FAIL, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) IDirectInputDevice8_Release( device ); + + hr = dinput_create_device( &di, &instances[1], &device ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + check_device_hid_serial( device, descs[1].serial_str ); + IDirectInputDevice8_Release( device ); + + hid_device_start( &descs[0], 1 ); + + instances_end = instances; + hr = dinput_enum_devices( &di, find_test_device_instances, &instances_end ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( instances_end == instances + 4, "Unexpected count %Iu.\n", instances_end - instances ); + memcpy( expect_instances, instances, 4 * sizeof(*instances) ); + + + /* + * Stop devices 0 and 2. After enumeration, their guidInstance values will + * be assigned to devices 1 and 3. + */ + hid_device_stop( &descs[0], 1 ); + hid_device_stop( &descs[2], 1 ); + + /* Stopped devices should return E_FAIL. */ + hr = dinput_create_device( &di, &instances[0], &device ); + todo_wine ok( hr == E_FAIL, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) IDirectInputDevice8_Release( device ); + hr = dinput_create_device( &di, &instances[2], &device ); + todo_wine ok( hr == E_FAIL, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) IDirectInputDevice8_Release( device ); + + /* After calling EnumDevices(), guidInstance values will be reassigned. */ + instances_end = instances; + hr = dinput_enum_devices( &di, find_test_device_instances, &instances_end ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( instances_end == instances + 2, "Unexpected count %Iu.\n", instances_end - instances ); + + for (UINT i = 0; i < instances_end - instances; i++) + { + const unsigned int expected_joystick = !i ? 1 : 3; + + winetest_push_context( "device %d", i ); + + todo_wine ok( IsEqualGUID( &expect_instances[expected_joystick - 1], &instances[i] ), + "Unexpected instance %s.\n", debugstr_guid( &instances[i] ) ); + hr = dinput_create_device( &di, &instances[i], &device ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + + check_device_hid_serial( device, descs[expected_joystick].serial_str ); + + IDirectInputDevice8_Release( device ); + winetest_pop_context(); + } + + /* + * Restart devices 0 and 2, they should get their old guidInstance values + * back after another call to EnumDevices(). + */ + hid_device_start( &descs[0], 1 ); + hid_device_start( &descs[2], 1 ); + + for (UINT i = 0; i < instances_end - instances; i++) + { + const unsigned int expected_joystick = !i ? 1 : 3; + + winetest_push_context( "device %d", i ); + + todo_wine ok( IsEqualGUID( &expect_instances[expected_joystick - 1], &instances[i] ), + "Unexpected instance %s.\n", debugstr_guid( &instances[i] ) ); + hr = dinput_create_device( &di, &instances[i], &device ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + + check_device_hid_serial( device, descs[expected_joystick].serial_str ); + + IDirectInputDevice8_Release( device ); + winetest_pop_context(); + } + + /* guidInstance values are all back to what they were. */ + instances_end = instances; + hr = dinput_enum_devices( &di, find_test_device_instances, &instances_end ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( instances_end == instances + 4, "Unexpected count %Iu.\n", instances_end - instances ); + + for (UINT i = 0; i < instances_end - instances; i++) + { + winetest_push_context( "device %d", i ); + + todo_wine_if( !(i & 0x1) ) + ok( IsEqualGUID( &expect_instances[i], &instances[i] ), + "Unexpected guidInstance %s.\n", debugstr_guid( &instances[i] ) ); + + hr = dinput_create_device( &di, &instances[i], &device ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + + check_device_hid_serial( device, descs[i].serial_str ); + + IDirectInputDevice8_Release( device ); + winetest_pop_context(); + } + + /* Stop all devices. */ + hid_device_stop( descs, ARRAY_SIZE(descs) ); + + + /* + * Call EnumDevices() with all devices stopped. Test behavior of device + * creation without calling EnumDevices() with the devices present + * beforehand. + */ + instances_end = instances; + hr = dinput_enum_devices( &di, find_test_device_instances, &instances_end ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( instances_end == instances, "Unexpected count %Iu.\n", instances_end - instances ); + + for (UINT i = 0; i < ARRAY_SIZE(descs); i++) + { + winetest_push_context( "device %d", i ); + + hr = dinput_create_device( &di, &expect_instances[i], &device ); + ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); + + /* + * Start the joystick device. This will succeed, even without having + * called EnumDevices() beforehand. + */ + hid_device_start( &descs[i], 1 ); + + hr = dinput_create_device( &di, &expect_instances[i], &device ); + todo_wine ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) + { + check_device_hid_serial( device, descs[i].serial_str ); + IDirectInputDevice8_Release( device ); + } + hid_device_stop( &descs[i], 1 ); + + hr = dinput_create_device( &di, &expect_instances[i], &device ); + todo_wine ok( hr == E_FAIL, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) IDirectInputDevice8_Release( device ); + + hid_device_start( &descs[i], 1 ); + winetest_pop_context(); + } + + hid_device_stop( descs, ARRAY_SIZE(descs) ); + + + /* Reset device list. */ + instances_end = instances; + hr = dinput_enum_devices( &di, find_test_device_instances, &instances_end ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( instances_end == instances, "Unexpected count %Iu.\n", instances_end - instances ); + + + /* + * Start device 0, create a device with guidInstance 0. + * Stop device 0. + * Start device 1, attempt to create a device with guidInstance 1. + * Fails. + * Try to create a device with guidInstance 0, which is now associated + * with device 1. + */ + hid_device_start( &descs[0], 1 ); + + hr = dinput_create_device( &di, &expect_instances[0], &device ); + todo_wine ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) + { + check_device_hid_serial( device, descs[0].serial_str ); + IDirectInputDevice8_Release( device ); + } + hid_device_stop( &descs[0], 1 ); + + hr = dinput_create_device( &di, &expect_instances[0], &device ); + todo_wine ok( hr == E_FAIL, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) IDirectInputDevice8_Release( device ); + + + /* Start device 1. */ + hid_device_start( &descs[1], 1 ); + + /* + * This still fails with E_FAIL, as expect_instances[0] is still associated + * with device 0. + */ + hr = dinput_create_device( &di, &expect_instances[0], &device ); + todo_wine ok( hr == E_FAIL, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) IDirectInputDevice8_Release( device ); + + /* + * expect_instances[1] is not currently associated with a device, which + * means attempting to use this GUID results in what seems to be an + * internal call to EnumDevices(). With device 0 currently stopped, + * expect_instances[0] gets reassigned to device 1. + */ + hr = dinput_create_device( &di, &expect_instances[1], &device ); + ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); + + hr = dinput_create_device( &di, &expect_instances[0], &device ); + todo_wine ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) + { + check_device_hid_serial( device, descs[1].serial_str ); + IDirectInputDevice8_Release( device ); + } + hid_device_stop( &descs[1], 1 ); + + +done: + ref = dinput_release( &di ); + ok( ref == 0, "Release returned %ld\n", ref ); + cleanup_registry_keys(); + winetest_pop_context(); +} + START_TEST( joystick8 ) { char **argv; @@ -6000,6 +6511,10 @@ START_TEST( joystick8 ) test_simple_joystick( 0x700 ); test_simple_joystick( 0x800 ); + test_joystick_instance_guid( 0x500 ); + test_joystick_instance_guid( 0x700 ); + test_joystick_instance_guid( 0x800 ); + test_many_axes_joystick(); test_driving_wheel_axes(); test_rawinput( argv ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10538
This merge request was approved by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10538
participants (3)
-
Connor McAdams -
Rémi Bernon -
Rémi Bernon (@rbernon)