https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0f3133c308093d78975d9f34f38d0a4ed2cd97b3

commit 0f3133c308093d78975d9f34f38d0a4ed2cd97b3
Author:     Hervé Poussineau <[email protected]>
AuthorDate: Fri Apr 2 20:00:31 2021 +0200
Commit:     Hervé Poussineau <[email protected]>
CommitDate: Fri Apr 2 21:41:09 2021 +0200

    [SETUPAPI] Use CM_* functions to get list of devices
    
    - this prevents duplicating the code with umpnpmgr::PNP_GetDeviceList
    - we can enumerate devices on other computers
    
    This is part of the bugfix for CORE-17529
---
 dll/win32/setupapi/devclass.c         | 280 ++++++++++------------------------
 dll/win32/setupapi/devinst.c          |   2 +-
 dll/win32/setupapi/setupapi_private.h |   3 +
 3 files changed, 86 insertions(+), 199 deletions(-)

diff --git a/dll/win32/setupapi/devclass.c b/dll/win32/setupapi/devclass.c
index 86fc33d281b..b8531b0093d 100644
--- a/dll/win32/setupapi/devclass.c
+++ b/dll/win32/setupapi/devclass.c
@@ -117,231 +117,115 @@ SetupDiDestroyClassImageList(
     return ret;
 }
 
-/***********************************************************************
- *             SETUP_CreateDevicesListFromEnumerator
- *
- * PARAMS
- *   list [IO] Device info set to fill with discovered devices.
- *   pClassGuid [I] If specified, only devices which belong to this class will 
be added.
- *   Enumerator [I] Location to search devices to add.
- *   hEnumeratorKey [I] Registry key corresponding to Enumerator key. Must 
have KEY_ENUMERATE_SUB_KEYS right.
- *
- * RETURNS
- *   Success: ERROR_SUCCESS.
- *   Failure: an error code.
- */
-static LONG
-SETUP_CreateDevicesListFromEnumerator(
+LONG
+SETUP_CreateDevicesList(
     IN OUT struct DeviceInfoSet *list,
-    IN CONST GUID *pClassGuid OPTIONAL,
-    IN LPCWSTR Enumerator,
-    IN HKEY hEnumeratorKey) /* handle to Enumerator registry key */
+    IN PCWSTR MachineName OPTIONAL,
+    IN CONST GUID *Class OPTIONAL,
+    IN PCWSTR Enumerator OPTIONAL)
 {
-    HKEY hDeviceIdKey = NULL, hInstanceIdKey;
-    WCHAR KeyBuffer[MAX_PATH];
-    WCHAR InstancePath[MAX_PATH];
-    LPWSTR pEndOfInstancePath; /* Pointer into InstancePath buffer */
+    PWCHAR Buffer = NULL;
+    DWORD BufferLength = 4096;
+    PCWSTR InstancePath;
     struct DeviceInfo *deviceInfo;
-    DWORD i = 0, j;
-    DWORD dwLength, dwRegType;
-    DWORD rc;
+    WCHAR ClassGuidBuffer[MAX_GUID_STRING_LEN];
+    DWORD ClassGuidBufferSize;
+    GUID ClassGuid;
+    DEVINST dnDevInst;
+    CONFIGRET cr;
 
-    /* Enumerate device IDs (subkeys of hEnumeratorKey) */
-    while (TRUE)
-    {
-        dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
-        rc = RegEnumKeyExW(hEnumeratorKey, i, KeyBuffer, &dwLength, NULL, 
NULL, NULL, NULL);
-        if (rc == ERROR_NO_MORE_ITEMS)
-            break;
-        if (rc != ERROR_SUCCESS)
-            goto cleanup;
-        i++;
-
-        /* Open device id sub key */
-        if (hDeviceIdKey != NULL)
-            RegCloseKey(hDeviceIdKey);
-        rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, 
KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey);
-        if (rc != ERROR_SUCCESS)
-            goto cleanup;
+    Buffer = HeapAlloc(GetProcessHeap(), 0, BufferLength);
+    if (!Buffer)
+       return ERROR_NOT_ENOUGH_MEMORY;
 
-        if (FAILED(StringCchCopyW(InstancePath, _countof(InstancePath), 
Enumerator)) ||
-            FAILED(StringCchCatW(InstancePath, _countof(InstancePath), 
BackSlash))  ||
-            FAILED(StringCchCatW(InstancePath, _countof(InstancePath), 
KeyBuffer))  ||
-            FAILED(StringCchCatW(InstancePath, _countof(InstancePath), 
BackSlash)))
+    do
+    {
+        cr = CM_Get_Device_ID_List_ExW(Enumerator,
+                                       Buffer,
+                                       BufferLength,
+                                       Enumerator ? 
CM_GETIDLIST_FILTER_ENUMERATOR : CM_GETIDLIST_FILTER_NONE,
+                                       list->hMachine);
+        if (cr == CR_BUFFER_SMALL)
         {
-            rc = ERROR_GEN_FAILURE;
-            goto cleanup;
+            if (Buffer)
+                HeapFree(GetProcessHeap(), 0, Buffer);
+            BufferLength *= 2;
+            Buffer = HeapAlloc(GetProcessHeap(), 0, BufferLength);
+            if (!Buffer)
+                return ERROR_NOT_ENOUGH_MEMORY;
         }
-
-        pEndOfInstancePath = &InstancePath[strlenW(InstancePath)];
-
-        /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
-        j = 0;
-        while (TRUE)
+        else if (cr != CR_SUCCESS)
         {
-            GUID KeyGuid;
+            TRACE("CM_Get_Device_ID_List_ExW() failed with status 0x%x\n", cr);
+            if (Buffer)
+                HeapFree(GetProcessHeap(), 0, Buffer);
+            return GetErrorCodeFromCrCode(cr);
+        }
+    }
+    while (cr != CR_SUCCESS);
 
-            dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
-            rc = RegEnumKeyExW(hDeviceIdKey, j, KeyBuffer, &dwLength, NULL, 
NULL, NULL, NULL);
-            if (rc == ERROR_NO_MORE_ITEMS)
-                break;
-            if (rc != ERROR_SUCCESS)
-                goto cleanup;
-            j++;
+    for (InstancePath = Buffer; *InstancePath != UNICODE_NULL; InstancePath += 
wcslen(InstancePath) + 1)
+    {
+        /* Check that device really exists */
+        TRACE("Checking %S\n", InstancePath);
+        cr = CM_Locate_DevNode_Ex(&dnDevInst,
+                                  (DEVINSTID_W)InstancePath,
+                                  CM_LOCATE_DEVNODE_NORMAL,
+                                  list->hMachine);
+        if (cr != CR_SUCCESS)
+        {
+            ERR("CM_Locate_DevNode_ExW('%S') failed with status 0x%x\n", 
InstancePath, cr);
+            continue;
+        }
 
-            /* Open instance id sub key */
-            rc = RegOpenKeyExW(hDeviceIdKey, KeyBuffer, 0, KEY_QUERY_VALUE, 
&hInstanceIdKey);
-            if (rc != ERROR_SUCCESS)
-                goto cleanup;
-            *pEndOfInstancePath = '\0';
-            strcatW(InstancePath, KeyBuffer);
-
-            /* Read ClassGUID value */
-            dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
-            rc = RegQueryValueExW(hInstanceIdKey, ClassGUID, NULL, &dwRegType, 
(LPBYTE)KeyBuffer, &dwLength);
-            RegCloseKey(hInstanceIdKey);
-            if (rc == ERROR_FILE_NOT_FOUND)
+        /* Retrieve GUID of this device */
+        if (Class)
+        {
+            ClassGuidBufferSize = sizeof(ClassGuidBuffer);
+            cr = CM_Get_DevNode_Registry_Property_ExW(dnDevInst,
+                                                      CM_DRP_CLASSGUID,
+                                                      NULL,
+                                                      ClassGuidBuffer,
+                                                      &ClassGuidBufferSize,
+                                                      0,
+                                                      list->hMachine);
+            if (cr == CR_SUCCESS)
             {
-                if (pClassGuid)
-                    /* Skip this bad entry as we can't verify it */
+                ClassGuidBuffer[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace 
the } by a NULL character */
+                if (UuidFromStringW(&ClassGuidBuffer[1], &ClassGuid) != 
RPC_S_OK)
+                {
+                    /* Bad GUID, skip the entry */
+                    ERR("Invalid ClassGUID '%S' for device %S\n", 
ClassGuidBuffer, InstancePath);
                     continue;
-                /* Set a default GUID for this device */
-                memcpy(&KeyGuid, &GUID_NULL, sizeof(GUID));
-            }
-            else if (rc != ERROR_SUCCESS)
-            {
-                goto cleanup;
-            }
-            else if (dwRegType != REG_SZ || dwLength < MAX_GUID_STRING_LEN * 
sizeof(WCHAR))
-            {
-                rc = ERROR_GEN_FAILURE;
-                goto cleanup;
+                }
             }
             else
             {
-                KeyBuffer[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace the } by 
a NULL character */
-                if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK)
-                    /* Bad GUID, skip the entry */
-                    continue;
+                TRACE("Using default class GUID_NULL for device %S\n", 
InstancePath);
+                memcpy(&ClassGuid, &GUID_NULL, sizeof(GUID));
             }
 
-            if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid))
+            if (!IsEqualIID(&ClassGuid, Class))
             {
-                /* Skip this entry as it is not the right device class */
+                TRACE("Skipping %S due to wrong class GUID\n", InstancePath);
                 continue;
             }
-
-            /* Add the entry to the list */
-            if (!CreateDeviceInfo(list, InstancePath, &KeyGuid, &deviceInfo))
-            {
-                rc = GetLastError();
-                goto cleanup;
-            }
-            TRACE("Adding '%s' to device info set %p\n", 
debugstr_w(InstancePath), list);
-            InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
         }
-    }
-
-    rc = ERROR_SUCCESS;
-
-cleanup:
-    if (hDeviceIdKey != NULL)
-        RegCloseKey(hDeviceIdKey);
-    return rc;
-}
-
-LONG
-SETUP_CreateDevicesList(
-    IN OUT struct DeviceInfoSet *list,
-    IN PCWSTR MachineName OPTIONAL,
-    IN CONST GUID *Class OPTIONAL,
-    IN PCWSTR Enumerator OPTIONAL)
-{
-    HKEY HKLM = HKEY_LOCAL_MACHINE;
-    HKEY hEnumKey = NULL;
-    HKEY hEnumeratorKey = NULL;
-    WCHAR KeyBuffer[MAX_PATH];
-    DWORD i;
-    DWORD dwLength;
-    DWORD rc;
-
-    if (Class && IsEqualIID(Class, &GUID_NULL))
-        Class = NULL;
-
-    /* Open Enum key (if applicable) */
-    if (MachineName != NULL)
-    {
-        rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
-        if (rc != ERROR_SUCCESS)
-            goto cleanup;
-    }
-
-    rc = RegOpenKeyExW(
-        HKLM,
-        REGSTR_PATH_SYSTEMENUM,
-        0,
-        KEY_ENUMERATE_SUB_KEYS,
-        &hEnumKey);
-    if (rc != ERROR_SUCCESS)
-        goto cleanup;
 
-    /* If enumerator is provided, call directly 
SETUP_CreateDevicesListFromEnumerator.
-     * Else, enumerate all enumerators and call 
SETUP_CreateDevicesListFromEnumerator
-     * for each one.
-     */
-    if (Enumerator)
-    {
-        rc = RegOpenKeyExW(
-            hEnumKey,
-            Enumerator,
-            0,
-            KEY_ENUMERATE_SUB_KEYS,
-            &hEnumeratorKey);
-        if (rc != ERROR_SUCCESS)
+        /* Good! Create a device info element */
+        if (!CreateDeviceInfo(list, InstancePath, &ClassGuid, &deviceInfo))
         {
-            if (rc == ERROR_FILE_NOT_FOUND)
-                rc = ERROR_INVALID_DATA;
-            goto cleanup;
+            ERR("Failed to create info for %S\n", InstancePath);
+            HeapFree(GetProcessHeap(), 0, Buffer);
+            return GetLastError();
         }
-        rc = SETUP_CreateDevicesListFromEnumerator(list, Class, Enumerator, 
hEnumeratorKey);
-    }
-    else
-    {
-        /* Enumerate enumerators */
-        i = 0;
-        while (TRUE)
-        {
-            dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
-            rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, 
NULL, NULL);
-            if (rc == ERROR_NO_MORE_ITEMS)
-                break;
-            else if (rc != ERROR_SUCCESS)
-                goto cleanup;
-            i++;
-
-            /* Open sub key */
-            if (hEnumeratorKey != NULL)
-                RegCloseKey(hEnumeratorKey);
-            rc = RegOpenKeyExW(hEnumKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, 
&hEnumeratorKey);
-            if (rc != ERROR_SUCCESS)
-                goto cleanup;
 
-            /* Call SETUP_CreateDevicesListFromEnumerator */
-            rc = SETUP_CreateDevicesListFromEnumerator(list, Class, KeyBuffer, 
hEnumeratorKey);
-            if (rc != ERROR_SUCCESS)
-                goto cleanup;
-        }
-        rc = ERROR_SUCCESS;
+        TRACE("Adding device %s to list\n", debugstr_w(InstancePath));
+        InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
     }
 
-cleanup:
-    if (HKLM != HKEY_LOCAL_MACHINE)
-        RegCloseKey(HKLM);
-    if (hEnumKey != NULL)
-        RegCloseKey(hEnumKey);
-    if (hEnumeratorKey != NULL)
-        RegCloseKey(hEnumeratorKey);
-    return rc;
+    HeapFree(GetProcessHeap(), 0, Buffer);
+    return ERROR_SUCCESS;
 }
 
 static BOOL
diff --git a/dll/win32/setupapi/devinst.c b/dll/win32/setupapi/devinst.c
index 167d8062c98..d629e138f1d 100644
--- a/dll/win32/setupapi/devinst.c
+++ b/dll/win32/setupapi/devinst.c
@@ -88,7 +88,7 @@ static void SETUPDI_GuidToString(const GUID *guid, LPWSTR 
guidStr)
         guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
 }
 
-static DWORD
+DWORD
 GetErrorCodeFromCrCode(const IN CONFIGRET cr)
 {
   switch (cr)
diff --git a/dll/win32/setupapi/setupapi_private.h 
b/dll/win32/setupapi/setupapi_private.h
index 63c391867bb..fb758142645 100644
--- a/dll/win32/setupapi/setupapi_private.h
+++ b/dll/win32/setupapi/setupapi_private.h
@@ -298,6 +298,9 @@ UINT CALLBACK QUEUE_callback_WtoA( void *context, UINT 
notification, UINT_PTR, U
 
 /* devinst.c */
 
+DWORD
+GetErrorCodeFromCrCode(const IN CONFIGRET cr);
+
 BOOL
 CreateDeviceInfo(
     IN struct DeviceInfoSet *list,

Reply via email to