From 1d17352ce275492554bb2fc06a227060017876e5 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sun, 29 Jul 2018 20:26:28 -0500 Subject: [PATCH] setupapi: Correctly implement SetupDiCreateDeviceInterfaceRegKey(). This family of functions manipulates the "Device Parameters" subkey, not its parent. Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/setupapi/devinst.c | 127 +++++++++++----------------------- dlls/setupapi/tests/devinst.c | 57 +++++++++++++++ 2 files changed, 97 insertions(+), 87 deletions(-) diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 8b97eb5b70e..44d2cb97684 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -76,6 +76,7 @@ static const WCHAR Enum[] = {'S','y','s','t','e','m','\\', 'E','n','u','m',0}; static const WCHAR DeviceDesc[] = {'D','e','v','i','c','e','D','e','s','c',0}; static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0}; +static const WCHAR DeviceParameters[] = {'D','e','v','i','c','e',' ','P','a','r','a','m','e','t','e','r','s',0}; static const WCHAR HardwareId[] = {'H','a','r','d','w','a','r','e','I','D',0}; static const WCHAR CompatibleIDs[] = {'C','o','m','p','a','t','i','b','l','e','I','d','s',0}; static const WCHAR Service[] = {'S','e','r','v','i','c','e',0}; @@ -2559,111 +2560,63 @@ static PWSTR SETUPDI_GetInstancePath(struct device_iface *iface) /*********************************************************************** * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@) */ -HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW( - HDEVINFO DeviceInfoSet, - PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, - DWORD Reserved, - REGSAM samDesired, - HINF InfHandle, - PCWSTR InfSectionName) +HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(HDEVINFO devinfo, + SP_DEVICE_INTERFACE_DATA *iface_data, DWORD reserved, REGSAM access, + HINF hinf, const WCHAR *section) { - struct DeviceInfoSet *set = DeviceInfoSet; - HKEY key = INVALID_HANDLE_VALUE, interfacesKey; - LONG l; + struct DeviceInfoSet *set = devinfo; + struct device_iface *iface; + HKEY refstr_key, params_key; + WCHAR *path; + LONG ret; - TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved, - samDesired, InfHandle, InfSectionName); + TRACE("%p %p %d %#x %p %s\n", devinfo, iface_data, reserved, access, hinf, + debugstr_w(section)); - if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE || + if (!devinfo || devinfo == INVALID_HANDLE_VALUE || set->magic != SETUP_DEVICE_INFO_SET_MAGIC) { SetLastError(ERROR_INVALID_HANDLE); return INVALID_HANDLE_VALUE; } - if (!DeviceInterfaceData || - DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || - !DeviceInterfaceData->Reserved) + if (!iface_data || iface_data->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || + !iface_data->Reserved) { SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } - if (InfHandle && !InfSectionName) + if (hinf && !section) { SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; } - if (!(l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, NULL, 0, - samDesired, NULL, &interfacesKey, NULL))) + + iface = (struct device_iface *)iface_data->Reserved; + if (!(path = get_refstr_key_path(iface))) { - HKEY parent; - WCHAR bracedGuidString[39]; - - SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, - bracedGuidString); - if (!(l = RegCreateKeyExW(interfacesKey, bracedGuidString, 0, NULL, 0, - samDesired, NULL, &parent, NULL))) - { - struct device_iface *ifaceInfo = - (struct device_iface *)DeviceInterfaceData->Reserved; - PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo); - PWSTR interfKeyName = HeapAlloc(GetProcessHeap(), 0, - (lstrlenW(ifaceInfo->symlink) + 1) * sizeof(WCHAR)); - HKEY interfKey; - WCHAR *ptr; - - lstrcpyW(interfKeyName, ifaceInfo->symlink); - if (lstrlenW(ifaceInfo->symlink) > 3) - { - interfKeyName[0] = '#'; - interfKeyName[1] = '#'; - interfKeyName[3] = '#'; - } - ptr = strchrW(interfKeyName, '\\'); - if (ptr) - *ptr = 0; - l = RegCreateKeyExW(parent, interfKeyName, 0, NULL, 0, - samDesired, NULL, &interfKey, NULL); - if (!l) - { - struct device *device = ifaceInfo->device; - - l = RegSetValueExW(interfKey, DeviceInstance, 0, REG_SZ, - (BYTE *)device->instanceId, - (lstrlenW(device->instanceId) + 1) * sizeof(WCHAR)); - if (!l) - { - if (instancePath) - { - LONG l; - - l = RegCreateKeyExW(interfKey, instancePath, 0, NULL, 0, - samDesired, NULL, &key, NULL); - if (l) - { - SetLastError(l); - key = INVALID_HANDLE_VALUE; - } - else if (InfHandle) - FIXME("INF section installation unsupported\n"); - } - } - else - SetLastError(l); - RegCloseKey(interfKey); - } - else - SetLastError(l); - HeapFree(GetProcessHeap(), 0, interfKeyName); - HeapFree(GetProcessHeap(), 0, instancePath); - RegCloseKey(parent); - } - else - SetLastError(l); - RegCloseKey(interfacesKey); + SetLastError(ERROR_OUTOFMEMORY); + return INVALID_HANDLE_VALUE; } - else - SetLastError(l); - return key; + + ret = RegCreateKeyExW(HKEY_LOCAL_MACHINE, path, 0, NULL, 0, 0, NULL, + &refstr_key, NULL); + heap_free(path); + if (ret) + { + SetLastError(ret); + return INVALID_HANDLE_VALUE; + } + + ret = RegCreateKeyExW(refstr_key, DeviceParameters, 0, NULL, 0, access, + NULL, ¶ms_key, NULL); + RegCloseKey(refstr_key); + if (ret) + { + SetLastError(ret); + return INVALID_HANDLE_VALUE; + } + + return params_key; } /*********************************************************************** diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 2bb8027534d..95d0dc40ea8 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -1376,6 +1376,62 @@ static void test_devnode(void) SetupDiDestroyDeviceInfoList(set); } +static void test_device_interface_key(void) +{ + const char keypath[] = "System\\CurrentControlSet\\Control\\DeviceClasses\\" + "{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\" + "##?#ROOT#LEGACY_BOGUS#0001#{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; + SP_DEVICE_INTERFACE_DATA iface = { sizeof(iface) }; + SP_DEVINFO_DATA devinfo = { sizeof(devinfo) }; + HKEY parent, key, dikey; + char buffer[5]; + HDEVINFO set; + LONG sz, ret; + + set = SetupDiGetClassDevsA(NULL, NULL, 0, DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevs failed: %#x\n", GetLastError()); + + ret = SetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0001", &guid, NULL, NULL, 0, &devinfo); + ok(ret, "SetupDiCreateDeviceInfo failed: %#x\n", GetLastError()); + + ret = SetupDiCreateDeviceInterfaceA(set, &devinfo, &guid, NULL, 0, &iface); + ok(ret, "SetupDiCreateDeviceInterface failed: %#x\n", GetLastError()); + + ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &parent); + ok(!ret, "failed to open device parent key: %u\n", ret); + + ret = RegOpenKeyA(parent, "#\\Device Parameters", &key); + ok(ret == ERROR_FILE_NOT_FOUND, "key shouldn't exist\n"); + + dikey = SetupDiCreateDeviceInterfaceRegKeyA(set, &iface, 0, KEY_ALL_ACCESS, NULL, NULL); + ok(dikey != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError()); + + ret = RegOpenKeyA(parent, "#\\Device Parameters", &key); + ok(!ret, "key should exist: %u\n", ret); + + ret = RegSetValueA(key, NULL, REG_SZ, "test", 5); + sz = sizeof(buffer); + ret = RegQueryValueA(dikey, NULL, buffer, &sz); + ok(!ret, "RegQueryValue failed: %u\n", ret); + ok(!strcmp(buffer, "test"), "got wrong data %s\n", buffer); + + RegCloseKey(dikey); + RegCloseKey(key); + + ret = SetupDiDeleteDeviceInterfaceRegKey(set, &iface, 0); +todo_wine + ok(ret, "got error %u\n", GetLastError()); + + ret = RegOpenKeyA(parent, "#\\Device Parameters", &key); +todo_wine + ok(ret == ERROR_FILE_NOT_FOUND, "key shouldn't exist\n"); + + RegCloseKey(parent); + SetupDiRemoveDeviceInterface(set, &iface); + SetupDiRemoveDevice(set, &devinfo); + SetupDiDestroyDeviceInfoList(set); +} + START_TEST(devinst) { HKEY hkey; @@ -1414,4 +1470,5 @@ START_TEST(devinst) testDeviceRegistryPropertyW(); testSetupDiGetINFClassA(); test_devnode(); + test_device_interface_key(); }