[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / pnproot.c
index 45759c2..7a62ed2 100644 (file)
@@ -1,18 +1,17 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/io/pnproot.c
+ * PROJECT:         ReactOS Kernel
+ * COPYRIGHT:       GPL - See COPYING in the top level directory
+ * FILE:            ntoskrnl/io/pnpmgr/pnproot.c
  * PURPOSE:         PnP manager root device
- *
  * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
- *                  Copyright 2007 Hervé Poussineau (hpoussin@reactos.org)
+ *                  Copyright 2007 Herv? Poussineau (hpoussin@reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 /* GLOBALS *******************************************************************/
 
 
 typedef struct _PNPROOT_DEVICE
 {
-  // Entry on device list
-  LIST_ENTRY ListEntry;
-  // Physical Device Object of device
-  PDEVICE_OBJECT Pdo;
-  // Device ID
-  UNICODE_STRING DeviceID;
-  // Instance ID
-  UNICODE_STRING InstanceID;
-  // Device description
-  UNICODE_STRING DeviceDescription;
-  // Resource requirement list
-  PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
-  ULONG ResourceRequirementsListSize;
-  // Associated resource list
-  PCM_RESOURCE_LIST ResourceList;
-  ULONG ResourceListSize;
+    // Entry on device list
+    LIST_ENTRY ListEntry;
+    // Physical Device Object of device
+    PDEVICE_OBJECT Pdo;
+    // Device ID
+    UNICODE_STRING DeviceID;
+    // Instance ID
+    UNICODE_STRING InstanceID;
+    // Device description
+    UNICODE_STRING DeviceDescription;
+    // Resource requirement list
+    PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
+    // Associated resource list
+    PCM_RESOURCE_LIST ResourceList;
+    ULONG ResourceListSize;
 } PNPROOT_DEVICE, *PPNPROOT_DEVICE;
 
 typedef enum
 {
-  dsStopped,
-  dsStarted,
-  dsPaused,
-  dsRemoved,
-  dsSurpriseRemoved
+    dsStopped,
+    dsStarted,
+    dsPaused,
+    dsRemoved,
+    dsSurpriseRemoved
 } PNPROOT_DEVICE_STATE;
 
 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
 {
-  // Wether this device extension is for an FDO or PDO
-  BOOLEAN IsFDO;
+    // Wether this device extension is for an FDO or PDO
+    BOOLEAN IsFDO;
 } PNPROOT_COMMON_DEVICE_EXTENSION, *PPNPROOT_COMMON_DEVICE_EXTENSION;
 
 /* Physical Device Object device extension for a child device */
 typedef struct _PNPROOT_PDO_DEVICE_EXTENSION
 {
-  // Common device data
-  PNPROOT_COMMON_DEVICE_EXTENSION Common;
-  // Informations about the device
-  PPNPROOT_DEVICE DeviceInfo;
+    // Common device data
+    PNPROOT_COMMON_DEVICE_EXTENSION Common;
+    // Informations about the device
+    PPNPROOT_DEVICE DeviceInfo;
 } PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION;
 
 /* Physical Device Object device extension for the Root bus device object */
 typedef struct _PNPROOT_FDO_DEVICE_EXTENSION
 {
-  // Common device data
-  PNPROOT_COMMON_DEVICE_EXTENSION Common;
-  // Lower device object
-  PDEVICE_OBJECT Ldo;
-  // Current state of the driver
-  PNPROOT_DEVICE_STATE State;
-  // Namespace device list
-  LIST_ENTRY DeviceListHead;
-  // Number of (not removed) devices in device list
-  ULONG DeviceListCount;
-  // Lock for namespace device list
-  KGUARDED_MUTEX DeviceListLock;
+    // Common device data
+    PNPROOT_COMMON_DEVICE_EXTENSION Common;
+    // Lower device object
+    PDEVICE_OBJECT Ldo;
+    // Current state of the driver
+    PNPROOT_DEVICE_STATE State;
+    // Namespace device list
+    LIST_ENTRY DeviceListHead;
+    // Number of (not removed) devices in device list
+    ULONG DeviceListCount;
+    // Lock for namespace device list
+    KGUARDED_MUTEX DeviceListLock;
 } PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION;
 
 typedef struct _BUFFER
 {
-  PVOID *Buffer;
-  PULONG Length;
+    PVOID *Data;
+    PULONG Length;
 } BUFFER, *PBUFFER;
 
 static PDEVICE_OBJECT PnpRootDeviceObject = NULL;
@@ -93,467 +91,494 @@ static PDEVICE_OBJECT PnpRootDeviceObject = NULL;
 
 static NTSTATUS
 LocateChildDevice(
-       IN PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension,
-       IN PCWSTR DeviceId,
-       IN PCWSTR InstanceId,
-       OUT PPNPROOT_DEVICE* ChildDevice)
+    IN PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension,
+    IN PCWSTR DeviceId,
+    IN PCWSTR InstanceId,
+    OUT PPNPROOT_DEVICE* ChildDevice)
 {
-       PPNPROOT_DEVICE Device;
-       UNICODE_STRING DeviceIdU, InstanceIdU;
-
-       RtlInitUnicodeString(&DeviceIdU, DeviceId);
-       RtlInitUnicodeString(&InstanceIdU, InstanceId);
-
-       LIST_FOR_EACH(Device, &DeviceExtension->DeviceListHead, PNPROOT_DEVICE, ListEntry)
-       {
-               if (RtlEqualUnicodeString(&DeviceIdU, &Device->DeviceID, TRUE)
-                && RtlEqualUnicodeString(&InstanceIdU, &Device->InstanceID, TRUE))
-               {
-                       *ChildDevice = Device;
-                       return STATUS_SUCCESS;
-               }
-       }
-
-       return STATUS_NO_SUCH_DEVICE;
+    PPNPROOT_DEVICE Device;
+    UNICODE_STRING DeviceIdU, InstanceIdU;
+    PLIST_ENTRY NextEntry;
+
+    /* Initialize the strings to compare  */
+    RtlInitUnicodeString(&DeviceIdU, DeviceId);
+    RtlInitUnicodeString(&InstanceIdU, InstanceId);
+
+    /* Start looping */
+    for (NextEntry = DeviceExtension->DeviceListHead.Flink;
+         NextEntry != &DeviceExtension->DeviceListHead;
+         NextEntry = NextEntry->Flink)
+    {
+        /* Get the entry */
+        Device = CONTAINING_RECORD(NextEntry, PNPROOT_DEVICE, ListEntry);
+
+        /* See if the strings match */
+        if (RtlEqualUnicodeString(&DeviceIdU, &Device->DeviceID, TRUE) &&
+            RtlEqualUnicodeString(&InstanceIdU, &Device->InstanceID, TRUE))
+        {
+            /* They do, so set the pointer and return success */
+            *ChildDevice = Device;
+            return STATUS_SUCCESS;
+        }
+    }
+
+    /* No device found */
+    return STATUS_NO_SUCH_DEVICE;
 }
 
 /* Creates a new PnP device for a legacy driver */
 NTSTATUS
 PnpRootCreateDevice(
-  IN PUNICODE_STRING ServiceName,
-  IN PDEVICE_OBJECT *PhysicalDeviceObject)
+    IN PUNICODE_STRING ServiceName,
+    OUT PDEVICE_OBJECT *PhysicalDeviceObject,
+    OUT OPTIONAL PUNICODE_STRING FullInstancePath)
 {
-  PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-  UNICODE_STRING UnknownServiceName = RTL_CONSTANT_STRING(L"UNKNOWN");
-  PUNICODE_STRING LocalServiceName;
-  PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
-  WCHAR DevicePath[MAX_PATH + 1];
-  WCHAR InstancePath[5];
-  PPNPROOT_DEVICE Device = NULL;
-  NTSTATUS Status;
-  ULONG i;
-
-  DeviceExtension = PnpRootDeviceObject->DeviceExtension;
-  KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
+    PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
+    PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
+    WCHAR DevicePath[MAX_PATH + 1];
+    WCHAR InstancePath[5];
+    PPNPROOT_DEVICE Device = NULL;
+    NTSTATUS Status;
+    UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\\");
+    ULONG NextInstance;
+    UNICODE_STRING EnumKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM);
+    HANDLE EnumHandle, DeviceKeyHandle = INVALID_HANDLE_VALUE;
+    RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+    OBJECT_ATTRIBUTES ObjectAttributes;
+
+    DeviceExtension = PnpRootDeviceObject->DeviceExtension;
+    KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
+
+    DPRINT("Creating a PnP root device for service '%wZ'\n", ServiceName);
+
+    _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\\%wZ", REGSTR_KEY_ROOTENUM, ServiceName);
+
+    /* Initialize a PNPROOT_DEVICE structure */
+    Device = ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
+    if (!Device)
+    {
+        DPRINT("ExAllocatePoolWithTag() failed\n");
+        Status = STATUS_NO_MEMORY;
+        goto cleanup;
+    }
+    RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
+    if (!RtlCreateUnicodeString(&Device->DeviceID, DevicePath))
+    {
+        Status = STATUS_NO_MEMORY;
+        goto cleanup;
+    }
 
-  if (ServiceName)
-    LocalServiceName = ServiceName;
-  else
-    LocalServiceName = &UnknownServiceName;
+    Status = IopOpenRegistryKeyEx(&EnumHandle, NULL, &EnumKeyName, KEY_READ);
+    if (NT_SUCCESS(Status))
+    {
+        InitializeObjectAttributes(&ObjectAttributes, &Device->DeviceID, OBJ_CASE_INSENSITIVE, EnumHandle, NULL);
+        Status = ZwCreateKey(&DeviceKeyHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, 0, NULL);
+        ZwClose(EnumHandle);
+    }
 
-  DPRINT("Creating a PnP root device for service '%wZ'\n", LocalServiceName);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to open registry key\n");
+        goto cleanup;
+    }
 
-  /* Search for a free instance ID */
-  _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\\LEGACY_%wZ", REGSTR_KEY_ROOTENUM, LocalServiceName);
-  for (i = 0; i < 9999; i++)
-  {
-    _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", i);
-    Status = LocateChildDevice(DeviceExtension, DevicePath, InstancePath, &Device);
-    if (Status == STATUS_NO_SUCH_DEVICE)
-      break;
-  }
-  if (i > 9999)
-  {
-    DPRINT1("Too much legacy devices reported for service '%wZ'\n", &LocalServiceName);
-    Status = STATUS_INSUFFICIENT_RESOURCES;
-    goto cleanup;
-  }
+tryagain:
+    RtlZeroMemory(QueryTable, sizeof(QueryTable));
+    QueryTable[0].Name = L"NextInstance";
+    QueryTable[0].EntryContext = &NextInstance;
+    QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+
+    Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
+                                    (PWSTR)DeviceKeyHandle,
+                                    QueryTable,
+                                    NULL,
+                                    NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        for (NextInstance = 0; NextInstance <= 9999; NextInstance++)
+        {
+             _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", NextInstance);
+             Status = LocateChildDevice(DeviceExtension, DevicePath, InstancePath, &Device);
+             if (Status == STATUS_NO_SUCH_DEVICE)
+                 break;
+        }
 
-  /* FIXME: save the new device to registry? */
+        if (NextInstance > 9999)
+        {
+            DPRINT1("Too many legacy devices reported for service '%wZ'\n", ServiceName);
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto cleanup;
+        }
+    }
 
-  /* Initialize a PNPROOT_DEVICE structure */
-  Device = ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
-  if (!Device)
-  {
-    DPRINT("ExAllocatePoolWithTag() failed\n");
-    Status = STATUS_NO_MEMORY;
-    goto cleanup;
-  }
-  RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
-  if (!RtlCreateUnicodeString(&Device->DeviceID, DevicePath))
-  {
-    Status = STATUS_NO_MEMORY;
-    goto cleanup;
-  }
-  if (!RtlCreateUnicodeString(&Device->InstanceID, InstancePath))
-  {
-    Status = STATUS_NO_MEMORY;
-    goto cleanup;
-  }
-
-  /* Initialize a device object */
-  Status = IoCreateDevice(
-    PnpRootDeviceObject->DriverObject,
-    sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
-    NULL,
-    FILE_DEVICE_CONTROLLER,
-    FILE_AUTOGENERATED_DEVICE_NAME,
-    FALSE,
-    &Device->Pdo);
-  if (!NT_SUCCESS(Status))
-  {
-    DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
-    Status = STATUS_NO_MEMORY;
-    goto cleanup;
-  }
-
-  PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
-  RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
-  PdoDeviceExtension->Common.IsFDO = FALSE;
-  PdoDeviceExtension->DeviceInfo = Device;
-
-  Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
-  Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
-
-  InsertTailList(
-    &DeviceExtension->DeviceListHead,
-    &Device->ListEntry);
-    DeviceExtension->DeviceListCount++;
+    _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", NextInstance);
+    Status = LocateChildDevice(DeviceExtension, DevicePath, InstancePath, &Device);
+    if (Status != STATUS_NO_SUCH_DEVICE || NextInstance > 9999)
+    {
+        DPRINT1("NextInstance value is corrupt! (%d)\n", NextInstance);
+        RtlDeleteRegistryValue(RTL_REGISTRY_HANDLE,
+                               (PWSTR)DeviceKeyHandle,
+                               L"NextInstance");
+        goto tryagain;
+    }
 
-  *PhysicalDeviceObject = Device->Pdo;
-  DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject, &Device->DeviceID, &Device->InstanceID);
-  Device = NULL;
-  Status = STATUS_SUCCESS;
+    NextInstance++;
+    Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE,
+                                   (PWSTR)DeviceKeyHandle,
+                                   L"NextInstance",
+                                   REG_DWORD,
+                                   &NextInstance,
+                                   sizeof(NextInstance));
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to write new NextInstance value! (0x%x)\n", Status);
+        goto cleanup;
+    }
 
-cleanup:
-  KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
-  if (Device)
-  {
-    if (Device->Pdo)
-      IoDeleteDevice(Device->Pdo);
-    RtlFreeUnicodeString(&Device->DeviceID);
-    RtlFreeUnicodeString(&Device->InstanceID);
-    ExFreePoolWithTag(Device, TAG_PNP_ROOT);
-  }
-  return Status;
-}
+    if (!RtlCreateUnicodeString(&Device->InstanceID, InstancePath))
+    {
+        Status = STATUS_NO_MEMORY;
+        goto cleanup;
+    }
 
-static NTSTATUS STDCALL
-ForwardIrpAndWaitCompletion(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       IN PVOID Context)
-{
-       if (Irp->PendingReturned)
-               KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
-       return STATUS_MORE_PROCESSING_REQUIRED;
-}
+    if (FullInstancePath)
+    {
+        FullInstancePath->MaximumLength = Device->DeviceID.Length + PathSep.Length + Device->InstanceID.Length;
+        FullInstancePath->Length = 0;
+        FullInstancePath->Buffer = ExAllocatePool(PagedPool, FullInstancePath->MaximumLength);
+        if (!FullInstancePath->Buffer)
+        {
+            Status = STATUS_NO_MEMORY;
+            goto cleanup;
+        }
 
-static NTSTATUS
-ForwardIrpAndWait(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp)
-{
-       PDEVICE_OBJECT LowerDevice;
-       KEVENT Event;
-       NTSTATUS Status;
+        RtlAppendUnicodeStringToString(FullInstancePath, &Device->DeviceID);
+        RtlAppendUnicodeStringToString(FullInstancePath, &PathSep);
+        RtlAppendUnicodeStringToString(FullInstancePath, &Device->InstanceID);
+    }
 
-       ASSERT(((PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO);
-       LowerDevice = ((PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Ldo;
+    /* Initialize a device object */
+    Status = IoCreateDevice(
+        PnpRootDeviceObject->DriverObject,
+        sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
+        NULL,
+        FILE_DEVICE_CONTROLLER,
+        FILE_AUTOGENERATED_DEVICE_NAME,
+        FALSE,
+        &Device->Pdo);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
+        Status = STATUS_NO_MEMORY;
+        goto cleanup;
+    }
 
-       ASSERT(LowerDevice);
+    PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
+    RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
+    PdoDeviceExtension->Common.IsFDO = FALSE;
+    PdoDeviceExtension->DeviceInfo = Device;
 
-       KeInitializeEvent(&Event, NotificationEvent, FALSE);
-       IoCopyCurrentIrpStackLocationToNext(Irp);
+    Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
+    Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
 
-       DPRINT("Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
-       IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
+    InsertTailList(
+        &DeviceExtension->DeviceListHead,
+        &Device->ListEntry);
+    DeviceExtension->DeviceListCount++;
 
-       Status = IoCallDriver(LowerDevice, Irp);
-       if (Status == STATUS_PENDING)
-       {
-               Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
-               if (NT_SUCCESS(Status))
-                       Status = Irp->IoStatus.Status;
-       }
+    *PhysicalDeviceObject = Device->Pdo;
+    DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject, &Device->DeviceID, &Device->InstanceID);
+    Device = NULL;
+    Status = STATUS_SUCCESS;
 
-       return Status;
+cleanup:
+    KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
+    if (Device)
+    {
+        if (Device->Pdo)
+            IoDeleteDevice(Device->Pdo);
+        RtlFreeUnicodeString(&Device->DeviceID);
+        RtlFreeUnicodeString(&Device->InstanceID);
+        ExFreePoolWithTag(Device, TAG_PNP_ROOT);
+    }
+    if (DeviceKeyHandle != INVALID_HANDLE_VALUE)
+        ZwClose(DeviceKeyHandle);
+    return Status;
 }
 
 static NTSTATUS NTAPI
 QueryStringCallback(
-       IN PWSTR ValueName,
-       IN ULONG ValueType,
-       IN PVOID ValueData,
-       IN ULONG ValueLength,
-       IN PVOID Context,
-       IN PVOID EntryContext)
+    IN PWSTR ValueName,
+    IN ULONG ValueType,
+    IN PVOID ValueData,
+    IN ULONG ValueLength,
+    IN PVOID Context,
+    IN PVOID EntryContext)
 {
-       PUNICODE_STRING String = (PUNICODE_STRING)EntryContext;
-
-       if (ValueType != REG_SZ || ValueLength == 0 || ValueLength % sizeof(WCHAR) != 0)
-               return STATUS_SUCCESS;
-
-       String->Buffer = ExAllocatePoolWithTag(PagedPool, ValueLength, TAG_PNP_ROOT);
-       if (String->Buffer == NULL)
-               return STATUS_NO_MEMORY;
-       String->Length = String->MaximumLength = (USHORT)ValueLength;
-       RtlCopyMemory(String->Buffer, ValueData, ValueLength);
-       if (ValueLength > 0 && String->Buffer[ValueLength / sizeof(WCHAR) - 1] == L'\0')
-               String->Length -= sizeof(WCHAR);
-       return STATUS_SUCCESS;
+    PUNICODE_STRING Destination = (PUNICODE_STRING)EntryContext;
+    UNICODE_STRING Source;
+
+    if (ValueType != REG_SZ || ValueLength == 0 || ValueLength % sizeof(WCHAR) != 0)
+        return STATUS_SUCCESS;
+
+    Source.MaximumLength = Source.Length = ValueLength;
+    Source.Buffer = ValueData;
+    if (Source.Length > 0 && Source.Buffer[Source.Length / sizeof(WCHAR) - 1] == UNICODE_NULL)
+        Source.Length -= sizeof(WCHAR);
+    return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &Source, Destination);
 }
 
 static NTSTATUS NTAPI
 QueryBinaryValueCallback(
-       IN PWSTR ValueName,
-       IN ULONG ValueType,
-       IN PVOID ValueData,
-       IN ULONG ValueLength,
-       IN PVOID Context,
-       IN PVOID EntryContext)
+    IN PWSTR ValueName,
+    IN ULONG ValueType,
+    IN PVOID ValueData,
+    IN ULONG ValueLength,
+    IN PVOID Context,
+    IN PVOID EntryContext)
 {
-       PBUFFER Buffer = (PBUFFER)EntryContext;
-       PVOID BinaryValue;
-
-       if (ValueLength == 0)
-       {
-               *Buffer->Buffer = NULL;
-               return STATUS_SUCCESS;
-       }
-
-       BinaryValue = ExAllocatePoolWithTag(PagedPool, ValueLength, TAG_PNP_ROOT);
-       if (BinaryValue == NULL)
-               return STATUS_NO_MEMORY;
-       RtlCopyMemory(BinaryValue, ValueData, ValueLength);
-       *Buffer->Buffer = BinaryValue;
-       if (Buffer->Length) *Buffer->Length = ValueLength;
-       return STATUS_SUCCESS;
+    PBUFFER Buffer = (PBUFFER)EntryContext;
+    PVOID BinaryValue;
+
+    if (ValueLength == 0)
+    {
+        *Buffer->Data = NULL;
+        return STATUS_SUCCESS;
+    }
+
+    BinaryValue = ExAllocatePoolWithTag(PagedPool, ValueLength, TAG_PNP_ROOT);
+    if (BinaryValue == NULL)
+        return STATUS_NO_MEMORY;
+    RtlCopyMemory(BinaryValue, ValueData, ValueLength);
+    *Buffer->Data = BinaryValue;
+    if (Buffer->Length) *Buffer->Length = ValueLength;
+    return STATUS_SUCCESS;
 }
 
 static NTSTATUS
 EnumerateDevices(
-       IN PDEVICE_OBJECT DeviceObject)
+    IN PDEVICE_OBJECT DeviceObject)
 {
-  PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  PKEY_BASIC_INFORMATION KeyInfo = NULL, SubKeyInfo = NULL;
-  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L"\\" REGSTR_KEY_ROOTENUM);
-  UNICODE_STRING SubKeyName;
-  WCHAR DevicePath[MAX_PATH + 1];
-  RTL_QUERY_REGISTRY_TABLE QueryTable[5];
-  PPNPROOT_DEVICE Device = NULL;
-  HANDLE KeyHandle = INVALID_HANDLE_VALUE;
-  HANDLE SubKeyHandle = INVALID_HANDLE_VALUE;
-  HANDLE DeviceKeyHandle = INVALID_HANDLE_VALUE;
-  ULONG BufferSize;
-  ULONG ResultSize;
-  ULONG Index1, Index2;
-  BUFFER Buffer1, Buffer2;
-  NTSTATUS Status = STATUS_UNSUCCESSFUL;
-
-  DPRINT("EnumerateDevices(FDO %p)\n", DeviceObject);
-
-  DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-  KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
-
-  BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH + 1) * sizeof(WCHAR);
-  KeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
-  if (!KeyInfo)
-  {
-    DPRINT("ExAllocatePoolWithTag() failed\n");
-    Status = STATUS_NO_MEMORY;
-    goto cleanup;
-  }
-  SubKeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
-  if (!SubKeyInfo)
-  {
-    DPRINT("ExAllocatePoolWithTag() failed\n");
-    Status = STATUS_NO_MEMORY;
-    goto cleanup;
-  }
-
-  InitializeObjectAttributes(
-    &ObjectAttributes,
-    &KeyName,
-    OBJ_CASE_INSENSITIVE,
-    NULL,
-    NULL);
-
-  Status = ZwOpenKey(&KeyHandle, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes);
-  if (!NT_SUCCESS(Status))
-  {
-    DPRINT("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyName, Status);
-    goto cleanup;
-  }
-
-  /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
-   * KeyHandle. We'll first do a first enumeration to have first level keys,
-   * and an inner one to have the real devices list.
-   */
-  Index1 = 0;
-  while (TRUE)
-  {
-    Status = ZwEnumerateKey(
-      KeyHandle,
-      Index1,
-      KeyBasicInformation,
-      KeyInfo,
-      BufferSize,
-      &ResultSize);
-    if (Status == STATUS_NO_MORE_ENTRIES)
+    PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
+    PKEY_BASIC_INFORMATION KeyInfo = NULL, SubKeyInfo = NULL;
+    UNICODE_STRING LegacyU = RTL_CONSTANT_STRING(L"LEGACY_");
+    UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L"\\" REGSTR_KEY_ROOTENUM);
+    UNICODE_STRING SubKeyName;
+    WCHAR DevicePath[MAX_PATH + 1];
+    RTL_QUERY_REGISTRY_TABLE QueryTable[5];
+    PPNPROOT_DEVICE Device = NULL;
+    HANDLE KeyHandle = INVALID_HANDLE_VALUE;
+    HANDLE SubKeyHandle = INVALID_HANDLE_VALUE;
+    HANDLE DeviceKeyHandle = INVALID_HANDLE_VALUE;
+    ULONG BufferSize;
+    ULONG ResultSize;
+    ULONG Index1, Index2;
+    BUFFER Buffer1, Buffer2;
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+    DPRINT("EnumerateDevices(FDO %p)\n", DeviceObject);
+
+    DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
+
+    BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH + 1) * sizeof(WCHAR);
+    KeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
+    if (!KeyInfo)
     {
-      Status = STATUS_SUCCESS;
-      break;
+        DPRINT("ExAllocatePoolWithTag() failed\n");
+        Status = STATUS_NO_MEMORY;
+        goto cleanup;
     }
-    else if (!NT_SUCCESS(Status))
+    SubKeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
+    if (!SubKeyInfo)
     {
-      DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
-      goto cleanup;
+        DPRINT("ExAllocatePoolWithTag() failed\n");
+        Status = STATUS_NO_MEMORY;
+        goto cleanup;
     }
 
-    /* Terminate the string */
-    KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
-
-    /* Open the key */
-    RtlInitUnicodeString(&SubKeyName, KeyInfo->Name);
-    InitializeObjectAttributes(
-      &ObjectAttributes,
-      &SubKeyName,
-      0, /* Attributes */
-      KeyHandle,
-      NULL); /* Security descriptor */
-    Status = ZwOpenKey(&SubKeyHandle, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes);
+    Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &KeyName, KEY_ENUMERATE_SUB_KEYS);
     if (!NT_SUCCESS(Status))
     {
-      DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
-      break;
+        DPRINT("IopOpenRegistryKeyEx(%wZ) failed with status 0x%08lx\n", &KeyName, Status);
+        goto cleanup;
     }
 
-    /* Enumerate the sub-keys */
-    Index2 = 0;
+    /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
+     * KeyHandle. We'll first do a first enumeration to have first level keys,
+     * and an inner one to have the real devices list.
+     */
+    Index1 = 0;
     while (TRUE)
     {
-      Status = ZwEnumerateKey(
-        SubKeyHandle,
-        Index2,
-        KeyBasicInformation,
-        SubKeyInfo,
-        BufferSize,
-        &ResultSize);
-      if (Status == STATUS_NO_MORE_ENTRIES)
-        break;
-      else if (!NT_SUCCESS(Status))
-      {
-        DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
-        break;
-      }
-
-      /* Terminate the string */
-      SubKeyInfo->Name[SubKeyInfo->NameLength / sizeof(WCHAR)] = 0;
-
-      _snwprintf(
-        DevicePath,
-        sizeof(DevicePath) / sizeof(WCHAR),
-        L"%s\\%s", REGSTR_KEY_ROOTENUM, KeyInfo->Name);
-      DPRINT("Found device %S\\%s!\n", DevicePath, SubKeyInfo->Name);
-      if (LocateChildDevice(DeviceExtension, DevicePath, SubKeyInfo->Name, &Device) == STATUS_NO_SUCH_DEVICE)
-      {
-        /* Create a PPNPROOT_DEVICE object, and add if in the list of known devices */
-        Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
-        if (!Device)
+        Status = ZwEnumerateKey(
+            KeyHandle,
+            Index1,
+            KeyBasicInformation,
+            KeyInfo,
+            BufferSize,
+            &ResultSize);
+        if (Status == STATUS_NO_MORE_ENTRIES)
         {
-          DPRINT("ExAllocatePoolWithTag() failed\n");
-          Status = STATUS_NO_MEMORY;
-          goto cleanup;
+            Status = STATUS_SUCCESS;
+            break;
         }
-        RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
-
-        /* Fill device ID and instance ID */
-        if (!RtlCreateUnicodeString(&Device->DeviceID, DevicePath))
+        else if (!NT_SUCCESS(Status))
         {
-          DPRINT("RtlCreateUnicodeString() failed\n");
-          Status = STATUS_NO_MEMORY;
-          goto cleanup;
+            DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
+            goto cleanup;
         }
 
-        if (!RtlCreateUnicodeString(&Device->InstanceID, SubKeyInfo->Name))
+        /* Terminate the string */
+        KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
+
+        /* Check if it is a legacy driver */
+        RtlInitUnicodeString(&SubKeyName, KeyInfo->Name);
+        if (RtlPrefixUnicodeString(&LegacyU, &SubKeyName, FALSE))
         {
-          DPRINT("RtlCreateUnicodeString() failed\n");
-          Status = STATUS_NO_MEMORY;
-          goto cleanup;
+            DPRINT("Ignoring legacy driver '%wZ'\n", &SubKeyName);
+            Index1++;
+            continue;
         }
 
-        /* Open registry key to fill other informations */
-        InitializeObjectAttributes(
-          &ObjectAttributes,
-          &Device->InstanceID,
-          0, /* Attributes */
-          SubKeyHandle,
-          NULL); /* Security descriptor */
-        Status = ZwOpenKey(&DeviceKeyHandle, KEY_READ, &ObjectAttributes);
+        /* Open the key */
+        Status = IopOpenRegistryKeyEx(&SubKeyHandle, KeyHandle, &SubKeyName, KEY_ENUMERATE_SUB_KEYS);
         if (!NT_SUCCESS(Status))
         {
-          DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
-          break;
+            DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status);
+            break;
         }
 
-        /* Fill other informations */
-        Buffer1.Buffer = (PVOID *)&Device->ResourceRequirementsList;
-        Buffer1.Length = NULL;
-        Buffer2.Buffer = (PVOID *)&Device->ResourceList;
-        Buffer2.Length = &Device->ResourceListSize;
-        RtlZeroMemory(QueryTable, sizeof(QueryTable));
-        QueryTable[0].QueryRoutine = QueryStringCallback;
-        QueryTable[0].Name = L"DeviceDesc";
-        QueryTable[0].EntryContext = &Device->DeviceDescription;
-        QueryTable[1].Flags = RTL_QUERY_REGISTRY_SUBKEY;
-        QueryTable[1].Name = L"LogConf";
-        QueryTable[2].QueryRoutine = QueryBinaryValueCallback;
-        QueryTable[2].Name = L"BasicConfigVector";
-        QueryTable[2].EntryContext = &Buffer1;
-        QueryTable[3].QueryRoutine = QueryBinaryValueCallback;
-        QueryTable[3].Name = L"BootConfig";
-        QueryTable[3].EntryContext = &Buffer2;
-
-        Status = RtlQueryRegistryValues(
-          RTL_REGISTRY_HANDLE,
-          (PCWSTR)DeviceKeyHandle,
-          QueryTable,
-          NULL,
-          NULL);
-        if (!NT_SUCCESS(Status))
+        /* Enumerate the sub-keys */
+        Index2 = 0;
+        while (TRUE)
         {
-          DPRINT("RtlQueryRegistryValues() failed with status 0x%08lx\n", Status);
-          break;
+            Status = ZwEnumerateKey(
+                SubKeyHandle,
+                Index2,
+                KeyBasicInformation,
+                SubKeyInfo,
+                BufferSize,
+                &ResultSize);
+            if (Status == STATUS_NO_MORE_ENTRIES)
+                break;
+            else if (!NT_SUCCESS(Status))
+            {
+                DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
+                break;
+            }
+
+            /* Terminate the string */
+            SubKeyInfo->Name[SubKeyInfo->NameLength / sizeof(WCHAR)] = 0;
+
+            _snwprintf(
+                DevicePath,
+                sizeof(DevicePath) / sizeof(WCHAR),
+                L"%s\\%s", REGSTR_KEY_ROOTENUM, KeyInfo->Name);
+            DPRINT("Found device %S\\%s!\n", DevicePath, SubKeyInfo->Name);
+            if (LocateChildDevice(DeviceExtension, DevicePath, SubKeyInfo->Name, &Device) == STATUS_NO_SUCH_DEVICE)
+            {
+                /* Create a PPNPROOT_DEVICE object, and add if in the list of known devices */
+                Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
+                if (!Device)
+                {
+                    DPRINT("ExAllocatePoolWithTag() failed\n");
+                    Status = STATUS_NO_MEMORY;
+                    goto cleanup;
+                }
+                RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
+
+                /* Fill device ID and instance ID */
+                if (!RtlCreateUnicodeString(&Device->DeviceID, DevicePath))
+                {
+                    DPRINT("RtlCreateUnicodeString() failed\n");
+                    Status = STATUS_NO_MEMORY;
+                    goto cleanup;
+                }
+
+                if (!RtlCreateUnicodeString(&Device->InstanceID, SubKeyInfo->Name))
+                {
+                    DPRINT("RtlCreateUnicodeString() failed\n");
+                    Status = STATUS_NO_MEMORY;
+                    goto cleanup;
+                }
+
+                /* Open registry key to fill other informations */
+                Status = IopOpenRegistryKeyEx(&DeviceKeyHandle, SubKeyHandle, &Device->InstanceID, KEY_READ);
+                if (!NT_SUCCESS(Status))
+                {
+                    DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status);
+                    break;
+                }
+
+                /* Fill other informations */
+                Buffer1.Data = (PVOID *)&Device->ResourceRequirementsList;
+                Buffer1.Length = NULL;
+                Buffer2.Data = (PVOID *)&Device->ResourceList;
+                Buffer2.Length = &Device->ResourceListSize;
+                RtlZeroMemory(QueryTable, sizeof(QueryTable));
+                QueryTable[0].QueryRoutine = QueryStringCallback;
+                QueryTable[0].Name = L"DeviceDesc";
+                QueryTable[0].EntryContext = &Device->DeviceDescription;
+                QueryTable[1].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+                QueryTable[1].Name = L"LogConf";
+                QueryTable[2].QueryRoutine = QueryBinaryValueCallback;
+                QueryTable[2].Name = L"BasicConfigVector";
+                QueryTable[2].EntryContext = &Buffer1;
+                QueryTable[3].QueryRoutine = QueryBinaryValueCallback;
+                QueryTable[3].Name = L"BootConfig";
+                QueryTable[3].EntryContext = &Buffer2;
+
+                Status = RtlQueryRegistryValues(
+                    RTL_REGISTRY_HANDLE,
+                    (PCWSTR)DeviceKeyHandle,
+                    QueryTable,
+                    NULL,
+                    NULL);
+                if (!NT_SUCCESS(Status))
+                {
+                    DPRINT("RtlQueryRegistryValues() failed with status 0x%08lx\n", Status);
+                    break;
+                }
+
+                ZwClose(DeviceKeyHandle);
+                DeviceKeyHandle = INVALID_HANDLE_VALUE;
+
+                /* Insert the newly created device into the list */
+                InsertTailList(
+                    &DeviceExtension->DeviceListHead,
+                    &Device->ListEntry);
+                DeviceExtension->DeviceListCount++;
+            }
+            Device = NULL;
+
+            Index2++;
         }
 
-        ZwClose(DeviceKeyHandle);
-        DeviceKeyHandle = INVALID_HANDLE_VALUE;
-
-        /* Insert the newly created device into the list */
-        InsertTailList(
-          &DeviceExtension->DeviceListHead,
-          &Device->ListEntry);
-        DeviceExtension->DeviceListCount++;
-      }
-      Device = NULL;
-
-      Index2++;
+        ZwClose(SubKeyHandle);
+        SubKeyHandle = INVALID_HANDLE_VALUE;
+        Index1++;
     }
 
-    ZwClose(SubKeyHandle);
-    SubKeyHandle = INVALID_HANDLE_VALUE;
-    Index1++;
-  }
-
 cleanup:
-  if (Device)
-  {
-    /* We have a device that has not been added to device list. We need to clean it up */
-    /* FIXME */
-    ExFreePoolWithTag(Device, TAG_PNP_ROOT);
-  }
-  if (DeviceKeyHandle != INVALID_HANDLE_VALUE)
-    ZwClose(DeviceKeyHandle);
-  if (SubKeyHandle != INVALID_HANDLE_VALUE)
-    ZwClose(SubKeyHandle);
-  if (KeyHandle != INVALID_HANDLE_VALUE)
-    ZwClose(KeyHandle);
-  ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
-  ExFreePoolWithTag(SubKeyInfo, TAG_PNP_ROOT);
-  KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
-  return Status;
+    if (Device)
+    {
+        /* We have a device that has not been added to device list. We need to clean it up */
+        /* FIXME */
+        ExFreePoolWithTag(Device, TAG_PNP_ROOT);
+    }
+    if (DeviceKeyHandle != INVALID_HANDLE_VALUE)
+        ZwClose(DeviceKeyHandle);
+    if (SubKeyHandle != INVALID_HANDLE_VALUE)
+        ZwClose(SubKeyHandle);
+    if (KeyHandle != INVALID_HANDLE_VALUE)
+        ZwClose(KeyHandle);
+    if (KeyInfo)
+        ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
+    if (SubKeyInfo)
+        ExFreePoolWithTag(SubKeyInfo, TAG_PNP_ROOT);
+    KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
+    return Status;
 }
 
 /* FUNCTION: Handle IRP_MN_QUERY_DEVICE_RELATIONS IRPs for the root bus device object
@@ -565,104 +590,112 @@ cleanup:
  */
 static NTSTATUS
 PnpRootQueryDeviceRelations(
-  IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
 {
-  PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
-  PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-  PDEVICE_RELATIONS Relations = NULL, OtherRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
-  PPNPROOT_DEVICE Device = NULL;
-  ULONG Size;
-  NTSTATUS Status;
+    PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
+    PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
+    PDEVICE_RELATIONS Relations = NULL, OtherRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
+    PPNPROOT_DEVICE Device = NULL;
+    ULONG Size;
+    NTSTATUS Status;
+    PLIST_ENTRY NextEntry;
 
-  DPRINT("PnpRootQueryDeviceRelations(FDO %p, Irp %p)\n", DeviceObject, Irp);
+    DPRINT("PnpRootQueryDeviceRelations(FDO %p, Irp %p)\n", DeviceObject, Irp);
 
-  Status = EnumerateDevices(DeviceObject);
-  if (!NT_SUCCESS(Status))
-  {
-    DPRINT("EnumerateDevices() failed with status 0x%08lx\n", Status);
-    return Status;
-  }
+    Status = EnumerateDevices(DeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("EnumerateDevices() failed with status 0x%08lx\n", Status);
+        return Status;
+    }
 
-  DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
-  Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) + sizeof(PDEVICE_OBJECT) * DeviceExtension->DeviceListCount;
-  if (OtherRelations)
-  {
-    /* Another bus driver has already created a DEVICE_RELATIONS
-     * structure so we must merge this structure with our own */
-    
-    Size += sizeof(PDEVICE_OBJECT) * OtherRelations->Count;
-  }
-  Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
-  if (!Relations)
-  {
-    DPRINT("ExAllocatePoolWithTag() failed\n");
-    Status = STATUS_NO_MEMORY;
-    goto cleanup;
-  }
-  RtlZeroMemory(Relations, Size);
-  if (OtherRelations)
-  {
-    Relations->Count = OtherRelations->Count;
-    RtlCopyMemory(Relations->Objects, OtherRelations->Objects, sizeof(PDEVICE_OBJECT) * OtherRelations->Count);
-  }
+    Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) + sizeof(PDEVICE_OBJECT) * DeviceExtension->DeviceListCount;
+    if (OtherRelations)
+    {
+        /* Another bus driver has already created a DEVICE_RELATIONS
+         * structure so we must merge this structure with our own */
 
-  KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
-  LIST_FOR_EACH(Device, &DeviceExtension->DeviceListHead, PNPROOT_DEVICE, ListEntry)
-  {
-    if (!Device->Pdo)
+        Size += sizeof(PDEVICE_OBJECT) * OtherRelations->Count;
+    }
+    Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
+    if (!Relations)
     {
-      /* Create a physical device object for the
-       * device as it does not already have one */
-      Status = IoCreateDevice(
-        DeviceObject->DriverObject,
-        sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
-        NULL,
-        FILE_DEVICE_CONTROLLER,
-        FILE_AUTOGENERATED_DEVICE_NAME,
-        FALSE,
-        &Device->Pdo);
-      if (!NT_SUCCESS(Status))
-      {
-        DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
-        break;
-      }
+        DPRINT("ExAllocatePoolWithTag() failed\n");
+        Status = STATUS_NO_MEMORY;
+        goto cleanup;
+    }
+    RtlZeroMemory(Relations, Size);
+    if (OtherRelations)
+    {
+        Relations->Count = OtherRelations->Count;
+        RtlCopyMemory(Relations->Objects, OtherRelations->Objects, sizeof(PDEVICE_OBJECT) * OtherRelations->Count);
+    }
 
-      PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
-      RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
-      PdoDeviceExtension->Common.IsFDO = FALSE;
-      PdoDeviceExtension->DeviceInfo = Device;
+    KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
 
-      Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
-      Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
-    }
+    /* Start looping */
+    for (NextEntry = DeviceExtension->DeviceListHead.Flink;
+         NextEntry != &DeviceExtension->DeviceListHead;
+         NextEntry = NextEntry->Flink)
+    {
+        /* Get the entry */
+        Device = CONTAINING_RECORD(NextEntry, PNPROOT_DEVICE, ListEntry);
+    
+        if (!Device->Pdo)
+        {
+            /* Create a physical device object for the
+             * device as it does not already have one */
+            Status = IoCreateDevice(
+                DeviceObject->DriverObject,
+                sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
+                NULL,
+                FILE_DEVICE_CONTROLLER,
+                FILE_AUTOGENERATED_DEVICE_NAME,
+                FALSE,
+                &Device->Pdo);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
+                break;
+            }
+
+            PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
+            RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
+            PdoDeviceExtension->Common.IsFDO = FALSE;
+            PdoDeviceExtension->DeviceInfo = Device;
+
+            Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
+            Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
+        }
 
-    /* Reference the physical device object. The PnP manager
-       will dereference it again when it is no longer needed */
-    ObReferenceObject(Device->Pdo);
+        /* Reference the physical device object. The PnP manager
+         will dereference it again when it is no longer needed */
+        ObReferenceObject(Device->Pdo);
 
-    Relations->Objects[Relations->Count++] = Device->Pdo;
-  }
-  KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
+        Relations->Objects[Relations->Count++] = Device->Pdo;
+    }
+    KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
 
-  Irp->IoStatus.Information = (ULONG_PTR)Relations;
+    Irp->IoStatus.Information = (ULONG_PTR)Relations;
 
 cleanup:
-  if (!NT_SUCCESS(Status))
-  {
-    if (OtherRelations)
-      ExFreePool(OtherRelations);
-    if (Relations)
-      ExFreePool(Relations);
-    if (Device && Device->Pdo)
+    if (!NT_SUCCESS(Status))
     {
-      IoDeleteDevice(Device->Pdo);
-      Device->Pdo = NULL;
+        if (OtherRelations)
+            ExFreePool(OtherRelations);
+        if (Relations)
+            ExFreePool(Relations);
+        if (Device && Device->Pdo)
+        {
+            IoDeleteDevice(Device->Pdo);
+            Device->Pdo = NULL;
+        }
     }
-  }
 
-  return Status;
+    return Status;
 }
 
 /*
@@ -675,343 +708,309 @@ cleanup:
  */
 static NTSTATUS
 PnpRootFdoPnpControl(
-  IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
 {
-  PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-  PIO_STACK_LOCATION IrpSp;
-  NTSTATUS Status;
-
-  DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-  Status = Irp->IoStatus.Status;
-  IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
-  switch (IrpSp->MinorFunction)
-  {
-    case IRP_MN_QUERY_DEVICE_RELATIONS:
-      DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
-      Status = PnpRootQueryDeviceRelations(DeviceObject, Irp);
-      break;
-
-    case IRP_MN_START_DEVICE:
-      DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
-      Status = ForwardIrpAndWait(DeviceObject, Irp);
-      if (NT_SUCCESS(Status))
-        DeviceExtension->State = dsStarted;
-      Status = STATUS_SUCCESS;
-      break;
+    PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
+    PIO_STACK_LOCATION IrpSp;
+    NTSTATUS Status;
 
-    case IRP_MN_STOP_DEVICE:
-      DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
-      /* Root device cannot be stopped */
-      Status = STATUS_NOT_SUPPORTED;
-      break;
+    DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    Status = Irp->IoStatus.Status;
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
-    default:
-      DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction);
-      Status = STATUS_NOT_IMPLEMENTED;
-      break;
-  }
+    switch (IrpSp->MinorFunction)
+    {
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+            DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
+            Status = PnpRootQueryDeviceRelations(DeviceObject, Irp);
+            break;
+
+        case IRP_MN_START_DEVICE:
+            DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
+            if (!IoForwardIrpSynchronously(DeviceExtension->Ldo, Irp))
+                Status = STATUS_UNSUCCESSFUL;
+            else
+            {
+                Status = Irp->IoStatus.Status;
+                if (NT_SUCCESS(Status))
+                    DeviceExtension->State = dsStarted;
+            }
+
+            Irp->IoStatus.Status = Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return Status;
+
+         case IRP_MN_STOP_DEVICE:
+             DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
+             /* Root device cannot be stopped */
+             Irp->IoStatus.Status = Status = STATUS_INVALID_DEVICE_REQUEST;
+             IoCompleteRequest(Irp, IO_NO_INCREMENT);
+             return Status;
+
+        default:
+            DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction);
+            break;
+    }
 
-  if (Status != STATUS_PENDING)
-  {
-    Irp->IoStatus.Status = Status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-  }
+    if (Status != STATUS_PENDING)
+    {
+       Irp->IoStatus.Status = Status;
+       IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
 
-  return Status;
+    return Status;
 }
 
 static NTSTATUS
 PdoQueryDeviceRelations(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       IN PIO_STACK_LOCATION IrpSp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
 {
-       //PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
-       PDEVICE_RELATIONS Relations;
-       DEVICE_RELATION_TYPE RelationType;
-       NTSTATUS Status = Irp->IoStatus.Status;
-
-       //DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-       RelationType = IrpSp->Parameters.QueryDeviceRelations.Type;
-
-       switch (RelationType)
-       {
-               /* FIXME: remove */
-               case BusRelations:
-               {
-                       if (IoGetAttachedDevice(DeviceObject) != DeviceObject)
-                       {
-                               /* We're not alone in the stack */
-                               PDEVICE_NODE DeviceNode;
-                               DeviceNode = IopGetDeviceNode(IopGetDeviceNode(DeviceObject)->PhysicalDeviceObject);
-                               DPRINT1("Device stack for '%wZ' (%wZ) is misbehaving ; shouldn't receive IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n",
-                                       &DeviceNode->InstancePath, &DeviceNode->ServiceName);
-                       }
-                       break;
-               }
-
-               case TargetDeviceRelation:
-               {
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
-                       Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
-                       if (!Relations)
-                       {
-                               DPRINT("ExAllocatePoolWithTag() failed\n");
-                               Status = STATUS_NO_MEMORY;
-                       }
-                       else
-                       {
-                               ObReferenceObject(DeviceObject);
-                               Relations->Count = 1;
-                               Relations->Objects[0] = DeviceObject;
-                               Status = STATUS_SUCCESS;
-                               Irp->IoStatus.Information = (ULONG_PTR)Relations;
-                       }
-                       break;
-               }
-
-               default:
-               {
-                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / unknown relation type 0x%lx\n", RelationType);
-               }
-       }
-
-       return Status;
+    PDEVICE_RELATIONS Relations;
+    NTSTATUS Status = Irp->IoStatus.Status;
+
+    if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
+        return Status;
+
+    DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
+    Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
+    if (!Relations)
+    {
+        DPRINT("ExAllocatePoolWithTag() failed\n");
+        Status = STATUS_NO_MEMORY;
+    }
+    else
+    {
+        ObReferenceObject(DeviceObject);
+        Relations->Count = 1;
+        Relations->Objects[0] = DeviceObject;
+        Status = STATUS_SUCCESS;
+        Irp->IoStatus.Information = (ULONG_PTR)Relations;
+    }
+
+    return Status;
 }
 
 static NTSTATUS
 PdoQueryCapabilities(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       IN PIO_STACK_LOCATION IrpSp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
 {
-       PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-       PDEVICE_CAPABILITIES DeviceCapabilities;
+    PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
+    PDEVICE_CAPABILITIES DeviceCapabilities;
 
-       DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-       DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
+    DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
 
-       if (DeviceCapabilities->Version != 1)
-               return STATUS_REVISION_MISMATCH;
+    if (DeviceCapabilities->Version != 1)
+        return STATUS_REVISION_MISMATCH;
 
-       DeviceCapabilities->UniqueID = TRUE;
-       /* FIXME: Fill other fields */
+    DeviceCapabilities->UniqueID = TRUE;
+    /* FIXME: Fill other fields */
 
-       return STATUS_SUCCESS;
+    return STATUS_SUCCESS;
 }
 
 static NTSTATUS
 PdoQueryResources(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       IN PIO_STACK_LOCATION IrpSp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
 {
-       PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
-       PCM_RESOURCE_LIST ResourceList;
-
-       DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-       if (DeviceExtension->DeviceInfo->ResourceList == NULL)
-       {
-               /* Create an empty resource list */
-               ResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
-               if (!ResourceList)
-                       return STATUS_NO_MEMORY;
-
-               ResourceList->Count = 0;
-
-               Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-       }
-       else
-       {
-               /* Copy existing resource requirement list */
-               ResourceList = ExAllocatePool(
-                       PagedPool,
-                       FIELD_OFFSET(CM_RESOURCE_LIST, List) + DeviceExtension->DeviceInfo->ResourceListSize);
-               if (!ResourceList)
-                       return STATUS_NO_MEMORY;
-
-               ResourceList->Count = 1;
-               RtlCopyMemory(
-                       &ResourceList->List,
-                       DeviceExtension->DeviceInfo->ResourceList,
-                       DeviceExtension->DeviceInfo->ResourceListSize);
-                       Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-       }
-
-       return STATUS_SUCCESS;
+    PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
+    PCM_RESOURCE_LIST ResourceList;
+
+    DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    if (DeviceExtension->DeviceInfo->ResourceList)
+    {
+        /* Copy existing resource requirement list */
+        ResourceList = ExAllocatePool(
+            PagedPool,
+            DeviceExtension->DeviceInfo->ResourceListSize);
+        if (!ResourceList)
+            return STATUS_NO_MEMORY;
+
+        RtlCopyMemory(
+            ResourceList,
+            DeviceExtension->DeviceInfo->ResourceList,
+            DeviceExtension->DeviceInfo->ResourceListSize);
+
+        Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
+
+        return STATUS_SUCCESS;
+    }
+    else
+    {
+        /* No resources so just return without changing the status */
+        return Irp->IoStatus.Status;
+    }
 }
 
 static NTSTATUS
 PdoQueryResourceRequirements(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       IN PIO_STACK_LOCATION IrpSp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
 {
-       PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
-       PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
-       ULONG ResourceListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List);
-
-       DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-       if (DeviceExtension->DeviceInfo->ResourceRequirementsList == NULL)
-       {
-               /* Create an empty resource list */
-               ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
-               if (!ResourceList)
-                       return STATUS_NO_MEMORY;
-
-               RtlZeroMemory(ResourceList, ResourceListSize);
-               ResourceList->ListSize = ResourceListSize;
-
-               Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-       }
-       else
-       {
-               /* Copy existing resource requirement list */
-               ResourceList = ExAllocatePool(PagedPool, DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize);
-               if (!ResourceList)
-                       return STATUS_NO_MEMORY;
-
-               RtlCopyMemory(
-                       ResourceList,
-                       DeviceExtension->DeviceInfo->ResourceRequirementsList,
-                       DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize);
-                       Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-       }
-
-       return STATUS_SUCCESS;
+    PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
+    PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
+
+    DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+    if (DeviceExtension->DeviceInfo->ResourceRequirementsList)
+    {
+        /* Copy existing resource requirement list */
+        ResourceList = ExAllocatePool(PagedPool, DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize);
+        if (!ResourceList)
+            return STATUS_NO_MEMORY;
+
+        RtlCopyMemory(
+            ResourceList,
+            DeviceExtension->DeviceInfo->ResourceRequirementsList,
+            DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize);
+
+        Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
+
+        return STATUS_SUCCESS;
+    }
+    else
+    {
+        /* No resource requirements so just return without changing the status */
+        return Irp->IoStatus.Status;
+    }
 }
 
 static NTSTATUS
 PdoQueryDeviceText(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       IN PIO_STACK_LOCATION IrpSp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
 {
-       PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
-       DEVICE_TEXT_TYPE DeviceTextType;
-       NTSTATUS Status = Irp->IoStatus.Status;
-
-       DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-       DeviceTextType = IrpSp->Parameters.QueryDeviceText.DeviceTextType;
-
-       switch (DeviceTextType)
-       {
-               case DeviceTextDescription:
-               {
-                       UNICODE_STRING String;
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
-
-                       Status = RtlDuplicateUnicodeString(
-                               RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
-                               &DeviceExtension->DeviceInfo->DeviceDescription,
-                               &String);
-                       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
-                       break;
-               }
-
-               case DeviceTextLocationInformation:
-               {
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
-                       Status = STATUS_NOT_SUPPORTED;
-                       break;
-               }
-
-               default:
-               {
-                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown query id type 0x%lx\n", DeviceTextType);
-               }
-       }
-
-       return Status;
+    PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
+    DEVICE_TEXT_TYPE DeviceTextType;
+    NTSTATUS Status = Irp->IoStatus.Status;
+
+    DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    DeviceTextType = IrpSp->Parameters.QueryDeviceText.DeviceTextType;
+
+    switch (DeviceTextType)
+    {
+        case DeviceTextDescription:
+        {
+            UNICODE_STRING String;
+            DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
+
+            Status = RtlDuplicateUnicodeString(
+                RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+                &DeviceExtension->DeviceInfo->DeviceDescription,
+                &String);
+            Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
+            break;
+        }
+
+        case DeviceTextLocationInformation:
+        {
+            DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
+            Status = STATUS_NOT_SUPPORTED;
+            break;
+        }
+
+        default:
+        {
+            DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown query id type 0x%lx\n", DeviceTextType);
+        }
+    }
+
+    return Status;
 }
 
 static NTSTATUS
 PdoQueryId(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       IN PIO_STACK_LOCATION IrpSp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
 {
-       PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
-       BUS_QUERY_ID_TYPE IdType;
-       NTSTATUS Status = Irp->IoStatus.Status;
-
-       DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-       IdType = IrpSp->Parameters.QueryId.IdType;
-
-       switch (IdType)
-       {
-               case BusQueryDeviceID:
-               {
-                       UNICODE_STRING String;
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
-
-                       Status = RtlDuplicateUnicodeString(
-                               RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
-                               &DeviceExtension->DeviceInfo->DeviceID,
-                               &String);
-                       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
-                       break;
-               }
-
-               case BusQueryHardwareIDs:
-               case BusQueryCompatibleIDs:
-               {
-                       /* Optional, do nothing */
-                       break;
-               }
-
-               case BusQueryInstanceID:
-               {
-                       UNICODE_STRING String;
-                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
-
-                       Status = RtlDuplicateUnicodeString(
-                               RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
-                               &DeviceExtension->DeviceInfo->InstanceID,
-                               &String);
-                       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
-                       break;
-               }
-
-               default:
-               {
-                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
-               }
-       }
-
-       return Status;
+    PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
+    BUS_QUERY_ID_TYPE IdType;
+    NTSTATUS Status = Irp->IoStatus.Status;
+
+    DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    IdType = IrpSp->Parameters.QueryId.IdType;
+
+    switch (IdType)
+    {
+        case BusQueryDeviceID:
+        {
+            UNICODE_STRING String;
+            DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
+
+            Status = RtlDuplicateUnicodeString(
+                RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+                &DeviceExtension->DeviceInfo->DeviceID,
+                &String);
+            Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
+            break;
+        }
+
+        case BusQueryHardwareIDs:
+        case BusQueryCompatibleIDs:
+        {
+            /* Optional, do nothing */
+            break;
+        }
+
+        case BusQueryInstanceID:
+        {
+            UNICODE_STRING String;
+            DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
+
+            Status = RtlDuplicateUnicodeString(
+                RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+                &DeviceExtension->DeviceInfo->InstanceID,
+                &String);
+            Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
+            break;
+        }
+
+        default:
+        {
+            DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
+        }
+    }
+
+    return Status;
 }
 
 static NTSTATUS
 PdoQueryBusInformation(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp,
-       IN PIO_STACK_LOCATION IrpSp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
 {
-       PPNP_BUS_INFORMATION BusInfo;
-       NTSTATUS Status;
-
-       BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), TAG_PNP_ROOT);
-       if (!BusInfo)
-               Status = STATUS_NO_MEMORY;
-       else
-       {
-               RtlCopyMemory(
-                       &BusInfo->BusTypeGuid,
-                       &GUID_BUS_TYPE_INTERNAL,
-                       sizeof(BusInfo->BusTypeGuid));
-               BusInfo->LegacyBusType = PNPBus;
-               /* We're the only root bus enumerator on the computer */
-               BusInfo->BusNumber = 0;
-               Irp->IoStatus.Information = (ULONG_PTR)BusInfo;
-               Status = STATUS_SUCCESS;
-       }
-
-       return Status;
+    PPNP_BUS_INFORMATION BusInfo;
+    NTSTATUS Status;
+
+    BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), TAG_PNP_ROOT);
+    if (!BusInfo)
+        Status = STATUS_NO_MEMORY;
+    else
+    {
+        RtlCopyMemory(
+            &BusInfo->BusTypeGuid,
+            &GUID_BUS_TYPE_INTERNAL,
+            sizeof(BusInfo->BusTypeGuid));
+        BusInfo->LegacyBusType = PNPBus;
+        /* We're the only root bus enumerator on the computer */
+        BusInfo->BusNumber = 0;
+        Irp->IoStatus.Information = (ULONG_PTR)BusInfo;
+        Status = STATUS_SUCCESS;
+    }
+
+    return Status;
 }
 
 /*
@@ -1074,24 +1073,24 @@ PnpRootPdoPnpControl(
       Status = PdoQueryId(DeviceObject, Irp, IrpSp);
       break;
 
-    case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */
-      DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
-      Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
-      break;
+        case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */
+            DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
+            Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
+            break;
 
-    default:
-      DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction);
-      Status = STATUS_NOT_IMPLEMENTED;
-      break;
-  }
+        default:
+            DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction);
+            Status = STATUS_NOT_IMPLEMENTED;
+            break;
+    }
 
-  if (Status != STATUS_PENDING)
-  {
-    Irp->IoStatus.Status = Status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-  }
+    if (Status != STATUS_PENDING)
+    {
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
 
-  return Status;
+    return Status;
 }
 
 /*
@@ -1104,94 +1103,92 @@ PnpRootPdoPnpControl(
  */
 static NTSTATUS NTAPI
 PnpRootPnpControl(
-  IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
 {
-  PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
-  NTSTATUS Status;
+    PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
+    NTSTATUS Status;
 
-  DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
-  if (DeviceExtension->IsFDO)
-    Status = PnpRootFdoPnpControl(DeviceObject, Irp);
-  else
-    Status = PnpRootPdoPnpControl(DeviceObject, Irp);
+    if (DeviceExtension->IsFDO)
+        Status = PnpRootFdoPnpControl(DeviceObject, Irp);
+    else
+        Status = PnpRootPdoPnpControl(DeviceObject, Irp);
 
-  return Status;
+    return Status;
 }
 
 NTSTATUS
-STDCALL
+NTAPI
 PnpRootAddDevice(
-  IN PDRIVER_OBJECT DriverObject,
-  IN PDEVICE_OBJECT PhysicalDeviceObject)
+    IN PDRIVER_OBJECT DriverObject,
+    IN PDEVICE_OBJECT PhysicalDeviceObject)
 {
-  PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-  NTSTATUS Status;
+    PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
+    NTSTATUS Status;
 
-  DPRINT("PnpRootAddDevice(DriverObject %p, Pdo %p)\n", DriverObject, PhysicalDeviceObject);
+    DPRINT("PnpRootAddDevice(DriverObject %p, Pdo %p)\n", DriverObject, PhysicalDeviceObject);
 
-  if (!PhysicalDeviceObject)
-  {
-    DPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject);
-    Status = STATUS_INSUFFICIENT_RESOURCES;
-    KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-  }
-
-  Status = IoCreateDevice(
-    DriverObject,
-    sizeof(PNPROOT_FDO_DEVICE_EXTENSION),
-    NULL,
-    FILE_DEVICE_BUS_EXTENDER,
-    FILE_DEVICE_SECURE_OPEN,
-    TRUE,
-    &PnpRootDeviceObject);
-  if (!NT_SUCCESS(Status))
-  {
-    DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
-    KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-  }
-  DPRINT("Created FDO %p\n", PnpRootDeviceObject);
-
-  DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
-  RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION));
-
-  DeviceExtension->Common.IsFDO = TRUE;
-  DeviceExtension->State = dsStopped;
-  InitializeListHead(&DeviceExtension->DeviceListHead);
-  DeviceExtension->DeviceListCount = 0;
-  KeInitializeGuardedMutex(&DeviceExtension->DeviceListLock);
-
-  Status = IoAttachDeviceToDeviceStackSafe(
-    PnpRootDeviceObject,
-    PhysicalDeviceObject,
-    &DeviceExtension->Ldo);
-  if (!NT_SUCCESS(Status))
-  {
-    DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
-    KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-  }
+    if (!PhysicalDeviceObject)
+    {
+        DPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject);
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
+
+    Status = IoCreateDevice(
+        DriverObject,
+        sizeof(PNPROOT_FDO_DEVICE_EXTENSION),
+        NULL,
+        FILE_DEVICE_BUS_EXTENDER,
+        FILE_DEVICE_SECURE_OPEN,
+        TRUE,
+        &PnpRootDeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
+        KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
+    DPRINT("Created FDO %p\n", PnpRootDeviceObject);
 
-  PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+    DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
+    RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION));
 
-  DPRINT("Done AddDevice()\n");
+    DeviceExtension->Common.IsFDO = TRUE;
+    DeviceExtension->State = dsStopped;
+    InitializeListHead(&DeviceExtension->DeviceListHead);
+    DeviceExtension->DeviceListCount = 0;
+    KeInitializeGuardedMutex(&DeviceExtension->DeviceListLock);
 
-  return STATUS_SUCCESS;
+    Status = IoAttachDeviceToDeviceStackSafe(
+        PnpRootDeviceObject,
+        PhysicalDeviceObject,
+        &DeviceExtension->Ldo);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
+        KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
+
+    PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+    DPRINT("Done AddDevice()\n");
+
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS NTAPI
 PnpRootDriverEntry(
-  IN PDRIVER_OBJECT DriverObject,
-  IN PUNICODE_STRING RegistryPath)
+    IN PDRIVER_OBJECT DriverObject,
+    IN PUNICODE_STRING RegistryPath)
 {
-  DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject, RegistryPath);
+    DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject, RegistryPath);
 
-  DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
+    DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
 
-  DriverObject->MajorFunction[IRP_MJ_PNP] = PnpRootPnpControl;
-  //DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl;
+    DriverObject->MajorFunction[IRP_MJ_PNP] = PnpRootPnpControl;
+    //DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl;
 
-  return STATUS_SUCCESS;
+    return STATUS_SUCCESS;
 }
-
-/* EOF */