https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0f3133c308093d78975d9f...
commit 0f3133c308093d78975d9f34f38d0a4ed2cd97b3 Author: Hervé Poussineau hpoussin@reactos.org AuthorDate: Fri Apr 2 20:00:31 2021 +0200 Commit: Hervé Poussineau hpoussin@reactos.org 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,