[HALACPI]
authorCameron Gutman <aicommander@gmail.com>
Mon, 30 Jan 2012 16:23:44 +0000 (16:23 +0000)
committerCameron Gutman <aicommander@gmail.com>
Mon, 30 Jan 2012 16:23:44 +0000 (16:23 +0000)
- Create PDO earlier so ACPI can be loaded earlier in boot
[HIVESYS]
- Create critical device database with required devices for USB boot
[NTOSKRNL]
- Read the CDDB and install devices that are critical for boot
- This implementation won't be 100% correct until a PnP manager rewrite but it should work well enough for our needs
- Not complete and disabled atm

svn path=/branches/usb-bringup-trunk/; revision=55328

boot/bootdata/hivesys_i386.inf
hal/halx86/acpi/halpnpdd.c
ntoskrnl/io/pnpmgr/pnpmgr.c

index c126286..e82d5d3 100644 (file)
@@ -8,6 +8,44 @@ HKLM,"SYSTEM\CurrentControlSet\Control","WaitToKillServiceTimeout",2,"20000"
 HKLM,"SYSTEM\CurrentControlSet\Control\Biosinfo","InfName",2,"biosinfo.inf"
 HKLM,"SYSTEM\CurrentControlSet\Control\PnP",,0x00000012
 
+; Critical Device Database
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\acpipic_up","ClassGUID",0x00000000,"{4D36E966-E325-11CE-BFC1-08002BE10318}"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\*PNP0A03","Service",0x00000000,"pci"
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\*PNP0A03","ClassGUID",0x00000000,"{4D36E97D-E325-11CE-BFC1-08002BE10318}"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\*PNP0C08","Service",0x00000000,"acpi"
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\*PNP0C08","ClassGUID",0x00000000,"{4D36E97D-E325-11CE-BFC1-08002BE10318}"
+
+;HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0300","Service",0x00000000,"usbuhci"
+;HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0300","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0310","Service",0x00000000,"usbohci"
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0310","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0320","Service",0x00000000,"usbehci"
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0320","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#Class_08&SubClass_06&Prot_50","Service",0x00000000,"usbstor"
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#Class_08&SubClass_06&Prot_50","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#COMPOSITE","Service",0x00000000,"usbccgp"
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#COMPOSITE","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#CLASS_09","Service",0x00000000,"usbhub"
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#CLASS_09","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#ROOT_HUB","Service",0x00000000,"usbhub"
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#ROOT_HUB","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#ROOT_HUB20","Service",0x00000000,"usbhub"
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#ROOT_HUB20","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
+
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\GenDisk","Service",0x00000000,"disk"
+HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\GenDisk","ClassGUID",0x00000000,"{4D36E967-E325-11CE-BFC1-08002BE10318}"
+
+
 HKLM,"SYSTEM\CurrentControlSet\Control\SafeBoot","AlternateShell",2,"cmd.exe"
 
 ; Safe Boot drivers
@@ -1413,10 +1451,61 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Packet","ImagePath",0x00020000,"system32
 HKLM,"SYSTEM\CurrentControlSet\Services\Packet","Start",0x00010001,0x00000004
 HKLM,"SYSTEM\CurrentControlSet\Services\Packet","Type",0x00010001,0x00000001
 
+; USB hub driver
+HKLM,"SYSTEM\CurrentControlSet\Services\usbhub","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\usbhub","Group",0x00000000,"Boot Bus"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbhub","Tag",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\usbhub","ImagePath",0x00020000,"system32\drivers\usbhub.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbhub","Start",0x00010001,0x00000000
+
+; EHCI controller driver
+HKLM,"SYSTEM\CurrentControlSet\Services\usbehci","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\usbehci","Group",0x00000000,"Boot Bus"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbehci","Tag",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\usbehci","ImagePath",0x00020000,"system32\drivers\usbehci.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbehci","Start",0x00010001,0x00000000
+
+; OHCI controller driver
+HKLM,"SYSTEM\CurrentControlSet\Services\usbohci","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\usbohci","Group",0x00000000,"Boot Bus"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbohci","Tag",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\usbohci","ImagePath",0x00020000,"system32\drivers\usbohci.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbohci","Start",0x00010001,0x00000000
+
+; UHCI controller driver
+HKLM,"SYSTEM\CurrentControlSet\Services\usbuhci","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\usbuhci","Group",0x00000000,"Boot Bus"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbuhci","Tag",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\usbuhci","ImagePath",0x00020000,"system32\drivers\usbuhci.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbuhci","Start",0x00010001,0x00000000
+
+; USB storage driver
+HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Group",0x00000000,"Primary Disk"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Tag",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","ImagePath",0x00020000,"system32\drivers\usbstor.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Start",0x00010001,0x00000000
+
+; USB composite generic parent
+HKLM,"SYSTEM\CurrentControlSet\Services\usbccgp","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\usbccgp","Group",0x00000000,"Boot Bus"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbccgp","Tag",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\usbccgp","ImagePath",0x00020000,"system32\drivers\usbccgp.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\usbccgp","Start",0x00010001,0x00000000
+
+; ACPI driver
+HKLM,"SYSTEM\CurrentControlSet\Services\acpi","ErrorControl",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\acpi","Group",0x00000000,"Boot Bus"
+HKLM,"SYSTEM\CurrentControlSet\Services\acpi","Tag",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\acpi","ImagePath",0x00020000,"system32\drivers\acpi.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\acpi","Start",0x00010001,0x00000000
+
 ; PCI Bus driver
 HKLM,"SYSTEM\CurrentControlSet\Services\Pci","ErrorControl",0x00010001,0x00000001
-HKLM,"SYSTEM\CurrentControlSet\Services\Pci","Group",0x00000000,"Boot Bus "
+HKLM,"SYSTEM\CurrentControlSet\Services\Pci","Group",0x00000000,"Boot Bus"
 HKLM,"SYSTEM\CurrentControlSet\Services\Pci","Tag",0x00010001,0x00000002
+HKLM,"SYSTEM\CurrentControlSet\Services\Pci","ImagePath",0x00020000,"system32\drivers\pci.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\Pci","Start",0x00010001,0x00000000
 HKLM,"SYSTEM\CurrentControlSet\Services\Pci\Parameters","1045C621",0x00030003,04,00,00,00,00,00,00,00
 HKLM,"SYSTEM\CurrentControlSet\Services\Pci\Parameters","10950640",0x00030003,04,00,00,00,00,00,00,00
 HKLM,"SYSTEM\CurrentControlSet\Services\Pci\Parameters","80861230",0x00030003,04,00,00,00,00,00,00,00
index 8ca5dd3..926ef20 100644 (file)
@@ -57,47 +57,6 @@ HalpReportDetectedDevices(IN PDRIVER_OBJECT DriverObject,
                           IN ULONG Count)
 {
     PFDO_EXTENSION FdoExtension = Context;
-    PPDO_EXTENSION PdoExtension;
-    PDEVICE_OBJECT PdoDeviceObject;
-    NTSTATUS Status;
-    PDESCRIPTION_HEADER Wdrt;
-
-    /* Create the PDO */
-    Status = IoCreateDevice(DriverObject,
-                            sizeof(PDO_EXTENSION),
-                            NULL,
-                            FILE_DEVICE_BUS_EXTENDER,
-                            FILE_AUTOGENERATED_DEVICE_NAME,
-                            FALSE,
-                            &PdoDeviceObject);
-    if (!NT_SUCCESS(Status))
-    {
-        /* Fail */
-        DPRINT1("HAL: Could not create ACPI device object status=0x%08x\n", Status);
-        return;
-    }
-
-    /* Setup the PDO device extension */
-    PdoExtension = PdoDeviceObject->DeviceExtension;
-    PdoExtension->ExtensionType = PdoExtensionType;
-    PdoExtension->PhysicalDeviceObject = PdoDeviceObject;
-    PdoExtension->ParentFdoExtension = FdoExtension;
-    PdoExtension->PdoType = AcpiPdo;
-    
-    /* Add the PDO to the head of the list */
-    PdoExtension->Next = FdoExtension->ChildPdoList;
-    FdoExtension->ChildPdoList = PdoExtension;
-    
-    /* Initialization is finished */
-    PdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
-
-    /* Find the ACPI watchdog table */
-    Wdrt = HalAcpiGetTable(0, 'TRDW');
-    if (Wdrt)
-    {
-        /* FIXME: TODO */
-        DPRINT1("You have an ACPI Watchdog. That's great! You should be proud ;-)\n");
-    }
 
     /* Invalidate device relations since we added a new device */
     IoInvalidateDeviceRelations(FdoExtension->PhysicalDeviceObject, BusRelations);
@@ -110,7 +69,11 @@ HalpAddDevice(IN PDRIVER_OBJECT DriverObject,
 {
     NTSTATUS Status;
     PFDO_EXTENSION FdoExtension;
+    PPDO_EXTENSION PdoExtension;
     PDEVICE_OBJECT DeviceObject, AttachedDevice;
+    PDEVICE_OBJECT PdoDeviceObject;
+    PDESCRIPTION_HEADER Wdrt;
+
     DPRINT("HAL: PnP Driver ADD!\n");
 
     /* Create the FDO */
@@ -150,10 +113,47 @@ HalpAddDevice(IN PDRIVER_OBJECT DriverObject,
     /* Save the attachment */
     FdoExtension->AttachedDeviceObject = AttachedDevice;
 
+    /* Create the PDO */
+    Status = IoCreateDevice(DriverObject,
+                            sizeof(PDO_EXTENSION),
+                            NULL,
+                            FILE_DEVICE_BUS_EXTENDER,
+                            FILE_AUTOGENERATED_DEVICE_NAME,
+                            FALSE,
+                            &PdoDeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        DPRINT1("HAL: Could not create ACPI device object status=0x%08x\n", Status);
+        return Status;
+    }
+
+    /* Setup the PDO device extension */
+    PdoExtension = PdoDeviceObject->DeviceExtension;
+    PdoExtension->ExtensionType = PdoExtensionType;
+    PdoExtension->PhysicalDeviceObject = PdoDeviceObject;
+    PdoExtension->ParentFdoExtension = FdoExtension;
+    PdoExtension->PdoType = AcpiPdo;
+    
+    /* Add the PDO to the head of the list */
+    PdoExtension->Next = FdoExtension->ChildPdoList;
+    FdoExtension->ChildPdoList = PdoExtension;
+
+    /* Initialization is finished */
+    PdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+    /* Find the ACPI watchdog table */
+    Wdrt = HalAcpiGetTable(0, 'TRDW');
+    if (Wdrt)
+    {
+        /* FIXME: TODO */
+        DPRINT1("You have an ACPI Watchdog. That's great! You should be proud ;-)\n");
+    }
+
     /* Register for reinitialization to report devices later */
-    IoRegisterDriverReinitialization(DriverObject,
-                                     HalpReportDetectedDevices,
-                                     FdoExtension);
+    IoRegisterBootDriverReinitialization(DriverObject,
+                                         HalpReportDetectedDevices,
+                                         FdoExtension);
 
     /* Return status */
     DPRINT("Device added %lx\n", Status);
index 9d20b97..c92deeb 100644 (file)
@@ -57,6 +57,370 @@ IopGetDeviceNode(PDEVICE_OBJECT DeviceObject)
    return ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode;
 }
 
+VOID
+IopFixupDeviceId(PWCHAR String)
+{
+    ULONG Length = wcslen(String), i;
+
+    for (i = 0; i < Length; i++)
+    {
+        if (String[i] == L'\\')
+            String[i] = L'#';
+    }
+}
+
+VOID
+NTAPI
+IopInstallCriticalDevice(PDEVICE_NODE DeviceNode)
+{
+    NTSTATUS Status;
+    HANDLE CriticalDeviceKey, InstanceKey;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING CriticalDeviceKeyU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\CriticalDeviceDatabase");
+    UNICODE_STRING CompatibleIdU = RTL_CONSTANT_STRING(L"CompatibleIDs");
+    UNICODE_STRING HardwareIdU = RTL_CONSTANT_STRING(L"HardwareID");
+    UNICODE_STRING ServiceU = RTL_CONSTANT_STRING(L"Service");
+    UNICODE_STRING ClassGuidU = RTL_CONSTANT_STRING(L"ClassGUID");
+    PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
+    ULONG HidLength = 0, CidLength = 0, BufferLength;
+    PWCHAR IdBuffer, OriginalIdBuffer;
+    
+    /* Open the device instance key */
+    Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey);
+    if (Status != STATUS_SUCCESS)
+        return;
+
+    Status = ZwQueryValueKey(InstanceKey,
+                             &HardwareIdU,
+                             KeyValuePartialInformation,
+                             NULL,
+                             0,
+                             &HidLength);
+    if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL)
+    {
+        ZwClose(InstanceKey);
+        return;
+    }
+
+    Status = ZwQueryValueKey(InstanceKey,
+                             &CompatibleIdU,
+                             KeyValuePartialInformation,
+                             NULL,
+                             0,
+                             &CidLength);
+    if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL)
+    {
+        CidLength = 0;
+    }
+
+    BufferLength = HidLength + CidLength;
+    BufferLength -= (((CidLength != 0) ? 2 : 1) * FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data));
+
+    /* Allocate a buffer to hold data from both */
+    OriginalIdBuffer = IdBuffer = ExAllocatePool(PagedPool, BufferLength);
+    if (!IdBuffer)
+    {
+        ZwClose(InstanceKey);
+        return;
+    }
+
+    /* Compute the buffer size */
+    if (HidLength > CidLength)
+        BufferLength = HidLength;
+    else
+        BufferLength = CidLength;
+
+    PartialInfo = ExAllocatePool(PagedPool, BufferLength);
+    if (!PartialInfo)
+    {
+        ZwClose(InstanceKey);
+        ExFreePool(OriginalIdBuffer);
+        return;
+    }
+
+    Status = ZwQueryValueKey(InstanceKey,
+                             &HardwareIdU,
+                             KeyValuePartialInformation,
+                             PartialInfo,
+                             HidLength,
+                             &HidLength);
+    if (Status != STATUS_SUCCESS)
+    {
+        ExFreePool(PartialInfo);
+        ExFreePool(OriginalIdBuffer);
+        ZwClose(InstanceKey);
+        return;
+    }
+
+    /* Copy in HID info first (without 2nd terminating NULL if CID is present) */
+    HidLength = PartialInfo->DataLength - ((CidLength != 0) ? sizeof(WCHAR) : 0);
+    RtlCopyMemory(IdBuffer, PartialInfo->Data, HidLength);
+
+    if (CidLength != 0)
+    {
+        Status = ZwQueryValueKey(InstanceKey,
+                                 &CompatibleIdU,
+                                 KeyValuePartialInformation,
+                                 PartialInfo,
+                                 CidLength,
+                                 &CidLength);
+        if (Status != STATUS_SUCCESS)
+        {
+            ExFreePool(PartialInfo);
+            ExFreePool(OriginalIdBuffer);
+            ZwClose(InstanceKey);
+            return;
+        }
+        
+        /* Copy CID next */
+        CidLength = PartialInfo->DataLength;
+        RtlCopyMemory(((PUCHAR)IdBuffer) + HidLength, PartialInfo->Data, CidLength);
+    }
+
+    /* Free our temp buffer */
+    ExFreePool(PartialInfo);
+    
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &CriticalDeviceKeyU,
+                               OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = ZwOpenKey(&CriticalDeviceKey,
+                       KEY_ENUMERATE_SUB_KEYS,
+                       &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        /* The critical device database doesn't exist because
+         * we're probably in 1st stage setup, but it's ok */
+        ExFreePool(OriginalIdBuffer);
+        ZwClose(InstanceKey);
+        return;
+    }
+
+    while (*IdBuffer)
+    {
+        ULONG StringLength = (ULONG)wcslen(IdBuffer) + 1, Index;
+        
+        IopFixupDeviceId(IdBuffer);
+        
+        /* Look through all subkeys for a match */
+        for (Index = 0; TRUE; Index++)
+        {
+            ULONG NeededLength;
+            PKEY_BASIC_INFORMATION BasicInfo;
+            
+            Status = ZwEnumerateKey(CriticalDeviceKey,
+                                    Index,
+                                    KeyBasicInformation,
+                                    NULL,
+                                    0,
+                                    &NeededLength);
+            if (Status == STATUS_NO_MORE_ENTRIES)
+                break;
+            else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
+            {
+                UNICODE_STRING ChildIdNameU, RegKeyNameU;
+
+                BasicInfo = ExAllocatePool(PagedPool, NeededLength);
+                if (!BasicInfo)
+                {
+                    /* No memory */
+                    ExFreePool(OriginalIdBuffer);
+                    ZwClose(CriticalDeviceKey);
+                    ZwClose(InstanceKey);
+                    return;
+                }
+
+                Status = ZwEnumerateKey(CriticalDeviceKey,
+                                        Index,
+                                        KeyBasicInformation,
+                                        BasicInfo,
+                                        NeededLength,
+                                        &NeededLength);
+                if (Status != STATUS_SUCCESS)
+                {
+                    /* This shouldn't happen */
+                    ExFreePool(BasicInfo);
+                    continue;
+                }
+
+                ChildIdNameU.Buffer = IdBuffer;
+                ChildIdNameU.MaximumLength = ChildIdNameU.Length = (StringLength - 1) * sizeof(WCHAR);
+                RegKeyNameU.Buffer = BasicInfo->Name;
+                RegKeyNameU.MaximumLength = RegKeyNameU.Length = BasicInfo->NameLength;
+
+                if (RtlEqualUnicodeString(&ChildIdNameU, &RegKeyNameU, TRUE))
+                {
+                    HANDLE ChildKeyHandle;
+
+                    InitializeObjectAttributes(&ObjectAttributes,
+                                               &ChildIdNameU,
+                                               OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
+                                               CriticalDeviceKey,
+                                               NULL);
+
+                    Status = ZwOpenKey(&ChildKeyHandle,
+                                       KEY_QUERY_VALUE,
+                                       &ObjectAttributes);
+                    if (Status != STATUS_SUCCESS)
+                    {
+                        ExFreePool(BasicInfo);
+                        continue;
+                    }
+
+                    /* Check if there's already a driver installed */
+                    Status = ZwQueryValueKey(InstanceKey,
+                                             &ClassGuidU,
+                                             KeyValuePartialInformation,
+                                             NULL,
+                                             0,
+                                             &NeededLength);
+                    if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
+                    {
+                        ExFreePool(BasicInfo);
+                        continue;
+                    }
+
+                    Status = ZwQueryValueKey(ChildKeyHandle,
+                                             &ClassGuidU,
+                                             KeyValuePartialInformation,
+                                             NULL,
+                                             0,
+                                             &NeededLength);
+                    if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL)
+                    {
+                        ExFreePool(BasicInfo);
+                        continue;
+                    }
+
+                    PartialInfo = ExAllocatePool(PagedPool, NeededLength);
+                    if (!PartialInfo)
+                    {
+                        ExFreePool(OriginalIdBuffer);
+                        ExFreePool(BasicInfo);
+                        ZwClose(InstanceKey);
+                        ZwClose(ChildKeyHandle);
+                        ZwClose(CriticalDeviceKey);
+                        return;
+                    }
+
+                    /* Read ClassGUID entry in the CDDB */
+                    Status = ZwQueryValueKey(ChildKeyHandle,
+                                             &ClassGuidU,
+                                             KeyValuePartialInformation,
+                                             PartialInfo,
+                                             NeededLength,
+                                             &NeededLength);
+                    if (Status != STATUS_SUCCESS)
+                    {
+                        ExFreePool(BasicInfo);
+                        continue;
+                    }
+
+                    /* Write it to the ENUM key */
+                    Status = ZwSetValueKey(InstanceKey,
+                                           &ClassGuidU,
+                                           0,
+                                           REG_SZ,
+                                           PartialInfo->Data,
+                                           PartialInfo->DataLength);
+                    if (Status != STATUS_SUCCESS)
+                    {
+                        ExFreePool(BasicInfo);
+                        ExFreePool(PartialInfo);
+                        ZwClose(ChildKeyHandle);
+                        continue;
+                    }
+
+                    Status = ZwQueryValueKey(ChildKeyHandle,
+                                             &ServiceU,
+                                             KeyValuePartialInformation,
+                                             NULL,
+                                             0,
+                                             &NeededLength);
+                    if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
+                    {
+                        ExFreePool(PartialInfo);
+                        PartialInfo = ExAllocatePool(PagedPool, NeededLength);
+                        if (!PartialInfo)
+                        {
+                            ExFreePool(OriginalIdBuffer);
+                            ExFreePool(BasicInfo);
+                            ZwClose(InstanceKey);
+                            ZwClose(ChildKeyHandle);
+                            ZwClose(CriticalDeviceKey);
+                            return;
+                        }
+
+                        /* Read the service entry from the CDDB */
+                        Status = ZwQueryValueKey(ChildKeyHandle,
+                                                 &ServiceU,
+                                                 KeyValuePartialInformation,
+                                                 PartialInfo,
+                                                 NeededLength,
+                                                 &NeededLength);
+                        if (Status != STATUS_SUCCESS)
+                        {
+                            ExFreePool(BasicInfo);
+                            ExFreePool(PartialInfo);
+                            ZwClose(ChildKeyHandle);
+                            continue;
+                        }
+
+                        /* Write it to the ENUM key */
+                        Status = ZwSetValueKey(InstanceKey,
+                                               &ServiceU,
+                                               0,
+                                               REG_SZ,
+                                               PartialInfo->Data,
+                                               PartialInfo->DataLength);
+                        if (Status != STATUS_SUCCESS)
+                        {
+                            ExFreePool(BasicInfo);
+                            ExFreePool(PartialInfo);
+                            ZwClose(ChildKeyHandle);
+                            continue;
+                        }
+
+                        DPRINT1("Installed service '%S' for critical device '%wZ'\n", PartialInfo->Data, &ChildIdNameU);
+                    }
+                    else
+                    {
+                        DPRINT1("Installed NULL service for critical device '%wZ'\n", &ChildIdNameU);
+                    }
+
+                    /* We need to enumerate children */
+                    DeviceNode->Flags |= DNF_NEED_TO_ENUM;
+
+                    ExFreePool(OriginalIdBuffer);
+                    ExFreePool(PartialInfo);
+                    ExFreePool(BasicInfo);
+                    ZwClose(InstanceKey);
+                    ZwClose(ChildKeyHandle);
+                    ZwClose(CriticalDeviceKey);
+
+                    /* That's it */
+                    return;
+                }
+
+                ExFreePool(BasicInfo);
+            }
+            else
+            {
+                /* Umm, not sure what happened here */
+                continue;
+            }
+        }
+
+        /* Advance to the next ID */
+        IdBuffer += StringLength;
+    }
+    
+    ExFreePool(OriginalIdBuffer);
+    ZwClose(InstanceKey);
+    ZwClose(CriticalDeviceKey);
+}
+
 NTSTATUS
 FASTCALL
 IopInitializeDevice(PDEVICE_NODE DeviceNode,
@@ -1869,6 +2233,8 @@ IopEnumerateDevice(
                                   &DeviceNode->InstancePath);
     }
 
+    DeviceNode->Flags &= ~DNF_NEED_TO_ENUM;
+
     DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
 
     Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
@@ -2053,6 +2419,9 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
       WCHAR RegKeyBuffer[MAX_PATH];
       UNICODE_STRING RegKey;
 
+      /* Install the service for this if it's in the CDDB */
+      //IopInstallCriticalDevice(DeviceNode);
+
       RegKey.Length = 0;
       RegKey.MaximumLength = sizeof(RegKeyBuffer);
       RegKey.Buffer = RegKeyBuffer;
@@ -2184,7 +2553,25 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
    if (IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED) ||
        IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) ||
        IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED))
+   {
+       if (DeviceNode->Flags & DNF_NEED_TO_ENUM)
+       {
+           Status = IopInitializeDevice(DeviceNode, NULL);
+           if (NT_SUCCESS(Status))
+           {
+               /* HACK */
+               DeviceNode->Flags &= ~DNF_STARTED;
+               Status = IopStartDevice(DeviceNode);
+               if (!NT_SUCCESS(Status))
+               {
+                   DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
+                           &DeviceNode->InstancePath, Status);
+               }
+           }
+           DeviceNode->Flags &= ~DNF_NEED_TO_ENUM;
+       }
        return STATUS_SUCCESS;
+   }
 
    if (DeviceNode->ServiceName.Buffer == NULL)
    {