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
,
95 IN PCUNICODE_STRING DeviceId
,
97 OUT PPNPROOT_DEVICE
* ChildDevice
)
99 PPNPROOT_DEVICE Device
;
100 UNICODE_STRING InstanceIdU
;
101 PLIST_ENTRY NextEntry
;
103 /* Initialize the string to compare */
104 RtlInitUnicodeString(&InstanceIdU
, InstanceId
);
107 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
108 NextEntry
!= &DeviceExtension
->DeviceListHead
;
109 NextEntry
= NextEntry
->Flink
)
112 Device
= CONTAINING_RECORD(NextEntry
, PNPROOT_DEVICE
, ListEntry
);
114 /* See if the strings match */
115 if (RtlEqualUnicodeString(DeviceId
, &Device
->DeviceID
, TRUE
) &&
116 RtlEqualUnicodeString(&InstanceIdU
, &Device
->InstanceID
, TRUE
))
118 /* They do, so set the pointer and return success */
119 *ChildDevice
= Device
;
120 return STATUS_SUCCESS
;
124 /* No device found */
125 return STATUS_NO_SUCH_DEVICE
;
129 PnpRootRegisterDevice(
130 IN PDEVICE_OBJECT DeviceObject
)
132 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
= PnpRootDeviceObject
->DeviceExtension
;
133 PPNPROOT_DEVICE Device
;
134 PDEVICE_NODE DeviceNode
;
136 UNICODE_STRING InstancePathCopy
;
138 Device
= ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
139 if (!Device
) return STATUS_NO_MEMORY
;
141 DeviceNode
= IopGetDeviceNode(DeviceObject
);
142 if (!RtlCreateUnicodeString(&InstancePathCopy
, DeviceNode
->InstancePath
.Buffer
))
144 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
145 return STATUS_NO_MEMORY
;
148 InstancePath
= wcsrchr(InstancePathCopy
.Buffer
, L
'\\');
149 ASSERT(InstancePath
);
151 if (!RtlCreateUnicodeString(&Device
->InstanceID
, InstancePath
+ 1))
153 RtlFreeUnicodeString(&InstancePathCopy
);
154 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
155 return STATUS_NO_MEMORY
;
158 InstancePath
[0] = UNICODE_NULL
;
160 if (!RtlCreateUnicodeString(&Device
->DeviceID
, InstancePathCopy
.Buffer
))
162 RtlFreeUnicodeString(&InstancePathCopy
);
163 RtlFreeUnicodeString(&Device
->InstanceID
);
164 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
165 return STATUS_NO_MEMORY
;
168 InstancePath
[0] = L
'\\';
170 Device
->Pdo
= DeviceObject
;
172 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
173 InsertTailList(&DeviceExtension
->DeviceListHead
,
175 DeviceExtension
->DeviceListCount
++;
176 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
178 RtlFreeUnicodeString(&InstancePathCopy
);
180 return STATUS_SUCCESS
;
183 /* Creates a new PnP device for a legacy driver */
186 IN PUNICODE_STRING ServiceName
,
187 IN OPTIONAL PDRIVER_OBJECT DriverObject
,
188 OUT PDEVICE_OBJECT
*PhysicalDeviceObject
,
189 OUT OPTIONAL PUNICODE_STRING FullInstancePath
)
191 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
192 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
193 UNICODE_STRING DevicePath
;
194 WCHAR InstancePath
[5];
195 PPNPROOT_DEVICE Device
= NULL
;
197 UNICODE_STRING PathSep
= RTL_CONSTANT_STRING(L
"\\");
199 UNICODE_STRING EnumKeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM
);
200 HANDLE EnumHandle
, DeviceKeyHandle
= NULL
, InstanceKeyHandle
;
201 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
202 OBJECT_ATTRIBUTES ObjectAttributes
;
204 DeviceExtension
= PnpRootDeviceObject
->DeviceExtension
;
205 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
207 DPRINT("Creating a PnP root device for service '%wZ'\n", ServiceName
);
209 DevicePath
.Length
= 0;
210 DevicePath
.MaximumLength
= sizeof(REGSTR_KEY_ROOTENUM
) + sizeof(L
'\\') + ServiceName
->Length
;
211 DevicePath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
212 DevicePath
.MaximumLength
,
214 if (DevicePath
.Buffer
== NULL
)
216 DPRINT1("ExAllocatePoolWithTag() failed\n");
217 Status
= STATUS_NO_MEMORY
;
220 RtlAppendUnicodeToString(&DevicePath
, REGSTR_KEY_ROOTENUM L
"\\");
221 RtlAppendUnicodeStringToString(&DevicePath
, ServiceName
);
223 /* Initialize a PNPROOT_DEVICE structure */
224 Device
= ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
227 DPRINT("ExAllocatePoolWithTag() failed\n");
228 Status
= STATUS_NO_MEMORY
;
231 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
232 Device
->DeviceID
= DevicePath
;
233 RtlInitEmptyUnicodeString(&DevicePath
, NULL
, 0);
235 Status
= IopOpenRegistryKeyEx(&EnumHandle
, NULL
, &EnumKeyName
, KEY_READ
);
236 if (NT_SUCCESS(Status
))
238 InitializeObjectAttributes(&ObjectAttributes
,
240 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
243 Status
= ZwCreateKey(&DeviceKeyHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
244 ObCloseHandle(EnumHandle
, KernelMode
);
247 if (!NT_SUCCESS(Status
))
249 DPRINT1("Failed to open registry key\n");
254 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
255 QueryTable
[0].Name
= L
"NextInstance";
256 QueryTable
[0].EntryContext
= &NextInstance
;
257 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
259 Status
= RtlQueryRegistryValues(RTL_REGISTRY_HANDLE
,
260 (PWSTR
)DeviceKeyHandle
,
264 if (!NT_SUCCESS(Status
))
266 for (NextInstance
= 0; NextInstance
<= 9999; NextInstance
++)
268 _snwprintf(InstancePath
, sizeof(InstancePath
) / sizeof(WCHAR
), L
"%04lu", NextInstance
);
269 Status
= LocateChildDevice(DeviceExtension
, &Device
->DeviceID
, InstancePath
, &Device
);
270 if (Status
== STATUS_NO_SUCH_DEVICE
)
274 if (NextInstance
> 9999)
276 DPRINT1("Too many legacy devices reported for service '%wZ'\n", ServiceName
);
277 Status
= STATUS_INSUFFICIENT_RESOURCES
;
282 _snwprintf(InstancePath
, sizeof(InstancePath
) / sizeof(WCHAR
), L
"%04lu", NextInstance
);
283 Status
= LocateChildDevice(DeviceExtension
, &Device
->DeviceID
, InstancePath
, &Device
);
284 if (Status
!= STATUS_NO_SUCH_DEVICE
|| NextInstance
> 9999)
286 DPRINT1("NextInstance value is corrupt! (%lu)\n", NextInstance
);
287 RtlDeleteRegistryValue(RTL_REGISTRY_HANDLE
,
288 (PWSTR
)DeviceKeyHandle
,
294 Status
= RtlWriteRegistryValue(RTL_REGISTRY_HANDLE
,
295 (PWSTR
)DeviceKeyHandle
,
299 sizeof(NextInstance
));
300 if (!NT_SUCCESS(Status
))
302 DPRINT1("Failed to write new NextInstance value! (0x%x)\n", Status
);
306 if (!RtlCreateUnicodeString(&Device
->InstanceID
, InstancePath
))
308 Status
= STATUS_NO_MEMORY
;
312 /* Finish creating the instance path in the registry */
313 InitializeObjectAttributes(&ObjectAttributes
,
315 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
318 Status
= ZwCreateKey(&InstanceKeyHandle
, KEY_QUERY_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
319 if (!NT_SUCCESS(Status
))
321 DPRINT1("Failed to create instance path (0x%x)\n", Status
);
325 /* Just close the handle */
326 ObCloseHandle(InstanceKeyHandle
, KernelMode
);
328 if (FullInstancePath
)
330 FullInstancePath
->MaximumLength
= Device
->DeviceID
.Length
+ PathSep
.Length
+ Device
->InstanceID
.Length
;
331 FullInstancePath
->Length
= 0;
332 FullInstancePath
->Buffer
= ExAllocatePool(PagedPool
, FullInstancePath
->MaximumLength
);
333 if (!FullInstancePath
->Buffer
)
335 Status
= STATUS_NO_MEMORY
;
339 RtlAppendUnicodeStringToString(FullInstancePath
, &Device
->DeviceID
);
340 RtlAppendUnicodeStringToString(FullInstancePath
, &PathSep
);
341 RtlAppendUnicodeStringToString(FullInstancePath
, &Device
->InstanceID
);
344 /* Initialize a device object */
345 Status
= IoCreateDevice(
346 DriverObject
? DriverObject
: PnpRootDeviceObject
->DriverObject
,
347 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
349 FILE_DEVICE_CONTROLLER
,
350 FILE_AUTOGENERATED_DEVICE_NAME
,
353 if (!NT_SUCCESS(Status
))
355 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
356 Status
= STATUS_NO_MEMORY
;
360 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
361 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
362 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
363 PdoDeviceExtension
->DeviceInfo
= Device
;
365 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
366 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
369 &DeviceExtension
->DeviceListHead
,
371 DeviceExtension
->DeviceListCount
++;
373 *PhysicalDeviceObject
= Device
->Pdo
;
374 DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject
, &Device
->DeviceID
, &Device
->InstanceID
);
376 Status
= STATUS_SUCCESS
;
379 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
383 IoDeleteDevice(Device
->Pdo
);
384 RtlFreeUnicodeString(&Device
->DeviceID
);
385 RtlFreeUnicodeString(&Device
->InstanceID
);
386 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
388 RtlFreeUnicodeString(&DevicePath
);
389 if (DeviceKeyHandle
!= NULL
)
390 ObCloseHandle(DeviceKeyHandle
, KernelMode
);
394 static NTSTATUS NTAPI
399 IN ULONG ValueLength
,
401 IN PVOID EntryContext
)
403 PUNICODE_STRING Destination
= (PUNICODE_STRING
)EntryContext
;
404 UNICODE_STRING Source
;
406 if (ValueType
!= REG_SZ
|| ValueLength
== 0 || ValueLength
% sizeof(WCHAR
) != 0)
408 Destination
->Length
= 0;
409 Destination
->MaximumLength
= 0;
410 Destination
->Buffer
= NULL
;
411 return STATUS_SUCCESS
;
414 Source
.MaximumLength
= Source
.Length
= (USHORT
)ValueLength
;
415 Source
.Buffer
= ValueData
;
417 return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &Source
, Destination
);
420 static NTSTATUS NTAPI
421 QueryBinaryValueCallback(
425 IN ULONG ValueLength
,
427 IN PVOID EntryContext
)
429 PBUFFER Buffer
= (PBUFFER
)EntryContext
;
432 if (ValueLength
== 0)
434 *Buffer
->Data
= NULL
;
435 return STATUS_SUCCESS
;
438 BinaryValue
= ExAllocatePoolWithTag(PagedPool
, ValueLength
, TAG_PNP_ROOT
);
439 if (BinaryValue
== NULL
)
440 return STATUS_NO_MEMORY
;
441 RtlCopyMemory(BinaryValue
, ValueData
, ValueLength
);
442 *Buffer
->Data
= BinaryValue
;
443 if (Buffer
->Length
) *Buffer
->Length
= ValueLength
;
444 return STATUS_SUCCESS
;
449 CreateDeviceFromRegistry(
450 _Inout_ PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
,
451 _Inout_ PUNICODE_STRING DevicePath
,
452 _In_ PCWSTR InstanceId
,
453 _In_ HANDLE SubKeyHandle
)
456 PPNPROOT_DEVICE Device
;
457 HANDLE DeviceKeyHandle
= NULL
;
458 RTL_QUERY_REGISTRY_TABLE QueryTable
[4];
459 BUFFER Buffer1
, Buffer2
;
461 /* If the device already exists, there's nothing to do */
462 Status
= LocateChildDevice(DeviceExtension
, DevicePath
, InstanceId
, &Device
);
463 if (Status
!= STATUS_NO_SUCH_DEVICE
)
465 return STATUS_SUCCESS
;
468 /* Create a PPNPROOT_DEVICE object, and add it to the list of known devices */
469 Device
= ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
472 DPRINT("ExAllocatePoolWithTag() failed\n");
473 Status
= STATUS_NO_MEMORY
;
476 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
478 /* Fill device ID and instance ID */
479 Device
->DeviceID
= *DevicePath
;
480 RtlInitEmptyUnicodeString(DevicePath
, NULL
, 0);
481 if (!RtlCreateUnicodeString(&Device
->InstanceID
, InstanceId
))
483 DPRINT1("RtlCreateUnicodeString() failed\n");
484 Status
= STATUS_NO_MEMORY
;
488 /* Open registry key to fill other informations */
489 Status
= IopOpenRegistryKeyEx(&DeviceKeyHandle
, SubKeyHandle
, &Device
->InstanceID
, KEY_READ
);
490 if (!NT_SUCCESS(Status
))
492 /* If our key disappeared, let the caller go on */
493 DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n",
494 &Device
->InstanceID
, Status
);
495 Status
= STATUS_SUCCESS
;
499 /* Fill information from the device instance key */
500 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
501 QueryTable
[0].QueryRoutine
= QueryStringCallback
;
502 QueryTable
[0].Name
= L
"DeviceDesc";
503 QueryTable
[0].EntryContext
= &Device
->DeviceDescription
;
505 RtlQueryRegistryValues(RTL_REGISTRY_HANDLE
,
506 (PCWSTR
)DeviceKeyHandle
,
511 /* Fill information from the LogConf subkey */
512 Buffer1
.Data
= (PVOID
*)&Device
->ResourceRequirementsList
;
513 Buffer1
.Length
= NULL
;
514 Buffer2
.Data
= (PVOID
*)&Device
->ResourceList
;
515 Buffer2
.Length
= &Device
->ResourceListSize
;
516 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
517 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_SUBKEY
;
518 QueryTable
[0].Name
= L
"LogConf";
519 QueryTable
[1].QueryRoutine
= QueryBinaryValueCallback
;
520 QueryTable
[1].Name
= L
"BasicConfigVector";
521 QueryTable
[1].EntryContext
= &Buffer1
;
522 QueryTable
[2].QueryRoutine
= QueryBinaryValueCallback
;
523 QueryTable
[2].Name
= L
"BootConfig";
524 QueryTable
[2].EntryContext
= &Buffer2
;
526 if (!NT_SUCCESS(RtlQueryRegistryValues(RTL_REGISTRY_HANDLE
,
527 (PCWSTR
)DeviceKeyHandle
,
532 /* Non-fatal error */
533 DPRINT1("Failed to read the LogConf key for %wZ\\%S\n", &Device
->DeviceID
, InstanceId
);
536 /* Insert the newly created device into the list */
537 InsertTailList(&DeviceExtension
->DeviceListHead
,
539 DeviceExtension
->DeviceListCount
++;
543 if (DeviceKeyHandle
!= NULL
)
545 ZwClose(DeviceKeyHandle
);
549 /* We have a device that has not been added to device list. We need to clean it up */
550 RtlFreeUnicodeString(&Device
->DeviceID
);
551 RtlFreeUnicodeString(&Device
->InstanceID
);
552 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
559 IN PDEVICE_OBJECT DeviceObject
)
561 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
562 PKEY_BASIC_INFORMATION KeyInfo
= NULL
, SubKeyInfo
= NULL
;
563 UNICODE_STRING LegacyU
= RTL_CONSTANT_STRING(L
"LEGACY_");
564 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L
"\\" REGSTR_KEY_ROOTENUM
);
565 UNICODE_STRING SubKeyName
;
566 UNICODE_STRING DevicePath
;
567 HANDLE KeyHandle
= NULL
;
568 HANDLE SubKeyHandle
= NULL
;
569 ULONG KeyInfoSize
, SubKeyInfoSize
;
571 ULONG Index1
, Index2
;
572 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
574 DPRINT("EnumerateDevices(FDO %p)\n", DeviceObject
);
576 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
577 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
579 /* Should hold most key names, but we reallocate below if it's too small */
580 KeyInfoSize
= FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
) + 64 * sizeof(WCHAR
);
581 KeyInfo
= ExAllocatePoolWithTag(PagedPool
,
582 KeyInfoSize
+ sizeof(UNICODE_NULL
),
586 DPRINT("ExAllocatePoolWithTag() failed\n");
587 Status
= STATUS_NO_MEMORY
;
590 SubKeyInfoSize
= KeyInfoSize
;
591 SubKeyInfo
= ExAllocatePoolWithTag(PagedPool
,
592 SubKeyInfoSize
+ sizeof(UNICODE_NULL
),
596 DPRINT("ExAllocatePoolWithTag() failed\n");
597 Status
= STATUS_NO_MEMORY
;
601 Status
= IopOpenRegistryKeyEx(&KeyHandle
, NULL
, &KeyName
, KEY_ENUMERATE_SUB_KEYS
);
602 if (!NT_SUCCESS(Status
))
604 DPRINT("IopOpenRegistryKeyEx(%wZ) failed with status 0x%08lx\n", &KeyName
, Status
);
608 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
609 * KeyHandle. We'll first do a first enumeration to have first level keys,
610 * and an inner one to have the real devices list.
615 Status
= ZwEnumerateKey(
622 if (Status
== STATUS_NO_MORE_ENTRIES
)
624 Status
= STATUS_SUCCESS
;
627 else if (Status
== STATUS_BUFFER_OVERFLOW
||
628 Status
== STATUS_BUFFER_TOO_SMALL
)
630 ASSERT(KeyInfoSize
< ResultSize
);
631 KeyInfoSize
= ResultSize
;
632 ExFreePoolWithTag(KeyInfo
, TAG_PNP_ROOT
);
633 KeyInfo
= ExAllocatePoolWithTag(PagedPool
,
634 KeyInfoSize
+ sizeof(UNICODE_NULL
),
638 DPRINT1("ExAllocatePoolWithTag(%lu) failed\n", KeyInfoSize
);
639 Status
= STATUS_NO_MEMORY
;
644 else if (!NT_SUCCESS(Status
))
646 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
650 /* Terminate the string */
651 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
653 /* Check if it is a legacy driver */
654 RtlInitUnicodeString(&SubKeyName
, KeyInfo
->Name
);
655 if (RtlPrefixUnicodeString(&LegacyU
, &SubKeyName
, FALSE
))
657 DPRINT("Ignoring legacy driver '%wZ'\n", &SubKeyName
);
663 Status
= IopOpenRegistryKeyEx(&SubKeyHandle
, KeyHandle
, &SubKeyName
, KEY_ENUMERATE_SUB_KEYS
);
664 if (!NT_SUCCESS(Status
))
666 DPRINT("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n",
667 &SubKeyName
, Status
);
671 /* Enumerate the sub-keys */
675 Status
= ZwEnumerateKey(
682 if (Status
== STATUS_NO_MORE_ENTRIES
)
686 else if (Status
== STATUS_BUFFER_OVERFLOW
||
687 Status
== STATUS_BUFFER_TOO_SMALL
)
689 ASSERT(SubKeyInfoSize
< ResultSize
);
690 SubKeyInfoSize
= ResultSize
;
691 ExFreePoolWithTag(SubKeyInfo
, TAG_PNP_ROOT
);
692 SubKeyInfo
= ExAllocatePoolWithTag(PagedPool
,
693 SubKeyInfoSize
+ sizeof(UNICODE_NULL
),
697 DPRINT1("ExAllocatePoolWithTag(%lu) failed\n", SubKeyInfoSize
);
698 Status
= STATUS_NO_MEMORY
;
703 else if (!NT_SUCCESS(Status
))
705 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
709 /* Terminate the string */
710 SubKeyInfo
->Name
[SubKeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
712 /* Compute device ID */
713 DevicePath
.Length
= 0;
714 DevicePath
.MaximumLength
= sizeof(REGSTR_KEY_ROOTENUM
) + sizeof(L
'\\') + SubKeyName
.Length
;
715 DevicePath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
716 DevicePath
.MaximumLength
,
718 if (DevicePath
.Buffer
== NULL
)
720 DPRINT1("ExAllocatePoolWithTag() failed\n");
721 Status
= STATUS_NO_MEMORY
;
725 RtlAppendUnicodeToString(&DevicePath
, REGSTR_KEY_ROOTENUM L
"\\");
726 RtlAppendUnicodeStringToString(&DevicePath
, &SubKeyName
);
727 DPRINT("Found device %wZ\\%S!\n", &DevicePath
, SubKeyInfo
->Name
);
728 Status
= CreateDeviceFromRegistry(DeviceExtension
,
733 /* If CreateDeviceFromRegistry didn't take ownership and zero this,
736 RtlFreeUnicodeString(&DevicePath
);
738 if (!NT_SUCCESS(Status
))
746 ZwClose(SubKeyHandle
);
752 if (SubKeyHandle
!= NULL
)
753 ZwClose(SubKeyHandle
);
754 if (KeyHandle
!= NULL
)
757 ExFreePoolWithTag(KeyInfo
, TAG_PNP_ROOT
);
759 ExFreePoolWithTag(SubKeyInfo
, TAG_PNP_ROOT
);
760 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
764 /* FUNCTION: Handle IRP_MN_QUERY_DEVICE_RELATIONS IRPs for the root bus device object
766 * DeviceObject = Pointer to functional device object of the root bus driver
767 * Irp = Pointer to IRP that should be handled
772 PnpRootQueryDeviceRelations(
773 IN PDEVICE_OBJECT DeviceObject
,
776 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
777 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
778 PDEVICE_RELATIONS Relations
= NULL
, OtherRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
779 PPNPROOT_DEVICE Device
= NULL
;
782 PLIST_ENTRY NextEntry
;
784 DPRINT("PnpRootQueryDeviceRelations(FDO %p, Irp %p)\n", DeviceObject
, Irp
);
786 Status
= EnumerateDevices(DeviceObject
);
787 if (!NT_SUCCESS(Status
))
789 DPRINT("EnumerateDevices() failed with status 0x%08lx\n", Status
);
793 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
795 Size
= FIELD_OFFSET(DEVICE_RELATIONS
, Objects
) + sizeof(PDEVICE_OBJECT
) * DeviceExtension
->DeviceListCount
;
798 /* Another bus driver has already created a DEVICE_RELATIONS
799 * structure so we must merge this structure with our own */
801 Size
+= sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
;
803 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, Size
);
806 DPRINT("ExAllocatePoolWithTag() failed\n");
807 Status
= STATUS_NO_MEMORY
;
810 RtlZeroMemory(Relations
, Size
);
813 Relations
->Count
= OtherRelations
->Count
;
814 RtlCopyMemory(Relations
->Objects
, OtherRelations
->Objects
, sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
);
817 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
820 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
821 NextEntry
!= &DeviceExtension
->DeviceListHead
;
822 NextEntry
= NextEntry
->Flink
)
825 Device
= CONTAINING_RECORD(NextEntry
, PNPROOT_DEVICE
, ListEntry
);
829 /* Create a physical device object for the
830 * device as it does not already have one */
831 Status
= IoCreateDevice(
832 DeviceObject
->DriverObject
,
833 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
835 FILE_DEVICE_CONTROLLER
,
836 FILE_AUTOGENERATED_DEVICE_NAME
,
839 if (!NT_SUCCESS(Status
))
841 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
845 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
846 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
847 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
848 PdoDeviceExtension
->DeviceInfo
= Device
;
850 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
851 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
854 /* Reference the physical device object. The PnP manager
855 will dereference it again when it is no longer needed */
856 ObReferenceObject(Device
->Pdo
);
858 Relations
->Objects
[Relations
->Count
++] = Device
->Pdo
;
860 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
862 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
865 if (!NT_SUCCESS(Status
))
868 ExFreePool(OtherRelations
);
870 ExFreePool(Relations
);
871 if (Device
&& Device
->Pdo
)
873 IoDeleteDevice(Device
->Pdo
);
882 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
884 * DeviceObject = Pointer to functional device object of the root bus driver
885 * Irp = Pointer to IRP that should be handled
890 PnpRootFdoPnpControl(
891 IN PDEVICE_OBJECT DeviceObject
,
894 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
895 PIO_STACK_LOCATION IrpSp
;
898 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
899 Status
= Irp
->IoStatus
.Status
;
900 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
902 switch (IrpSp
->MinorFunction
)
904 case IRP_MN_QUERY_DEVICE_RELATIONS
:
905 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
906 Status
= PnpRootQueryDeviceRelations(DeviceObject
, Irp
);
909 case IRP_MN_START_DEVICE
:
910 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
911 if (!IoForwardIrpSynchronously(DeviceExtension
->Ldo
, Irp
))
912 Status
= STATUS_UNSUCCESSFUL
;
915 Status
= Irp
->IoStatus
.Status
;
916 if (NT_SUCCESS(Status
))
917 DeviceExtension
->State
= dsStarted
;
920 Irp
->IoStatus
.Status
= Status
;
921 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
924 case IRP_MN_STOP_DEVICE
:
925 DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
926 /* Root device cannot be stopped */
927 Irp
->IoStatus
.Status
= Status
= STATUS_INVALID_DEVICE_REQUEST
;
928 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
932 DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
936 if (Status
!= STATUS_PENDING
)
938 Irp
->IoStatus
.Status
= Status
;
939 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
946 PdoQueryDeviceRelations(
947 IN PDEVICE_OBJECT DeviceObject
,
949 IN PIO_STACK_LOCATION IrpSp
)
951 PDEVICE_RELATIONS Relations
;
952 NTSTATUS Status
= Irp
->IoStatus
.Status
;
954 if (IrpSp
->Parameters
.QueryDeviceRelations
.Type
!= TargetDeviceRelation
)
957 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
958 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
));
961 DPRINT("ExAllocatePoolWithTag() failed\n");
962 Status
= STATUS_NO_MEMORY
;
966 ObReferenceObject(DeviceObject
);
967 Relations
->Count
= 1;
968 Relations
->Objects
[0] = DeviceObject
;
969 Status
= STATUS_SUCCESS
;
970 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
977 PdoQueryCapabilities(
978 IN PDEVICE_OBJECT DeviceObject
,
980 IN PIO_STACK_LOCATION IrpSp
)
982 PDEVICE_CAPABILITIES DeviceCapabilities
;
984 DeviceCapabilities
= IrpSp
->Parameters
.DeviceCapabilities
.Capabilities
;
986 if (DeviceCapabilities
->Version
!= 1)
987 return STATUS_REVISION_MISMATCH
;
989 DeviceCapabilities
->UniqueID
= TRUE
;
990 /* FIXME: Fill other fields */
992 return STATUS_SUCCESS
;
997 IN PDEVICE_OBJECT DeviceObject
,
999 IN PIO_STACK_LOCATION IrpSp
)
1001 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
1002 PCM_RESOURCE_LIST ResourceList
;
1004 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1006 if (DeviceExtension
->DeviceInfo
->ResourceList
)
1008 /* Copy existing resource requirement list */
1009 ResourceList
= ExAllocatePool(
1011 DeviceExtension
->DeviceInfo
->ResourceListSize
);
1013 return STATUS_NO_MEMORY
;
1017 DeviceExtension
->DeviceInfo
->ResourceList
,
1018 DeviceExtension
->DeviceInfo
->ResourceListSize
);
1020 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
1022 return STATUS_SUCCESS
;
1026 /* No resources so just return without changing the status */
1027 return Irp
->IoStatus
.Status
;
1032 PdoQueryResourceRequirements(
1033 IN PDEVICE_OBJECT DeviceObject
,
1035 IN PIO_STACK_LOCATION IrpSp
)
1037 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
1038 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList
;
1040 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1042 if (DeviceExtension
->DeviceInfo
->ResourceRequirementsList
)
1044 /* Copy existing resource requirement list */
1045 ResourceList
= ExAllocatePool(PagedPool
, DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
1047 return STATUS_NO_MEMORY
;
1051 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
,
1052 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
1054 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
1056 return STATUS_SUCCESS
;
1060 /* No resource requirements so just return without changing the status */
1061 return Irp
->IoStatus
.Status
;
1067 IN PDEVICE_OBJECT DeviceObject
,
1069 IN PIO_STACK_LOCATION IrpSp
)
1071 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
1072 DEVICE_TEXT_TYPE DeviceTextType
;
1073 NTSTATUS Status
= Irp
->IoStatus
.Status
;
1075 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1076 DeviceTextType
= IrpSp
->Parameters
.QueryDeviceText
.DeviceTextType
;
1078 switch (DeviceTextType
)
1080 case DeviceTextDescription
:
1082 UNICODE_STRING String
;
1083 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
1085 if (DeviceExtension
->DeviceInfo
->DeviceDescription
.Buffer
!= NULL
)
1087 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
1088 &DeviceExtension
->DeviceInfo
->DeviceDescription
,
1090 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
1095 case DeviceTextLocationInformation
:
1097 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
1103 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown query id type 0x%lx\n", DeviceTextType
);
1112 IN PDEVICE_OBJECT DeviceObject
,
1114 IN PIO_STACK_LOCATION IrpSp
)
1116 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
1117 BUS_QUERY_ID_TYPE IdType
;
1118 NTSTATUS Status
= Irp
->IoStatus
.Status
;
1120 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1121 IdType
= IrpSp
->Parameters
.QueryId
.IdType
;
1125 case BusQueryDeviceID
:
1127 UNICODE_STRING String
;
1128 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
1130 Status
= RtlDuplicateUnicodeString(
1131 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
1132 &DeviceExtension
->DeviceInfo
->DeviceID
,
1134 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
1138 case BusQueryHardwareIDs
:
1139 case BusQueryCompatibleIDs
:
1141 /* Optional, do nothing */
1145 case BusQueryInstanceID
:
1147 UNICODE_STRING String
;
1148 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
1150 Status
= RtlDuplicateUnicodeString(
1151 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
1152 &DeviceExtension
->DeviceInfo
->InstanceID
,
1154 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
1160 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
1168 PdoQueryBusInformation(
1169 IN PDEVICE_OBJECT DeviceObject
,
1171 IN PIO_STACK_LOCATION IrpSp
)
1173 PPNP_BUS_INFORMATION BusInfo
;
1176 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNP_BUS_INFORMATION
), TAG_PNP_ROOT
);
1178 Status
= STATUS_NO_MEMORY
;
1182 &BusInfo
->BusTypeGuid
,
1183 &GUID_BUS_TYPE_INTERNAL
,
1184 sizeof(BusInfo
->BusTypeGuid
));
1185 BusInfo
->LegacyBusType
= PNPBus
;
1186 /* We're the only root bus enumerator on the computer */
1187 BusInfo
->BusNumber
= 0;
1188 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInfo
;
1189 Status
= STATUS_SUCCESS
;
1196 * FUNCTION: Handle Plug and Play IRPs for the child device
1198 * DeviceObject = Pointer to physical device object of the child device
1199 * Irp = Pointer to IRP that should be handled
1204 PnpRootPdoPnpControl(
1205 IN PDEVICE_OBJECT DeviceObject
,
1208 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
1209 PPNPROOT_FDO_DEVICE_EXTENSION FdoDeviceExtension
;
1210 PIO_STACK_LOCATION IrpSp
;
1213 DeviceExtension
= DeviceObject
->DeviceExtension
;
1214 FdoDeviceExtension
= PnpRootDeviceObject
->DeviceExtension
;
1215 Status
= Irp
->IoStatus
.Status
;
1216 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1218 switch (IrpSp
->MinorFunction
)
1220 case IRP_MN_START_DEVICE
: /* 0x00 */
1221 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1222 Status
= STATUS_SUCCESS
;
1225 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x07 */
1226 Status
= PdoQueryDeviceRelations(DeviceObject
, Irp
, IrpSp
);
1229 case IRP_MN_QUERY_CAPABILITIES
: /* 0x09 */
1230 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
1231 Status
= PdoQueryCapabilities(DeviceObject
, Irp
, IrpSp
);
1234 case IRP_MN_QUERY_RESOURCES
: /* 0x0a */
1235 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
1236 Status
= PdoQueryResources(DeviceObject
, Irp
, IrpSp
);
1239 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
: /* 0x0b */
1240 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1241 Status
= PdoQueryResourceRequirements(DeviceObject
, Irp
, IrpSp
);
1244 case IRP_MN_QUERY_DEVICE_TEXT
: /* 0x0c */
1245 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1246 Status
= PdoQueryDeviceText(DeviceObject
, Irp
, IrpSp
);
1249 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0x0d */
1250 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1253 case IRP_MN_REMOVE_DEVICE
:
1254 /* Remove the device from the device list and decrement the device count*/
1255 KeAcquireGuardedMutex(&FdoDeviceExtension
->DeviceListLock
);
1256 RemoveEntryList(&DeviceExtension
->DeviceInfo
->ListEntry
);
1257 FdoDeviceExtension
->DeviceListCount
--;
1258 KeReleaseGuardedMutex(&FdoDeviceExtension
->DeviceListLock
);
1260 /* Free some strings we created */
1261 RtlFreeUnicodeString(&DeviceExtension
->DeviceInfo
->DeviceDescription
);
1262 RtlFreeUnicodeString(&DeviceExtension
->DeviceInfo
->DeviceID
);
1263 RtlFreeUnicodeString(&DeviceExtension
->DeviceInfo
->InstanceID
);
1265 /* Free the resource requirements list */
1266 if (DeviceExtension
->DeviceInfo
->ResourceRequirementsList
!= NULL
)
1267 ExFreePool(DeviceExtension
->DeviceInfo
->ResourceRequirementsList
);
1269 /* Free the boot resources list */
1270 if (DeviceExtension
->DeviceInfo
->ResourceList
!= NULL
)
1271 ExFreePool(DeviceExtension
->DeviceInfo
->ResourceList
);
1273 /* Free the device info */
1274 ExFreePool(DeviceExtension
->DeviceInfo
);
1276 /* Finally, delete the device object */
1277 IoDeleteDevice(DeviceObject
);
1279 /* Return success */
1280 Status
= STATUS_SUCCESS
;
1283 case IRP_MN_QUERY_ID
: /* 0x13 */
1284 Status
= PdoQueryId(DeviceObject
, Irp
, IrpSp
);
1287 case IRP_MN_QUERY_PNP_DEVICE_STATE
: /* 0x14 */
1288 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
1291 case IRP_MN_QUERY_BUS_INFORMATION
: /* 0x15 */
1292 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
1293 Status
= PdoQueryBusInformation(DeviceObject
, Irp
, IrpSp
);
1297 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
1301 if (Status
!= STATUS_PENDING
)
1303 Irp
->IoStatus
.Status
= Status
;
1304 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1311 * FUNCTION: Handle Plug and Play IRPs
1313 * DeviceObject = Pointer to PDO or FDO
1314 * Irp = Pointer to IRP that should be handled
1318 static NTSTATUS NTAPI
1320 IN PDEVICE_OBJECT DeviceObject
,
1323 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension
;
1326 DeviceExtension
= (PPNPROOT_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1328 if (DeviceExtension
->IsFDO
)
1329 Status
= PnpRootFdoPnpControl(DeviceObject
, Irp
);
1331 Status
= PnpRootPdoPnpControl(DeviceObject
, Irp
);
1337 * FUNCTION: Handle Power IRPs
1339 * DeviceObject = Pointer to PDO or FDO
1340 * Irp = Pointer to IRP that should be handled
1344 static NTSTATUS NTAPI
1345 PnpRootPowerControl(
1346 IN PDEVICE_OBJECT DeviceObject
,
1349 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
1350 PIO_STACK_LOCATION IrpSp
;
1353 DeviceExtension
= DeviceObject
->DeviceExtension
;
1354 Status
= Irp
->IoStatus
.Status
;
1355 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1357 if (DeviceExtension
->Common
.IsFDO
)
1359 ASSERT(!DeviceExtension
->Common
.IsFDO
);
1360 PoStartNextPowerIrp(Irp
);
1361 IoCopyCurrentIrpStackLocationToNext(Irp
);
1362 Status
= PoCallDriver(DeviceExtension
->Ldo
, Irp
);
1366 switch (IrpSp
->MinorFunction
)
1368 case IRP_MN_QUERY_POWER
:
1369 case IRP_MN_SET_POWER
:
1370 Status
= STATUS_SUCCESS
;
1373 Irp
->IoStatus
.Status
= Status
;
1374 PoStartNextPowerIrp(Irp
);
1375 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1384 IN PDRIVER_OBJECT DriverObject
,
1385 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1387 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
1390 DPRINT("PnpRootAddDevice(DriverObject %p, Pdo %p)\n", DriverObject
, PhysicalDeviceObject
);
1392 if (!PhysicalDeviceObject
)
1394 DPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject
);
1395 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1396 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1399 Status
= IoCreateDevice(
1401 sizeof(PNPROOT_FDO_DEVICE_EXTENSION
),
1403 FILE_DEVICE_BUS_EXTENDER
,
1404 FILE_DEVICE_SECURE_OPEN
,
1406 &PnpRootDeviceObject
);
1407 if (!NT_SUCCESS(Status
))
1409 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
1410 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1412 DPRINT("Created FDO %p\n", PnpRootDeviceObject
);
1414 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)PnpRootDeviceObject
->DeviceExtension
;
1415 RtlZeroMemory(DeviceExtension
, sizeof(PNPROOT_FDO_DEVICE_EXTENSION
));
1417 DeviceExtension
->Common
.IsFDO
= TRUE
;
1418 DeviceExtension
->State
= dsStopped
;
1419 InitializeListHead(&DeviceExtension
->DeviceListHead
);
1420 DeviceExtension
->DeviceListCount
= 0;
1421 KeInitializeGuardedMutex(&DeviceExtension
->DeviceListLock
);
1423 Status
= IoAttachDeviceToDeviceStackSafe(
1424 PnpRootDeviceObject
,
1425 PhysicalDeviceObject
,
1426 &DeviceExtension
->Ldo
);
1427 if (!NT_SUCCESS(Status
))
1429 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
1430 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1433 PnpRootDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1435 DPRINT("Done AddDevice()\n");
1437 return STATUS_SUCCESS
;
1441 PDEVICE_OBJECT IopPfnDumpDeviceObject
;
1445 _In_ PDEVICE_OBJECT DeviceObject
,
1448 PIO_STACK_LOCATION IoStack
;
1450 if (DeviceObject
!= IopPfnDumpDeviceObject
)
1452 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
1453 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1454 return STATUS_INVALID_DEVICE_REQUEST
;
1457 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1458 if (IoStack
->MajorFunction
== IRP_MJ_CREATE
)
1460 MmDumpArmPfnDatabase(TRUE
);
1463 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1464 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1465 return STATUS_SUCCESS
;
1471 IN PDRIVER_OBJECT DriverObject
,
1472 IN PUNICODE_STRING RegistryPath
)
1476 UNICODE_STRING PfnDumpDeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\PfnDump");
1479 DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject
, RegistryPath
);
1481 IopRootDriverObject
= DriverObject
;
1483 DriverObject
->DriverExtension
->AddDevice
= PnpRootAddDevice
;
1486 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = PnpRootCreateClose
;
1487 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = PnpRootCreateClose
;
1489 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = PnpRootPnpControl
;
1490 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = PnpRootPowerControl
;
1493 Status
= IoCreateDevice(DriverObject
,
1496 FILE_DEVICE_UNKNOWN
,
1499 &IopPfnDumpDeviceObject
);
1500 if (!NT_SUCCESS(Status
))
1502 DPRINT1("Creating PFN Dump device failed with %lx\n", Status
);
1506 IopPfnDumpDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1510 return STATUS_SUCCESS
;