https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a9b88efa7c12334482fbc…
commit a9b88efa7c12334482fbc8ffb3b386bf8d316bf9
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Sat Dec 29 22:08:35 2018 +0100
Commit: Eric Kohl <eric.kohl(a)reactos.org>
CommitDate: Sat Dec 29 22:13:32 2018 +0100
[UMPNPMGR] PNP_GetDeviceList / PNP_GetDeviceListSize: Implement the buffer size
calculation and device instance enumeration for a given enumerator and device name.
---
base/services/umpnpmgr/umpnpmgr.c | 265 ++++++++++++++++++++++++++++++--------
1 file changed, 214 insertions(+), 51 deletions(-)
diff --git a/base/services/umpnpmgr/umpnpmgr.c b/base/services/umpnpmgr/umpnpmgr.c
index 94bc37e914..3c96571dad 100644
--- a/base/services/umpnpmgr/umpnpmgr.c
+++ b/base/services/umpnpmgr/umpnpmgr.c
@@ -184,6 +184,53 @@ NtStatusToCrError(NTSTATUS Status)
}
+static VOID
+SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
+ OUT LPWSTR pszEnumerator,
+ OUT LPWSTR pszDevice,
+ OUT LPWSTR pszInstance)
+{
+ WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN];
+ LPWSTR lpEnumerator = NULL;
+ LPWSTR lpDevice = NULL;
+ LPWSTR lpInstance = NULL;
+ LPWSTR ptr;
+
+ wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID);
+
+ *pszEnumerator = 0;
+ *pszDevice = 0;
+ *pszInstance = 0;
+
+ lpEnumerator = szLocalDeviceInstanceID;
+
+ ptr = wcschr(lpEnumerator, L'\\');
+ if (ptr != NULL)
+ {
+ *ptr = 0;
+ lpDevice = ++ptr;
+
+ ptr = wcschr(lpDevice, L'\\');
+ if (ptr != NULL)
+ {
+ *ptr = 0;
+ lpInstance = ++ptr;
+ }
+ }
+
+ if (lpEnumerator != NULL)
+ wcscpy(pszEnumerator, lpEnumerator);
+
+ if (lpDevice != NULL)
+ wcscpy(pszDevice, lpDevice);
+
+ if (lpInstance != NULL)
+ wcscpy(pszInstance, lpInstance);
+}
+
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
/* Function 0 */
DWORD
WINAPI
@@ -482,6 +529,77 @@ PNP_EnumerateSubKeys(
}
+static
+CONFIGRET
+GetDeviceInstanceList(
+ _In_ PWSTR pszDevice,
+ _Inout_ PWSTR pszBuffer,
+ _Inout_ PDWORD pulLength)
+{
+ WCHAR szInstanceBuffer[MAX_DEVICE_ID_LEN];
+ WCHAR szPathBuffer[512];
+ HKEY hDeviceKey;
+ DWORD dwInstanceLength, dwPathLength, dwUsedLength;
+ DWORD dwIndex, dwError;
+ PWSTR pPtr;
+ CONFIGRET ret = CR_SUCCESS;
+
+ dwError = RegOpenKeyExW(hEnumKey,
+ pszDevice,
+ 0,
+ KEY_ENUMERATE_SUB_KEYS,
+ &hDeviceKey);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("Failed to open the device key (Error %lu)\n", dwError);
+ return CR_REGISTRY_ERROR;
+ }
+
+ dwUsedLength = 0;
+ pPtr = pszBuffer;
+
+ for (dwIndex = 0; ; dwIndex++)
+ {
+ dwInstanceLength = MAX_DEVICE_ID_LEN;
+ dwError = RegEnumKeyExW(hDeviceKey,
+ dwIndex,
+ szInstanceBuffer,
+ &dwInstanceLength,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (dwError != ERROR_SUCCESS)
+ break;
+
+ wsprintf(szPathBuffer, L"%s\\%s", pszDevice, szInstanceBuffer);
+ DPRINT("Path: %S\n", szPathBuffer);
+
+ dwPathLength = wcslen(szPathBuffer) + 1;
+ if (dwUsedLength + dwPathLength + 1 > *pulLength)
+ {
+ ret = CR_BUFFER_SMALL;
+ break;
+ }
+
+ wcscpy(pPtr, szPathBuffer);
+ dwUsedLength += dwPathLength;
+ pPtr += dwPathLength;
+
+ *pPtr = UNICODE_NULL;
+ }
+
+ RegCloseKey(hDeviceKey);
+
+ if (ret == CR_SUCCESS)
+ *pulLength = dwUsedLength + 1;
+ else
+ *pulLength = 0;
+
+ return ret;
+}
+
+
/* Function 10 */
DWORD
WINAPI
@@ -493,6 +611,9 @@ PNP_GetDeviceList(
DWORD ulFlags)
{
PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
+ WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
+ WCHAR szDevice[MAX_DEVICE_ID_LEN];
+ WCHAR szInstance[MAX_DEVICE_ID_LEN];
CONFIGRET ret = CR_SUCCESS;
NTSTATUS Status;
@@ -501,11 +622,12 @@ PNP_GetDeviceList(
if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
return CR_INVALID_FLAG;
- if (pulLength == NULL || pszFilter == NULL)
+ if (pulLength == NULL)
return CR_INVALID_POINTER;
-// if (Buffer == NULL)
-// return CR_INVALID_POINTER;
+ if ((ulFlags != CM_GETIDLIST_FILTER_NONE) &&
+ (pszFilter == NULL))
+ return CR_INVALID_POINTER;
if (ulFlags &
(CM_GETIDLIST_FILTER_BUSRELATIONS |
@@ -553,7 +675,21 @@ PNP_GetDeviceList(
}
else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
{
- ret = CR_CALL_NOT_IMPLEMENTED;
+ SplitDeviceInstanceID(pszFilter,
+ szEnumerator,
+ szDevice,
+ szInstance);
+
+ if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL)
+ {
+ ret = GetDeviceInstanceList(pszFilter,
+ Buffer,
+ pulLength);
+ }
+ else
+ {
+ ret = CR_CALL_NOT_IMPLEMENTED;
+ }
}
else /* CM_GETIDLIST_FILTER_NONE */
{
@@ -564,6 +700,58 @@ PNP_GetDeviceList(
}
+static
+CONFIGRET
+GetDeviceInstanceListSize(
+ _In_ LPCWSTR pszDevice,
+ _Out_ PULONG pulLength)
+{
+ HKEY hDeviceKey;
+ DWORD dwSubKeys, dwMaxSubKeyLength;
+ DWORD dwError;
+
+ /* Open the device key */
+ dwError = RegOpenKeyExW(hEnumKey,
+ pszDevice,
+ 0,
+ KEY_READ,
+ &hDeviceKey);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("Failed to open the device key (Error %lu)\n", dwError);
+ return CR_REGISTRY_ERROR;
+ }
+
+ /* Retrieve the number of device instances and the maximum name length */
+ dwError = RegQueryInfoKeyW(hDeviceKey,
+ NULL,
+ NULL,
+ NULL,
+ &dwSubKeys,
+ &dwMaxSubKeyLength,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError);
+ dwSubKeys = 0;
+ dwMaxSubKeyLength = 0;
+ }
+
+ /* Close the device key */
+ RegCloseKey(hDeviceKey);
+
+ /* Return the largest possible buffer size */
+ *pulLength = (dwSubKeys * (wcslen(pszDevice) + 1 + dwMaxSubKeyLength + 1)) + 1;
+
+ return CR_SUCCESS;
+}
+
+
/* Function 11 */
DWORD
WINAPI
@@ -574,6 +762,9 @@ PNP_GetDeviceListSize(
DWORD ulFlags)
{
PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
+ WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
+ WCHAR szDevice[MAX_DEVICE_ID_LEN];
+ WCHAR szInstance[MAX_DEVICE_ID_LEN];
CONFIGRET ret = CR_SUCCESS;
NTSTATUS Status;
@@ -582,7 +773,11 @@ PNP_GetDeviceListSize(
if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
return CR_INVALID_FLAG;
- if (pulLength == NULL || pszFilter == NULL)
+ if (pulLength == NULL)
+ return CR_INVALID_POINTER;
+
+ if ((ulFlags != CM_GETIDLIST_FILTER_NONE) &&
+ (pszFilter == NULL))
return CR_INVALID_POINTER;
*pulLength = 0;
@@ -633,7 +828,20 @@ PNP_GetDeviceListSize(
}
else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
{
- ret = CR_CALL_NOT_IMPLEMENTED;
+ SplitDeviceInstanceID(pszFilter,
+ szEnumerator,
+ szDevice,
+ szInstance);
+
+ if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL)
+ {
+ ret = GetDeviceInstanceListSize(pszFilter,
+ pulLength);
+ }
+ else
+ {
+ ret = CR_CALL_NOT_IMPLEMENTED;
+ }
}
else /* CM_GETIDLIST_FILTER_NONE */
{
@@ -1630,51 +1838,6 @@ done:
}
-static VOID
-SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
- OUT LPWSTR pszEnumerator,
- OUT LPWSTR pszDevice,
- OUT LPWSTR pszInstance)
-{
- WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN];
- LPWSTR lpEnumerator = NULL;
- LPWSTR lpDevice = NULL;
- LPWSTR lpInstance = NULL;
- LPWSTR ptr;
-
- wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID);
-
- *pszEnumerator = 0;
- *pszDevice = 0;
- *pszInstance = 0;
-
- lpEnumerator = szLocalDeviceInstanceID;
-
- ptr = wcschr(lpEnumerator, L'\\');
- if (ptr != NULL)
- {
- *ptr = 0;
- lpDevice = ++ptr;
-
- ptr = wcschr(lpDevice, L'\\');
- if (ptr != NULL)
- {
- *ptr = 0;
- lpInstance = ++ptr;
- }
- }
-
- if (lpEnumerator != NULL)
- wcscpy(pszEnumerator, lpEnumerator);
-
- if (lpDevice != NULL)
- wcscpy(pszDevice, lpDevice);
-
- if (lpInstance != NULL)
- wcscpy(pszInstance, lpInstance);
-}
-
-
static CONFIGRET
CreateDeviceInstance(LPWSTR pszDeviceID)
{