[NTOSKRNL] Minor PnP enhancements.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 22 Apr 2018 14:31:53 +0000 (16:31 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 22 Apr 2018 14:52:45 +0000 (16:52 +0200)
- For non-PnP devices reported to the PnP manager through the
  IoReportDetectedDevice() function, store the corresponding
  service/driver name and (non-)legacy information inside their
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\ entries.
- Drivers flagged as "DRVO_BUILTIN_DRIVER" (basically, only those
  created via a IoCreateDriver() call) have their "Service" name that
  contain "\Driver\", which should be stripped before being used in
  building e.g. the corresponding "DETECTEDxxx" PnP compatible IDs.
  CORE-14247

- Use explicit REG_OPTION_NON_VOLATILE flag where needed in the
  IopCreateDeviceKeyPath() calls.
- Save NULL-terminated REG-SZ string properties in the enumeration tree
  for each device enumerated inside \Enum\Root\.
- Always use upcased key name for the "LEGACY_***" elements in \Enum\Root\.
- Add a default "ConfigFlags" value for the legacy elements.
- Simplify few parts of code.

ntoskrnl/io/pnpmgr/pnpmgr.c
ntoskrnl/io/pnpmgr/pnpreport.c

index 3337495..62ad7a2 100644 (file)
@@ -98,7 +98,7 @@ IopInstallCriticalDevice(PDEVICE_NODE DeviceNode)
     PWCHAR IdBuffer, OriginalIdBuffer;
 
     /* Open the device instance key */
-    Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey);
+    Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
     if (Status != STATUS_SUCCESS)
         return;
 
@@ -800,7 +800,7 @@ IopStartDevice(
    IopStartAndEnumerateDevice(DeviceNode);
 
    /* FIX: Should be done in new device instance code */
-   Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceHandle);
+   Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceHandle);
    if (!NT_SUCCESS(Status))
        goto ByeBye;
 
@@ -817,7 +817,7 @@ IopStartDevice(
        goto ByeBye;
 
    RtlInitUnicodeString(&KeyName, L"ActiveService");
-   Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_SZ, DeviceNode->ServiceName.Buffer, DeviceNode->ServiceName.Length);
+   Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_SZ, DeviceNode->ServiceName.Buffer, DeviceNode->ServiceName.Length + sizeof(UNICODE_NULL));
    // }
 
 ByeBye:
@@ -873,7 +873,7 @@ IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode,
    else
        DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
 
-   Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey);
+   Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
    if (NT_SUCCESS(Status))
    {
       /* Set 'Capabilities' value */
@@ -1067,7 +1067,7 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
 
    if (!PhysicalDeviceObject)
    {
-      FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName1->Length;
+      FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName1->Length + sizeof(UNICODE_NULL);
       FullServiceName.Length = 0;
       FullServiceName.Buffer = ExAllocatePool(PagedPool, FullServiceName.MaximumLength);
       if (!FullServiceName.Buffer)
@@ -1078,6 +1078,7 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
 
       RtlAppendUnicodeStringToString(&FullServiceName, &LegacyPrefix);
       RtlAppendUnicodeStringToString(&FullServiceName, ServiceName1);
+      RtlUpcaseUnicodeString(&FullServiceName, &FullServiceName, FALSE);
 
       Status = PnpRootCreateDevice(&FullServiceName, NULL, &PhysicalDeviceObject, &Node->InstancePath);
       if (!NT_SUCCESS(Status))
@@ -1097,7 +1098,9 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
           return Status;
       }
 
-      Node->ServiceName.Buffer = ExAllocatePool(PagedPool, ServiceName1->Length);
+      Node->ServiceName.MaximumLength = ServiceName1->Length + sizeof(UNICODE_NULL);
+      Node->ServiceName.Length = 0;
+      Node->ServiceName.Buffer = ExAllocatePool(PagedPool, Node->ServiceName.MaximumLength);
       if (!Node->ServiceName.Buffer)
       {
           ZwClose(InstanceHandle);
@@ -1106,39 +1109,39 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
           return Status;
       }
 
-      Node->ServiceName.MaximumLength = ServiceName1->Length;
-      Node->ServiceName.Length = 0;
-
-      RtlAppendUnicodeStringToString(&Node->ServiceName, ServiceName1);
+      RtlCopyUnicodeString(&Node->ServiceName, ServiceName1);
 
       if (ServiceName)
       {
           RtlInitUnicodeString(&KeyName, L"Service");
-          Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName->Buffer, ServiceName->Length);
+          Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName->Buffer, ServiceName->Length + sizeof(UNICODE_NULL));
       }
 
       if (NT_SUCCESS(Status))
       {
           RtlInitUnicodeString(&KeyName, L"Legacy");
-
           LegacyValue = 1;
           Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
+
+          RtlInitUnicodeString(&KeyName, L"ConfigFlags");
+          LegacyValue = 0;
+          ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
+
           if (NT_SUCCESS(Status))
           {
               RtlInitUnicodeString(&KeyName, L"Class");
-
-              RtlInitUnicodeString(&ClassName, L"LegacyDriver\0");
+              RtlInitUnicodeString(&ClassName, L"LegacyDriver");
               Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassName.Buffer, ClassName.Length + sizeof(UNICODE_NULL));
               if (NT_SUCCESS(Status))
               {
                   RtlInitUnicodeString(&KeyName, L"ClassGUID");
-
-                  RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}\0");
+                  RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
                   Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassGUID.Buffer, ClassGUID.Length + sizeof(UNICODE_NULL));
                   if (NT_SUCCESS(Status))
                   {
+                      // FIXME: Retrieve the real "description" by looking at the "DisplayName" string
+                      // of the corresponding CurrentControlSet\Services\xxx entry for this driver.
                       RtlInitUnicodeString(&KeyName, L"DeviceDesc");
-
                       Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName1->Buffer, ServiceName1->Length + sizeof(UNICODE_NULL));
                   }
               }
@@ -2244,7 +2247,7 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
     /*
      * Create registry key for the instance id, if it doesn't exist yet
      */
-    Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey);
+    Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
@@ -2719,10 +2722,7 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
              DeviceCaps.RawDeviceOK)
          {
             DPRINT("%wZ is using parent bus driver (%wZ)\n", &DeviceNode->InstancePath, &ParentDeviceNode->ServiceName);
-
-            DeviceNode->ServiceName.Length = 0;
-            DeviceNode->ServiceName.MaximumLength = 0;
-            DeviceNode->ServiceName.Buffer = NULL;
+            RtlInitEmptyUnicodeString(&DeviceNode->ServiceName, NULL, 0);
          }
          else if (ClassGUID.Length != 0)
          {
index 0d6943b..00b3547 100644 (file)
@@ -173,15 +173,17 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
     NTSTATUS Status;
     HANDLE InstanceKey;
     ULONG RequiredLength;
-    UNICODE_STRING ValueName, ServiceName;
+    UNICODE_STRING ValueName, ServiceLongName, ServiceName;
     WCHAR HardwareId[256];
     PWCHAR IfString;
     ULONG IdLength;
+    ULONG LegacyValue;
 
     DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n",
            DeviceObject, DeviceObject ? *DeviceObject : NULL);
 
-    ServiceName = DriverObject->DriverExtension->ServiceKeyName;
+    ServiceLongName = DriverObject->DriverExtension->ServiceKeyName;
+    ServiceName = ServiceLongName;
 
     /* If the interface type is unknown, treat it as internal */
     if (LegacyBusType == InterfaceTypeUndefined)
@@ -194,6 +196,42 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
     if (!IfString)
         return STATUS_INVALID_PARAMETER;
 
+    /*
+     * Drivers that have been created via a direct IoCreateDriver() call
+     * have their ServiceKeyName set to \Driver\DriverName. We need to
+     * strip everything up to the last path separator and keep what remains.
+     */
+    if (DriverObject->Flags & DRVO_BUILTIN_DRIVER)
+    {
+        /*
+         * Find the last path separator.
+         * NOTE: Since ServiceName is not necessarily NULL-terminated,
+         * we cannot use wcsrchr().
+         */
+        if (ServiceName.Buffer && ServiceName.Length >= sizeof(WCHAR))
+        {
+            ValueName.Length = 1;
+            ValueName.Buffer = ServiceName.Buffer + (ServiceName.Length / sizeof(WCHAR)) - 1;
+
+            while ((ValueName.Buffer > ServiceName.Buffer) && (*ValueName.Buffer != L'\\'))
+            {
+                --ValueName.Buffer;
+                ++ValueName.Length;
+            }
+            if (*ValueName.Buffer == L'\\')
+            {
+                ++ValueName.Buffer;
+                --ValueName.Length;
+            }
+            ValueName.Length *= sizeof(WCHAR);
+
+            /* Shorten the string */
+            ServiceName.MaximumLength -= (ServiceName.Length - ValueName.Length);
+            ServiceName.Length = ValueName.Length;
+            ServiceName.Buffer = ValueName.Buffer;
+        }
+    }
+
     /* We use the caller's PDO if they supplied one */
     if (DeviceObject && *DeviceObject)
     {
@@ -218,7 +256,6 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
                                  Pdo,
                                  NULL,
                                  &DeviceNode);
-
     if (!NT_SUCCESS(Status))
     {
         DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status);
@@ -252,6 +289,23 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
     if (!NT_SUCCESS(Status))
         return Status;
 
+    /* Save the driver name */
+    RtlInitUnicodeString(&ValueName, L"Service");
+    Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_SZ, ServiceLongName.Buffer, ServiceLongName.Length + sizeof(UNICODE_NULL));
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("Failed to write the Service name value: 0x%x\n", Status);
+    }
+
+    /* Report as non-legacy driver */
+    RtlInitUnicodeString(&ValueName, L"Legacy");
+    LegacyValue = 0;
+    Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("Failed to write the Legacy value: 0x%x\n", Status);
+    }
+
     /* Add DETECTEDInterfaceType\DriverName */
     IdLength = 0;
     IdLength += swprintf(&HardwareId[IdLength],