[ros-diffs] [hpoussin] 26988: Rewrite pnproot: - Don't create multiple devices with the same pnp id (Root\UNKNOWN\0000) - Use RtlQueryRegistryValues to read multiple registry values - Keep devices list in memory instead of always reading the registry - Support IRP_MN_QUERY_DEVICE_TEXT/IRP_MN_QUERY_ID/IRP_MN_QUERY_BUS_INFORMATION/IRP_MN_FILTER_RESOURCE_REQUIREMENTS - Better error handling - ...

hpoussin at svn.reactos.org hpoussin at svn.reactos.org
Fri Jun 8 17:35:21 CEST 2007


Author: hpoussin
Date: Mon Jun  4 13:15:04 2007
New Revision: 26988

URL: http://svn.reactos.org/svn/reactos?rev=26988&view=rev
Log:
Rewrite pnproot:
- Don't create multiple devices with the same pnp id (Root\UNKNOWN\0000)
- Use RtlQueryRegistryValues to read multiple registry values
- Keep devices list in memory instead of always reading the registry
- Support IRP_MN_QUERY_DEVICE_TEXT/IRP_MN_QUERY_ID/IRP_MN_QUERY_BUS_INFORMATION/IRP_MN_FILTER_RESOURCE_REQUIREMENTS
- Better error handling
- ...

Modified:
    trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c

Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c?rev=26988&r1=26987&r2=26988&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c (original)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c Mon Jun  4 13:15:04 2007
@@ -5,6 +5,7 @@
  * PURPOSE:         PnP manager root device
  *
  * PROGRAMMERS:     Casper S. Hornstrup (chorns at users.sourceforge.net)
+ *                  Copyright 2007 Hervé Poussineau (hpoussin at reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
@@ -25,19 +26,18 @@
   LIST_ENTRY ListEntry;
   // Physical Device Object of device
   PDEVICE_OBJECT Pdo;
-  // Service name
-  UNICODE_STRING ServiceName;
   // Device ID
   UNICODE_STRING DeviceID;
   // Instance ID
   UNICODE_STRING InstanceID;
   // Device description
   UNICODE_STRING DeviceDescription;
-  // Boot resource list
-  PCM_FULL_RESOURCE_DESCRIPTOR BootResourceList;
-  SIZE_T BootResourceListSize;
   // Resource requirement list
   PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
+  ULONG ResourceRequirementsListSize;
+  // Associated resource list
+  PCM_RESOURCE_LIST ResourceList;
+  ULONG ResourceListSize;
 } PNPROOT_DEVICE, *PPNPROOT_DEVICE;
 
 typedef enum
@@ -49,39 +49,26 @@
   dsSurpriseRemoved
 } PNPROOT_DEVICE_STATE;
 
-
-#include <pshpack1.h>
-
 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
 {
-  // Pointer to device object, this device extension is associated with
-  PDEVICE_OBJECT DeviceObject;
   // Wether this device extension is for an FDO or PDO
   BOOLEAN IsFDO;
-  // Wether the device is removed
-  BOOLEAN Removed;
-  // Current device power state for the device
-  DEVICE_POWER_STATE DevicePowerState;
 } 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;
-  // Device
-  PPNPROOT_DEVICE Device;
+  // Informations about the device
+  PPNPROOT_DEVICE DeviceInfo;
 } PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION;
 
-
-/* Functional Device Object device extension for the PCI driver device object */
+/* 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;
-  // Physical Device Object
-  PDEVICE_OBJECT Pdo;
   // Lower device object
   PDEVICE_OBJECT Ldo;
   // Current state of the driver
@@ -91,43 +78,110 @@
   // Number of (not removed) devices in device list
   ULONG DeviceListCount;
   // Lock for namespace device list
-  // FIXME: Use fast mutex instead?
-  KSPIN_LOCK DeviceListLock;
+  KGUARDED_MUTEX DeviceListLock;
 } PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION;
 
-#include <poppack.h>
-
-
-
-PDEVICE_OBJECT PnpRootDeviceObject;
-
+typedef struct _BUFFER
+{
+  PVOID *Buffer;
+  PULONG Length;
+} BUFFER, *PBUFFER;
+
+static PDEVICE_OBJECT PnpRootDeviceObject = NULL;
 
 /* FUNCTIONS *****************************************************************/
 
-/* Physical Device Object routines */
-
+static NTSTATUS
+LocateChildDevice(
+	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;
+}
+
+/* Creates a new PnP device for a legacy driver */
 NTSTATUS
 PnpRootCreateDevice(
-  PUNICODE_STRING ServiceName,
-  PDEVICE_OBJECT *PhysicalDeviceObject)
-{
+  IN PUNICODE_STRING ServiceName,
+  IN PDEVICE_OBJECT *PhysicalDeviceObject)
+{
+  PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
+  UNICODE_STRING UnknownServiceName = RTL_CONSTANT_STRING(L"UNKNOWN");
+  PUNICODE_STRING LocalServiceName;
   PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
-  PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-  PPNPROOT_DEVICE Device;
+  WCHAR DevicePath[MAX_PATH + 1];
+  WCHAR InstancePath[5];
+  PPNPROOT_DEVICE Device = NULL;
   NTSTATUS Status;
-
-  /* This function should be obsoleted soon */
-
-  DPRINT("Called\n");
-
-  DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
-
-  Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
+  ULONG i;
+
+  DeviceExtension = PnpRootDeviceObject->DeviceExtension;
+  KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
+
+  if (ServiceName)
+    LocalServiceName = ServiceName;
+  else
+    LocalServiceName = &UnknownServiceName;
+
+  DPRINT("Creating a PnP root device for service '%wZ'\n", LocalServiceName);
+
+  /* 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;
+  }
+
+  /* FIXME: save the new device to registry? */
+
+  /* Initialize a PNPROOT_DEVICE structure */
+  Device = ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
   if (!Device)
-    return STATUS_INSUFFICIENT_RESOURCES;
-
-  RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
-
+  {
+    DPRINT("ExAllocatePoolWithTag() failed\n");
+    Status = STATUS_NO_MEMORY;
+    goto cleanup;
+  }
+  RtlZeroMemory(Device, sizeof(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),
@@ -136,564 +190,198 @@
     FILE_AUTOGENERATED_DEVICE_NAME,
     FALSE,
     &Device->Pdo);
-  if (!NT_SUCCESS(Status)) {
-    DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
-    ExFreePool(Device);
-    return Status;
-  }
+  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;
 
-  //Device->Pdo->Flags |= DO_POWER_PAGABLE;
-
-  PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
-
-  RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
-
-  PdoDeviceExtension->Common.IsFDO = FALSE;
-
-  PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
-
-  PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
-
-  ExInterlockedInsertTailList(
+  InsertTailList(
     &DeviceExtension->DeviceListHead,
-    &Device->ListEntry,
-    &DeviceExtension->DeviceListLock);
-
-  DeviceExtension->DeviceListCount++;
+    &Device->ListEntry);
+    DeviceExtension->DeviceListCount++;
 
   *PhysicalDeviceObject = Device->Pdo;
-
-  return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-PdoQueryId(
-  IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp,
-  PIO_STACK_LOCATION IrpSp)
-{
-  PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
-  UNICODE_STRING String;
-  NTSTATUS Status;
-
-  DPRINT("Called\n");
-
-  DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-//  Irp->IoStatus.Information = 0;
-
+  DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject, &Device->DeviceID, &Device->InstanceID);
+  Device = NULL;
   Status = STATUS_SUCCESS;
 
-  RtlInitUnicodeString(&String, NULL);
-
-  switch (IrpSp->Parameters.QueryId.IdType) {
-    case BusQueryDeviceID:
-      if (DeviceExtension->Device)
-        Status = RtlDuplicateUnicodeString(TRUE,
-                                         &DeviceExtension->Device->DeviceID,
-                                         &String);
-      else
-        Status = RtlCreateUnicodeString(&String, ENUM_NAME_ROOT L"\\LEGACY_UNKNOWN");
-
-      DPRINT("DeviceID: %wZ\n", &String);
-
-      Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
-      break;
-
-    case BusQueryHardwareIDs:
-    case BusQueryCompatibleIDs:
-      Status = STATUS_NOT_IMPLEMENTED;
-      break;
-
-    case BusQueryInstanceID:
-      if (DeviceExtension->Device)
-        Status = RtlDuplicateUnicodeString(TRUE,
-                                         &DeviceExtension->Device->InstanceID,
-                                         &String);
-      else
-        Status = RtlCreateUnicodeString(&String, L"0000");
-
-      DPRINT("InstanceID: %S\n", String.Buffer);
-
-      Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
-      break;
-
-    case BusQueryDeviceSerialNumber:
-    default:
-      Status = STATUS_NOT_IMPLEMENTED;
-  }
-
+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;
 }
 
-
-NTSTATUS
-PdoQueryResources(
-  IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp,
-  PIO_STACK_LOCATION IrpSp)
-{
-  PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
-  PCM_RESOURCE_LIST ResourceList;
-  ULONG ResourceListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List);
-
-  DPRINT("Called\n");
-
-  DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-  
-  if (!DeviceExtension->Device || DeviceExtension->Device->BootResourceList == NULL)
-  {
-    /* Create an empty resource list */
-    ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
-    if (ResourceList == NULL)
-      return STATUS_INSUFFICIENT_RESOURCES;
-
-    ResourceList->Count = 0;
-
-    Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-  }
-  else
-  {
-    /* Copy existing resource list */
-    ResourceList = ExAllocatePool(PagedPool,
-      FIELD_OFFSET(CM_RESOURCE_LIST, List) +  DeviceExtension->Device->BootResourceListSize);
-    if (ResourceList == NULL)
-      return STATUS_INSUFFICIENT_RESOURCES;
-
-    ResourceList->Count = 1;
-    RtlCopyMemory(
-      &ResourceList->List,
-      DeviceExtension->Device->BootResourceList,
-      DeviceExtension->Device->BootResourceListSize);
-    Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-  }
-
-  return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-PdoQueryResourceRequirements(
-  IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp,
-  PIO_STACK_LOCATION IrpSp)
-{
-  PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
-  PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
-  ULONG ResourceListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List);
-
-  DPRINT("Called\n");
-
-  DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-  
-  if (!DeviceExtension->Device || DeviceExtension->Device->ResourceRequirementsList == NULL)
-  {
-    /* Create an empty resource list */
-    ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
-    if (ResourceList == NULL)
-      return STATUS_INSUFFICIENT_RESOURCES;
-
-    RtlZeroMemory(ResourceList, ResourceListSize);
-    ResourceList->ListSize = ResourceListSize;
-
-    Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-  }
-  else
-  {
-    /* Copy existing resource requirement list */
-    ResourceList = ExAllocatePool(PagedPool, DeviceExtension->Device->ResourceRequirementsList->ListSize);
-    if (ResourceList == NULL)
-      return STATUS_INSUFFICIENT_RESOURCES;
-
-    RtlCopyMemory(
-      ResourceList,
-      DeviceExtension->Device->ResourceRequirementsList,
-      DeviceExtension->Device->ResourceRequirementsList->ListSize);
-    Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-  }
-
-  return STATUS_SUCCESS;
-}
-
-
-static NTSTATUS
-PnpRootPdoQueryCapabilities(
-  IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp,
-  PIO_STACK_LOCATION IrpSp)
+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;
+}
+
+static NTSTATUS
+ForwardIrpAndWait(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp)
+{
+	PDEVICE_OBJECT LowerDevice;
+	KEVENT Event;
+	NTSTATUS Status;
+
+	ASSERT(((PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO);
+	LowerDevice = ((PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Ldo;
+
+	ASSERT(LowerDevice);
+
+	KeInitializeEvent(&Event, NotificationEvent, FALSE);
+	IoCopyCurrentIrpStackLocationToNext(Irp);
+
+	DPRINT("Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
+	IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
+
+	Status = IoCallDriver(LowerDevice, Irp);
+	if (Status == STATUS_PENDING)
+	{
+		Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
+		if (NT_SUCCESS(Status))
+			Status = Irp->IoStatus.Status;
+	}
+
+	return Status;
+}
+
+static NTSTATUS NTAPI
+QueryStringCallback(
+	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 = ValueLength;
+	RtlCopyMemory(String->Buffer, ValueData, ValueLength);
+	if (ValueLength > 0 && String->Buffer[ValueLength / sizeof(WCHAR) - 1] == L'\0')
+		String->Length -= sizeof(WCHAR);
+	return STATUS_SUCCESS;
+}
+
+static NTSTATUS NTAPI
+QueryBinaryValueCallback(
+	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;
+}
+
+static NTSTATUS
+EnumerateDevices(
+	IN PDEVICE_OBJECT DeviceObject)
 {
   PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-  PDEVICE_CAPABILITIES DeviceCapabilities;
-
-  DPRINT("Called\n");
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  PKEY_BASIC_INFORMATION KeyInfo = NULL, SubKeyInfo = NULL;
+  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM "\\" REGSTR_KEY_ROOTENUM);
+  UNICODE_STRING SubKeyName;
+  WCHAR DevicePath[MAX_PATH + 1];
+  RTL_QUERY_REGISTRY_TABLE QueryTable[4];
+  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;
-  DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
-
-  if (DeviceCapabilities->Version != 1)
-    return STATUS_UNSUCCESSFUL;
-
-  DeviceCapabilities->UniqueID = TRUE;
-  /* FIXME: Fill other fields */
-
-  return STATUS_SUCCESS;
-}
-
-
-/*
- * FUNCTION: Handle Plug and Play IRPs for the child device
- * ARGUMENTS:
- *     DeviceObject = Pointer to physical device object of the child device
- *     Irp          = Pointer to IRP that should be handled
- * RETURNS:
- *     Status
- */
-NTSTATUS
-PnpRootPdoPnpControl(
-  PDEVICE_OBJECT DeviceObject,
-  PIRP Irp)
-{
-  PIO_STACK_LOCATION IrpSp;
-  NTSTATUS Status;
-
-  DPRINT("Called\n");
-
-  Status = Irp->IoStatus.Status;
-
-  IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
-  switch (IrpSp->MinorFunction) {
-#if 0
-  case IRP_MN_QUERY_BUS_INFORMATION:
-    break;
-
-  case IRP_MN_QUERY_DEVICE_RELATIONS:
-    /* FIXME: Handle for TargetDeviceRelation */
-    break;
-#endif
-
-  case IRP_MN_QUERY_ID:
-    Status = PdoQueryId(DeviceObject, Irp, IrpSp);
-    break;
-
-  case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
-    Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
-    break;
-
-  case IRP_MN_QUERY_RESOURCES:
-    Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
-    break;
-
-  case IRP_MN_QUERY_CAPABILITIES:
-    Status = PnpRootPdoQueryCapabilities(DeviceObject, Irp, IrpSp);
-    break;
-
-  case IRP_MN_START_DEVICE:
-  case IRP_MN_QUERY_STOP_DEVICE:
-  case IRP_MN_CANCEL_STOP_DEVICE:
-  case IRP_MN_STOP_DEVICE:
-  case IRP_MN_QUERY_REMOVE_DEVICE:
-  case IRP_MN_CANCEL_REMOVE_DEVICE:
-  case IRP_MN_REMOVE_DEVICE:
-  case IRP_MN_SURPRISE_REMOVAL:
-    Status = STATUS_SUCCESS;
-    break;
-
-  default:
-    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
-    break;
-  }
-
-  Irp->IoStatus.Status = Status;
-  IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-  DPRINT("Leaving. Status 0x%X\n", Status);
-
-  return Status;
-}
-
-
-/*
- * FUNCTION: Handle power management IRPs for the child device
- * ARGUMENTS:
- *     DeviceObject = Pointer to physical device object of the child device
- *     Irp          = Pointer to IRP that should be handled
- * RETURNS:
- *     Status
- */
-NTSTATUS
-PnpRootPdoPowerControl(
-  PDEVICE_OBJECT DeviceObject,
-  PIRP Irp)
-{
-  PIO_STACK_LOCATION IrpSp;
-  NTSTATUS Status;
-
-  DPRINT("Called\n");
-
-  Status = Irp->IoStatus.Status;
-
-  IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
-  switch (IrpSp->MinorFunction) {
-  default:
-    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
-    Status = STATUS_NOT_IMPLEMENTED;
-    break;
-  }
-
-  Irp->IoStatus.Status = Status;
-  IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-  DPRINT("Leaving. Status 0x%X\n", Status);
-
-  return Status;
-}
-
-
-/* Functional Device Object routines */
-
-static NTSTATUS
-PnpRootReadRegistryBinary(
-  IN PWSTR KeyName,
-  IN PWSTR ValueKeyName,
-  OUT PVOID* Buffer,
-  OUT SIZE_T* BufferSize OPTIONAL)
-{
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING KeyNameU;
-  UNICODE_STRING ValueKeyNameU;
-  KEY_VALUE_PARTIAL_INFORMATION Size;
-  PKEY_VALUE_PARTIAL_INFORMATION Data = NULL;
-  ULONG DataSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION);
-  HANDLE KeyHandle;
-  NTSTATUS Status;
-  
-  DPRINT("Called\n");
-  
-  RtlInitUnicodeString(&KeyNameU, KeyName);
-  RtlInitUnicodeString(&ValueKeyNameU, ValueKeyName);
-  
+  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,
-    &KeyNameU,
+    &KeyName,
     OBJ_CASE_INSENSITIVE,
-    NULL, /* Root dir */
-    NULL); /* Security descriptor */
-  Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
-  if (!NT_SUCCESS(Status))
-  {
-    DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
-    return Status;
-  }
-  
-  Status = ZwQueryValueKey(
-    KeyHandle,
-    &ValueKeyNameU,
-    KeyValuePartialInformation,
-    &Size, DataSize,
-    &DataSize);
-  if (Status != STATUS_BUFFER_OVERFLOW)
-  {
-    DPRINT("ZwQueryValueKey() failed (Status 0x%08lx)\n", Status);
-    ZwClose(KeyHandle);
-    return Status;
-  }
-  
-  while (Status == STATUS_BUFFER_OVERFLOW)
-  {
-    if (Data)
-      ExFreePoolWithTag(Data, TAG_PNP_ROOT);
-    Data = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, DataSize, TAG_PNP_ROOT);
-    if (!Data)
-    {
-      DPRINT("ExAllocatePoolWithTag() failed\n", Status);
-      ZwClose(KeyHandle);
-      return STATUS_NO_MEMORY;
-    }
-    
-    Status = ZwQueryValueKey(
-      KeyHandle,
-      &ValueKeyNameU,
-      KeyValuePartialInformation,
-      Data, DataSize,
-      &DataSize);
-    if (NT_SUCCESS(Status))
-    {
-      *Buffer = ExAllocatePoolWithTag(PagedPool, Data->DataLength, TAG_PNP_ROOT);
-      if (BufferSize) *BufferSize = Data->DataLength;
-      if (!*Buffer)
-      {
-        DPRINT("ExAllocatePoolWithTag() failed\n", Status);
-        ExFreePoolWithTag(Data, TAG_PNP_ROOT);
-        ZwClose(KeyHandle);
-        return STATUS_NO_MEMORY;
-      }
-      
-      RtlCopyMemory(
-        *Buffer,
-        Data->Data,
-        Data->DataLength);
-      break;
-    }
-  }
-  
-  if (Data)
-    ExFreePoolWithTag(Data, TAG_PNP_ROOT);
-  ZwClose(KeyHandle);
-  
-  return Status;
-}
-
-NTSTATUS
-PnpRootFdoReadDeviceInfo(
-  PPNPROOT_DEVICE Device)
-{
-  RTL_QUERY_REGISTRY_TABLE QueryTable[2];
-  PUNICODE_STRING DeviceDesc;
-  WCHAR KeyName[MAX_PATH];
-  NTSTATUS Status;
-
-  DPRINT("Called\n");
-
-  /* Retrieve configuration from Enum key */
-
-  DeviceDesc = &Device->DeviceDescription;
-
-  wcscpy(KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
-  wcscat(KeyName, ENUM_NAME_ROOT);
-  wcscat(KeyName, L"\\");
-  wcscat(KeyName, Device->ServiceName.Buffer);
-  wcscat(KeyName, L"\\");
-  wcscat(KeyName, Device->InstanceID.Buffer);
-
-  DPRINT("KeyName %S\n", KeyName);
-
-  /* 1. Read informations in instance key */
-  RtlZeroMemory(QueryTable, sizeof(QueryTable));
-
-  RtlInitUnicodeString(DeviceDesc, NULL);
-
-  QueryTable[0].Name = L"DeviceDesc";
-  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
-  QueryTable[0].EntryContext = DeviceDesc;
-
-  Status = RtlQueryRegistryValues(
-    RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
-    KeyName,
-    QueryTable,
     NULL,
     NULL);
 
-  DPRINT("RtlQueryRegistryValues() returned status 0x%08lx\n", Status);
-
-  if (!NT_SUCCESS(Status))
-  {
-    Device->DeviceDescription.Buffer = NULL;
-  }
-
-  DPRINT("Got device description: %S\n", DeviceDesc->Buffer);
-
-  /* 2. Read informations in instance key, LogConf subkey */
-  RtlZeroMemory(QueryTable, sizeof(QueryTable));
-  wcscat(KeyName, L"\\LogConf");
-  
-  Status = PnpRootReadRegistryBinary(
-    KeyName,
-    L"BasicConfigVector",
-    (PVOID*)&Device->ResourceRequirementsList,
-    NULL);
-
-  DPRINT("PnpRootReadRegistryBinary() returned status 0x%08lx\n", Status);
-
-  if (!NT_SUCCESS(Status))
-  {
-    /* FIXME: */
-  }
-
-  Status = PnpRootReadRegistryBinary(
-    KeyName,
-    L"BootConfig",
-    (PVOID*)&Device->BootResourceList,
-    &Device->BootResourceListSize);
-
-  DPRINT("PnpRootReadRegistryBinary() returned status 0x%08lx\n", Status);
-
-  if (!NT_SUCCESS(Status))
-  {
-    /* FIXME: */
-  }
-
-  return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-PnpRootFdoEnumerateDevices(
-  PDEVICE_OBJECT DeviceObject)
-{
-  PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-  OBJECT_ATTRIBUTES ObjectAttributes, SubKeyAttributes;
-  PKEY_BASIC_INFORMATION KeyInfo, SubKeyInfo;
-  UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\" ENUM_NAME_ROOT);
-  UNICODE_STRING SubKeyName;
-  PPNPROOT_DEVICE Device;
-  WCHAR Buffer[MAX_PATH];
-  HANDLE KeyHandle, SubKeyHandle;
-  ULONG BufferSize;
-  ULONG ResultSize;
-  NTSTATUS Status;
-  ULONG Index1, Index2;
-
-  DPRINT("Called\n");
-
-  DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-  BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR);
-  KeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
-  if (!KeyInfo)
-  {
-    return STATUS_INSUFFICIENT_RESOURCES;
-  }
-  SubKeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
-  if (!SubKeyInfo)
-  {
-    ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
-    return STATUS_INSUFFICIENT_RESOURCES;
-  }
-
-  InitializeObjectAttributes(
-    &ObjectAttributes,
-		&KeyName,
-		OBJ_CASE_INSENSITIVE,
-		NULL,
-		NULL);
-
   Status = ZwOpenKey(&KeyHandle, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes);
   if (!NT_SUCCESS(Status))
   {
-    DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
-    ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
-    ExFreePoolWithTag(SubKeyInfo, TAG_PNP_ROOT);
-    return Status;
-  }
-
-  /* FIXME: Disabled due to still using the old method of auto loading drivers e.g.
-            there are more entries in the list than found in the registry as some
-            drivers are passed on the command line */
-//  DeviceExtension->DeviceListCount = 0;
+    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(
@@ -703,30 +391,35 @@
       KeyInfo,
       BufferSize,
       &ResultSize);
-    if (!NT_SUCCESS(Status))
+    if (Status == STATUS_NO_MORE_ENTRIES)
     {
-      DPRINT("ZwEnumerateKey() (Status 0x%08lx)\n", Status);
-      break;
+      Status = STATUS_SUCCESS;
+      break;
+    }
+    else if (!NT_SUCCESS(Status))
+    {
+      DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
+      goto cleanup;
     }
 
     /* Terminate the string */
     KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
-    
+
     /* Open the key */
     RtlInitUnicodeString(&SubKeyName, KeyInfo->Name);
     InitializeObjectAttributes(
-      &SubKeyAttributes,
+      &ObjectAttributes,
       &SubKeyName,
       0, /* Attributes */
       KeyHandle,
       NULL); /* Security descriptor */
-    Status = ZwOpenKey(&SubKeyHandle, KEY_ENUMERATE_SUB_KEYS, &SubKeyAttributes);
+    Status = ZwOpenKey(&SubKeyHandle, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes);
     if (!NT_SUCCESS(Status))
     {
-      DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
+      DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
       break;
     }
-    
+
     /* Enumerate the sub-keys */
     Index2 = 0;
     while (TRUE)
@@ -738,125 +431,190 @@
         SubKeyInfo,
         BufferSize,
         &ResultSize);
-      if (!NT_SUCCESS(Status))
+      if (Status == STATUS_NO_MORE_ENTRIES)
+        break;
+      else if (!NT_SUCCESS(Status))
       {
-        DPRINT("ZwEnumerateKey() (Status 0x%08lx)\n", Status);
+        DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
         break;
       }
-      
+
       /* Terminate the string */
       SubKeyInfo->Name[SubKeyInfo->NameLength / sizeof(WCHAR)] = 0;
-      
-      Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
-      if (!Device)
+
+      _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)
       {
-        /* FIXME: */
-        DPRINT("ExAllocatePoolWithTag() failed\n");
-        break;
+        /* 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 */
+        InitializeObjectAttributes(
+          &ObjectAttributes,
+          &Device->InstanceID,
+          0, /* Attributes */
+          SubKeyHandle,
+          NULL); /* Security descriptor */
+        Status = ZwOpenKey(&DeviceKeyHandle, KEY_READ, &ObjectAttributes);
+        if (!NT_SUCCESS(Status))
+        {
+          DPRINT("ZwOpenKey() 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[2].QueryRoutine = QueryBinaryValueCallback;
+        QueryTable[2].Name = L"BootConfig";
+        QueryTable[2].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;
       }
 
-      RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
-
-      if (!RtlCreateUnicodeString(&Device->ServiceName, KeyInfo->Name))
-      {
-        /* FIXME: */
-        DPRINT("RtlCreateUnicodeString() failed\n");
-      }
-
-      wcscpy(Buffer, ENUM_NAME_ROOT);
-      wcscat(Buffer, L"\\");
-      wcscat(Buffer, KeyInfo->Name);
-
-      if (!RtlCreateUnicodeString(&Device->DeviceID, Buffer))
-      {
-        /* FIXME: */
-        DPRINT("RtlCreateUnicodeString() failed\n");
-      }
-
-      DPRINT("Got entry: %S\n", Device->DeviceID.Buffer);
-
-      if (!RtlCreateUnicodeString(
-        &Device->InstanceID,
-        SubKeyInfo->Name))
-      {
-        /* FIXME: */
-        DPRINT("RtlCreateUnicodeString() failed\n");
-      }
-
-      Status = PnpRootFdoReadDeviceInfo(Device);
-      if (!NT_SUCCESS(Status))
-      {
-        /* FIXME */
-        DPRINT("PnpRootFdoReadDeviceInfo() failed with status 0x%08lx\n", Status);
-      }
-
-      ExInterlockedInsertTailList(
-        &DeviceExtension->DeviceListHead,
-        &Device->ListEntry,
-        &DeviceExtension->DeviceListLock);
-
-      DeviceExtension->DeviceListCount++;
-      
       Index2++;
     }
-    
+
     ZwClose(SubKeyHandle);
+    SubKeyHandle = INVALID_HANDLE_VALUE;
     Index1++;
   }
 
-  ZwClose(KeyHandle);
-
+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);
-
-  return STATUS_SUCCESS;
-}
-
-
-NTSTATUS
-PnpRootQueryBusRelations(
+  KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
+  return Status;
+}
+
+/* FUNCTION: Handle IRP_MN_QUERY_DEVICE_RELATIONS IRPs for the root bus device object
+ * ARGUMENTS:
+ *     DeviceObject = Pointer to functional device object of the root bus driver
+ *     Irp          = Pointer to IRP that should be handled
+ * RETURNS:
+ *     Status
+ */
+static NTSTATUS
+PnpRootQueryDeviceRelations(
   IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp,
-  IN PIO_STACK_LOCATION IrpSp)
+  IN PIRP Irp)
 {
   PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
   PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-  PDEVICE_RELATIONS Relations;
-  PPNPROOT_DEVICE Device;
+  PDEVICE_RELATIONS Relations = NULL, OtherRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
+  PPNPROOT_DEVICE Device = NULL;
+  ULONG Size;
   NTSTATUS Status;
-  ULONG Size;
-  ULONG i;
-
-  DPRINT("Called\n");
-
-  Status = PnpRootFdoEnumerateDevices(DeviceObject);
+
+  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;
+  }
 
   DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
-  if (Irp->IoStatus.Information)
-  {
-    /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
-              structure so we must merge this structure with our own */
-  }
-
-  Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
-    (DeviceExtension->DeviceListCount - 1);
-
+  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)
-    return STATUS_INSUFFICIENT_RESOURCES;
-
-  Relations->Count = DeviceExtension->DeviceListCount;
-
-  i = 0;
-  LIST_FOR_EACH(Device,&DeviceExtension->DeviceListHead,PNPROOT_DEVICE, ListEntry) 
+  {
+    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);
+  }
+
+  KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
+  LIST_FOR_EACH(Device, &DeviceExtension->DeviceListHead, PNPROOT_DEVICE, ListEntry)
   {
     if (!Device->Pdo)
     {
       /* Create a physical device object for the
-         device as it does not already have one */
+       * device as it does not already have one */
       Status = IoCreateDevice(
         DeviceObject->DriverObject,
         sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
@@ -867,88 +625,45 @@
         &Device->Pdo);
       if (!NT_SUCCESS(Status))
       {
-        DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
-        ExFreePool(Relations);
-        return Status;
+        DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
+        break;
       }
 
-      DPRINT("Created PDO 0x%p\n", Device->Pdo);
+      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;
-
-      //Device->Pdo->Flags |= DO_POWER_PAGABLE;
-
-      PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
-
-      RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
-
-      PdoDeviceExtension->Common.IsFDO = FALSE;
-
-      PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
-
-      PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
-
-      PdoDeviceExtension->Device = Device;
-
-      DPRINT("DeviceID: %wZ  PDO %p\n",
-        &PdoDeviceExtension->Device->DeviceID,
-        Device->Pdo);
-
-      DPRINT("InstanceID: %wZ  PDO %p\n",
-        &PdoDeviceExtension->Device->InstanceID,
-        Device->Pdo);
-
-      DPRINT("ResourceRequirementsList: %p  PDO %p\n",
-        PdoDeviceExtension->Device->ResourceRequirementsList,
-        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[i] = Device->Pdo;
-
-    i++;
-  }
-
-  if (NT_SUCCESS(Status))
-  {
-    Irp->IoStatus.Information = (ULONG_PTR)Relations;
-  }
-  else
-  {
-    Irp->IoStatus.Information = 0;
+    Relations->Objects[Relations->Count++] = Device->Pdo;
+  }
+  KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock);
+
+  Irp->IoStatus.Information = (ULONG_PTR)Relations;
+
+cleanup:
+  if (!NT_SUCCESS(Status))
+  {
+    if (OtherRelations)
+      ExFreePool(OtherRelations);
+    if (Relations)
+      ExFreePool(Relations);
+    if (Device && Device->Pdo)
+    {
+      IoDeleteDevice(Device->Pdo);
+      Device->Pdo = NULL;
+    }
   }
 
   return Status;
 }
-
-
-NTSTATUS
-PnpRootQueryDeviceRelations(
-  IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp,
-  IN PIO_STACK_LOCATION IrpSp)
-{
-  NTSTATUS Status;
-
-  DPRINT("Called\n");
-
-  switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
-  case BusRelations:
-    Status = PnpRootQueryBusRelations(DeviceObject, Irp, IrpSp);
-    break;
-
-  default:
-    Status = STATUS_NOT_IMPLEMENTED;
-  }
-
-  return Status;
-}
-
 
 /*
  * FUNCTION: Handle Plug and Play IRPs for the root bus device object
@@ -958,8 +673,7 @@
  * RETURNS:
  *     Status
  */
-NTSTATUS
-STDCALL
+static NTSTATUS
 PnpRootFdoPnpControl(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp)
@@ -968,84 +682,417 @@
   PIO_STACK_LOCATION IrpSp;
   NTSTATUS Status;
 
-  DPRINT("Called\n");
-
   DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
   Status = Irp->IoStatus.Status;
-
   IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
-  switch (IrpSp->MinorFunction) {
-  case IRP_MN_QUERY_DEVICE_RELATIONS:
-    Status = PnpRootQueryDeviceRelations(DeviceObject, Irp, IrpSp);
-    break;
-
-  case IRP_MN_START_DEVICE:
-    DeviceExtension->State = dsStarted;
-    Status = STATUS_SUCCESS;
-    break;
-
-  case IRP_MN_STOP_DEVICE:
-    /* Root device cannot be stopped */
-    Status = STATUS_UNSUCCESSFUL;
-    break;
-
-  default:
-    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
-    Status = STATUS_NOT_IMPLEMENTED;
-    break;
-  }
-
-  if (Status != STATUS_PENDING) {
+  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;
+
+    case IRP_MN_STOP_DEVICE:
+      DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
+      /* Root device cannot be stopped */
+      Status = STATUS_NOT_SUPPORTED;
+      break;
+
+    default:
+      DPRINT("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);
   }
 
-  DPRINT("Leaving. Status 0x%X\n", Status);
-
   return Status;
 }
 
+static NTSTATUS
+PdoQueryDeviceRelations(
+	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;
+}
+
+static NTSTATUS
+PdoQueryCapabilities(
+	IN PDEVICE_OBJECT DeviceObject,
+	IN PIRP Irp,
+	IN PIO_STACK_LOCATION IrpSp)
+{
+	PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
+	PDEVICE_CAPABILITIES DeviceCapabilities;
+
+	DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+	DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
+
+	if (DeviceCapabilities->Version != 1)
+		return STATUS_REVISION_MISMATCH;
+
+	DeviceCapabilities->UniqueID = TRUE;
+	/* FIXME: Fill other fields */
+
+	return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+PdoQueryResources(
+	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;
+}
+
+static NTSTATUS
+PdoQueryResourceRequirements(
+	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;
+}
+
+static NTSTATUS
+PdoQueryDeviceText(
+	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;
+}
+
+static NTSTATUS
+PdoQueryId(
+	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;
+}
+
+static NTSTATUS
+PdoQueryBusInformation(
+	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;
+}
 
 /*
- * FUNCTION: Handle power management IRPs for the root bus device object
+ * FUNCTION: Handle Plug and Play IRPs for the child device
  * ARGUMENTS:
- *     DeviceObject = Pointer to functional device object of the root bus driver
+ *     DeviceObject = Pointer to physical device object of the child device
  *     Irp          = Pointer to IRP that should be handled
  * RETURNS:
  *     Status
  */
-NTSTATUS
-STDCALL
-PnpRootFdoPowerControl(
+static NTSTATUS
+PnpRootPdoPnpControl(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp)
 {
+  PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
   PIO_STACK_LOCATION IrpSp;
   NTSTATUS Status;
 
-  DPRINT("Called\n");
-
+  DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+  Status = Irp->IoStatus.Status;
   IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
-  switch (IrpSp->MinorFunction) {
-  default:
-    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
-    Status = STATUS_NOT_IMPLEMENTED;
-    break;
-  }
-
-  if (Status != STATUS_PENDING) {
+  switch (IrpSp->MinorFunction)
+  {
+    case IRP_MN_START_DEVICE: /* 0x00 */
+      DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
+      Status = STATUS_SUCCESS;
+      break;
+
+    case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
+      Status = PdoQueryDeviceRelations(DeviceObject, Irp, IrpSp);
+      break;
+
+    case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */
+      DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
+      Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp);
+      break;
+
+    case IRP_MN_QUERY_RESOURCES: /* 0x0a */
+      DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
+      Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
+      break;
+
+   case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */
+      DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
+      Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
+      break;
+
+    case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */
+      DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
+      Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
+      break;
+
+    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */
+        DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
+        break;
+
+    case IRP_MN_QUERY_ID: /* 0x13 */
+      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;
+
+    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);
   }
 
-  DPRINT("Leaving. Status 0x%X\n", Status);
-
   return Status;
 }
-
 
 /*
  * FUNCTION: Handle Plug and Play IRPs
@@ -1055,8 +1102,7 @@
  * RETURNS:
  *     Status
  */
-NTSTATUS
-STDCALL
+static NTSTATUS NTAPI
 PnpRootPnpControl(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp)
@@ -1066,49 +1112,13 @@
 
   DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
-  DPRINT("DeviceObject 0x%p  DeviceExtension 0x%p  IsFDO %d\n",
-    DeviceObject,
-    DeviceExtension,
-    DeviceExtension->IsFDO);
-
-  if (DeviceExtension->IsFDO) {
+  if (DeviceExtension->IsFDO)
     Status = PnpRootFdoPnpControl(DeviceObject, Irp);
-  } else {
+  else
     Status = PnpRootPdoPnpControl(DeviceObject, Irp);
-  }
 
   return Status;
 }
-
-
-/*
- * FUNCTION: Handle power management IRPs
- * ARGUMENTS:
- *     DeviceObject = Pointer to PDO or FDO
- *     Irp          = Pointer to IRP that should be handled
- * RETURNS:
- *     Status
- */
-NTSTATUS
-STDCALL
-PnpRootPowerControl(
-  IN PDEVICE_OBJECT DeviceObject,
-  IN PIRP Irp)
-{
-  PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
-  NTSTATUS Status;
-
-  DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-  if (DeviceExtension->IsFDO) {
-    Status = PnpRootFdoPowerControl(DeviceObject, Irp);
-  } else {
-    Status = PnpRootPdoPowerControl(DeviceObject, Irp);
-  }
-
-  return Status;
-}
-
 
 NTSTATUS
 STDCALL
@@ -1119,7 +1129,14 @@
   PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
   NTSTATUS Status;
 
-  DPRINT("Called\n");
+  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,
@@ -1129,59 +1146,50 @@
     FILE_DEVICE_SECURE_OPEN,
     TRUE,
     &PnpRootDeviceObject);
-  if (!NT_SUCCESS(Status)) {
+  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;
-
-  DeviceExtension->Ldo = IoAttachDeviceToDeviceStack(
+  InitializeListHead(&DeviceExtension->DeviceListHead);
+  DeviceExtension->DeviceListCount = 0;
+  KeInitializeGuardedMutex(&DeviceExtension->DeviceListLock);
+
+  Status = IoAttachDeviceToDeviceStackSafe(
     PnpRootDeviceObject,
-    PhysicalDeviceObject);
-
-  if (!PnpRootDeviceObject) {
-    CPRINT("PnpRootDeviceObject 0x%p\n", 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) {
-    CPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject);
-    KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
-  }
-
-  InitializeListHead(&DeviceExtension->DeviceListHead);
-
-  DeviceExtension->DeviceListCount = 0;
-
-  KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
-
   PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
 
-  //PnpRootDeviceObject->Flags |= DO_POWER_PAGABLE;
-
   DPRINT("Done AddDevice()\n");
 
   return STATUS_SUCCESS;
 }
 
-
-NTSTATUS
-STDCALL
+NTSTATUS NTAPI
 PnpRootDriverEntry(
   IN PDRIVER_OBJECT DriverObject,
   IN PUNICODE_STRING RegistryPath)
 {
-  DPRINT("Called\n");
+  DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject, RegistryPath);
+
+  DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
 
   DriverObject->MajorFunction[IRP_MJ_PNP] = PnpRootPnpControl;
-  DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl;
-  DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
+  //DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl;
 
   return STATUS_SUCCESS;
 }




More information about the Ros-diffs mailing list