https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0fed07b7e4c70e5be3068aeae224d69b39ee7046

commit 0fed07b7e4c70e5be3068aeae224d69b39ee7046
Author:     Victor Perevertkin <[email protected]>
AuthorDate: Fri Mar 19 07:57:41 2021 +0300
Commit:     Victor Perevertkin <[email protected]>
CommitDate: Fri Mar 19 07:57:41 2021 +0300

    [NTOS:PNP] Initialize DeviceDesc and LocationInformation registry fields
    
    for manually reported devices, as it is required by the newdev.dll
    for installing drivers from INF files
    
    CORE-17212 CORE-17398
    
    Co-authored-by: Stanislav Motylkov <[email protected]>
---
 ntoskrnl/include/internal/io.h |  12 +++
 ntoskrnl/io/pnpmgr/devaction.c | 199 ++++++++++++++++++++++-------------------
 ntoskrnl/io/pnpmgr/pnpirp.c    |  31 +++++++
 ntoskrnl/io/pnpmgr/pnpreport.c |   3 +
 4 files changed, 151 insertions(+), 94 deletions(-)

diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h
index 5e84f8e120f..e43f4769c94 100644
--- a/ntoskrnl/include/internal/io.h
+++ b/ntoskrnl/include/internal/io.h
@@ -753,6 +753,11 @@ PnpRegSzToString(
     OUT PUSHORT StringLength OPTIONAL
 );
 
+VOID
+PiSetDevNodeText(
+    _In_ PDEVICE_NODE DeviceNode,
+    _In_ HANDLE InstanceKey);
+
 //
 // Initialization Routines
 //
@@ -1381,6 +1386,13 @@ PiIrpQueryDeviceRelations(
     _In_ PDEVICE_NODE DeviceNode,
     _In_ DEVICE_RELATION_TYPE Type);
 
+NTSTATUS
+PiIrpQueryDeviceText(
+    _In_ PDEVICE_NODE DeviceNode,
+    _In_ LCID POINTER_ALIGNMENT LocaleId,
+    _In_ DEVICE_TEXT_TYPE Type,
+    _Out_ PWSTR *DeviceText);
+
 NTSTATUS
 PiIrpQueryPnPDeviceState(
     _In_ PDEVICE_NODE DeviceNode,
diff --git a/ntoskrnl/io/pnpmgr/devaction.c b/ntoskrnl/io/pnpmgr/devaction.c
index aa1ac12f6c2..1cf30fa8575 100644
--- a/ntoskrnl/io/pnpmgr/devaction.c
+++ b/ntoskrnl/io/pnpmgr/devaction.c
@@ -1081,34 +1081,123 @@ IopQueryCompatibleIds(PDEVICE_NODE DeviceNode,
     return Status;
 }
 
+/**
+ * @brief      Sets the DeviceNode's DeviceDesc and LocationInformation 
registry values
+ */
+VOID
+PiSetDevNodeText(
+    _In_ PDEVICE_NODE DeviceNode,
+    _In_ HANDLE InstanceKey)
+{
+    PAGED_CODE();
+
+    LCID localeId;
+
+    // Get the Locale ID
+    NTSTATUS status = ZwQueryDefaultLocale(FALSE, &localeId);
+    if (!NT_SUCCESS(status))
+    {
+        DPRINT1("ZwQueryDefaultLocale() failed with status %x\n", status);
+        return;
+    }
+
+    // Step 1: write DeviceDesc key if not exists
+
+    UNICODE_STRING valDeviceDesc = RTL_CONSTANT_STRING(L"DeviceDesc");
+    ULONG len;
+
+    status = ZwQueryValueKey(InstanceKey, &valDeviceDesc, 
KeyValueBasicInformation, NULL, 0, &len);
+    if (!NT_SUCCESS(status))
+    {
+        PWSTR deviceDesc = NULL;
+        status = PiIrpQueryDeviceText(DeviceNode, localeId, 
DeviceTextDescription, &deviceDesc);
+
+        if (deviceDesc && deviceDesc[0] != UNICODE_NULL)
+        {
+            status = ZwSetValueKey(InstanceKey,
+                                   &valDeviceDesc,
+                                   0,
+                                   REG_SZ,
+                                   deviceDesc,
+                                   ((ULONG)wcslen(deviceDesc) + 1) * 
sizeof(WCHAR));
+
+            if (!NT_SUCCESS(status))
+            {
+                DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
+            }
+        }
+        else
+        {
+            // This key is mandatory, so even if the Irp fails, we still write 
it
+            UNICODE_STRING unknownDeviceDesc = RTL_CONSTANT_STRING(L"Unknown 
device");
+            DPRINT("Driver didn't return DeviceDesc (status %x)\n", status);
+
+            status = ZwSetValueKey(InstanceKey,
+                                   &valDeviceDesc,
+                                   0,
+                                   REG_SZ,
+                                   unknownDeviceDesc.Buffer,
+                                   unknownDeviceDesc.MaximumLength);
+            if (!NT_SUCCESS(status))
+            {
+                DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
+            }
+        }
+
+        if (deviceDesc)
+        {
+            ExFreePoolWithTag(deviceDesc, 0);
+        }
+    }
+
+    // Step 2: LocaltionInformation is overwritten unconditionally
+
+    PWSTR deviceLocationInfo = NULL;
+    status = PiIrpQueryDeviceText(DeviceNode,
+                                  localeId,
+                                  DeviceTextLocationInformation,
+                                  &deviceLocationInfo);
+
+    if (deviceLocationInfo && deviceLocationInfo[0] != UNICODE_NULL)
+    {
+        UNICODE_STRING valLocationInfo = 
RTL_CONSTANT_STRING(L"LocationInformation");
+
+        status = ZwSetValueKey(InstanceKey,
+                               &valLocationInfo,
+                               0,
+                               REG_SZ,
+                               deviceLocationInfo,
+                               ((ULONG)wcslen(deviceLocationInfo) + 1) * 
sizeof(WCHAR));
+        if (!NT_SUCCESS(status))
+        {
+            DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
+        }
+    }
+
+    if (deviceLocationInfo)
+    {
+        ExFreePoolWithTag(deviceLocationInfo, 0);
+    }
+    else
+    {
+        DPRINT("Driver didn't return LocationInformation (status %x)\n", 
status);
+    }
+}
+
 static
 NTSTATUS
 PiInitializeDevNode(
     _In_ PDEVICE_NODE DeviceNode)
 {
     IO_STATUS_BLOCK IoStatusBlock;
-    PWSTR DeviceDescription;
-    PWSTR LocationInformation;
-    IO_STACK_LOCATION Stack;
     NTSTATUS Status;
-    ULONG RequiredLength;
-    LCID LocaleId;
     HANDLE InstanceKey = NULL;
-    UNICODE_STRING ValueName;
     UNICODE_STRING InstancePathU;
     PDEVICE_OBJECT OldDeviceObject;
 
     DPRINT("PiProcessNewDevNode(%p)\n", DeviceNode);
     DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject);
 
-    /* Get Locale ID */
-    Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status);
-        return Status;
-    }
-
     /*
      * FIXME: For critical errors, cleanup and disable device, but always
      * return STATUS_SUCCESS.
@@ -1163,86 +1252,8 @@ PiInitializeDevNode(
 
     DeviceNode->Flags |= DNF_IDS_QUERIED;
 
-    DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device 
stack\n");
-
-    Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription;
-    Stack.Parameters.QueryDeviceText.LocaleId = LocaleId;
-    Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
-                               &IoStatusBlock,
-                               IRP_MN_QUERY_DEVICE_TEXT,
-                               &Stack);
-    DeviceDescription = NT_SUCCESS(Status) ? (PWSTR)IoStatusBlock.Information
-                                           : NULL;
-    /* This key is mandatory, so even if the Irp fails, we still write it */
-    RtlInitUnicodeString(&ValueName, L"DeviceDesc");
-    if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, 
NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND)
-    {
-        if (DeviceDescription &&
-            *DeviceDescription != UNICODE_NULL)
-        {
-            /* This key is overriden when a driver is installed. Don't write 
the
-             * new description if another one already exists */
-            Status = ZwSetValueKey(InstanceKey,
-                                   &ValueName,
-                                   0,
-                                   REG_SZ,
-                                   DeviceDescription,
-                                   ((ULONG)wcslen(DeviceDescription) + 1) * 
sizeof(WCHAR));
-        }
-        else
-        {
-            UNICODE_STRING DeviceDesc = RTL_CONSTANT_STRING(L"Unknown device");
-            DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place 
unknown device there\n", Status);
-
-            Status = ZwSetValueKey(InstanceKey,
-                                   &ValueName,
-                                   0,
-                                   REG_SZ,
-                                   DeviceDesc.Buffer,
-                                   DeviceDesc.MaximumLength);
-            if (!NT_SUCCESS(Status))
-            {
-                DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status);
-            }
-
-        }
-    }
-
-    if (DeviceDescription)
-    {
-        ExFreePoolWithTag(DeviceDescription, 0);
-    }
-
-    DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device 
stack\n");
-
-    Stack.Parameters.QueryDeviceText.DeviceTextType = 
DeviceTextLocationInformation;
-    Stack.Parameters.QueryDeviceText.LocaleId = LocaleId;
-    Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
-                               &IoStatusBlock,
-                               IRP_MN_QUERY_DEVICE_TEXT,
-                               &Stack);
-    if (NT_SUCCESS(Status) && IoStatusBlock.Information)
-    {
-        LocationInformation = (PWSTR)IoStatusBlock.Information;
-        DPRINT("LocationInformation: %S\n", LocationInformation);
-        RtlInitUnicodeString(&ValueName, L"LocationInformation");
-        Status = ZwSetValueKey(InstanceKey,
-                               &ValueName,
-                               0,
-                               REG_SZ,
-                               LocationInformation,
-                               ((ULONG)wcslen(LocationInformation) + 1) * 
sizeof(WCHAR));
-        if (!NT_SUCCESS(Status))
-        {
-            DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
-        }
-
-        ExFreePoolWithTag(LocationInformation, 0);
-    }
-    else
-    {
-        DPRINT("IopInitiatePnpIrp() failed (Status %x) or 
IoStatusBlock.Information=NULL\n", Status);
-    }
+    // Set the device's DeviceDesc and LocationInformation fields
+    PiSetDevNodeText(DeviceNode, InstanceKey);
 
     DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
 
diff --git a/ntoskrnl/io/pnpmgr/pnpirp.c b/ntoskrnl/io/pnpmgr/pnpirp.c
index 03fc0d1aafc..48d924d6c7c 100644
--- a/ntoskrnl/io/pnpmgr/pnpirp.c
+++ b/ntoskrnl/io/pnpmgr/pnpirp.c
@@ -196,6 +196,37 @@ PiIrpQueryDeviceRelations(
     return status;
 }
 
+// IRP_MN_QUERY_DEVICE_TEXT (0x0C)
+NTSTATUS
+PiIrpQueryDeviceText(
+    _In_ PDEVICE_NODE DeviceNode,
+    _In_ LCID POINTER_ALIGNMENT LocaleId,
+    _In_ DEVICE_TEXT_TYPE Type,
+    _Out_ PWSTR *DeviceText)
+{
+    PAGED_CODE();
+
+    ASSERT(DeviceNode);
+    ASSERT(DeviceNode->State == DeviceNodeUninitialized);
+
+    ULONG_PTR longText;
+    IO_STACK_LOCATION stack = {
+        .MajorFunction = IRP_MJ_PNP,
+        .MinorFunction = IRP_MN_QUERY_DEVICE_TEXT,
+        .Parameters.QueryDeviceText.DeviceTextType = Type,
+        .Parameters.QueryDeviceText.LocaleId = LocaleId
+    };
+
+    NTSTATUS status;
+    status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &stack, 
(PVOID)&longText);
+    if (NT_SUCCESS(status))
+    {
+        *DeviceText = (PVOID)longText;
+    }
+
+    return status;
+}
+
 // IRP_MN_QUERY_PNP_DEVICE_STATE (0x14)
 NTSTATUS
 PiIrpQueryPnPDeviceState(
diff --git a/ntoskrnl/io/pnpmgr/pnpreport.c b/ntoskrnl/io/pnpmgr/pnpreport.c
index 8104a8f178b..65e256075da 100644
--- a/ntoskrnl/io/pnpmgr/pnpreport.c
+++ b/ntoskrnl/io/pnpmgr/pnpreport.c
@@ -294,6 +294,9 @@ IoReportDetectedDevice(
         return Status;
     }
 
+    // Set the device's DeviceDesc and LocationInformation fields
+    PiSetDevNodeText(DeviceNode, InstanceKey);
+
     /* Assign the resources to the device node */
     DeviceNode->BootResources = ResourceList;
     DeviceNode->ResourceRequirements = ResourceRequirements;

Reply via email to