[PATCH v2 1/4] setupapi: Store the path to the driver key in the device key.

Zebediah Figura z.figura12 at gmail.com
Tue Jan 22 22:10:29 CST 2019


Signed-off-by: Zebediah Figura <z.figura12 at 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




More information about the wine-devel mailing list