[UMPNPMGR] PNP_GetDeviceList / PNP_GetDeviceListSize: Implement the buffer size calculation and device instance enumeration for a given enumerator and device name.

This commit is contained in:
Eric Kohl 2018-12-29 22:08:35 +01:00
parent 830f2998ab
commit a9b88efa7c

View file

@ -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)
{