3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnproot.c
6 * PURPOSE: PnP manager root device
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 16/04/2001 CSH Created
12 /* INCLUDES ******************************************************************/
14 #include <ddk/ntddk.h>
15 #include <reactos/bugcodes.h>
16 #include <internal/io.h>
17 #include <internal/registry.h>
20 #include <internal/debug.h>
22 /* GLOBALS *******************************************************************/
24 #define ENUM_NAME_ROOT L"Root"
26 /* DATA **********************************************************************/
28 typedef struct _PNPROOT_DEVICE {
29 // Entry on device list
31 // Physical Device Object of device
34 UNICODE_STRING ServiceName;
36 UNICODE_STRING DeviceID;
38 UNICODE_STRING InstanceID;
40 UNICODE_STRING DeviceDescription;
41 } PNPROOT_DEVICE, *PPNPROOT_DEVICE;
49 } PNPROOT_DEVICE_STATE;
52 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
54 // Pointer to device object, this device extension is associated with
55 PDEVICE_OBJECT DeviceObject;
56 // Wether this device extension is for an FDO or PDO
58 // Wether the device is removed
60 // Current device power state for the device
61 DEVICE_POWER_STATE DevicePowerState;
62 } __attribute((packed)) PNPROOT_COMMON_DEVICE_EXTENSION, *PPNPROOT_COMMON_DEVICE_EXTENSION;
64 /* Physical Device Object device extension for a child device */
65 typedef struct _PNPROOT_PDO_DEVICE_EXTENSION
68 PNPROOT_COMMON_DEVICE_EXTENSION Common;
70 UNICODE_STRING DeviceID;
72 UNICODE_STRING InstanceID;
73 } __attribute((packed)) PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION;
75 /* Functional Device Object device extension for the PCI driver device object */
76 typedef struct _PNPROOT_FDO_DEVICE_EXTENSION
79 PNPROOT_COMMON_DEVICE_EXTENSION Common;
80 // Physical Device Object
82 // Lower device object
84 // Current state of the driver
85 PNPROOT_DEVICE_STATE State;
86 // Namespace device list
87 LIST_ENTRY DeviceListHead;
88 // Number of (not removed) devices in device list
89 ULONG DeviceListCount;
90 // Lock for namespace device list
91 // FIXME: Use fast mutex instead?
92 KSPIN_LOCK DeviceListLock;
93 } __attribute((packed)) PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION;
96 PDEVICE_OBJECT PnpRootDeviceObject;
99 /* FUNCTIONS *****************************************************************/
101 /* Physical Device Object routines */
105 PDEVICE_OBJECT *PhysicalDeviceObject)
107 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
108 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
109 PPNPROOT_DEVICE Device;
112 /* This function should be obsoleted soon */
116 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
118 Device = (PPNPROOT_DEVICE)ExAllocatePool(PagedPool, sizeof(PNPROOT_DEVICE));
120 return STATUS_INSUFFICIENT_RESOURCES;
122 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
124 Status = IoCreateDevice(
125 PnpRootDeviceObject->DriverObject,
126 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
128 FILE_DEVICE_CONTROLLER,
132 if (!NT_SUCCESS(Status)) {
133 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
138 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
140 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
142 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
144 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
146 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
148 PdoDeviceExtension->Common.IsFDO = FALSE;
150 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
152 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
154 if (!IopCreateUnicodeString(
155 &PdoDeviceExtension->DeviceID,
161 DPRINT("IopCreateUnicodeString() failed\n");
164 if (!IopCreateUnicodeString(
165 &PdoDeviceExtension->InstanceID,
170 DPRINT("IopCreateUnicodeString() failed\n");
173 ExInterlockedInsertTailList(
174 &DeviceExtension->DeviceListHead,
176 &DeviceExtension->DeviceListLock);
178 DeviceExtension->DeviceListCount++;
180 *PhysicalDeviceObject = Device->Pdo;
182 return STATUS_SUCCESS;
188 IN PDEVICE_OBJECT DeviceObject,
190 PIO_STACK_LOCATION IrpSp)
192 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
193 UNICODE_STRING String;
198 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
200 // Irp->IoStatus.Information = 0;
202 Status = STATUS_SUCCESS;
204 RtlInitUnicodeString(&String, NULL);
206 switch (IrpSp->Parameters.QueryId.IdType) {
207 case BusQueryDeviceID:
208 Status = IopCreateUnicodeString(
210 DeviceExtension->DeviceID.Buffer,
213 DPRINT("DeviceID: %S\n", String.Buffer);
215 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
218 case BusQueryHardwareIDs:
219 case BusQueryCompatibleIDs:
220 Status = STATUS_NOT_IMPLEMENTED;
223 case BusQueryInstanceID:
224 Status = IopCreateUnicodeString(
226 DeviceExtension->InstanceID.Buffer,
229 DPRINT("InstanceID: %S\n", String.Buffer);
231 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
234 case BusQueryDeviceSerialNumber:
236 Status = STATUS_NOT_IMPLEMENTED;
244 PnpRootPdoPnpControl(
245 PDEVICE_OBJECT DeviceObject,
248 * FUNCTION: Handle Plug and Play IRPs for the child device
250 * DeviceObject = Pointer to physical device object of the child device
251 * Irp = Pointer to IRP that should be handled
256 PIO_STACK_LOCATION IrpSp;
261 Status = Irp->IoStatus.Status;
263 IrpSp = IoGetCurrentIrpStackLocation(Irp);
265 switch (IrpSp->MinorFunction) {
267 case IRP_MN_CANCEL_REMOVE_DEVICE:
270 case IRP_MN_CANCEL_STOP_DEVICE:
273 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
279 case IRP_MN_QUERY_BUS_INFORMATION:
282 case IRP_MN_QUERY_CAPABILITIES:
285 case IRP_MN_QUERY_DEVICE_RELATIONS:
286 /* FIXME: Possibly handle for RemovalRelations */
289 case IRP_MN_QUERY_DEVICE_TEXT:
292 case IRP_MN_QUERY_ID:
293 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
296 case IRP_MN_QUERY_PNP_DEVICE_STATE:
299 case IRP_MN_QUERY_REMOVE_DEVICE:
302 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
305 case IRP_MN_QUERY_RESOURCES:
308 case IRP_MN_QUERY_STOP_DEVICE:
311 case IRP_MN_REMOVE_DEVICE:
314 case IRP_MN_SET_LOCK:
317 case IRP_MN_START_DEVICE:
320 case IRP_MN_STOP_DEVICE:
323 case IRP_MN_SURPRISE_REMOVAL:
327 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
331 Irp->IoStatus.Status = Status;
332 IoCompleteRequest(Irp, IO_NO_INCREMENT);
334 DPRINT("Leaving. Status 0x%X\n", Status);
340 PnpRootPdoPowerControl(
341 PDEVICE_OBJECT DeviceObject,
344 * FUNCTION: Handle power management IRPs for the child device
346 * DeviceObject = Pointer to physical device object of the child device
347 * Irp = Pointer to IRP that should be handled
352 PIO_STACK_LOCATION IrpSp;
357 Status = Irp->IoStatus.Status;
359 IrpSp = IoGetCurrentIrpStackLocation(Irp);
361 switch (IrpSp->MinorFunction) {
363 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
367 Irp->IoStatus.Status = Status;
368 IoCompleteRequest(Irp, IO_NO_INCREMENT);
370 DPRINT("Leaving. Status 0x%X\n", Status);
376 /* Functional Device Object routines */
379 PnpRootFdoReadDeviceInfo(
380 PPNPROOT_DEVICE Device)
382 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
383 PUNICODE_STRING DeviceDesc;
384 WCHAR KeyName[MAX_PATH];
390 /* Retrieve configuration from Enum key */
392 DeviceDesc = &Device->DeviceDescription;
394 wcscpy(KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
395 wcscat(KeyName, ENUM_NAME_ROOT);
396 wcscat(KeyName, L"\\");
397 wcscat(KeyName, Device->ServiceName.Buffer);
398 wcscat(KeyName, L"\\");
399 wcscat(KeyName, Device->InstanceID.Buffer);
401 DPRINT("KeyName %S\n", KeyName);
403 Status = RtlpGetRegistryHandle(
404 RTL_REGISTRY_ABSOLUTE,
408 if (!NT_SUCCESS(Status))
410 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
414 RtlZeroMemory(QueryTable, sizeof(QueryTable));
416 RtlInitUnicodeString(DeviceDesc, NULL);
418 QueryTable[0].Name = L"DeviceDesc";
419 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
420 QueryTable[0].EntryContext = DeviceDesc;
422 Status = RtlQueryRegistryValues(
431 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
433 if (!NT_SUCCESS(Status))
438 DPRINT("Got device description: %S\n", DeviceDesc->Buffer);
440 return STATUS_SUCCESS;
445 PnpRootFdoEnumerateDevices(
446 PDEVICE_OBJECT DeviceObject)
448 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
449 OBJECT_ATTRIBUTES ObjectAttributes;
450 PKEY_BASIC_INFORMATION KeyInfo;
451 UNICODE_STRING KeyName;
452 PPNPROOT_DEVICE Device;
453 WCHAR Buffer[MAX_PATH];
462 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
464 BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR);
465 KeyInfo = ExAllocatePool(PagedPool, BufferSize);
468 return STATUS_INSUFFICIENT_RESOURCES;
471 RtlInitUnicodeStringFromLiteral(
473 L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\" \
476 InitializeObjectAttributes(
479 OBJ_CASE_INSENSITIVE,
483 Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
484 if (!NT_SUCCESS(Status))
486 DPRINT("NtOpenKey() failed (Status %x)\n", Status);
491 /* FIXME: Disabled due to still using the old method of auto loading drivers e.g.
492 there are more entries in the list than found in the registry as some
493 drivers are passed on the command line */
494 // DeviceExtension->DeviceListCount = 0;
498 Status = ZwEnumerateKey(
505 if (!NT_SUCCESS(Status))
507 DPRINT("ZwEnumerateKey() (Status %x)\n", Status);
511 /* Terminate the string */
512 KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
514 Device = (PPNPROOT_DEVICE)ExAllocatePool(PagedPool, sizeof(PNPROOT_DEVICE));
521 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
523 if (!IopCreateUnicodeString(&Device->ServiceName, KeyInfo->Name, PagedPool))
526 DPRINT("IopCreateUnicodeString() failed\n");
529 wcscpy(Buffer, ENUM_NAME_ROOT);
530 wcscat(Buffer, L"\\");
531 wcscat(Buffer, KeyInfo->Name);
533 if (!IopCreateUnicodeString(&Device->DeviceID, Buffer, PagedPool))
536 DPRINT("IopCreateUnicodeString() failed\n");
539 DPRINT("Got entry: %S\n", Device->DeviceID.Buffer);
541 if (!IopCreateUnicodeString(
547 DPRINT("IopCreateUnicodeString() failed\n");
550 Status = PnpRootFdoReadDeviceInfo(Device);
551 if (!NT_SUCCESS(Status))
553 DPRINT("PnpRootFdoReadDeviceInfo() failed with status %x\n", Status);
557 ExInterlockedInsertTailList(
558 &DeviceExtension->DeviceListHead,
560 &DeviceExtension->DeviceListLock);
562 DeviceExtension->DeviceListCount++;
567 DPRINT("Entries found: %d\n", Index);
573 return STATUS_SUCCESS;
578 PnpRootQueryBusRelations(
579 IN PDEVICE_OBJECT DeviceObject,
581 IN PIO_STACK_LOCATION IrpSp)
583 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
584 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
585 PDEVICE_RELATIONS Relations;
586 PLIST_ENTRY CurrentEntry;
587 PPNPROOT_DEVICE Device;
594 Status = PnpRootFdoEnumerateDevices(DeviceObject);
595 if (!NT_SUCCESS(Status))
598 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
600 if (Irp->IoStatus.Information)
602 /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
603 structure so we must merge this structure with our own */
606 Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
607 (DeviceExtension->DeviceListCount - 1);
609 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
611 return STATUS_INSUFFICIENT_RESOURCES;
613 Relations->Count = DeviceExtension->DeviceListCount;
616 CurrentEntry = DeviceExtension->DeviceListHead.Flink;
617 while (CurrentEntry != &DeviceExtension->DeviceListHead)
619 Device = CONTAINING_RECORD(CurrentEntry, PNPROOT_DEVICE, ListEntry);
623 /* Create a physical device object for the
624 device as it does not already have one */
625 Status = IoCreateDevice(
626 DeviceObject->DriverObject,
627 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
629 FILE_DEVICE_CONTROLLER,
633 if (!NT_SUCCESS(Status))
635 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
636 ExFreePool(Relations);
640 DPRINT("Created PDO %x\n", Device->Pdo);
642 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
644 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
646 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
648 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
650 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
652 PdoDeviceExtension->Common.IsFDO = FALSE;
654 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
656 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
658 if (!IopCreateUnicodeString(
659 &PdoDeviceExtension->DeviceID,
660 Device->DeviceID.Buffer,
663 DPRINT("Insufficient resources\n");
667 DPRINT("DeviceID: %S PDO %x\n",
668 PdoDeviceExtension->DeviceID.Buffer,
671 if (!IopCreateUnicodeString(
672 &PdoDeviceExtension->InstanceID,
673 Device->InstanceID.Buffer,
676 DPRINT("Insufficient resources\n");
682 /* Reference the physical device object. The PnP manager
683 will dereference it again when it is no longer needed */
684 ObReferenceObject(Device->Pdo);
686 Relations->Objects[i] = Device->Pdo;
690 CurrentEntry = CurrentEntry->Flink;
693 if (NT_SUCCESS(Status))
695 Irp->IoStatus.Information = (ULONG_PTR)Relations;
699 Irp->IoStatus.Information = 0;
707 PnpRootQueryDeviceRelations(
708 IN PDEVICE_OBJECT DeviceObject,
710 IN PIO_STACK_LOCATION IrpSp)
716 switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
718 Status = PnpRootQueryBusRelations(DeviceObject, Irp, IrpSp);
722 Status = STATUS_NOT_IMPLEMENTED;
731 PnpRootFdoPnpControl(
732 IN PDEVICE_OBJECT DeviceObject,
735 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
737 * DeviceObject = Pointer to functional device object of the root bus driver
738 * Irp = Pointer to IRP that should be handled
743 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
744 PIO_STACK_LOCATION IrpSp;
749 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
751 Status = Irp->IoStatus.Status;
753 IrpSp = IoGetCurrentIrpStackLocation(Irp);
755 switch (IrpSp->MinorFunction) {
756 case IRP_MN_QUERY_DEVICE_RELATIONS:
757 Status = PnpRootQueryDeviceRelations(DeviceObject, Irp, IrpSp);
760 case IRP_MN_START_DEVICE:
761 DeviceExtension->State = dsStarted;
762 Status = STATUS_SUCCESS;
765 case IRP_MN_STOP_DEVICE:
766 /* Root device cannot be stopped */
767 Status = STATUS_UNSUCCESSFUL;
771 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
772 Status = STATUS_NOT_IMPLEMENTED;
776 if (Status != STATUS_PENDING) {
777 Irp->IoStatus.Status = Status;
778 IoCompleteRequest(Irp, IO_NO_INCREMENT);
781 DPRINT("Leaving. Status 0x%X\n", Status);
789 PnpRootFdoPowerControl(
790 IN PDEVICE_OBJECT DeviceObject,
793 * FUNCTION: Handle power management IRPs for the root bus device object
795 * DeviceObject = Pointer to functional device object of the root bus driver
796 * Irp = Pointer to IRP that should be handled
801 PIO_STACK_LOCATION IrpSp;
806 IrpSp = IoGetCurrentIrpStackLocation(Irp);
808 switch (IrpSp->MinorFunction) {
810 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
811 Status = STATUS_NOT_IMPLEMENTED;
815 if (Status != STATUS_PENDING) {
816 Irp->IoStatus.Status = Status;
817 IoCompleteRequest(Irp, IO_NO_INCREMENT);
820 DPRINT("Leaving. Status 0x%X\n", Status);
829 IN PDEVICE_OBJECT DeviceObject,
832 * FUNCTION: Handle Plug and Play IRPs
834 * DeviceObject = Pointer to PDO or FDO
835 * Irp = Pointer to IRP that should be handled
840 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
843 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
845 DPRINT("DeviceObject %x DeviceExtension %x IsFDO %d\n",
848 DeviceExtension->IsFDO);
850 if (DeviceExtension->IsFDO) {
851 Status = PnpRootFdoPnpControl(DeviceObject, Irp);
853 Status = PnpRootPdoPnpControl(DeviceObject, Irp);
863 IN PDEVICE_OBJECT DeviceObject,
866 * FUNCTION: Handle power management IRPs
868 * DeviceObject = Pointer to PDO or FDO
869 * Irp = Pointer to IRP that should be handled
874 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
877 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
879 if (DeviceExtension->IsFDO) {
880 Status = PnpRootFdoPowerControl(DeviceObject, Irp);
882 Status = PnpRootPdoPowerControl(DeviceObject, Irp);
892 IN PDRIVER_OBJECT DriverObject,
893 IN PDEVICE_OBJECT PhysicalDeviceObject)
895 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
900 Status = IoCreateDevice(
902 sizeof(PNPROOT_FDO_DEVICE_EXTENSION),
904 FILE_DEVICE_BUS_EXTENDER,
905 FILE_DEVICE_SECURE_OPEN,
907 &PnpRootDeviceObject);
908 if (!NT_SUCCESS(Status)) {
909 CPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
910 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
913 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
915 RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION));
917 DeviceExtension->Common.IsFDO = TRUE;
919 DeviceExtension->State = dsStopped;
921 DeviceExtension->Ldo = IoAttachDeviceToDeviceStack(
923 PhysicalDeviceObject);
925 if (!PnpRootDeviceObject) {
926 CPRINT("PnpRootDeviceObject 0x%X\n", PnpRootDeviceObject);
927 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
930 if (!PhysicalDeviceObject) {
931 CPRINT("PhysicalDeviceObject 0x%X\n", PhysicalDeviceObject);
932 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
935 InitializeListHead(&DeviceExtension->DeviceListHead);
937 DeviceExtension->DeviceListCount = 0;
939 KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
941 PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
943 //PnpRootDeviceObject->Flags |= DO_POWER_PAGABLE;
945 DPRINT("Done AddDevice()\n");
947 return STATUS_SUCCESS;
954 IN PDRIVER_OBJECT DriverObject,
955 IN PUNICODE_STRING RegistryPath)
959 DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH) PnpRootPnpControl;
960 DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH) PnpRootPowerControl;
961 DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
963 return STATUS_SUCCESS;