Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/setupapi/devinst.c | 159 +++++++++++++++++-----------------
dlls/setupapi/tests/devinst.c | 108 ++++++++---------------
2 files changed, 116 insertions(+), 151 deletions(-)
diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c
index 55746562c8..855fa92d31 100644
--- a/dlls/setupapi/devinst.c
+++ b/dlls/setupapi/devinst.c
@@ -492,30 +492,85 @@ static HKEY SETUPDI_CreateDevKey(struct device *device)
return key;
}
-static HKEY SETUPDI_CreateDrvKey(struct device *device)
+static HKEY open_driver_key(struct device *device, REGSAM access)
{
- static const WCHAR slash[] = { '\\',0 };
- WCHAR classKeyPath[MAX_PATH];
- HKEY classKey, key = INVALID_HANDLE_VALUE;
+ HKEY class_key, key;
+ WCHAR path[50];
+ DWORD size = sizeof(path);
LONG l;
- lstrcpyW(classKeyPath, ControlClass);
- lstrcatW(classKeyPath, slash);
- SETUPDI_GuidToString(&device->set->ClassGuid,
- classKeyPath + lstrlenW(classKeyPath));
- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
- KEY_ALL_ACCESS, NULL, &classKey, NULL);
- if (!l)
+ if ((l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, ControlClass, 0, NULL, 0,
+ KEY_CREATE_SUB_KEY, NULL, &class_key, NULL)))
{
- static const WCHAR fmt[] = { '%','0','4','u',0 };
- WCHAR devId[10];
-
- sprintfW(devId, fmt, device->devnode);
- RegCreateKeyExW(classKey, devId, 0, NULL, 0, KEY_READ | KEY_WRITE,
- NULL, &key, NULL);
- RegCloseKey(classKey);
+ ERR("Failed to open driver class root key, error %u.\n", l);
+ SetLastError(l);
+ return INVALID_HANDLE_VALUE;
}
- return key;
+
+ if (!(l = RegGetValueW(device->key, NULL, Driver, RRF_RT_REG_SZ, NULL, path, &size)))
+ {
+ if (!(l = RegOpenKeyExW(class_key, path, 0, access, &key)))
+ {
+ RegCloseKey(class_key);
+ return key;
+ }
+ ERR("Failed to open driver key, error %u.\n", l);
+ }
+
+ RegCloseKey(class_key);
+ SetLastError(ERROR_KEY_DOES_NOT_EXIST);
+ return INVALID_HANDLE_VALUE;
+}
+
+static HKEY create_driver_key(struct device *device)
+{
+ static const WCHAR formatW[] = {'%','0','4','u',0};
+ static const WCHAR slash[] = { '\\',0 };
+ HKEY class_key, key;
+ WCHAR path[50];
+ LONG l;
+
+ if ((key = open_driver_key(device, KEY_READ | KEY_WRITE)) != INVALID_HANDLE_VALUE)
+ return key;
+
+ if ((l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, ControlClass, 0, NULL, 0,
+ KEY_CREATE_SUB_KEY, NULL, &class_key, NULL)))
+ {
+ ERR("Failed to open driver class root key, error %u.\n", l);
+ SetLastError(l);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ SETUPDI_GuidToString(&device->class, path);
+ strcatW(path, slash);
+ sprintfW(path + strlenW(path), formatW, device->devnode);
+ if (!(l = RegCreateKeyExW(class_key, path, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &key, NULL)))
+ {
+ RegSetValueExW(device->key, Driver, 0, REG_SZ, (BYTE *)path, strlenW(path) * sizeof(WCHAR));
+ RegCloseKey(class_key);
+ return key;
+ }
+ ERR("Failed to create driver key, error %u.\n", l);
+ RegCloseKey(class_key);
+ SetLastError(l);
+ return INVALID_HANDLE_VALUE;
+}
+
+static BOOL delete_driver_key(struct device *device)
+{
+ HKEY key;
+ LONG l;
+
+ if ((key = open_driver_key(device, KEY_READ | KEY_WRITE)) != INVALID_HANDLE_VALUE)
+ {
+ l = RegDeleteKeyW(key, emptyW);
+ RegCloseKey(key);
+
+ SetLastError(l);
+ return !l;
+ }
+
+ return FALSE;
}
struct PropertyMapEntry
@@ -1367,7 +1422,7 @@ HKEY WINAPI SetupDiCreateDevRegKeyW(HDEVINFO devinfo, SP_DEVINFO_DATA *device_da
key = SETUPDI_CreateDevKey(device);
break;
case DIREG_DRV:
- key = SETUPDI_CreateDrvKey(device);
+ key = create_driver_key(device);
break;
default:
WARN("unknown KeyType %d\n", KeyType);
@@ -3358,36 +3413,6 @@ static HKEY SETUPDI_OpenDevKey(struct device *device, REGSAM samDesired)
return key;
}
-static HKEY SETUPDI_OpenDrvKey(struct device *device, REGSAM samDesired)
-{
- static const WCHAR slash[] = { '\\',0 };
- WCHAR classKeyPath[MAX_PATH];
- HKEY classKey, key = INVALID_HANDLE_VALUE;
- LONG l;
-
- lstrcpyW(classKeyPath, ControlClass);
- lstrcatW(classKeyPath, slash);
- SETUPDI_GuidToString(&device->set->ClassGuid,
- classKeyPath + lstrlenW(classKeyPath));
- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
- KEY_ALL_ACCESS, NULL, &classKey, NULL);
- if (!l)
- {
- static const WCHAR fmt[] = { '%','0','4','u',0 };
- WCHAR devId[10];
-
- sprintfW(devId, fmt, device->devnode);
- l = RegOpenKeyExW(classKey, devId, 0, samDesired, &key);
- RegCloseKey(classKey);
- if (l)
- {
- SetLastError(ERROR_KEY_DOES_NOT_EXIST);
- return INVALID_HANDLE_VALUE;
- }
- }
- return key;
-}
-
/***********************************************************************
* SetupDiOpenDevRegKey (SETUPAPI.@)
*/
@@ -3427,7 +3452,7 @@ HKEY WINAPI SetupDiOpenDevRegKey(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data,
key = SETUPDI_OpenDevKey(device, samDesired);
break;
case DIREG_DRV:
- key = SETUPDI_OpenDrvKey(device, samDesired);
+ key = open_driver_key(device, samDesired);
break;
default:
WARN("unknown KeyType %d\n", KeyType);
@@ -3453,34 +3478,6 @@ static BOOL SETUPDI_DeleteDevKey(struct device *device)
return ret;
}
-static BOOL SETUPDI_DeleteDrvKey(struct device *device)
-{
- static const WCHAR slash[] = { '\\',0 };
- WCHAR classKeyPath[MAX_PATH];
- HKEY classKey;
- LONG l;
- BOOL ret = FALSE;
-
- lstrcpyW(classKeyPath, ControlClass);
- lstrcatW(classKeyPath, slash);
- SETUPDI_GuidToString(&device->set->ClassGuid,
- classKeyPath + lstrlenW(classKeyPath));
- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
- KEY_ALL_ACCESS, NULL, &classKey, NULL);
- if (!l)
- {
- static const WCHAR fmt[] = { '%','0','4','u',0 };
- WCHAR devId[10];
-
- sprintfW(devId, fmt, device->devnode);
- ret = RegDeleteTreeW(classKey, devId);
- RegCloseKey(classKey);
- }
- else
- SetLastError(l);
- return ret;
-}
-
/***********************************************************************
* SetupDiDeleteDevRegKey (SETUPAPI.@)
*/
@@ -3520,12 +3517,12 @@ BOOL WINAPI SetupDiDeleteDevRegKey(HDEVINFO devinfo, SP_DEVINFO_DATA *device_dat
ret = SETUPDI_DeleteDevKey(device);
break;
case DIREG_DRV:
- ret = SETUPDI_DeleteDrvKey(device);
+ ret = delete_driver_key(device);
break;
case DIREG_BOTH:
ret = SETUPDI_DeleteDevKey(device);
if (ret)
- ret = SETUPDI_DeleteDrvKey(device);
+ ret = delete_driver_key(device);
break;
default:
WARN("unknown KeyType %d\n", KeyType);
diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c
index 4abc188ea4..e90f4166b7 100644
--- a/dlls/setupapi/tests/devinst.c
+++ b/dlls/setupapi/tests/devinst.c
@@ -37,72 +37,6 @@
static GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}};
static GUID guid2 = {0x6a55b5a5, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}};
-static LSTATUS devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
-{
- LONG ret;
- DWORD dwMaxSubkeyLen, dwMaxValueLen;
- DWORD dwMaxLen, dwSize;
- WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
- HKEY hSubKey = hKey;
-
- if(lpszSubKey)
- {
- ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
- if (ret) return ret;
- }
-
- /* Get highest length for keys, values */
- ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
- &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
- if (ret) goto cleanup;
-
- dwMaxSubkeyLen++;
- dwMaxValueLen++;
- dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
- if (dwMaxLen > ARRAY_SIZE(szNameBuf))
- {
- /* Name too big: alloc a buffer for it */
- if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
- {
- ret = ERROR_NOT_ENOUGH_MEMORY;
- goto cleanup;
- }
- }
-
-
- /* Recursively delete all the subkeys */
- while (TRUE)
- {
- dwSize = dwMaxLen;
- if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
- NULL, NULL, NULL)) break;
-
- ret = devinst_RegDeleteTreeW(hSubKey, lpszName);
- if (ret) goto cleanup;
- }
-
- if (lpszSubKey)
- ret = RegDeleteKeyW(hKey, lpszSubKey);
- else
- while (TRUE)
- {
- dwSize = dwMaxLen;
- if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
- NULL, NULL, NULL, NULL)) break;
-
- ret = RegDeleteValueW(hKey, lpszName);
- if (ret) goto cleanup;
- }
-
-cleanup:
- /* Free buffer if allocated */
- if (lpszName != szNameBuf)
- HeapFree( GetProcessHeap(), 0, lpszName);
- if(lpszSubKey)
- RegCloseKey(hSubKey);
- return ret;
-}
-
static void test_create_device_list_ex(void)
{
static const WCHAR machine[] = { 'd','u','m','m','y',0 };
@@ -776,9 +710,11 @@ static void test_device_key(void)
'E','n','u','m','\\','R','o','o','t','\\',
'L','E','G','A','C','Y','_','B','O','G','U','S',0};
SP_DEVINFO_DATA device = {sizeof(device)};
+ char driver_path[50], data[4];
+ HKEY class_key, key;
+ DWORD size;
BOOL ret;
HDEVINFO set;
- HKEY key = NULL;
LONG res;
SetLastError(0xdeadbeef);
@@ -836,9 +772,13 @@ static void test_device_key(void)
ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
ok(GetLastError() == ERROR_KEY_DOES_NOT_EXIST, "Got unexpected error %#x.\n", GetLastError());
+ ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DRIVER, NULL,
+ (BYTE *)driver_path, sizeof(driver_path), NULL);
+ ok(!ret, "Expected failure.\n");
+ ok(GetLastError() == ERROR_INVALID_DATA, "Got unexpected error %#x.\n", GetLastError());
+
SetLastError(0xdeadbeef);
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key);
-todo_wine
ok(res == ERROR_FILE_NOT_FOUND, "Key should not exist.\n");
RegCloseKey(key);
@@ -852,6 +792,17 @@ todo_wine
ok(!RegOpenKeyW(HKEY_LOCAL_MACHINE, classKey, &key), "Key should exist.\n");
RegCloseKey(key);
+ res = RegOpenKeyA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Class", &class_key);
+ ok(!res, "Failed to open class key, error %u.\n", res);
+
+ ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DRIVER, NULL,
+ (BYTE *)driver_path, sizeof(driver_path), NULL);
+ ok(ret, "Failed to get driver property, error %#x.\n", GetLastError());
+ res = RegOpenKeyA(class_key, driver_path, &key);
+ ok(!res, "Failed to open driver key, error %u.\n", res);
+ RegSetValueExA(key, "foo", 0, REG_SZ, (BYTE *)"bar", sizeof("bar"));
+ RegCloseKey(key);
+
SetLastError(0xdeadbeef);
key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, 0);
todo_wine {
@@ -862,15 +813,32 @@ todo_wine {
key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ);
ok(key != INVALID_HANDLE_VALUE, "Failed to open device key, error %#x.\n", GetLastError());
+ size = sizeof(data);
+ res = RegQueryValueExA(key, "foo", NULL, NULL, (BYTE *)data, &size);
+ ok(!res, "Failed to get value, error %u.\n", res);
+ ok(!strcmp(data, "bar"), "Got wrong data %s.\n", data);
RegCloseKey(key);
+
+ ret = SetupDiDeleteDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV);
+ ok(ret, "Failed to delete device key, error %#x.\n", GetLastError());
+
+ res = RegOpenKeyA(class_key, driver_path, &key);
+ ok(res == ERROR_FILE_NOT_FOUND, "Key should not exist.\n");
+
+ key = SetupDiOpenDevRegKey(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DRV, 0);
+ ok(key == INVALID_HANDLE_VALUE, "Expected failure.\n");
+ ok(GetLastError() == ERROR_KEY_DOES_NOT_EXIST, "Got unexpected error %#x.\n", GetLastError());
+
+ RegCloseKey(class_key);
}
ret = SetupDiRemoveDevice(set, &device);
ok(ret, "Failed to remove device, error %#x.\n", GetLastError());
SetupDiDestroyDeviceInfoList(set);
- /* remove once Wine is fixed */
- devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey);
+ /* Vista+ deletes the key automatically. */
+ res = RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey);
+ ok(!res || res == ERROR_FILE_NOT_FOUND, "Failed to delete class key, error %u.\n", res);
}
static void test_register_device_iface(void)
--
2.17.1