Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NTOS:PNP] IopEnumerateDetectedDevices(): General refactoring #5276

Merged
merged 1 commit into from May 27, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
285 changes: 140 additions & 145 deletions ntoskrnl/io/pnpmgr/pnpmap.c
Expand Up @@ -12,8 +12,72 @@
#define NDEBUG
#include <debug.h>

/* TYPES *********************************************************************/

typedef struct _PNP_DETECT_IDENTIFIER_MAP
{
PWSTR DetectId;
PWSTR PnPId;
ULONG Counter;
} PNP_DETECT_IDENTIFIER_MAP;

/* DATA **********************************************************************/

static UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier");
static UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID");
static UNICODE_STRING ConfigurationDataU = RTL_CONSTANT_STRING(L"Configuration Data");
static UNICODE_STRING BootConfigU = RTL_CONSTANT_STRING(L"BootConfig");
static UNICODE_STRING LogConfU = RTL_CONSTANT_STRING(L"LogConf");

/* FIXME: There should be two sets of hardcoded PnP identifiers
* for the keyboard and pointer peripherals (see CORE-18963).
* They also can be parsed from a LegacyXlate sections of driver INF files.
*/

static
PNP_DETECT_IDENTIFIER_MAP PnPMap[] =
{
{ L"SerialController", L"*PNP0501\0", 0 },
{ L"KeyboardController", L"*PNP0303\0", 0 },
#if defined(SARCH_PC98)
{ L"PointerController", L"*nEC1F00\0", 0 },
#else
{ L"PointerController", L"*PNP0F13\0", 0 },
#endif
{ L"ParallelController", L"*PNP0400\0", 0 },
{ L"FloppyDiskPeripheral", L"*PNP0700\0", 0 },
{ NULL, NULL, 0 }
};

/* FUNCTIONS *****************************************************************/

static
CODE_SEG("INIT")
PWSTR
IopMapDetectedDeviceId(
_In_ PUNICODE_STRING DetectId,
_Out_ PULONG DeviceIndex)
{
ULONG i;
UNICODE_STRING CmpId;

if (!DetectId)
return NULL;

for (i = 0; PnPMap[i].DetectId; i++)
{
RtlInitUnicodeString(&CmpId, PnPMap[i].DetectId);

if (RtlCompareUnicodeString(DetectId, &CmpId, FALSE) == 0)
{
*DeviceIndex = PnPMap[i].Counter++;
break;
}
}

return PnPMap[i].PnPId;
}

static
CODE_SEG("INIT")
NTSTATUS
Expand All @@ -22,62 +86,18 @@ IopEnumerateDetectedDevices(
_In_opt_ PUNICODE_STRING RelativePath,
_In_ HANDLE hRootKey,
_In_ BOOLEAN EnumerateSubKeys,
_In_opt_ PCM_FULL_RESOURCE_DESCRIPTOR BootResources,
_In_opt_ ULONG BootResourcesLength,
_In_ PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources,
_In_ ULONG ParentBootResourcesLength)
{
UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier");
UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID");
UNICODE_STRING ConfigurationDataU = RTL_CONSTANT_STRING(L"Configuration Data");
UNICODE_STRING BootConfigU = RTL_CONSTANT_STRING(L"BootConfig");
UNICODE_STRING LogConfU = RTL_CONSTANT_STRING(L"LogConf");
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hDevicesKey = NULL;
HANDLE hDeviceKey = NULL;
HANDLE hLevel1Key, hLevel2Key = NULL, hLogConf;
UNICODE_STRING Level2NameU;
WCHAR Level2Name[5];
ULONG IndexDevice = 0;
ULONG IndexSubKey;
ULONG KeyIndex = 0;
PKEY_BASIC_INFORMATION pDeviceInformation = NULL;
ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR);
PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL;
ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR);
UNICODE_STRING DeviceName, ValueName;
ULONG RequiredSize;
PCM_FULL_RESOURCE_DESCRIPTOR BootResources = NULL;
ULONG BootResourcesLength;
NTSTATUS Status;

const UNICODE_STRING IdentifierSerial = RTL_CONSTANT_STRING(L"SerialController");
UNICODE_STRING HardwareIdSerial = RTL_CONSTANT_STRING(L"*PNP0501\0");
static ULONG DeviceIndexSerial = 0;
const UNICODE_STRING IdentifierKeyboard = RTL_CONSTANT_STRING(L"KeyboardController");
UNICODE_STRING HardwareIdKeyboard = RTL_CONSTANT_STRING(L"*PNP0303\0");
static ULONG DeviceIndexKeyboard = 0;
const UNICODE_STRING IdentifierMouse = RTL_CONSTANT_STRING(L"PointerController");
/* FIXME: IopEnumerateDetectedDevices() should be rewritten.
* The PnP identifiers can either be hardcoded or parsed from a LegacyXlate
* sections of driver INF files.
*/
#if defined(SARCH_PC98)
UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*nEC1F00\0");
#else
UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*PNP0F13\0");
#endif
static ULONG DeviceIndexMouse = 0;
const UNICODE_STRING IdentifierParallel = RTL_CONSTANT_STRING(L"ParallelController");
UNICODE_STRING HardwareIdParallel = RTL_CONSTANT_STRING(L"*PNP0400\0");
static ULONG DeviceIndexParallel = 0;
const UNICODE_STRING IdentifierFloppy = RTL_CONSTANT_STRING(L"FloppyDiskPeripheral");
UNICODE_STRING HardwareIdFloppy = RTL_CONSTANT_STRING(L"*PNP0700\0");
static ULONG DeviceIndexFloppy = 0;
UNICODE_STRING HardwareIdKey;
PUNICODE_STRING pHardwareId;
ULONG DeviceIndex = 0;
PUCHAR CmResourceList;
ULONG ListCount;

if (RelativePath)
if (!BootResources && RelativePath)
{
Status = IopOpenRegistryKeyEx(&hDevicesKey, hBaseKey, RelativePath, KEY_ENUMERATE_SUB_KEYS);

Expand All @@ -98,18 +118,24 @@ IopEnumerateDetectedDevices(
goto cleanup;
}

pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength);
if (!pValueInformation)
{
DPRINT("ExAllocatePool() failed\n");
Status = STATUS_NO_MEMORY;
goto cleanup;
}

while (TRUE)
{
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hDeviceKey = NULL;
HANDLE hLevel1Key, hLevel2Key = NULL, hLogConf;
UNICODE_STRING Level2NameU;
WCHAR Level2Name[5];
PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL;
ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR);
UNICODE_STRING DeviceName, ValueName;
ULONG RequiredSize;

UNICODE_STRING HardwareIdKey;
PWSTR pHardwareId;
ULONG DeviceIndex = 0;

Status = ZwEnumerateKey(hDevicesKey,
IndexDevice,
KeyIndex,
KeyBasicInformation,
pDeviceInformation,
DeviceInfoLength,
Expand All @@ -130,20 +156,51 @@ IopEnumerateDetectedDevices(
goto cleanup;
}

Status = ZwEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize);
Status = ZwEnumerateKey(hDevicesKey,
KeyIndex,
KeyBasicInformation,
pDeviceInformation,
DeviceInfoLength,
&RequiredSize);
}

if (!NT_SUCCESS(Status))
{
DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
goto cleanup;
}
IndexDevice++;
KeyIndex++;

/* Open device key */
DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength;
DeviceName.Buffer = pDeviceInformation->Name;

if (BootResources)
{
Status = IopEnumerateDetectedDevices(
hDevicesKey,
&DeviceName,
hRootKey,
TRUE,
NULL,
0,
BootResources,
BootResourcesLength);

if (!NT_SUCCESS(Status))
goto cleanup;

continue;
}

pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength);
if (!pValueInformation)
{
DPRINT("ExAllocatePool() failed\n");
Status = STATUS_NO_MEMORY;
goto cleanup;
}

Status = IopOpenRegistryKeyEx(&hDeviceKey, hDevicesKey, &DeviceName,
KEY_QUERY_VALUE + (EnumerateSubKeys ? KEY_ENUMERATE_SUB_KEYS : 0));

Expand Down Expand Up @@ -247,60 +304,18 @@ IopEnumerateDetectedDevices(

if (EnumerateSubKeys)
{
IndexSubKey = 0;
Status = IopEnumerateDetectedDevices(
hDeviceKey,
RelativePath,
hRootKey,
TRUE,
BootResources,
BootResourcesLength,
ParentBootResources,
ParentBootResourcesLength);

while (TRUE)
{
Status = ZwEnumerateKey(hDeviceKey,
IndexSubKey,
KeyBasicInformation,
pDeviceInformation,
DeviceInfoLength,
&RequiredSize);

if (Status == STATUS_NO_MORE_ENTRIES)
break;
else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
{
ExFreePool(pDeviceInformation);
DeviceInfoLength = RequiredSize;
pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength);

if (!pDeviceInformation)
{
DPRINT("ExAllocatePool() failed\n");
Status = STATUS_NO_MEMORY;
goto cleanup;
}

Status = ZwEnumerateKey(hDeviceKey,
IndexSubKey,
KeyBasicInformation,
pDeviceInformation,
DeviceInfoLength,
&RequiredSize);
}

if (!NT_SUCCESS(Status))
{
DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
goto cleanup;
}
IndexSubKey++;
DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength;
DeviceName.Buffer = pDeviceInformation->Name;

Status = IopEnumerateDetectedDevices(
hDeviceKey,
&DeviceName,
hRootKey,
TRUE,
BootResources,
BootResourcesLength);

if (!NT_SUCCESS(Status))
goto cleanup;
}
if (!NT_SUCCESS(Status))
goto cleanup;
}

/* Read identifier */
Expand Down Expand Up @@ -355,41 +370,18 @@ IopEnumerateDetectedDevices(
ValueName.Length -= sizeof(WCHAR);
}

if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierSerial, FALSE) == 0)
{
pHardwareId = &HardwareIdSerial;
DeviceIndex = DeviceIndexSerial++;
}
else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierKeyboard, FALSE) == 0)
{
pHardwareId = &HardwareIdKeyboard;
DeviceIndex = DeviceIndexKeyboard++;
}
else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierMouse, FALSE) == 0)
{
pHardwareId = &HardwareIdMouse;
DeviceIndex = DeviceIndexMouse++;
}
else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierParallel, FALSE) == 0)
{
pHardwareId = &HardwareIdParallel;
DeviceIndex = DeviceIndexParallel++;
}
else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierFloppy, FALSE) == 0)
{
pHardwareId = &HardwareIdFloppy;
DeviceIndex = DeviceIndexFloppy++;
}
else
pHardwareId = IopMapDetectedDeviceId(RelativePath, &DeviceIndex);
if (!pHardwareId)
{
/* Unknown key path */
DPRINT("Unknown key path '%wZ'\n", RelativePath);
goto nextdevice;
}

/* Prepare hardware id key (hardware id value without final \0) */
HardwareIdKey = *pHardwareId;
HardwareIdKey.Length -= sizeof(UNICODE_NULL);
HardwareIdKey.Length = wcslen(pHardwareId) * sizeof(WCHAR);
HardwareIdKey.MaximumLength = HardwareIdKey.Length + sizeof(UNICODE_NULL) * 2;
HardwareIdKey.Buffer = pHardwareId;

/* Add the detected device to Root key */
InitializeObjectAttributes(&ObjectAttributes, &HardwareIdKey, OBJ_KERNEL_HANDLE, hRootKey, NULL);
Expand Down Expand Up @@ -430,7 +422,7 @@ IopEnumerateDetectedDevices(
}

DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName, DeviceIndex, &HardwareIdKey);
Status = ZwSetValueKey(hLevel2Key, &HardwareIDU, 0, REG_MULTI_SZ, pHardwareId->Buffer, pHardwareId->MaximumLength);
Status = ZwSetValueKey(hLevel2Key, &HardwareIDU, 0, REG_MULTI_SZ, HardwareIdKey.Buffer, HardwareIdKey.MaximumLength);

if (!NT_SUCCESS(Status))
{
Expand Down Expand Up @@ -460,6 +452,9 @@ IopEnumerateDetectedDevices(

if (BootResourcesLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
{
PUCHAR CmResourceList;
ULONG ListCount;

CmResourceList = ExAllocatePool(PagedPool, BootResourcesLength + sizeof(ULONG));
if (!CmResourceList)
{
Expand Down Expand Up @@ -515,19 +510,17 @@ IopEnumerateDetectedDevices(
ZwClose(hDeviceKey);
hDeviceKey = NULL;
}
if (pValueInformation)
ExFreePool(pValueInformation);
}

Status = STATUS_SUCCESS;

cleanup:
if (hDevicesKey && hDevicesKey != hBaseKey)
ZwClose(hDevicesKey);
if (hDeviceKey)
ZwClose(hDeviceKey);
if (pDeviceInformation)
ExFreePool(pDeviceInformation);
if (pValueInformation)
ExFreePool(pValueInformation);

return Status;
}
Expand Down Expand Up @@ -647,6 +640,8 @@ IopUpdateRootKey(VOID)
hRoot,
TRUE,
NULL,
0,
NULL,
0);
ZwClose(hEnum);
}
Expand Down