This fixes SDL3 wrongly using their HIDAPI backend for XInput devices on Wine due to a case-sensitive check for `&IG_`.
From: Arkadiusz Hiler ahiler@codeweavers.com
This fixes SDL3 wrongly using their HIDAPI backend for XInput devices on Wine due to a case-sensitive check for `&IG_`. --- dlls/cfgmgr32/tests/Makefile.in | 2 +- dlls/cfgmgr32/tests/cfgmgr32.c | 41 +++++++++++++++++++++++++++++++++ dlls/setupapi/devinst.c | 20 +++++++--------- 3 files changed, 50 insertions(+), 13 deletions(-)
diff --git a/dlls/cfgmgr32/tests/Makefile.in b/dlls/cfgmgr32/tests/Makefile.in index 64a01ccf492..90f5ac496a3 100644 --- a/dlls/cfgmgr32/tests/Makefile.in +++ b/dlls/cfgmgr32/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = cfgmgr32.dll -IMPORTS = cfgmgr32 setupapi ole32 uuid +IMPORTS = cfgmgr32 setupapi ole32 uuid advapi32
SOURCES = \ cfgmgr32.c diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index 02741d0d963..ff9b45b760d 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -365,6 +365,46 @@ static void test_CM_Register_Notification( void ) } }
+static void check_device_path_casing(const WCHAR *original_path) +{ + HKEY current_key, tmp; + WCHAR *path = wcsdup(original_path); + WCHAR key_name[MAX_PATH]; + WCHAR separator[] = L"#"; + WCHAR *token, *context = NULL; + LSTATUS ret; + DWORD i; + + ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SYSTEM\CurrentControlSet\Enum", ¤t_key); + ok(!ret, "Failed to open enum key: %#lx.\n", ret); + + token = wcstok_s(path + 4, separator, &context); /* skip \?\ */ + while (token) + { + if (token[0] == L'{' && wcslen(token) == 38) break; /* reached GUID part, done */ + + i = 0; + while (!(ret = RegEnumKeyW(current_key, i++, key_name, ARRAY_SIZE(key_name)))) + { + if(!wcscmp(token, key_name)) + { + ret = RegOpenKeyW(current_key, token, &tmp); + ok(!ret, "Failed to open registry key %s: %#lx.\n", debugstr_w(token), ret); + RegCloseKey(current_key); + current_key = tmp; + break; + } + } + ok(!ret, "Failed to find %s in registry: %#lx.\n", debugstr_w(token), ret); + if (ret) break; + + token = wcstok_s(NULL, separator, &context); + } + + RegCloseKey(current_key); + free(path); +} + static void test_CM_Get_Device_Interface_List(void) { BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)]; @@ -420,6 +460,7 @@ static void test_CM_Get_Device_Interface_List(void) { DEVPROP_BOOLEAN val = DEVPROP_FALSE;
+ check_device_path_casing(p); set = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); ok(set != INVALID_HANDLE_VALUE, "got %p.\n", set); bret = SetupDiOpenDeviceInterfaceW(set, p, 0, &iface); diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 066bd6f09c2..f05b8054e39 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -407,8 +407,6 @@ static LPWSTR SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId, } }
- CharLowerW(ret); - return ret; }
@@ -3037,6 +3035,8 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(HDEVINFO devinfo, SP_DEVICE_INTERFA else DeviceInterfaceDetailData->DevicePath[0] = '\0';
+ CharLowerA(DeviceInterfaceDetailData->DevicePath); + ret = TRUE; } else @@ -3095,6 +3095,8 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(HDEVINFO devinfo, SP_DEVICE_INTERFA else DeviceInterfaceDetailData->DevicePath[0] = '\0';
+ CharLowerW(DeviceInterfaceDetailData->DevicePath); + ret = TRUE; } else @@ -4883,12 +4885,9 @@ static CONFIGRET get_device_interface_list(const GUID *class_guid, DEVINSTID_W d { const ULONG supported_flags = CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES;
- BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)]; SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; - SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_data; SP_DEVINFO_DATA device = { sizeof(device) }; ULONG query_flags = DIGCF_DEVICEINTERFACE; - CONFIGRET ret = CR_SUCCESS; unsigned int i, id_len; HDEVINFO set; ULONG needed; @@ -4915,15 +4914,12 @@ static CONFIGRET get_device_interface_list(const GUID *class_guid, DEVINSTID_W d if (set == INVALID_HANDLE_VALUE) return CR_SUCCESS;
- iface_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer; - iface_data->cbSize = sizeof(*iface_data); - p = buffer; for (i = 0; SetupDiEnumDeviceInterfaces(set, NULL, class_guid, i, &iface); ++i) { - ret = SetupDiGetDeviceInterfaceDetailW(set, &iface, iface_data, sizeof(iface_detail_buffer), NULL, &device); - if (!ret) continue; - id_len = wcslen(iface_data->DevicePath) + 1; + struct device_iface *device_iface; + device_iface = get_device_iface(set, &iface); + id_len = wcslen(device_iface->symlink) + 1; needed += id_len; if (buffer) { @@ -4933,7 +4929,7 @@ static CONFIGRET get_device_interface_list(const GUID *class_guid, DEVINSTID_W d *buffer = 0; return CR_BUFFER_SMALL; } - memcpy(p, iface_data->DevicePath, sizeof(*p) * id_len); + memcpy(p, device_iface->symlink, sizeof(*p) * id_len); p += id_len; } }
SDL code in question: https://github.com/libsdl-org/SDL/blob/release-3.2.16/src/hidapi/windows/hid...
At first I thought cfgmgr32 may be doing the opposite of SetupAPI and just force-uppercase everything, but during the course of writing tests turns out casing is used in the registry is preserved.