2 * PROJECT: ReactOS Kernel
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnproot.c
5 * PURPOSE: PnP manager root device
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Copyright 2007 Herv? Poussineau (hpoussin@reactos.org)
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 #define ENUM_NAME_ROOT L"Root"
20 /* DATA **********************************************************************/
22 typedef struct _PNPROOT_DEVICE
24 // Entry on device list
26 // Physical Device Object of device
29 UNICODE_STRING DeviceID
;
31 UNICODE_STRING InstanceID
;
33 UNICODE_STRING DeviceDescription
;
34 // Resource requirement list
35 PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList
;
36 // Associated resource list
37 PCM_RESOURCE_LIST ResourceList
;
38 ULONG ResourceListSize
;
39 } PNPROOT_DEVICE
, *PPNPROOT_DEVICE
;
48 } PNPROOT_DEVICE_STATE
;
50 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
52 // Wether this device extension is for an FDO or PDO
54 } PNPROOT_COMMON_DEVICE_EXTENSION
, *PPNPROOT_COMMON_DEVICE_EXTENSION
;
56 /* Physical Device Object device extension for a child device */
57 typedef struct _PNPROOT_PDO_DEVICE_EXTENSION
60 PNPROOT_COMMON_DEVICE_EXTENSION Common
;
61 // Informations about the device
62 PPNPROOT_DEVICE DeviceInfo
;
63 } PNPROOT_PDO_DEVICE_EXTENSION
, *PPNPROOT_PDO_DEVICE_EXTENSION
;
65 /* Physical Device Object device extension for the Root bus device object */
66 typedef struct _PNPROOT_FDO_DEVICE_EXTENSION
69 PNPROOT_COMMON_DEVICE_EXTENSION Common
;
70 // Lower device object
72 // Current state of the driver
73 PNPROOT_DEVICE_STATE State
;
74 // Namespace device list
75 LIST_ENTRY DeviceListHead
;
76 // Number of (not removed) devices in device list
77 ULONG DeviceListCount
;
78 // Lock for namespace device list
79 KGUARDED_MUTEX DeviceListLock
;
80 } PNPROOT_FDO_DEVICE_EXTENSION
, *PPNPROOT_FDO_DEVICE_EXTENSION
;
82 typedef struct _BUFFER
88 static PDEVICE_OBJECT PnpRootDeviceObject
= NULL
;
90 /* FUNCTIONS *****************************************************************/
94 IN PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
,
97 OUT PPNPROOT_DEVICE
* ChildDevice
)
99 PPNPROOT_DEVICE Device
;
100 UNICODE_STRING DeviceIdU
, InstanceIdU
;
101 PLIST_ENTRY NextEntry
;
103 /* Initialize the strings to compare */
104 RtlInitUnicodeString(&DeviceIdU
, DeviceId
);
105 RtlInitUnicodeString(&InstanceIdU
, InstanceId
);
108 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
109 NextEntry
!= &DeviceExtension
->DeviceListHead
;
110 NextEntry
= NextEntry
->Flink
)
113 Device
= CONTAINING_RECORD(NextEntry
, PNPROOT_DEVICE
, ListEntry
);
115 /* See if the strings match */
116 if (RtlEqualUnicodeString(&DeviceIdU
, &Device
->DeviceID
, TRUE
) &&
117 RtlEqualUnicodeString(&InstanceIdU
, &Device
->InstanceID
, TRUE
))
119 /* They do, so set the pointer and return success */
120 *ChildDevice
= Device
;
121 return STATUS_SUCCESS
;
125 /* No device found */
126 return STATUS_NO_SUCH_DEVICE
;
130 PnpRootRegisterDevice(
131 IN PDEVICE_OBJECT DeviceObject
)
133 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
= PnpRootDeviceObject
->DeviceExtension
;
134 PPNPROOT_DEVICE Device
;
135 PDEVICE_NODE DeviceNode
;
137 UNICODE_STRING InstancePathCopy
;
139 Device
= ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
140 if (!Device
) return STATUS_NO_MEMORY
;
142 DeviceNode
= IopGetDeviceNode(DeviceObject
);
143 if (!RtlCreateUnicodeString(&InstancePathCopy
, DeviceNode
->InstancePath
.Buffer
))
145 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
146 return STATUS_NO_MEMORY
;
149 InstancePath
= wcsrchr(InstancePathCopy
.Buffer
, L
'\\');
150 ASSERT(InstancePath
);
152 if (!RtlCreateUnicodeString(&Device
->InstanceID
, InstancePath
+ 1))
154 RtlFreeUnicodeString(&InstancePathCopy
);
155 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
156 return STATUS_NO_MEMORY
;
159 InstancePath
[0] = UNICODE_NULL
;
161 if (!RtlCreateUnicodeString(&Device
->DeviceID
, InstancePathCopy
.Buffer
))
163 RtlFreeUnicodeString(&InstancePathCopy
);
164 RtlFreeUnicodeString(&Device
->InstanceID
);
165 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
166 return STATUS_NO_MEMORY
;
169 InstancePath
[0] = L
'\\';
171 Device
->Pdo
= DeviceObject
;
173 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
174 InsertTailList(&DeviceExtension
->DeviceListHead
,
176 DeviceExtension
->DeviceListCount
++;
177 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
179 RtlFreeUnicodeString(&InstancePathCopy
);
181 return STATUS_SUCCESS
;
184 /* Creates a new PnP device for a legacy driver */
187 IN PUNICODE_STRING ServiceName
,
188 IN OPTIONAL PDRIVER_OBJECT DriverObject
,
189 OUT PDEVICE_OBJECT
*PhysicalDeviceObject
,
190 OUT OPTIONAL PUNICODE_STRING FullInstancePath
)
192 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
193 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
194 WCHAR DevicePath
[MAX_PATH
+ 1];
195 WCHAR InstancePath
[5];
196 PPNPROOT_DEVICE Device
= NULL
;
198 UNICODE_STRING PathSep
= RTL_CONSTANT_STRING(L
"\\");
200 UNICODE_STRING EnumKeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM
);
201 HANDLE EnumHandle
, DeviceKeyHandle
= INVALID_HANDLE_VALUE
, InstanceKeyHandle
;
202 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
203 OBJECT_ATTRIBUTES ObjectAttributes
;
205 DeviceExtension
= PnpRootDeviceObject
->DeviceExtension
;
206 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
208 DPRINT("Creating a PnP root device for service '%wZ'\n", ServiceName
);
210 _snwprintf(DevicePath
, sizeof(DevicePath
) / sizeof(WCHAR
), L
"%s\\%wZ", REGSTR_KEY_ROOTENUM
, ServiceName
);
212 /* Initialize a PNPROOT_DEVICE structure */
213 Device
= ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
216 DPRINT("ExAllocatePoolWithTag() failed\n");
217 Status
= STATUS_NO_MEMORY
;
220 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
221 if (!RtlCreateUnicodeString(&Device
->DeviceID
, DevicePath
))
223 Status
= STATUS_NO_MEMORY
;
227 Status
= IopOpenRegistryKeyEx(&EnumHandle
, NULL
, &EnumKeyName
, KEY_READ
);
228 if (NT_SUCCESS(Status
))
230 InitializeObjectAttributes(&ObjectAttributes
,
232 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
235 Status
= ZwCreateKey(&DeviceKeyHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
236 ObCloseHandle(EnumHandle
, KernelMode
);
239 if (!NT_SUCCESS(Status
))
241 DPRINT1("Failed to open registry key\n");
246 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
247 QueryTable
[0].Name
= L
"NextInstance";
248 QueryTable
[0].EntryContext
= &NextInstance
;
249 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
251 Status
= RtlQueryRegistryValues(RTL_REGISTRY_HANDLE
,
252 (PWSTR
)DeviceKeyHandle
,
256 if (!NT_SUCCESS(Status
))
258 for (NextInstance
= 0; NextInstance
<= 9999; NextInstance
++)
260 _snwprintf(InstancePath
, sizeof(InstancePath
) / sizeof(WCHAR
), L
"%04lu", NextInstance
);
261 Status
= LocateChildDevice(DeviceExtension
, DevicePath
, InstancePath
, &Device
);
262 if (Status
== STATUS_NO_SUCH_DEVICE
)
266 if (NextInstance
> 9999)
268 DPRINT1("Too many legacy devices reported for service '%wZ'\n", ServiceName
);
269 Status
= STATUS_INSUFFICIENT_RESOURCES
;
274 _snwprintf(InstancePath
, sizeof(InstancePath
) / sizeof(WCHAR
), L
"%04lu", NextInstance
);
275 Status
= LocateChildDevice(DeviceExtension
, DevicePath
, InstancePath
, &Device
);
276 if (Status
!= STATUS_NO_SUCH_DEVICE
|| NextInstance
> 9999)
278 DPRINT1("NextInstance value is corrupt! (%lu)\n", NextInstance
);
279 RtlDeleteRegistryValue(RTL_REGISTRY_HANDLE
,
280 (PWSTR
)DeviceKeyHandle
,
286 Status
= RtlWriteRegistryValue(RTL_REGISTRY_HANDLE
,
287 (PWSTR
)DeviceKeyHandle
,
291 sizeof(NextInstance
));
292 if (!NT_SUCCESS(Status
))
294 DPRINT1("Failed to write new NextInstance value! (0x%x)\n", Status
);
298 if (!RtlCreateUnicodeString(&Device
->InstanceID
, InstancePath
))
300 Status
= STATUS_NO_MEMORY
;
304 /* Finish creating the instance path in the registry */
305 InitializeObjectAttributes(&ObjectAttributes
,
307 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
310 Status
= ZwCreateKey(&InstanceKeyHandle
, KEY_QUERY_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
311 if (!NT_SUCCESS(Status
))
313 DPRINT1("Failed to create instance path (0x%x)\n", Status
);
317 /* Just close the handle */
318 ObCloseHandle(InstanceKeyHandle
, KernelMode
);
320 if (FullInstancePath
)
322 FullInstancePath
->MaximumLength
= Device
->DeviceID
.Length
+ PathSep
.Length
+ Device
->InstanceID
.Length
;
323 FullInstancePath
->Length
= 0;
324 FullInstancePath
->Buffer
= ExAllocatePool(PagedPool
, FullInstancePath
->MaximumLength
);
325 if (!FullInstancePath
->Buffer
)
327 Status
= STATUS_NO_MEMORY
;
331 RtlAppendUnicodeStringToString(FullInstancePath
, &Device
->DeviceID
);
332 RtlAppendUnicodeStringToString(FullInstancePath
, &PathSep
);
333 RtlAppendUnicodeStringToString(FullInstancePath
, &Device
->InstanceID
);
336 /* Initialize a device object */
337 Status
= IoCreateDevice(
338 DriverObject
? DriverObject
: PnpRootDeviceObject
->DriverObject
,
339 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
341 FILE_DEVICE_CONTROLLER
,
342 FILE_AUTOGENERATED_DEVICE_NAME
,
345 if (!NT_SUCCESS(Status
))
347 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
348 Status
= STATUS_NO_MEMORY
;
352 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
353 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
354 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
355 PdoDeviceExtension
->DeviceInfo
= Device
;
357 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
358 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
361 &DeviceExtension
->DeviceListHead
,
363 DeviceExtension
->DeviceListCount
++;
365 *PhysicalDeviceObject
= Device
->Pdo
;
366 DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject
, &Device
->DeviceID
, &Device
->InstanceID
);
368 Status
= STATUS_SUCCESS
;
371 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
375 IoDeleteDevice(Device
->Pdo
);
376 RtlFreeUnicodeString(&Device
->DeviceID
);
377 RtlFreeUnicodeString(&Device
->InstanceID
);
378 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
380 if (DeviceKeyHandle
!= INVALID_HANDLE_VALUE
)
381 ObCloseHandle(DeviceKeyHandle
, KernelMode
);
385 static NTSTATUS NTAPI
390 IN ULONG ValueLength
,
392 IN PVOID EntryContext
)
394 PUNICODE_STRING Destination
= (PUNICODE_STRING
)EntryContext
;
395 UNICODE_STRING Source
;
397 if (ValueType
!= REG_SZ
|| ValueLength
== 0 || ValueLength
% sizeof(WCHAR
) != 0)
399 Destination
->Length
= 0;
400 Destination
->MaximumLength
= 0;
401 Destination
->Buffer
= NULL
;
402 return STATUS_SUCCESS
;
405 Source
.MaximumLength
= Source
.Length
= (USHORT
)ValueLength
;
406 Source
.Buffer
= ValueData
;
408 return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &Source
, Destination
);
411 static NTSTATUS NTAPI
412 QueryBinaryValueCallback(
416 IN ULONG ValueLength
,
418 IN PVOID EntryContext
)
420 PBUFFER Buffer
= (PBUFFER
)EntryContext
;
423 if (ValueLength
== 0)
425 *Buffer
->Data
= NULL
;
426 return STATUS_SUCCESS
;
429 BinaryValue
= ExAllocatePoolWithTag(PagedPool
, ValueLength
, TAG_PNP_ROOT
);
430 if (BinaryValue
== NULL
)
431 return STATUS_NO_MEMORY
;
432 RtlCopyMemory(BinaryValue
, ValueData
, ValueLength
);
433 *Buffer
->Data
= BinaryValue
;
434 if (Buffer
->Length
) *Buffer
->Length
= ValueLength
;
435 return STATUS_SUCCESS
;
440 IN PDEVICE_OBJECT DeviceObject
)
442 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
443 PKEY_BASIC_INFORMATION KeyInfo
= NULL
, SubKeyInfo
= NULL
;
444 UNICODE_STRING LegacyU
= RTL_CONSTANT_STRING(L
"LEGACY_");
445 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L
"\\" REGSTR_KEY_ROOTENUM
);
446 UNICODE_STRING SubKeyName
;
447 WCHAR DevicePath
[MAX_PATH
+ 1];
448 RTL_QUERY_REGISTRY_TABLE QueryTable
[4];
449 PPNPROOT_DEVICE Device
= NULL
;
450 HANDLE KeyHandle
= INVALID_HANDLE_VALUE
;
451 HANDLE SubKeyHandle
= INVALID_HANDLE_VALUE
;
452 HANDLE DeviceKeyHandle
= INVALID_HANDLE_VALUE
;
455 ULONG Index1
, Index2
;
456 BUFFER Buffer1
, Buffer2
;
457 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
459 DPRINT("EnumerateDevices(FDO %p)\n", DeviceObject
);
461 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
462 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
464 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + (MAX_PATH
+ 1) * sizeof(WCHAR
);
465 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
468 DPRINT("ExAllocatePoolWithTag() failed\n");
469 Status
= STATUS_NO_MEMORY
;
472 SubKeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
475 DPRINT("ExAllocatePoolWithTag() failed\n");
476 Status
= STATUS_NO_MEMORY
;
480 Status
= IopOpenRegistryKeyEx(&KeyHandle
, NULL
, &KeyName
, KEY_ENUMERATE_SUB_KEYS
);
481 if (!NT_SUCCESS(Status
))
483 DPRINT("IopOpenRegistryKeyEx(%wZ) failed with status 0x%08lx\n", &KeyName
, Status
);
487 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
488 * KeyHandle. We'll first do a first enumeration to have first level keys,
489 * and an inner one to have the real devices list.
494 Status
= ZwEnumerateKey(
501 if (Status
== STATUS_NO_MORE_ENTRIES
)
503 Status
= STATUS_SUCCESS
;
506 else if (!NT_SUCCESS(Status
))
508 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
512 /* Terminate the string */
513 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
515 /* Check if it is a legacy driver */
516 RtlInitUnicodeString(&SubKeyName
, KeyInfo
->Name
);
517 if (RtlPrefixUnicodeString(&LegacyU
, &SubKeyName
, FALSE
))
519 DPRINT("Ignoring legacy driver '%wZ'\n", &SubKeyName
);
525 Status
= IopOpenRegistryKeyEx(&SubKeyHandle
, KeyHandle
, &SubKeyName
, KEY_ENUMERATE_SUB_KEYS
);
526 if (!NT_SUCCESS(Status
))
528 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status
);
532 /* Enumerate the sub-keys */
536 Status
= ZwEnumerateKey(
543 if (Status
== STATUS_NO_MORE_ENTRIES
)
545 else if (!NT_SUCCESS(Status
))
547 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
551 /* Terminate the string */
552 SubKeyInfo
->Name
[SubKeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
554 _snwprintf(DevicePath
, sizeof(DevicePath
) / sizeof(WCHAR
),
555 L
"%s\\%s", REGSTR_KEY_ROOTENUM
, KeyInfo
->Name
);
556 DPRINT("Found device %S\\%s!\n", DevicePath
, SubKeyInfo
->Name
);
557 if (LocateChildDevice(DeviceExtension
, DevicePath
, SubKeyInfo
->Name
, &Device
) == STATUS_NO_SUCH_DEVICE
)
559 /* Create a PPNPROOT_DEVICE object, and add if in the list of known devices */
560 Device
= (PPNPROOT_DEVICE
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
563 DPRINT("ExAllocatePoolWithTag() failed\n");
564 Status
= STATUS_NO_MEMORY
;
567 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
569 /* Fill device ID and instance ID */
570 if (!RtlCreateUnicodeString(&Device
->DeviceID
, DevicePath
))
572 DPRINT1("RtlCreateUnicodeString() failed\n");
573 Status
= STATUS_NO_MEMORY
;
577 if (!RtlCreateUnicodeString(&Device
->InstanceID
, SubKeyInfo
->Name
))
579 DPRINT1("RtlCreateUnicodeString() failed\n");
580 Status
= STATUS_NO_MEMORY
;
584 /* Open registry key to fill other informations */
585 Status
= IopOpenRegistryKeyEx(&DeviceKeyHandle
, SubKeyHandle
, &Device
->InstanceID
, KEY_READ
);
586 if (!NT_SUCCESS(Status
))
588 DPRINT1("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status
);
592 /* Fill information from the device instance key */
593 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
594 QueryTable
[0].QueryRoutine
= QueryStringCallback
;
595 QueryTable
[0].Name
= L
"DeviceDesc";
596 QueryTable
[0].EntryContext
= &Device
->DeviceDescription
;
598 RtlQueryRegistryValues(RTL_REGISTRY_HANDLE
,
599 (PCWSTR
)DeviceKeyHandle
,
604 /* Fill information from the LogConf subkey */
605 Buffer1
.Data
= (PVOID
*)&Device
->ResourceRequirementsList
;
606 Buffer1
.Length
= NULL
;
607 Buffer2
.Data
= (PVOID
*)&Device
->ResourceList
;
608 Buffer2
.Length
= &Device
->ResourceListSize
;
609 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
610 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_SUBKEY
;
611 QueryTable
[0].Name
= L
"LogConf";
612 QueryTable
[1].QueryRoutine
= QueryBinaryValueCallback
;
613 QueryTable
[1].Name
= L
"BasicConfigVector";
614 QueryTable
[1].EntryContext
= &Buffer1
;
615 QueryTable
[2].QueryRoutine
= QueryBinaryValueCallback
;
616 QueryTable
[2].Name
= L
"BootConfig";
617 QueryTable
[2].EntryContext
= &Buffer2
;
619 if (!NT_SUCCESS(RtlQueryRegistryValues(RTL_REGISTRY_HANDLE
,
620 (PCWSTR
)DeviceKeyHandle
,
625 /* Non-fatal error */
626 DPRINT1("Failed to read the LogConf key for %S\\%S\n", DevicePath
, SubKeyInfo
->Name
);
629 ZwClose(DeviceKeyHandle
);
630 DeviceKeyHandle
= INVALID_HANDLE_VALUE
;
632 /* Insert the newly created device into the list */
634 &DeviceExtension
->DeviceListHead
,
636 DeviceExtension
->DeviceListCount
++;
643 ZwClose(SubKeyHandle
);
644 SubKeyHandle
= INVALID_HANDLE_VALUE
;
651 /* We have a device that has not been added to device list. We need to clean it up */
653 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
655 if (DeviceKeyHandle
!= INVALID_HANDLE_VALUE
)
656 ZwClose(DeviceKeyHandle
);
657 if (SubKeyHandle
!= INVALID_HANDLE_VALUE
)
658 ZwClose(SubKeyHandle
);
659 if (KeyHandle
!= INVALID_HANDLE_VALUE
)
662 ExFreePoolWithTag(KeyInfo
, TAG_PNP_ROOT
);
664 ExFreePoolWithTag(SubKeyInfo
, TAG_PNP_ROOT
);
665 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
669 /* FUNCTION: Handle IRP_MN_QUERY_DEVICE_RELATIONS IRPs for the root bus device object
671 * DeviceObject = Pointer to functional device object of the root bus driver
672 * Irp = Pointer to IRP that should be handled
677 PnpRootQueryDeviceRelations(
678 IN PDEVICE_OBJECT DeviceObject
,
681 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
682 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
683 PDEVICE_RELATIONS Relations
= NULL
, OtherRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
684 PPNPROOT_DEVICE Device
= NULL
;
687 PLIST_ENTRY NextEntry
;
689 DPRINT("PnpRootQueryDeviceRelations(FDO %p, Irp %p)\n", DeviceObject
, Irp
);
691 Status
= EnumerateDevices(DeviceObject
);
692 if (!NT_SUCCESS(Status
))
694 DPRINT("EnumerateDevices() failed with status 0x%08lx\n", Status
);
698 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
700 Size
= FIELD_OFFSET(DEVICE_RELATIONS
, Objects
) + sizeof(PDEVICE_OBJECT
) * DeviceExtension
->DeviceListCount
;
703 /* Another bus driver has already created a DEVICE_RELATIONS
704 * structure so we must merge this structure with our own */
706 Size
+= sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
;
708 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, Size
);
711 DPRINT("ExAllocatePoolWithTag() failed\n");
712 Status
= STATUS_NO_MEMORY
;
715 RtlZeroMemory(Relations
, Size
);
718 Relations
->Count
= OtherRelations
->Count
;
719 RtlCopyMemory(Relations
->Objects
, OtherRelations
->Objects
, sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
);
722 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
725 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
726 NextEntry
!= &DeviceExtension
->DeviceListHead
;
727 NextEntry
= NextEntry
->Flink
)
730 Device
= CONTAINING_RECORD(NextEntry
, PNPROOT_DEVICE
, ListEntry
);
734 /* Create a physical device object for the
735 * device as it does not already have one */
736 Status
= IoCreateDevice(
737 DeviceObject
->DriverObject
,
738 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
740 FILE_DEVICE_CONTROLLER
,
741 FILE_AUTOGENERATED_DEVICE_NAME
,
744 if (!NT_SUCCESS(Status
))
746 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
750 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
751 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
752 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
753 PdoDeviceExtension
->DeviceInfo
= Device
;
755 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
756 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
759 /* Reference the physical device object. The PnP manager
760 will dereference it again when it is no longer needed */
761 ObReferenceObject(Device
->Pdo
);
763 Relations
->Objects
[Relations
->Count
++] = Device
->Pdo
;
765 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
767 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
770 if (!NT_SUCCESS(Status
))
773 ExFreePool(OtherRelations
);
775 ExFreePool(Relations
);
776 if (Device
&& Device
->Pdo
)
778 IoDeleteDevice(Device
->Pdo
);
787 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
789 * DeviceObject = Pointer to functional device object of the root bus driver
790 * Irp = Pointer to IRP that should be handled
795 PnpRootFdoPnpControl(
796 IN PDEVICE_OBJECT DeviceObject
,
799 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
800 PIO_STACK_LOCATION IrpSp
;
803 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
804 Status
= Irp
->IoStatus
.Status
;
805 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
807 switch (IrpSp
->MinorFunction
)
809 case IRP_MN_QUERY_DEVICE_RELATIONS
:
810 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
811 Status
= PnpRootQueryDeviceRelations(DeviceObject
, Irp
);
814 case IRP_MN_START_DEVICE
:
815 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
816 if (!IoForwardIrpSynchronously(DeviceExtension
->Ldo
, Irp
))
817 Status
= STATUS_UNSUCCESSFUL
;
820 Status
= Irp
->IoStatus
.Status
;
821 if (NT_SUCCESS(Status
))
822 DeviceExtension
->State
= dsStarted
;
825 Irp
->IoStatus
.Status
= Status
;
826 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
829 case IRP_MN_STOP_DEVICE
:
830 DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
831 /* Root device cannot be stopped */
832 Irp
->IoStatus
.Status
= Status
= STATUS_INVALID_DEVICE_REQUEST
;
833 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
837 DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
841 if (Status
!= STATUS_PENDING
)
843 Irp
->IoStatus
.Status
= Status
;
844 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
851 PdoQueryDeviceRelations(
852 IN PDEVICE_OBJECT DeviceObject
,
854 IN PIO_STACK_LOCATION IrpSp
)
856 PDEVICE_RELATIONS Relations
;
857 NTSTATUS Status
= Irp
->IoStatus
.Status
;
859 if (IrpSp
->Parameters
.QueryDeviceRelations
.Type
!= TargetDeviceRelation
)
862 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
863 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
));
866 DPRINT("ExAllocatePoolWithTag() failed\n");
867 Status
= STATUS_NO_MEMORY
;
871 ObReferenceObject(DeviceObject
);
872 Relations
->Count
= 1;
873 Relations
->Objects
[0] = DeviceObject
;
874 Status
= STATUS_SUCCESS
;
875 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
882 PdoQueryCapabilities(
883 IN PDEVICE_OBJECT DeviceObject
,
885 IN PIO_STACK_LOCATION IrpSp
)
887 PDEVICE_CAPABILITIES DeviceCapabilities
;
889 DeviceCapabilities
= IrpSp
->Parameters
.DeviceCapabilities
.Capabilities
;
891 if (DeviceCapabilities
->Version
!= 1)
892 return STATUS_REVISION_MISMATCH
;
894 DeviceCapabilities
->UniqueID
= TRUE
;
895 /* FIXME: Fill other fields */
897 return STATUS_SUCCESS
;
902 IN PDEVICE_OBJECT DeviceObject
,
904 IN PIO_STACK_LOCATION IrpSp
)
906 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
907 PCM_RESOURCE_LIST ResourceList
;
909 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
911 if (DeviceExtension
->DeviceInfo
->ResourceList
)
913 /* Copy existing resource requirement list */
914 ResourceList
= ExAllocatePool(
916 DeviceExtension
->DeviceInfo
->ResourceListSize
);
918 return STATUS_NO_MEMORY
;
922 DeviceExtension
->DeviceInfo
->ResourceList
,
923 DeviceExtension
->DeviceInfo
->ResourceListSize
);
925 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
927 return STATUS_SUCCESS
;
931 /* No resources so just return without changing the status */
932 return Irp
->IoStatus
.Status
;
937 PdoQueryResourceRequirements(
938 IN PDEVICE_OBJECT DeviceObject
,
940 IN PIO_STACK_LOCATION IrpSp
)
942 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
943 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList
;
945 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
947 if (DeviceExtension
->DeviceInfo
->ResourceRequirementsList
)
949 /* Copy existing resource requirement list */
950 ResourceList
= ExAllocatePool(PagedPool
, DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
952 return STATUS_NO_MEMORY
;
956 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
,
957 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
959 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
961 return STATUS_SUCCESS
;
965 /* No resource requirements so just return without changing the status */
966 return Irp
->IoStatus
.Status
;
972 IN PDEVICE_OBJECT DeviceObject
,
974 IN PIO_STACK_LOCATION IrpSp
)
976 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
977 DEVICE_TEXT_TYPE DeviceTextType
;
978 NTSTATUS Status
= Irp
->IoStatus
.Status
;
980 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
981 DeviceTextType
= IrpSp
->Parameters
.QueryDeviceText
.DeviceTextType
;
983 switch (DeviceTextType
)
985 case DeviceTextDescription
:
987 UNICODE_STRING String
;
988 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
990 if (DeviceExtension
->DeviceInfo
->DeviceDescription
.Buffer
!= NULL
)
992 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
993 &DeviceExtension
->DeviceInfo
->DeviceDescription
,
995 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
1000 case DeviceTextLocationInformation
:
1002 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
1008 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown query id type 0x%lx\n", DeviceTextType
);
1017 IN PDEVICE_OBJECT DeviceObject
,
1019 IN PIO_STACK_LOCATION IrpSp
)
1021 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
1022 BUS_QUERY_ID_TYPE IdType
;
1023 NTSTATUS Status
= Irp
->IoStatus
.Status
;
1025 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1026 IdType
= IrpSp
->Parameters
.QueryId
.IdType
;
1030 case BusQueryDeviceID
:
1032 UNICODE_STRING String
;
1033 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
1035 Status
= RtlDuplicateUnicodeString(
1036 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
1037 &DeviceExtension
->DeviceInfo
->DeviceID
,
1039 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
1043 case BusQueryHardwareIDs
:
1044 case BusQueryCompatibleIDs
:
1046 /* Optional, do nothing */
1050 case BusQueryInstanceID
:
1052 UNICODE_STRING String
;
1053 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
1055 Status
= RtlDuplicateUnicodeString(
1056 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
1057 &DeviceExtension
->DeviceInfo
->InstanceID
,
1059 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
1065 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
1073 PdoQueryBusInformation(
1074 IN PDEVICE_OBJECT DeviceObject
,
1076 IN PIO_STACK_LOCATION IrpSp
)
1078 PPNP_BUS_INFORMATION BusInfo
;
1081 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNP_BUS_INFORMATION
), TAG_PNP_ROOT
);
1083 Status
= STATUS_NO_MEMORY
;
1087 &BusInfo
->BusTypeGuid
,
1088 &GUID_BUS_TYPE_INTERNAL
,
1089 sizeof(BusInfo
->BusTypeGuid
));
1090 BusInfo
->LegacyBusType
= PNPBus
;
1091 /* We're the only root bus enumerator on the computer */
1092 BusInfo
->BusNumber
= 0;
1093 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInfo
;
1094 Status
= STATUS_SUCCESS
;
1101 * FUNCTION: Handle Plug and Play IRPs for the child device
1103 * DeviceObject = Pointer to physical device object of the child device
1104 * Irp = Pointer to IRP that should be handled
1109 PnpRootPdoPnpControl(
1110 IN PDEVICE_OBJECT DeviceObject
,
1113 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
1114 PPNPROOT_FDO_DEVICE_EXTENSION FdoDeviceExtension
;
1115 PIO_STACK_LOCATION IrpSp
;
1118 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1119 FdoDeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)PnpRootDeviceObject
->DeviceExtension
;
1120 Status
= Irp
->IoStatus
.Status
;
1121 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1123 switch (IrpSp
->MinorFunction
)
1125 case IRP_MN_START_DEVICE
: /* 0x00 */
1126 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1127 Status
= STATUS_SUCCESS
;
1130 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x07 */
1131 Status
= PdoQueryDeviceRelations(DeviceObject
, Irp
, IrpSp
);
1134 case IRP_MN_QUERY_CAPABILITIES
: /* 0x09 */
1135 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
1136 Status
= PdoQueryCapabilities(DeviceObject
, Irp
, IrpSp
);
1139 case IRP_MN_QUERY_RESOURCES
: /* 0x0a */
1140 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
1141 Status
= PdoQueryResources(DeviceObject
, Irp
, IrpSp
);
1144 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
: /* 0x0b */
1145 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1146 Status
= PdoQueryResourceRequirements(DeviceObject
, Irp
, IrpSp
);
1149 case IRP_MN_QUERY_DEVICE_TEXT
: /* 0x0c */
1150 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1151 Status
= PdoQueryDeviceText(DeviceObject
, Irp
, IrpSp
);
1154 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0x0d */
1155 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1158 case IRP_MN_REMOVE_DEVICE
:
1159 /* Remove the device from the device list and decrement the device count*/
1160 KeAcquireGuardedMutex(&FdoDeviceExtension
->DeviceListLock
);
1161 RemoveEntryList(&DeviceExtension
->DeviceInfo
->ListEntry
);
1162 FdoDeviceExtension
->DeviceListCount
--;
1163 KeReleaseGuardedMutex(&FdoDeviceExtension
->DeviceListLock
);
1165 /* Free some strings we created */
1166 RtlFreeUnicodeString(&DeviceExtension
->DeviceInfo
->DeviceDescription
);
1167 RtlFreeUnicodeString(&DeviceExtension
->DeviceInfo
->DeviceID
);
1168 RtlFreeUnicodeString(&DeviceExtension
->DeviceInfo
->InstanceID
);
1170 /* Free the resource requirements list */
1171 if (DeviceExtension
->DeviceInfo
->ResourceRequirementsList
!= NULL
)
1172 ExFreePool(DeviceExtension
->DeviceInfo
->ResourceRequirementsList
);
1174 /* Free the boot resources list */
1175 if (DeviceExtension
->DeviceInfo
->ResourceList
!= NULL
)
1176 ExFreePool(DeviceExtension
->DeviceInfo
->ResourceList
);
1178 /* Free the device info */
1179 ExFreePool(DeviceExtension
->DeviceInfo
);
1181 /* Finally, delete the device object */
1182 IoDeleteDevice(DeviceObject
);
1184 /* Return success */
1185 Status
= STATUS_SUCCESS
;
1188 case IRP_MN_QUERY_ID
: /* 0x13 */
1189 Status
= PdoQueryId(DeviceObject
, Irp
, IrpSp
);
1192 case IRP_MN_QUERY_BUS_INFORMATION
: /* 0x15 */
1193 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
1194 Status
= PdoQueryBusInformation(DeviceObject
, Irp
, IrpSp
);
1198 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
1202 if (Status
!= STATUS_PENDING
)
1204 Irp
->IoStatus
.Status
= Status
;
1205 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1212 * FUNCTION: Handle Plug and Play IRPs
1214 * DeviceObject = Pointer to PDO or FDO
1215 * Irp = Pointer to IRP that should be handled
1219 static NTSTATUS NTAPI
1221 IN PDEVICE_OBJECT DeviceObject
,
1224 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension
;
1227 DeviceExtension
= (PPNPROOT_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1229 if (DeviceExtension
->IsFDO
)
1230 Status
= PnpRootFdoPnpControl(DeviceObject
, Irp
);
1232 Status
= PnpRootPdoPnpControl(DeviceObject
, Irp
);
1240 IN PDRIVER_OBJECT DriverObject
,
1241 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1243 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
1246 DPRINT("PnpRootAddDevice(DriverObject %p, Pdo %p)\n", DriverObject
, PhysicalDeviceObject
);
1248 if (!PhysicalDeviceObject
)
1250 DPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject
);
1251 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1252 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1255 Status
= IoCreateDevice(
1257 sizeof(PNPROOT_FDO_DEVICE_EXTENSION
),
1259 FILE_DEVICE_BUS_EXTENDER
,
1260 FILE_DEVICE_SECURE_OPEN
,
1262 &PnpRootDeviceObject
);
1263 if (!NT_SUCCESS(Status
))
1265 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
1266 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1268 DPRINT("Created FDO %p\n", PnpRootDeviceObject
);
1270 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)PnpRootDeviceObject
->DeviceExtension
;
1271 RtlZeroMemory(DeviceExtension
, sizeof(PNPROOT_FDO_DEVICE_EXTENSION
));
1273 DeviceExtension
->Common
.IsFDO
= TRUE
;
1274 DeviceExtension
->State
= dsStopped
;
1275 InitializeListHead(&DeviceExtension
->DeviceListHead
);
1276 DeviceExtension
->DeviceListCount
= 0;
1277 KeInitializeGuardedMutex(&DeviceExtension
->DeviceListLock
);
1279 Status
= IoAttachDeviceToDeviceStackSafe(
1280 PnpRootDeviceObject
,
1281 PhysicalDeviceObject
,
1282 &DeviceExtension
->Ldo
);
1283 if (!NT_SUCCESS(Status
))
1285 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
1286 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1289 PnpRootDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1291 DPRINT("Done AddDevice()\n");
1293 return STATUS_SUCCESS
;
1298 IN PDRIVER_OBJECT DriverObject
,
1299 IN PUNICODE_STRING RegistryPath
)
1301 DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject
, RegistryPath
);
1303 IopRootDriverObject
= DriverObject
;
1305 DriverObject
->DriverExtension
->AddDevice
= PnpRootAddDevice
;
1307 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = PnpRootPnpControl
;
1308 //DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl;
1310 return STATUS_SUCCESS
;