https://git.reactos.org/?p=reactos.git;a=commitdiff;h=85ca8afb6038d15de75f7…
commit 85ca8afb6038d15de75f7af00a7f9d9035d520e1
Author:     Stanislav Motylkov <x86corez(a)gmail.com>
AuthorDate: Wed May 10 20:31:10 2023 +0200
Commit:     Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sat May 27 12:22:57 2023 +0200
    [NTOS:PNP] IopEnumerateDetectedDevices(): General refactoring
    CORE-18962
    - Deduplicate a while-loop by adding one more recursive call.
    - Add IopMapDetectedDeviceId() helper function with a structure
      in order to reduce hardcoded constants and checks.
---
 ntoskrnl/io/pnpmgr/pnpmap.c | 285 ++++++++++++++++++++++----------------------
 1 file changed, 140 insertions(+), 145 deletions(-)
diff --git a/ntoskrnl/io/pnpmgr/pnpmap.c b/ntoskrnl/io/pnpmgr/pnpmap.c
index 613e95a20c6..36a7f5bbedf 100644
--- a/ntoskrnl/io/pnpmgr/pnpmap.c
+++ b/ntoskrnl/io/pnpmgr/pnpmap.c
@@ -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
@@ -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);
@@ -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,
@@ -130,7 +156,12 @@ IopEnumerateDetectedDevices(
                 goto cleanup;
             }
-            Status = ZwEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation,
pDeviceInformation, DeviceInfoLength, &RequiredSize);
+            Status = ZwEnumerateKey(hDevicesKey,
+                                    KeyIndex,
+                                    KeyBasicInformation,
+                                    pDeviceInformation,
+                                    DeviceInfoLength,
+                                    &RequiredSize);
         }
         if (!NT_SUCCESS(Status))
@@ -138,12 +169,38 @@ IopEnumerateDetectedDevices(
             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));
@@ -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 */
@@ -355,32 +370,8 @@ 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);
@@ -388,8 +379,9 @@ IopEnumerateDetectedDevices(
         }
         /* 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);
@@ -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))
         {
@@ -460,6 +452,9 @@ IopEnumerateDetectedDevices(
         if (BootResourcesLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
         {
+            PUCHAR CmResourceList;
+            ULONG ListCount;
+
             CmResourceList = ExAllocatePool(PagedPool, BootResourcesLength +
sizeof(ULONG));
             if (!CmResourceList)
             {
@@ -515,6 +510,8 @@ nextdevice:
             ZwClose(hDeviceKey);
             hDeviceKey = NULL;
         }
+        if (pValueInformation)
+            ExFreePool(pValueInformation);
     }
     Status = STATUS_SUCCESS;
@@ -522,12 +519,8 @@ nextdevice:
 cleanup:
     if (hDevicesKey && hDevicesKey != hBaseKey)
         ZwClose(hDevicesKey);
-    if (hDeviceKey)
-        ZwClose(hDeviceKey);
     if (pDeviceInformation)
         ExFreePool(pDeviceInformation);
-    if (pValueInformation)
-        ExFreePool(pValueInformation);
     return Status;
 }
@@ -647,6 +640,8 @@ IopUpdateRootKey(VOID)
             hRoot,
             TRUE,
             NULL,
+            0,
+            NULL,
             0);
         ZwClose(hEnum);
     }