https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a9b88efa7c12334482fbc8...
commit a9b88efa7c12334482fbc8ffb3b386bf8d316bf9 Author: Eric Kohl eric.kohl@reactos.org AuthorDate: Sat Dec 29 22:08:35 2018 +0100 Commit: Eric Kohl eric.kohl@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) {