The code expects synchronous behaviour here, so until a better solution exists, IoSyn...
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / pnpmgr.c
index 22c1b2c..77a470d 100644 (file)
@@ -28,9 +28,6 @@ PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList = NULL;
 #if defined (ALLOC_PRAGMA)
 #pragma alloc_text(INIT, PnpInit)
 #pragma alloc_text(INIT, PnpInit2)
-#pragma alloc_text(INIT, IopUpdateRootKey)
-#pragma alloc_text(INIT, IopEnumerateDetectedDevices)
-#pragma alloc_text(INIT, IopIsAcpiComputer)
 #endif
 
 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
@@ -41,11 +38,18 @@ typedef struct _INVALIDATE_DEVICE_RELATION_DATA
     NTSTATUS Status;
 } INVALIDATE_DEVICE_RELATION_DATA, *PINVALIDATE_DEVICE_RELATION_DATA;
 
-static VOID CALLBACK
+static VOID NTAPI
 IopInvalidateDeviceRelations(
     IN PDEVICE_OBJECT DeviceObject,
     IN PVOID InvalidateContext);
 
+VOID
+NTAPI
+IoSynchronousInvalidateDeviceRelations(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN DEVICE_RELATION_TYPE Type);
+
+
 /* FUNCTIONS *****************************************************************/
 
 PDEVICE_NODE
@@ -132,12 +136,6 @@ IopStartDevice(
    Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->ResourceList;
    Stack.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->ResourceListTranslated;
 
-   /* FIXME: Not sure of this! */
-   if (!Stack.Parameters.StartDevice.AllocatedResources)
-      Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->BootResources;
-   if (!Stack.Parameters.StartDevice.AllocatedResourcesTranslated)
-      Stack.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->BootResources;
-
    Status = IopInitiatePnpIrp(
       Fdo,
       &IoStatusBlock,
@@ -153,7 +151,9 @@ IopStartDevice(
          if (IopDeviceNodeHasFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY))
       {
          DPRINT("Device needs enumeration, invalidating bus relations\n");
-         IoInvalidateDeviceRelations(DeviceNode->PhysicalDeviceObject, BusRelations);
+         /* Invalidate device relations synchronously
+            (otherwise there will be dirty read of DeviceNode) */
+         IoSynchronousInvalidateDeviceRelations(DeviceNode->PhysicalDeviceObject, BusRelations);
          IopDeviceNodeClearFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY);
       }
    }
@@ -602,7 +602,7 @@ IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject,
       return STATUS_INSUFFICIENT_RESOURCES;
 
    KeyName.Length = 0;
-   KeyName.MaximumLength = KeyNameLength;
+   KeyName.MaximumLength = (USHORT)KeyNameLength;
    KeyName.Buffer = KeyNameBuffer;
 
    /*
@@ -628,7 +628,7 @@ IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject,
          ExFreePool(KeyNameBuffer);
          return Status;
       }
-      KeyName.Length += DriverKeyLength - sizeof(UNICODE_NULL);
+      KeyName.Length += (USHORT)DriverKeyLength - sizeof(UNICODE_NULL);
    }
    else
    {
@@ -759,7 +759,7 @@ IopGetBusTypeGuidIndex(LPGUID BusTypeGuid)
                  sizeof(GUID));
 
    /* The new entry is the index */
-   FoundIndex = IopBusTypeGuidList->GuidCount;
+   FoundIndex = (USHORT)IopBusTypeGuidList->GuidCount;
    IopBusTypeGuidList->GuidCount++;
 
 Quickie:
@@ -937,11 +937,11 @@ IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject,
    Irp->IoStatus.Information = 0;
 
    IrpSp = IoGetNextIrpStackLocation(Irp);
-   IrpSp->MinorFunction = MinorFunction;
+   IrpSp->MinorFunction = (UCHAR)MinorFunction;
 
    if (Stack)
    {
-      RtlMoveMemory(&IrpSp->Parameters,
+      RtlCopyMemory(&IrpSp->Parameters,
                     &Stack->Parameters,
                     sizeof(Stack->Parameters));
    }
@@ -1229,30 +1229,70 @@ IopSetDeviceInstanceData(HANDLE InstanceKey,
 }
 
 
-NTSTATUS
-IopAssignDeviceResources(PDEVICE_NODE DeviceNode)
+static NTSTATUS
+IopAssignDeviceResources(
+   IN PDEVICE_NODE DeviceNode,
+   OUT ULONG *pRequiredSize)
 {
    PIO_RESOURCE_LIST ResourceList;
    PIO_RESOURCE_DESCRIPTOR ResourceDescriptor;
-   PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated;
+   PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw;
+   PCM_PARTIAL_RESOURCE_LIST pPartialResourceList;
    ULONG NumberOfResources = 0;
-   ULONG i;
+   ULONG Size;
+   ULONG i, j;
    NTSTATUS Status;
 
-   /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
-    * by using DeviceNode->ResourceRequirements */
+   if (!DeviceNode->BootResources && !DeviceNode->ResourceRequirements)
+   {
+      /* No resource needed for this device */
+      DeviceNode->ResourceList = NULL;
+      return STATUS_SUCCESS;
+   }
+
+   /* Fill DeviceNode->ResourceList
+    * FIXME: the PnP arbiter should go there!
+    * Actually, use the BootResources if provided, else the resource list #0
+    */
+
+   IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
 
-   if (!DeviceNode->ResourceRequirements
-      || DeviceNode->ResourceRequirements->AlternativeLists == 0)
+   if (DeviceNode->BootResources)
    {
-      DeviceNode->ResourceList = DeviceNode->ResourceListTranslated = NULL;
+      /* Browse the boot resources to know if we have some custom structures */
+      Size = FIELD_OFFSET(CM_RESOURCE_LIST, List);
+      for (i = 0; i < DeviceNode->BootResources->Count; i++)
+      {
+         pPartialResourceList = &DeviceNode->BootResources->List[i].PartialResourceList;
+         if (pPartialResourceList->Version != 1 || pPartialResourceList->Revision != 1)
+         {
+            Status = STATUS_REVISION_MISMATCH;
+            goto ByeBye;
+         }
+         Size += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors)
+            + pPartialResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
+         for (j = 0; j < pPartialResourceList->Count; j++)
+         {
+            if (pPartialResourceList->PartialDescriptors[j].Type == CmResourceTypeDeviceSpecific)
+               Size += pPartialResourceList->PartialDescriptors[j].u.DeviceSpecificData.DataSize;
+         }
+      }
+
+      DeviceNode->ResourceList = ExAllocatePool(PagedPool, Size);
+      if (!DeviceNode->ResourceList)
+      {
+         Status = STATUS_NO_MEMORY;
+         goto ByeBye;
+      }
+      RtlCopyMemory(DeviceNode->ResourceList, DeviceNode->BootResources, Size);
+
+      *pRequiredSize = Size;
       return STATUS_SUCCESS;
    }
 
+   /* Ok, here, we have to use the device requirement list */
    IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
 
-   /* FIXME: that's here that PnP arbiter should go */
-   /* Actually, simply use resource list #0 as assigned resource list */
    ResourceList = &DeviceNode->ResourceRequirements->List[0];
    if (ResourceList->Version != 1 || ResourceList->Revision != 1)
    {
@@ -1260,19 +1300,12 @@ IopAssignDeviceResources(PDEVICE_NODE DeviceNode)
       goto ByeBye;
    }
 
-   DeviceNode->ResourceList = ExAllocatePool(PagedPool,
-      sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+   Size = sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
+   *pRequiredSize = Size;
+   DeviceNode->ResourceList = ExAllocatePool(PagedPool, Size);
    if (!DeviceNode->ResourceList)
    {
-      Status = STATUS_INSUFFICIENT_RESOURCES;
-      goto ByeBye;
-   }
-
-   DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool,
-      sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
-   if (!DeviceNode->ResourceListTranslated)
-   {
-      Status = STATUS_INSUFFICIENT_RESOURCES;
+      Status = STATUS_NO_MEMORY;
       goto ByeBye;
    }
 
@@ -1282,12 +1315,6 @@ IopAssignDeviceResources(PDEVICE_NODE DeviceNode)
    DeviceNode->ResourceList->List[0].PartialResourceList.Version = 1;
    DeviceNode->ResourceList->List[0].PartialResourceList.Revision = 1;
 
-   DeviceNode->ResourceListTranslated->Count = 1;
-   DeviceNode->ResourceListTranslated->List[0].InterfaceType = DeviceNode->ResourceRequirements->InterfaceType;
-   DeviceNode->ResourceListTranslated->List[0].BusNumber = DeviceNode->ResourceRequirements->BusNumber;
-   DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Version = 1;
-   DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Revision = 1;
-
    for (i = 0; i < ResourceList->Count; i++)
    {
       ResourceDescriptor = &ResourceList->Descriptors[i];
@@ -1295,31 +1322,18 @@ IopAssignDeviceResources(PDEVICE_NODE DeviceNode)
       if (ResourceDescriptor->Option == 0 || ResourceDescriptor->Option == IO_RESOURCE_PREFERRED)
       {
          DescriptorRaw = &DeviceNode->ResourceList->List[0].PartialResourceList.PartialDescriptors[NumberOfResources];
-         DescriptorTranslated = &DeviceNode->ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[NumberOfResources];
          NumberOfResources++;
 
          /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
-         DescriptorRaw->Type = DescriptorTranslated->Type = ResourceDescriptor->Type;
-         DescriptorRaw->ShareDisposition = DescriptorTranslated->ShareDisposition = ResourceDescriptor->ShareDisposition;
-         DescriptorRaw->Flags = DescriptorTranslated->Flags = ResourceDescriptor->Flags;
+         DescriptorRaw->Type = ResourceDescriptor->Type;
+         DescriptorRaw->ShareDisposition = ResourceDescriptor->ShareDisposition;
+         DescriptorRaw->Flags = ResourceDescriptor->Flags;
          switch (ResourceDescriptor->Type)
          {
             case CmResourceTypePort:
             {
-               ULONG AddressSpace = 0; /* IO space */
                DescriptorRaw->u.Port.Start = ResourceDescriptor->u.Port.MinimumAddress;
-               DescriptorRaw->u.Port.Length = DescriptorTranslated->u.Port.Length
-                  = ResourceDescriptor->u.Port.Length;
-               if (!HalTranslateBusAddress(
-                  DeviceNode->ResourceRequirements->InterfaceType,
-                  DeviceNode->ResourceRequirements->BusNumber,
-                  DescriptorRaw->u.Port.Start,
-                  &AddressSpace,
-                  &DescriptorTranslated->u.Port.Start))
-               {
-                  Status = STATUS_UNSUCCESSFUL;
-                  goto ByeBye;
-               }
+               DescriptorRaw->u.Port.Length = ResourceDescriptor->u.Port.Length;
                break;
             }
             case CmResourceTypeInterrupt:
@@ -1379,54 +1393,26 @@ IopAssignDeviceResources(PDEVICE_NODE DeviceNode)
                      }
                   }
                }
-
-               DescriptorTranslated->u.Interrupt.Level = 0;
-               DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector(
-                  DeviceNode->ResourceRequirements->InterfaceType,
-                  DeviceNode->ResourceRequirements->BusNumber,
-                  DescriptorRaw->u.Interrupt.Level,
-                  DescriptorRaw->u.Interrupt.Vector,
-                  (PKIRQL)&DescriptorTranslated->u.Interrupt.Level,
-                  &DescriptorRaw->u.Interrupt.Affinity);
-               DescriptorTranslated->u.Interrupt.Affinity = DescriptorRaw->u.Interrupt.Affinity;
                break;
             }
             case CmResourceTypeMemory:
             {
-               ULONG AddressSpace = 1; /* Memory space */
                DescriptorRaw->u.Memory.Start = ResourceDescriptor->u.Memory.MinimumAddress;
-               DescriptorRaw->u.Memory.Length = DescriptorTranslated->u.Memory.Length
-                  = ResourceDescriptor->u.Memory.Length;
-               if (!HalTranslateBusAddress(
-                  DeviceNode->ResourceRequirements->InterfaceType,
-                  DeviceNode->ResourceRequirements->BusNumber,
-                  DescriptorRaw->u.Memory.Start,
-                  &AddressSpace,
-                  &DescriptorTranslated->u.Memory.Start))
-               {
-                  Status = STATUS_UNSUCCESSFUL;
-                  goto ByeBye;
-               }
+               DescriptorRaw->u.Memory.Length = ResourceDescriptor->u.Memory.Length;
                break;
             }
             case CmResourceTypeDma:
             {
-               DescriptorRaw->u.Dma.Channel = DescriptorTranslated->u.Dma.Channel
-                  = ResourceDescriptor->u.Dma.MinimumChannel;
-               DescriptorRaw->u.Dma.Port = DescriptorTranslated->u.Dma.Port
-                  = 0; /* FIXME */
-               DescriptorRaw->u.Dma.Reserved1 = DescriptorTranslated->u.Dma.Reserved1
-                  = 0;
+               DescriptorRaw->u.Dma.Channel = ResourceDescriptor->u.Dma.MinimumChannel;
+               DescriptorRaw->u.Dma.Port = 0; /* FIXME */
+               DescriptorRaw->u.Dma.Reserved1 = 0;
                break;
             }
             case CmResourceTypeBusNumber:
             {
-               DescriptorRaw->u.BusNumber.Start = DescriptorTranslated->u.BusNumber.Start
-                  = ResourceDescriptor->u.BusNumber.MinBusNumber;
-               DescriptorRaw->u.BusNumber.Length = DescriptorTranslated->u.BusNumber.Length
-                  = ResourceDescriptor->u.BusNumber.Length;
-               DescriptorRaw->u.BusNumber.Reserved = DescriptorTranslated->u.BusNumber.Reserved
-                  = ResourceDescriptor->u.BusNumber.Reserved;
+               DescriptorRaw->u.BusNumber.Start = ResourceDescriptor->u.BusNumber.MinBusNumber;
+               DescriptorRaw->u.BusNumber.Length = ResourceDescriptor->u.BusNumber.Length;
+               DescriptorRaw->u.BusNumber.Reserved = ResourceDescriptor->u.BusNumber.Reserved;
                break;
             }
             /*CmResourceTypeDevicePrivate:
@@ -1452,10 +1438,7 @@ IopAssignDeviceResources(PDEVICE_NODE DeviceNode)
    }
 
    DeviceNode->ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
-   DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Count = NumberOfResources;
 
-   IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
-   IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED);
    return STATUS_SUCCESS;
 
 ByeBye:
@@ -1464,13 +1447,111 @@ ByeBye:
       ExFreePool(DeviceNode->ResourceList);
       DeviceNode->ResourceList = NULL;
    }
-   if (DeviceNode->ResourceListTranslated)
+   return Status;
+}
+
+
+static NTSTATUS
+IopTranslateDeviceResources(
+   IN PDEVICE_NODE DeviceNode,
+   IN ULONG RequiredSize)
+{
+   PCM_PARTIAL_RESOURCE_LIST pPartialResourceList;
+   PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated;
+   ULONG i, j;
+   NTSTATUS Status;
+
+   if (!DeviceNode->ResourceList)
    {
-      ExFreePool(DeviceNode->ResourceListTranslated);
       DeviceNode->ResourceListTranslated = NULL;
+      return STATUS_SUCCESS;
    }
 
-   IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
+   /* That's easy to translate a resource list. Just copy the
+    * untranslated one and change few fields in the copy
+    */
+   DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, RequiredSize);
+   if (!DeviceNode->ResourceListTranslated)
+   {
+      Status =STATUS_NO_MEMORY;
+      goto cleanup;
+   }
+   RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, RequiredSize);
+
+   for (i = 0; i < DeviceNode->ResourceList->Count; i++)
+   {
+      pPartialResourceList = &DeviceNode->ResourceList->List[i].PartialResourceList;
+      for (j = 0; j < pPartialResourceList->Count; j++)
+      {
+         DescriptorRaw = &pPartialResourceList->PartialDescriptors[j];
+         DescriptorTranslated = &DeviceNode->ResourceListTranslated->List[i].PartialResourceList.PartialDescriptors[j];
+         switch (DescriptorRaw->Type)
+         {
+            case CmResourceTypePort:
+            {
+               ULONG AddressSpace = 0; /* IO space */
+               if (!HalTranslateBusAddress(
+                  DeviceNode->ResourceList->List[i].InterfaceType,
+                  DeviceNode->ResourceList->List[i].BusNumber,
+                  DescriptorRaw->u.Port.Start,
+                  &AddressSpace,
+                  &DescriptorTranslated->u.Port.Start))
+               {
+                  Status = STATUS_UNSUCCESSFUL;
+                  goto cleanup;
+               }
+               break;
+            }
+            case CmResourceTypeInterrupt:
+            {
+               DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector(
+                  DeviceNode->ResourceList->List[i].InterfaceType,
+                  DeviceNode->ResourceList->List[i].BusNumber,
+                  DescriptorRaw->u.Interrupt.Level,
+                  DescriptorRaw->u.Interrupt.Vector,
+                  (PKIRQL)&DescriptorTranslated->u.Interrupt.Level,
+                  &DescriptorRaw->u.Interrupt.Affinity);
+               break;
+            }
+            case CmResourceTypeMemory:
+            {
+               ULONG AddressSpace = 1; /* Memory space */
+               if (!HalTranslateBusAddress(
+                  DeviceNode->ResourceList->List[i].InterfaceType,
+                  DeviceNode->ResourceList->List[i].BusNumber,
+                  DescriptorRaw->u.Memory.Start,
+                  &AddressSpace,
+                  &DescriptorTranslated->u.Memory.Start))
+               {
+                  Status = STATUS_UNSUCCESSFUL;
+                  goto cleanup;
+               }
+            }
+
+            case CmResourceTypeDma:
+            case CmResourceTypeBusNumber:
+            case CmResourceTypeDeviceSpecific:
+               /* Nothing to do */
+               break;
+            default:
+               DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw->Type);
+               Status = STATUS_NOT_IMPLEMENTED;
+               goto cleanup;
+         }
+      }
+   }
+   return STATUS_SUCCESS;
+
+cleanup:
+   /* Yes! Also delete ResourceList because ResourceList and
+    * ResourceListTranslated should be a pair! */
+   ExFreePool(DeviceNode->ResourceList);
+   DeviceNode->ResourceList = NULL;
+   if (DeviceNode->ResourceListTranslated)
+   {
+      ExFreePool(DeviceNode->ResourceListTranslated);
+      DeviceNode->ResourceList = NULL;
+   }
    return Status;
 }
 
@@ -1546,14 +1627,14 @@ IopGetParentIdPrefix(PDEVICE_NODE DeviceNode,
          Status = STATUS_UNSUCCESSFUL;
       else
       {
-         KeyValue.Length = KeyValue.MaximumLength = ParentIdPrefixInformation->DataLength;
+         KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
          KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
       }
       goto cleanup;
    }
    if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
    {
-      KeyValue.Length = KeyValue.MaximumLength = ParentIdPrefixInformation->DataLength;
+      KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
       KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
       goto cleanup;
    }
@@ -2030,11 +2111,25 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
 
    ZwClose(InstanceKey);
 
-   Status = IopAssignDeviceResources(DeviceNode);
-   if (!NT_SUCCESS(Status))
+   IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
+   Status = IopAssignDeviceResources(DeviceNode, &RequiredLength);
+   if (NT_SUCCESS(Status))
    {
-      DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status);
+      Status = IopTranslateDeviceResources(DeviceNode, RequiredLength);
+      if (NT_SUCCESS(Status))
+      {
+         IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED);
+      }
+      else
+      {
+         DPRINT("IopTranslateDeviceResources() failed (Status 0x08lx)\n", Status);
+      }
+   }
+   else
+   {
+      DPRINT("IopAssignDeviceResources() failed (Status 0x08lx)\n", Status);
    }
+   IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
 
    DeviceNode->Flags |= DNF_PROCESSED;
 
@@ -2235,6 +2330,10 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
       PLDR_DATA_TABLE_ENTRY ModuleObject;
       PDRIVER_OBJECT DriverObject;
 
+      /* FIXME: Remove this once the bug is fixed */
+      if (DeviceNode->ServiceName.Buffer == NULL)
+          DPRINT1("Weird DeviceNode %p having ServiceName->Buffer==NULL. Probable stack corruption or memory overwrite.\n", DeviceNode);
+
       Status = IopLoadServiceModule(&DeviceNode->ServiceName, &ModuleObject);
       if (NT_SUCCESS(Status) || Status == STATUS_IMAGE_ALREADY_LOADED)
       {
@@ -2367,7 +2466,7 @@ IopInitializePnpServices(IN PDEVICE_NODE DeviceNode,
  * The call can be make synchronous by defining the Event field
  * of the INVALIDATE_DEVICE_RELATION_DATA structure
  */
-static VOID CALLBACK
+static VOID NTAPI
 IopInvalidateDeviceRelations(
     IN PDEVICE_OBJECT DeviceObject,
     IN PVOID InvalidateContext) /* PINVALIDATE_DEVICE_RELATION_DATA */
@@ -2387,7 +2486,7 @@ IopInvalidateDeviceRelations(
     NTSTATUS Status;
     ULONG i;
 
-    DPRINT("DeviceObject 0x%p, Type %d\n", DeviceObject, Type);
+    DPRINT("DeviceObject 0x%p\n", DeviceObject);
 
     DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
 
@@ -2524,79 +2623,14 @@ cleanup:
         ExFreePool(Data);
 }
 
-VOID INIT_FUNCTION
-PnpInit(VOID)
-{
-   PDEVICE_OBJECT Pdo;
-   NTSTATUS Status;
-
-   DPRINT("PnpInit()\n");
-
-   KeInitializeSpinLock(&IopDeviceTreeLock);
-
-   /* Initialize the Bus Type GUID List */
-   IopBusTypeGuidList = ExAllocatePool(PagedPool, sizeof(IO_BUS_TYPE_GUID_LIST));
-   RtlZeroMemory(IopBusTypeGuidList, sizeof(IO_BUS_TYPE_GUID_LIST));
-   ExInitializeFastMutex(&IopBusTypeGuidList->Lock);
-
-   /* Initialize PnP-Event notification support */
-   Status = IopInitPlugPlayEvents();
-   if (!NT_SUCCESS(Status))
-   {
-      CPRINT("IopInitPlugPlayEvents() failed\n");
-      KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-   }
-
-   /*
-    * Create root device node
-    */
-
-   Status = IopCreateDriverObject(&IopRootDriverObject, NULL, 0, FALSE, NULL, 0);
-   if (!NT_SUCCESS(Status))
-   {
-      CPRINT("IoCreateDriverObject() failed\n");
-      KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-   }
-
-   Status = IoCreateDevice(IopRootDriverObject, 0, NULL, FILE_DEVICE_CONTROLLER,
-      0, FALSE, &Pdo);
-   if (!NT_SUCCESS(Status))
-   {
-      CPRINT("IoCreateDevice() failed\n");
-      KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-   }
-
-   Status = IopCreateDeviceNode(NULL, Pdo, &IopRootDeviceNode);
-   if (!NT_SUCCESS(Status))
-   {
-      CPRINT("Insufficient resources\n");
-      KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-   }
-
-   if (!RtlCreateUnicodeString(&IopRootDeviceNode->InstancePath,
-       L"HTREE\\ROOT\\0"))
-   {
-     CPRINT("Failed to create the instance path!\n");
-     KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 0, 0, 0);
-   }
-
-   /* Report the device to the user-mode pnp manager */
-   IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
-                             &IopRootDeviceNode->InstancePath);
-
-   IopRootDeviceNode->PhysicalDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
-   PnpRootDriverEntry(IopRootDriverObject, NULL);
-   IopRootDriverObject->DriverExtension->AddDevice(
-      IopRootDriverObject,
-      IopRootDeviceNode->PhysicalDeviceObject);
-}
-
 static NTSTATUS INIT_FUNCTION
 IopEnumerateDetectedDevices(
    IN HANDLE hBaseKey,
    IN PUNICODE_STRING RelativePath,
    IN HANDLE hRootKey,
-   IN BOOLEAN EnumerateSubKeys)
+   IN BOOLEAN EnumerateSubKeys,
+   IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources,
+   IN ULONG ParentBootResourcesLength)
 {
    UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier");
    UNICODE_STRING DeviceDescU = RTL_CONSTANT_STRING(L"DeviceDesc");
@@ -2618,6 +2652,8 @@ IopEnumerateDetectedDevices(
    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 IdentifierPci = RTL_CONSTANT_STRING(L"PCI BIOS");
@@ -2629,10 +2665,10 @@ IopEnumerateDetectedDevices(
    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"KeyboardPeripheral");
+   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"PointerPeripheral");
+   const UNICODE_STRING IdentifierMouse = RTL_CONSTANT_STRING(L"PointerController");
    UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*PNP0F13\0");
    static ULONG DeviceIndexMouse = 0;
    PUNICODE_STRING pHardwareId;
@@ -2688,12 +2724,12 @@ IopEnumerateDetectedDevices(
       IndexDevice++;
 
       /* Open device key */
-      DeviceName.Length = DeviceName.MaximumLength = pDeviceInformation->NameLength;
+      DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength;
       DeviceName.Buffer = pDeviceInformation->Name;
       InitializeObjectAttributes(&ObjectAttributes, &DeviceName, OBJ_KERNEL_HANDLE, hDevicesKey, NULL);
       Status = ZwOpenKey(
          &hDeviceKey,
-         KEY_QUERY_VALUE + EnumerateSubKeys ? KEY_ENUMERATE_SUB_KEYS : 0,
+         KEY_QUERY_VALUE + (EnumerateSubKeys ? KEY_ENUMERATE_SUB_KEYS : 0),
          &ObjectAttributes);
       if (!NT_SUCCESS(Status))
       {
@@ -2701,6 +2737,87 @@ IopEnumerateDetectedDevices(
          goto cleanup;
       }
 
+      /* Read boot resources, and add then to parent ones */
+      Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize);
+      if (Status == STATUS_BUFFER_OVERFLOW)
+      {
+         ExFreePool(pValueInformation);
+         ValueInfoLength = RequiredSize;
+         pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength);
+         if (!pValueInformation)
+         {
+            DPRINT("ExAllocatePool() failed\n");
+            ZwDeleteKey(hLevel2Key);
+            Status = STATUS_NO_MEMORY;
+            goto cleanup;
+         }
+         Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize);
+      }
+      if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+      {
+         BootResources = ParentBootResources;
+         BootResourcesLength = ParentBootResourcesLength;
+      }
+      else if (!NT_SUCCESS(Status))
+      {
+         DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
+         goto nextdevice;
+      }
+      else if (pValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR)
+      {
+         DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_FULL_RESOURCE_DESCRIPTOR);
+         goto nextdevice;
+      }
+      else if (((PCM_FULL_RESOURCE_DESCRIPTOR)pValueInformation->Data)->PartialResourceList.Count == 0)
+      {
+         BootResources = ParentBootResources;
+         BootResourcesLength = ParentBootResourcesLength;
+      }
+      else
+      {
+         static const ULONG Header = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors);
+
+         /* Concatenate current resources and parent ones */
+         if (ParentBootResourcesLength == 0)
+            BootResourcesLength = pValueInformation->DataLength;
+         else
+            BootResourcesLength = ParentBootResourcesLength
+               + pValueInformation->DataLength
+               - Header;
+         BootResources = ExAllocatePool(PagedPool, BootResourcesLength);
+         if (!BootResources)
+         {
+            DPRINT("ExAllocatePool() failed\n");
+            goto nextdevice;
+         }
+         if (ParentBootResourcesLength == 0)
+         {
+            RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength);
+         }
+         else if (ParentBootResources->PartialResourceList.PartialDescriptors[ParentBootResources->PartialResourceList.Count - 1].Type == CmResourceTypeDeviceSpecific)
+         {
+            RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength);
+            RtlCopyMemory(
+               (PVOID)((ULONG_PTR)BootResources + pValueInformation->DataLength),
+               (PVOID)((ULONG_PTR)ParentBootResources + Header),
+               ParentBootResourcesLength - Header);
+            BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count;
+         }
+         else
+         {
+            RtlCopyMemory(BootResources, pValueInformation->Data, Header);
+            RtlCopyMemory(
+               (PVOID)((ULONG_PTR)BootResources + Header),
+               (PVOID)((ULONG_PTR)ParentBootResources + Header),
+               ParentBootResourcesLength - Header);
+            RtlCopyMemory(
+               (PVOID)((ULONG_PTR)BootResources + ParentBootResourcesLength),
+               pValueInformation->Data + Header,
+               pValueInformation->DataLength - Header);
+            BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count;
+         }
+      }
+
       if (EnumerateSubKeys)
       {
          IndexSubKey = 0;
@@ -2728,10 +2845,16 @@ IopEnumerateDetectedDevices(
                goto cleanup;
             }
             IndexSubKey++;
-            DeviceName.Length = DeviceName.MaximumLength = pDeviceInformation->NameLength;
+            DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength;
             DeviceName.Buffer = pDeviceInformation->Name;
 
-            Status = IopEnumerateDetectedDevices(hDeviceKey, &DeviceName, hRootKey, TRUE);
+            Status = IopEnumerateDetectedDevices(
+               hDeviceKey,
+               &DeviceName,
+               hRootKey,
+               TRUE,
+               BootResources,
+               BootResourcesLength);
             if (!NT_SUCCESS(Status))
                goto cleanup;
          }
@@ -2754,31 +2877,27 @@ IopEnumerateDetectedDevices(
       }
       if (!NT_SUCCESS(Status))
       {
-         DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
-         goto nextdevice;
+         if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
+         {
+            DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
+            goto nextdevice;
+         }
       }
       else if (pValueInformation->Type != REG_SZ)
       {
          DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_SZ);
          goto nextdevice;
       }
-
-      /* Assign hardware id to this device */
-      ValueName.Length = ValueName.MaximumLength = pValueInformation->DataLength;
-      ValueName.Buffer = (PWCHAR)pValueInformation->Data;
-      if (ValueName.Length >= sizeof(WCHAR) && ValueName.Buffer[ValueName.Length / sizeof(WCHAR) - 1] == UNICODE_NULL)
-         ValueName.Length -= sizeof(WCHAR);
-      if (RtlCompareUnicodeString(&ValueName, &IdentifierPci, FALSE) == 0)
+      else
       {
-         pHardwareId = &HardwareIdPci;
-         DeviceIndex = DeviceIndexPci++;
+         /* Assign hardware id to this device */
+         ValueName.Length = ValueName.MaximumLength = (USHORT)pValueInformation->DataLength;
+         ValueName.Buffer = (PWCHAR)pValueInformation->Data;
+         if (ValueName.Length >= sizeof(WCHAR) && ValueName.Buffer[ValueName.Length / sizeof(WCHAR) - 1] == UNICODE_NULL)
+            ValueName.Length -= sizeof(WCHAR);
       }
-      /*else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0)
-      {
-         pHardwareId = &HardwareIdAcpi;
-         DeviceIndex = DeviceIndexAcpi++;
-      }*/
-      else if (RtlCompareUnicodeString(RelativePath, &IdentifierSerial, FALSE) == 0)
+
+      if (RtlCompareUnicodeString(RelativePath, &IdentifierSerial, FALSE) == 0)
       {
          pHardwareId = &HardwareIdSerial;
          DeviceIndex = DeviceIndexSerial++;
@@ -2793,10 +2912,30 @@ IopEnumerateDetectedDevices(
          pHardwareId = &HardwareIdMouse;
          DeviceIndex = DeviceIndexMouse++;
       }
+      else if (NT_SUCCESS(Status))
+      {
+         /* Try to also match the device identifier */
+         if (RtlCompareUnicodeString(&ValueName, &IdentifierPci, FALSE) == 0)
+         {
+            pHardwareId = &HardwareIdPci;
+            DeviceIndex = DeviceIndexPci++;
+         }
+         /*else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0)
+         {
+            pHardwareId = &HardwareIdAcpi;
+            DeviceIndex = DeviceIndexAcpi++;
+         }*/
+         else
+         {
+            /* Unknown device */
+            DPRINT("Unknown device '%wZ'\n", &ValueName);
+            goto nextdevice;
+         }
+      }
       else
       {
-         /* Unknown device */
-         DPRINT("Unknown device %wZ in %wZ\n", &ValueName, RelativePath);
+         /* Unknown key path */
+         DPRINT("Unknown key path %wZ\n", RelativePath);
          goto nextdevice;
       }
 
@@ -2808,7 +2947,7 @@ IopEnumerateDetectedDevices(
          &ObjectAttributes,
          0,
          NULL,
-         REG_OPTION_VOLATILE,
+         REG_OPTION_NON_VOLATILE,
          NULL);
       if (!NT_SUCCESS(Status))
       {
@@ -2824,7 +2963,7 @@ IopEnumerateDetectedDevices(
          &ObjectAttributes,
          0,
          NULL,
-         REG_OPTION_VOLATILE,
+         REG_OPTION_NON_VOLATILE,
          NULL);
       ZwClose(hLevel1Key);
       if (!NT_SUCCESS(Status))
@@ -2847,61 +2986,37 @@ IopEnumerateDetectedDevices(
          ZwDeleteKey(hLevel2Key);
          goto nextdevice;
       }
-      /* Copy 'Configuration Data' to 'LogConf\BootConfig' */
-      Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize);
-      if (Status == STATUS_BUFFER_OVERFLOW)
+      if (BootResourcesLength > 0)
       {
-         ExFreePool(pValueInformation);
-         ValueInfoLength = RequiredSize;
-         pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength);
-         if (!pValueInformation)
+         /* Save boot resources to 'LogConf\BootConfig' */
+         InitializeObjectAttributes(&ObjectAttributes, &LogConfU, OBJ_KERNEL_HANDLE, hLevel2Key, NULL);
+         Status = ZwCreateKey(
+            &hLogConf,
+            KEY_SET_VALUE,
+            &ObjectAttributes,
+            0,
+            NULL,
+            REG_OPTION_VOLATILE,
+            NULL);
+         if (!NT_SUCCESS(Status))
          {
-            DPRINT("ExAllocatePool() failed\n");
+            DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
             ZwDeleteKey(hLevel2Key);
-            Status = STATUS_NO_MEMORY;
-            goto cleanup;
+            goto nextdevice;
+         }
+         Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, REG_FULL_RESOURCE_DESCRIPTOR, BootResources, BootResourcesLength);
+         ZwClose(hLogConf);
+         if (!NT_SUCCESS(Status))
+         {
+            DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
+            ZwDeleteKey(hLevel2Key);
+            goto nextdevice;
          }
-         Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize);
-      }
-      if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
-         goto nextdevice;
-      else if (!NT_SUCCESS(Status))
-      {
-         DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
-         ZwDeleteKey(hLevel2Key);
-         goto nextdevice;
-      }
-      else if (pValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR)
-      {
-         DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_FULL_RESOURCE_DESCRIPTOR);
-         ZwDeleteKey(hLevel2Key);
-         goto nextdevice;
-      }
-      InitializeObjectAttributes(&ObjectAttributes, &LogConfU, OBJ_KERNEL_HANDLE, hLevel2Key, NULL);
-      Status = ZwCreateKey(
-         &hLogConf,
-         KEY_SET_VALUE,
-         &ObjectAttributes,
-         0,
-         NULL,
-         REG_OPTION_VOLATILE,
-         NULL);
-      if (!NT_SUCCESS(Status))
-      {
-         DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
-         ZwDeleteKey(hLevel2Key);
-         goto nextdevice;
-      }
-      Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, pValueInformation->Type, pValueInformation->Data, pValueInformation->DataLength);
-      ZwClose(hLogConf);
-      if (!NT_SUCCESS(Status))
-      {
-         DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
-         ZwDeleteKey(hLevel2Key);
-         goto nextdevice;
       }
 
 nextdevice:
+      if (BootResources && BootResources != ParentBootResources)
+         ExFreePool(BootResources);
       if (hLevel2Key)
       {
          ZwClose(hLevel2Key);
@@ -3119,24 +3234,88 @@ IopUpdateRootKey(VOID)
          NULL,
          &MultiKeyPathU,
          hRoot,
-         TRUE);
+         TRUE,
+         NULL,
+         0);
       ZwClose(hRoot);
       return Status;
    }
 }
 
 VOID INIT_FUNCTION
-PnpInit2(VOID)
+PnpInit(VOID)
 {
-   NTSTATUS Status;
+    PDEVICE_OBJECT Pdo;
+    NTSTATUS Status;
 
-   /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
-   Status = IopUpdateRootKey();
-   if (!NT_SUCCESS(Status))
-   {
-      CPRINT("IopUpdateRootKey() failed\n");
-      KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-   }
+    DPRINT("PnpInit()\n");
+
+    KeInitializeSpinLock(&IopDeviceTreeLock);
+
+    /* Initialize the Bus Type GUID List */
+    IopBusTypeGuidList = ExAllocatePool(PagedPool, sizeof(IO_BUS_TYPE_GUID_LIST));
+    RtlZeroMemory(IopBusTypeGuidList, sizeof(IO_BUS_TYPE_GUID_LIST));
+    ExInitializeFastMutex(&IopBusTypeGuidList->Lock);
+
+    /* Initialize PnP-Event notification support */
+    Status = IopInitPlugPlayEvents();
+    if (!NT_SUCCESS(Status))
+    {
+        CPRINT("IopInitPlugPlayEvents() failed\n");
+        KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
+
+    /*
+    * Create root device node
+    */
+
+    Status = IopCreateDriverObject(&IopRootDriverObject, NULL, 0, FALSE, NULL, 0);
+    if (!NT_SUCCESS(Status))
+    {
+        CPRINT("IoCreateDriverObject() failed\n");
+        KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
+
+    Status = IoCreateDevice(IopRootDriverObject, 0, NULL, FILE_DEVICE_CONTROLLER,
+        0, FALSE, &Pdo);
+    if (!NT_SUCCESS(Status))
+    {
+        CPRINT("IoCreateDevice() failed\n");
+        KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
+
+    Status = IopCreateDeviceNode(NULL, Pdo, &IopRootDeviceNode);
+    if (!NT_SUCCESS(Status))
+    {
+        CPRINT("Insufficient resources\n");
+        KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
+
+    if (!RtlCreateUnicodeString(&IopRootDeviceNode->InstancePath,
+        L"HTREE\\ROOT\\0"))
+    {
+        CPRINT("Failed to create the instance path!\n");
+        KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 0, 0, 0);
+    }
+
+    /* Report the device to the user-mode pnp manager */
+    IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
+        &IopRootDeviceNode->InstancePath);
+
+    IopRootDeviceNode->PhysicalDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
+    PnpRootDriverEntry(IopRootDriverObject, NULL);
+    IopRootDriverObject->DriverExtension->AddDevice(
+        IopRootDriverObject,
+        IopRootDeviceNode->PhysicalDeviceObject);
+
+    /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
+    Status = IopUpdateRootKey();
+    if (!NT_SUCCESS(Status))
+    {
+        CPRINT("IopUpdateRootKey() failed\n");
+        KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
 }
 
+
 /* EOF */