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