From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/dinput/dinput_main.c | 1 + dlls/dinput/dinput_private.h | 1 + dlls/dinput/joystick_hid.c | 376 +++++++++++++++++++++++++++++----- dlls/dinput/tests/hotplug.c | 11 +- dlls/dinput/tests/joystick8.c | 40 ++-- 5 files changed, 346 insertions(+), 83 deletions(-) diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index e4bc1f7961d..aabad4ff97a 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -522,6 +522,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, void *reserved ) break; case DLL_PROCESS_DETACH: if (reserved) break; + hid_joystick_cleanup(); unregister_di_em_win_class(); break; } diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h index 0609b816b3b..7e7b1e490f5 100644 --- a/dlls/dinput/dinput_private.h +++ b/dlls/dinput/dinput_private.h @@ -56,6 +56,7 @@ extern HRESULT keyboard_enum_device( DWORD type, DWORD flags, DIDEVICEINSTANCEW extern HRESULT keyboard_create_device( struct dinput *dinput, const GUID *guid, IDirectInputDevice8W **out ); extern HRESULT hid_joystick_enum_device( DWORD type, DWORD flags, DIDEVICEINSTANCEW *instance, DWORD version, int index ); extern HRESULT hid_joystick_create_device( struct dinput *dinput, const GUID *guid, IDirectInputDevice8W **out ); +extern void hid_joystick_cleanup( void ); struct DevicePlayer { GUID instance_guid; diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 22709c4bfd9..e195d8ac43b 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -49,9 +49,216 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput); DEFINE_GUID( GUID_DEVINTERFACE_WINEXINPUT,0x6c53d5fd,0x6480,0x440f,0xb6,0x18,0x47,0x67,0x50,0xc5,0xe1,0xa6 ); -DEFINE_GUID( hid_joystick_guid, 0x9e573edb, 0x7734, 0x11d2, 0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7 ); DEFINE_GUID( device_path_guid, 0x00000000, 0x0000, 0x0000, 0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf8 ); +static HANDLE dinput_reg_mutex; +static BOOL WINAPI dinput_init_reg_mutex(INIT_ONCE *once, void *param, void **ctx) +{ + HANDLE mutex = CreateMutexW( NULL, FALSE, L"__wine_dinput_reg_mutex" ); + + if (mutex) dinput_reg_mutex = mutex; + + return !!mutex; +} + +static void get_dinput_reg_mutex( void ) +{ + static INIT_ONCE once = INIT_ONCE_STATIC_INIT; + + if (!dinput_reg_mutex) InitOnceExecuteOnce( &once, dinput_init_reg_mutex, NULL, NULL ); + WaitForSingleObject( dinput_reg_mutex, INFINITE ); +} + +static void release_dinput_reg_mutex( void ) +{ + assert(dinput_reg_mutex); + ReleaseMutex( dinput_reg_mutex ); +} + +/* Need to enter the mutex prior to accessing these registry entries. */ +static const WCHAR *dinput_path = L"System\\CurrentControlSet\\Control\\MediaProperties\\" + "PrivateProperties\\DirectInput"; +static BOOL get_device_instance_id_from_registry(WORD vid, WORD pid, unsigned int idx, GUID *guid_instance) +{ + BOOL ret_val = FALSE; + HKEY dev_key = NULL; + WCHAR buf[MAX_PATH]; + GUID guid = { 0 }; + DWORD len; + + memset( guid_instance, 0, sizeof(*guid_instance) ); + swprintf( buf, ARRAY_SIZE(buf), L"%s\\VID_%04X&PID_%04X\\Calibration\\%d", dinput_path, vid, pid, idx ); + if (RegOpenKeyExW( HKEY_CURRENT_USER, buf, 0, KEY_ALL_ACCESS, &dev_key )) goto exit; + + /* No preexisting guidInstance or failure to get value, invalid key. */ + len = sizeof(guid); + if (RegGetValueW( dev_key, NULL, L"GUID", RRF_RT_REG_BINARY, NULL, &guid, &len )) + { + WARN( "Failed to get guidInstance from key.\n" ); + goto exit; + } + + ret_val = TRUE; + *guid_instance = guid; + +exit: + RegCloseKey( dev_key ); + /* Got a non-existent or malformed key, delete it. */ + if (dev_key && !ret_val) RegDeleteKeyW( HKEY_CURRENT_USER, buf ); + return ret_val; +} + +static void set_device_instance_id_in_registry(WORD vid, WORD pid, unsigned int idx, GUID *guid_instance) +{ + HKEY dev_key = NULL; + WCHAR buf[MAX_PATH]; + + swprintf( buf, ARRAY_SIZE(buf), L"%s\\VID_%04X&PID_%04X\\Calibration\\%d", dinput_path, vid, pid, idx ); + if (RegCreateKeyExW( HKEY_CURRENT_USER, buf, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &dev_key, NULL )) + { + WARN( "Failed to create HKEY for device.\n" ); + goto exit; + } + + if (RegSetValueExW( dev_key, L"GUID", 0, REG_BINARY, (const BYTE *)guid_instance, + sizeof(*guid_instance) )) + WARN( "Failed to set instance GUID value in registry.\n" ); +exit: + RegCloseKey( dev_key ); +} + +/* + * Version 1 UUID timestamps are a count of the number of 100 nanosecond + * intervals since 00:00:00.00, 15 October 1582 (the date of Gregorian + * reform to the Christian calendar). FILETIME is a count of the number of 100 + * nanosecond intervals since 00:00:00.00, 1 January 1601. In order to convert + * a FILETIME value to a UUID timestamp, we need to add: + * - 17 days in October 1582. + * - 30 days in November 1582. + * - 31 days in December 1582. + * - 18 years between January 1583 and January 1601. + * - 5 leap days in those 18 years. + */ +#define UUID_TIME_TO_SYSTEM_TIME_DAYS ((ULONG64)((365 * 18) + 5 + 17 + 30 + 31)) +#define UUID_TIME_TO_SYSTEM_TIME_NS_DIFFERENCE ((UUID_TIME_TO_SYSTEM_TIME_DAYS) * 24 * 60 * 60 * 10000000) +DEFINE_GUID( dinput_joystick_uuid_init, 0x00000000, 0x0000, 0x1000, 0x80, 0x00, 0x00, 0x00, 'D', 'E', 'S', 'T' ); +static void create_v1_uuid(GUID *guid) +{ + GUID tmp = dinput_joystick_uuid_init; + static LONG clock_seq; + ULARGE_INTEGER time; + ULONG cur_seq; + + GetSystemTimeAsFileTime( (FILETIME *)&time ); + time.QuadPart += UUID_TIME_TO_SYSTEM_TIME_NS_DIFFERENCE; + tmp.Data1 = (time.QuadPart & 0xffffffff); + tmp.Data2 = ((time.QuadPart >> 32) & 0xffff); + tmp.Data3 |= ((time.QuadPart >> 48) & 0x0fff); + cur_seq = InterlockedIncrement( &clock_seq ); + tmp.Data4[1] |= (cur_seq & 0xff); + tmp.Data4[0] |= ((cur_seq & 0x3f00) >> 8); + *guid = tmp; +} + +static BOOL dinput_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size) +{ + SIZE_T max_capacity, new_capacity; + void *new_elements; + + if (count <= *capacity) + return TRUE; + + max_capacity = ~(SIZE_T)0 / size; + if (count > max_capacity) + return FALSE; + + new_capacity = max(1, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = count; + + new_elements = _recalloc( *elements, new_capacity, size ); + if (!new_elements) + return FALSE; + + *elements = new_elements; + *capacity = new_capacity; + return TRUE; +} + +struct dinput_joystick_instance +{ + DIDEVICEINSTANCEW di_device_instance; + WCHAR device_path[MAX_PATH]; + DWORD dev_idx; + + BOOL dev_idx_assigned; + WORD vid, pid; +}; + +static CRITICAL_SECTION joystick_crit; +static CRITICAL_SECTION_DEBUG joystick_critsect_debug = +{ + 0, 0, &joystick_crit, + { &joystick_critsect_debug.ProcessLocksList, &joystick_critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": joystick_crit") } +}; +static CRITICAL_SECTION joystick_crit = { &joystick_critsect_debug, -1, 0, 0, 0, 0 }; + +/* Need to enter the CS to access this array. */ +static struct +{ + struct dinput_joystick_instance *joysticks; + unsigned int count; + SIZE_T size; +} dinput_joysticks; + +static struct dinput_joystick_instance *dinput_get_joystick_instance(unsigned int idx) +{ + if (dinput_joysticks.count && (idx < dinput_joysticks.count)) + return &dinput_joysticks.joysticks[idx]; + return NULL; +} + +static BOOL dinput_add_joystick_instance(const struct dinput_joystick_instance *inst) +{ + if (!dinput_array_reserve( (void **)&dinput_joysticks.joysticks, + &dinput_joysticks.size, dinput_joysticks.count + 1, sizeof(*inst) )) + { + ERR("Failed to allocate memory for a new device instance.\n"); + return FALSE; + } + + dinput_joysticks.joysticks[dinput_joysticks.count++] = *inst; + return TRUE; +} + +static struct dinput_joystick_instance *dinput_get_joystick_instance_from_guid(const GUID *guid) +{ + struct dinput_joystick_instance *ret = NULL; + unsigned int i; + + for (i = 0; i < dinput_joysticks.count; i++) + { + struct dinput_joystick_instance *instance = &dinput_joysticks.joysticks[i]; + + if (IsEqualGUID( &instance->di_device_instance.guidInstance, guid ) + || IsEqualGUID( &instance->di_device_instance.guidProduct, guid )) + { + ret = instance; + break; + } + } + return ret; +} + +void hid_joystick_cleanup( void ) +{ + if (dinput_reg_mutex) CloseHandle( dinput_reg_mutex ); + if (dinput_joysticks.joysticks) free(dinput_joysticks.joysticks); +} + struct pid_control_report { BYTE id; @@ -1421,13 +1628,12 @@ static HRESULT hid_joystick_device_try_open( const WCHAR *path, HANDLE *device, BOOL has_accelerator, has_brake, has_clutch, has_z, has_pov; PHIDP_PREPARSED_DATA preparsed_data = NULL; HIDP_LINK_COLLECTION_NODE nodes[256]; - DWORD type, size, button_count = 0; + DWORD type, button_count = 0; HIDP_BUTTON_CAPS buttons[10]; HIDP_VALUE_CAPS value; HANDLE device_file; ULONG node_count; NTSTATUS status; - UINT32 handle; USHORT count; device_file = CreateFileW( path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, @@ -1450,14 +1656,7 @@ static HRESULT hid_joystick_device_try_open( const WCHAR *path, HANDLE *device, if (!HidD_GetProductString( device_file, instance->tszInstanceName, MAX_PATH * sizeof(WCHAR) )) goto failed; if (!HidD_GetProductString( device_file, instance->tszProductName, MAX_PATH * sizeof(WCHAR) )) goto failed; - if (!DeviceIoControl( device_file, IOCTL_HID_GET_WINE_RAWINPUT_HANDLE, NULL, 0, &handle, sizeof(handle), &size, NULL )) - { - ERR( "failed to get raw input handle, error %lu\n", GetLastError() ); - goto failed; - } - - instance->guidInstance = hid_joystick_guid; - instance->guidInstance.Data1 ^= handle; + instance->guidInstance = GUID_NULL; instance->guidProduct = dinput_pidvid_guid; instance->guidProduct.Data1 = MAKELONG( attrs->VendorID, attrs->ProductID ); instance->guidFFDriver = GUID_NULL; @@ -1572,21 +1771,24 @@ failed: return DIERR_DEVICENOTREG; } -static HRESULT hid_joystick_device_open( int index, const GUID *guid, DIDEVICEINSTANCEW *instance, - WCHAR *device_path, HANDLE *device, PHIDP_PREPARSED_DATA *preparsed, - HIDD_ATTRIBUTES *attrs, HIDP_CAPS *caps, DWORD version ) +static HRESULT hid_joystick_refresh_devices( void ) { char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)]; SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer; SP_DEVICE_INTERFACE_DATA iface = {.cbSize = sizeof(iface)}; SP_DEVINFO_DATA devinfo = {.cbSize = sizeof(devinfo)}; + struct dinput_joystick_instance cur_instance = { 0 }; WCHAR device_id[MAX_PATH], *tmp; + PHIDP_PREPARSED_DATA preparsed; + HIDD_ATTRIBUTES attrs = { 0 }; HDEVINFO set, xi_set; + HIDP_CAPS caps; + HANDLE device; BOOL override; UINT32 i = 0; GUID hid; - TRACE( "index %d, guid %s\n", index, debugstr_guid( guid ) ); + TRACE( "\n" ); HidD_GetHidGuid( &hid ); @@ -1594,18 +1796,25 @@ static HRESULT hid_joystick_device_open( int index, const GUID *guid, DIDEVICEIN if (set == INVALID_HANDLE_VALUE) return DIERR_DEVICENOTREG; xi_set = SetupDiGetClassDevsW( &GUID_DEVINTERFACE_WINEXINPUT, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT ); - *device = NULL; - *preparsed = NULL; + device = NULL; + preparsed = NULL; + + EnterCriticalSection( &joystick_crit ); + memset( dinput_joysticks.joysticks, 0, sizeof(*dinput_joysticks.joysticks) * dinput_joysticks.size ); + dinput_joysticks.count = 0; while (SetupDiEnumDeviceInterfaces( set, NULL, &hid, i++, &iface )) { + memset( &cur_instance, 0, sizeof(cur_instance) ); + cur_instance.di_device_instance.dwSize = sizeof(cur_instance.di_device_instance); + detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); if (!SetupDiGetDeviceInterfaceDetailW( set, &iface, detail, sizeof(buffer), NULL, &devinfo )) continue; - if (FAILED(hid_joystick_device_try_open( detail->DevicePath, device, preparsed, - attrs, caps, instance, version ))) + if (FAILED(hid_joystick_device_try_open( detail->DevicePath, &device, &preparsed, + &attrs, &caps, &cur_instance.di_device_instance, 0x0800 ))) continue; - if (device_instance_is_disabled( instance, &override )) + if (device_instance_is_disabled( &cur_instance.di_device_instance, &override )) goto next; if (override && SetupDiGetDeviceInstanceIdW( set, &devinfo, device_id, MAX_PATH, NULL ) && @@ -1619,58 +1828,102 @@ static HRESULT hid_joystick_device_open( int index, const GUID *guid, DIDEVICEIN if (!SetupDiGetDeviceInterfaceDetailW( xi_set, &iface, detail, sizeof(buffer), NULL, &devinfo )) goto next; - CloseHandle( *device ); - HidD_FreePreparsedData( *preparsed ); - if (FAILED(hid_joystick_device_try_open( detail->DevicePath, device, preparsed, - attrs, caps, instance, version ))) + CloseHandle( device ); + HidD_FreePreparsedData( preparsed ); + if (FAILED(hid_joystick_device_try_open( detail->DevicePath, &device, &preparsed, + &attrs, &caps, &cur_instance.di_device_instance, 0x0800 ))) continue; } - /* enumerate device by GUID */ - if (IsEqualGUID( guid, &instance->guidProduct ) || IsEqualGUID( guid, &instance->guidInstance )) break; + cur_instance.vid = attrs.VendorID; + cur_instance.pid = attrs.ProductID; + wcsncpy( cur_instance.device_path, detail->DevicePath, MAX_PATH ); + dinput_add_joystick_instance(&cur_instance); + next: + CloseHandle( device ); + HidD_FreePreparsedData( preparsed ); + device = NULL; + preparsed = NULL; + } - /* enumerate all devices */ - if (index >= 0 && !index--) break; + /* Assign device index for a particular VID/PID pair. */ + for (i = 0; i < dinput_joysticks.count; i++) + { + struct dinput_joystick_instance *inst = &dinput_joysticks.joysticks[i]; + unsigned int j, dev_idx; - next: - CloseHandle( *device ); - HidD_FreePreparsedData( *preparsed ); - *device = NULL; - *preparsed = NULL; + if (inst->dev_idx_assigned) continue; + + inst->dev_idx = dev_idx = 0; + inst->dev_idx_assigned = TRUE; + for (j = (i + 1); j < dinput_joysticks.count; j++) + { + struct dinput_joystick_instance *inst2 = &dinput_joysticks.joysticks[j]; + + if (inst2->vid == inst->vid && inst2->pid == inst->pid) + { + inst2->dev_idx = ++dev_idx; + inst2->dev_idx_assigned = TRUE; + } + } + } + + /* + * Get guidInstance values for each joystick device. If there is one in + * the registry already use that, and if not, create one. + */ + get_dinput_reg_mutex(); + for (i = 0; i < dinput_joysticks.count; i++) + { + struct dinput_joystick_instance *inst = &dinput_joysticks.joysticks[i]; + + if (!get_device_instance_id_from_registry( inst->vid, inst->pid, inst->dev_idx, + &inst->di_device_instance.guidInstance )) + { + create_v1_uuid( &inst->di_device_instance.guidInstance ); + set_device_instance_id_in_registry( inst->vid, inst->pid, inst->dev_idx, + &inst->di_device_instance.guidInstance ); + } } + release_dinput_reg_mutex(); + + LeaveCriticalSection( &joystick_crit ); if (xi_set != INVALID_HANDLE_VALUE) SetupDiDestroyDeviceInfoList( xi_set ); SetupDiDestroyDeviceInfoList( set ); - if (!*device || !*preparsed) return DIERR_DEVICENOTREG; - - lstrcpynW( device_path, detail->DevicePath, MAX_PATH ); return DI_OK; } HRESULT hid_joystick_enum_device( DWORD type, DWORD flags, DIDEVICEINSTANCEW *instance, DWORD version, int index ) { - HIDD_ATTRIBUTES attrs = {.Size = sizeof(attrs)}; - PHIDP_PREPARSED_DATA preparsed; + struct dinput_joystick_instance *inst = NULL; WCHAR device_path[MAX_PATH]; - GUID guid = GUID_NULL; - HIDP_CAPS caps; - HANDLE device; - HRESULT hr; + HRESULT hr = DI_OK; TRACE( "type %#lx, flags %#lx, instance %p, version %#lx, index %d\n", type, flags, instance, version, index ); - hr = hid_joystick_device_open( index, &guid, instance, device_path, &device, &preparsed, - &attrs, &caps, version ); + if (!index) hr = hid_joystick_refresh_devices(); if (hr != DI_OK) return hr; - HidD_FreePreparsedData( preparsed ); - CloseHandle( device ); + EnterCriticalSection( &joystick_crit ); + if ((inst = dinput_get_joystick_instance( index ))) + { + DWORD type = inst->di_device_instance.dwDevType & ~DIDEVTYPE_HID; + + *instance = inst->di_device_instance; + instance->dwDevType = device_type_for_version( type, version ) | DIDEVTYPE_HID; + wcsncpy( device_path, inst->device_path, MAX_PATH ); + } - TRACE( "found device %s, usage %04x:%04x, product %s, instance %s, name %s\n", debugstr_w(device_path), - instance->wUsagePage, instance->wUsage, debugstr_guid( &instance->guidProduct ), - debugstr_guid( &instance->guidInstance ), debugstr_w(instance->tszInstanceName) ); + if (!inst) hr = DIERR_DEVICENOTREG; + LeaveCriticalSection( &joystick_crit ); - return DI_OK; + if (hr == DI_OK) + TRACE( "found device %s, usage %04x:%04x, product %s, instance %s, name %s\n", debugstr_w(device_path), + instance->wUsagePage, instance->wUsage, debugstr_guid( &instance->guidProduct ), + debugstr_guid( &instance->guidInstance ), debugstr_w(instance->tszInstanceName) ); + + return hr; } static BOOL init_object_properties( struct dinput_device *device, UINT index, struct hid_value_caps *caps, @@ -2040,15 +2293,30 @@ HRESULT hid_joystick_create_device( struct dinput *dinput, const GUID *guid, IDi impl->base.dwCoopLevel = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND; impl->base.read_event = CreateEventW( NULL, TRUE, FALSE, NULL ); - if (memcmp( device_path_guid.Data4, guid->Data4, sizeof(device_path_guid.Data4) )) - hr = hid_joystick_device_open( -1, guid, &impl->base.instance, impl->device_path, &impl->device, &impl->preparsed, - &attrs, &impl->caps, dinput->dwVersion ); - else + if (!memcmp( device_path_guid.Data4, guid->Data4, sizeof(device_path_guid.Data4) )) { wcscpy( impl->device_path, *(const WCHAR **)guid ); hr = hid_joystick_device_try_open( impl->device_path, &impl->device, &impl->preparsed, &attrs, &impl->caps, &impl->base.instance, dinput->dwVersion ); } + else + { + struct dinput_joystick_instance *inst = NULL; + + EnterCriticalSection( &joystick_crit ); + /* If we don't get a device for this GUID initially, try enumerating. */ + if (!(inst = dinput_get_joystick_instance_from_guid( guid ))) hid_joystick_refresh_devices(); + if ((inst = dinput_get_joystick_instance_from_guid( guid ))) + { + wcscpy( impl->device_path, inst->device_path ); + hr = hid_joystick_device_try_open( impl->device_path, &impl->device, &impl->preparsed, &attrs, + &impl->caps, &impl->base.instance, dinput->dwVersion ); + if (hr == DI_OK) impl->base.instance.guidInstance = inst->di_device_instance.guidInstance; + } + else + hr = DIERR_DEVICENOTREG; + LeaveCriticalSection( &joystick_crit ); + } if (hr != DI_OK) goto failed; impl->base.caps.dwDevType = impl->base.instance.dwDevType; diff --git a/dlls/dinput/tests/hotplug.c b/dlls/dinput/tests/hotplug.c index 350050c0a42..e47fd768c18 100644 --- a/dlls/dinput/tests/hotplug.c +++ b/dlls/dinput/tests/hotplug.c @@ -229,13 +229,10 @@ static BOOL test_input_lost( DWORD version ) hr = dinput_test_create_device( version, &devinst, &device2 ); ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); ok( !!device2, "device2 is NULL.\n" ); - if (device2) - { - todo_wine ok( !memcmp( &guid_instance, &devinst.guidInstance, sizeof(guid_instance) ), - "Unexpected guidInstance.\n" ); - ref = IDirectInputDevice8_Release( device2 ); - ok( ref == 0, "Release returned %ld\n", ref ); - } + ok( !memcmp( &guid_instance, &devinst.guidInstance, sizeof(guid_instance) ), + "Unexpected guidInstance.\n" ); + ref = IDirectInputDevice8_Release( device2 ); + ok( ref == 0, "Release returned %ld\n", ref ); done: hid_device_stop( &desc, 1 ); diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index c5dc5c066bf..ee2e6357344 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -6197,13 +6197,13 @@ static void test_joystick_instance_guid( DWORD version ) { winetest_push_context( "device %d", i ); - todo_wine ok( !IsEqualGUID( &guid_instances[i], &devinsts[i].guidInstance ), "Unexpected guidInstance %s.\n", + ok( !IsEqualGUID( &guid_instances[i], &devinsts[i].guidInstance ), "Unexpected guidInstance %s.\n", debugstr_guid(&devinsts[i].guidInstance) ); /* Old guidInstance no longer works. */ device = NULL; hr = dinput_test_create_device_instance( version, &guid_instances[i], &device ); - todo_wine ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); + ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); if (device) IDirectInputDevice8_Release(device); guid_instances[i] = devinsts[i].guidInstance; @@ -6243,7 +6243,7 @@ static void test_joystick_instance_guid( DWORD version ) winetest_push_context( "device %d", i ); - todo_wine ok( IsEqualGUID( &guid_instances[expected_joystick - 1], &devinsts[i].guidInstance ), + ok( IsEqualGUID( &guid_instances[expected_joystick - 1], &devinsts[i].guidInstance ), "Unexpected guidInstance %s.\n", debugstr_guid(&devinsts[i].guidInstance) ); hr = dinput_test_create_device_instance( version, &devinsts[i].guidInstance, &device ); ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); @@ -6269,7 +6269,7 @@ static void test_joystick_instance_guid( DWORD version ) winetest_push_context( "device %d", i ); - todo_wine ok( IsEqualGUID( &guid_instances[expected_joystick - 1], &devinsts[i].guidInstance ), + ok( IsEqualGUID( &guid_instances[expected_joystick - 1], &devinsts[i].guidInstance ), "Unexpected guidInstance %s.\n", debugstr_guid(&devinsts[i].guidInstance) ); hr = dinput_test_create_device_instance( version, &devinsts[i].guidInstance, &device ); ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); @@ -6291,7 +6291,7 @@ static void test_joystick_instance_guid( DWORD version ) { winetest_push_context( "device %d", i ); - todo_wine_if(!(i & 0x1)) ok( IsEqualGUID( &guid_instances[i], &devinsts[i].guidInstance ), "Unexpected guidInstance %s.\n", + ok( IsEqualGUID( &guid_instances[i], &devinsts[i].guidInstance ), "Unexpected guidInstance %s.\n", debugstr_guid(&devinsts[i].guidInstance) ); hr = dinput_test_create_device_instance( version, &devinsts[i].guidInstance, &device ); @@ -6330,7 +6330,7 @@ static void test_joystick_instance_guid( DWORD version ) */ if (!start_joystick_test_device( &test_devs[i] )) goto done; hr = dinput_test_create_device_instance( version, &guid_instances[i], &device ); - todo_wine ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); if (device) { dinput_test_get_device_hid_serial_string(device, device_serial); @@ -6367,15 +6367,13 @@ static void test_joystick_instance_guid( DWORD version ) if (!start_joystick_test_device( &test_devs[0] )) goto done; hr = dinput_test_create_device_instance( version, &guid_instances[0], &device ); - todo_wine ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); - if (device) - { - dinput_test_get_device_hid_serial_string(device, device_serial); - ok( !wcscmp(test_devs[0].desc.instance_id, device_serial), "Unexpected device serial %s.\n", - debugstr_w(device_serial) ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + + dinput_test_get_device_hid_serial_string(device, device_serial); + ok( !wcscmp(test_devs[0].desc.instance_id, device_serial), "Unexpected device serial %s.\n", + debugstr_w(device_serial) ); + IDirectInputDevice8_Release(device); - IDirectInputDevice8_Release(device); - } stop_joystick_test_device( &test_devs[0] ); hr = dinput_test_create_device_instance( version, &guid_instances[0], &device ); @@ -6401,15 +6399,13 @@ static void test_joystick_instance_guid( DWORD version ) ok( hr == DIERR_DEVICENOTREG, "Unexpected hr %#lx.\n", hr ); hr = dinput_test_create_device_instance( version, &guid_instances[0], &device ); - todo_wine ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); - if (device) - { - dinput_test_get_device_hid_serial_string(device, device_serial); - ok( !wcscmp(test_devs[1].desc.instance_id, device_serial), "Unexpected device serial %s.\n", - debugstr_w(device_serial) ); + ok( hr == DI_OK, "Unexpected hr %#lx.\n", hr ); + + dinput_test_get_device_hid_serial_string(device, device_serial); + ok( !wcscmp(test_devs[1].desc.instance_id, device_serial), "Unexpected device serial %s.\n", + debugstr_w(device_serial) ); + IDirectInputDevice8_Release(device); - IDirectInputDevice8_Release(device); - } stop_joystick_test_device( &test_devs[1] ); done: -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10364