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
;
129 /* Creates a new PnP device for a legacy driver */
132 IN PUNICODE_STRING ServiceName
,
133 OUT PDEVICE_OBJECT
*PhysicalDeviceObject
,
134 OUT OPTIONAL PUNICODE_STRING FullInstancePath
)
136 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
137 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
138 WCHAR DevicePath
[MAX_PATH
+ 1];
139 WCHAR InstancePath
[5];
140 PPNPROOT_DEVICE Device
= NULL
;
143 UNICODE_STRING PathSep
= RTL_CONSTANT_STRING(L
"\\");
145 DeviceExtension
= PnpRootDeviceObject
->DeviceExtension
;
146 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
148 DPRINT("Creating a PnP root device for service '%wZ'\n", ServiceName
);
150 /* Search for a free instance ID */
151 _snwprintf(DevicePath
, sizeof(DevicePath
) / sizeof(WCHAR
), L
"%s\\%wZ", REGSTR_KEY_ROOTENUM
, ServiceName
);
152 for (i
= 0; i
< 9999; i
++)
154 _snwprintf(InstancePath
, sizeof(InstancePath
) / sizeof(WCHAR
), L
"%04lu", i
);
155 Status
= LocateChildDevice(DeviceExtension
, DevicePath
, InstancePath
, &Device
);
156 if (Status
== STATUS_NO_SUCH_DEVICE
)
161 DPRINT1("Too much legacy devices reported for service '%wZ'\n", ServiceName
);
162 Status
= STATUS_INSUFFICIENT_RESOURCES
;
166 /* Initialize a PNPROOT_DEVICE structure */
167 Device
= ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
170 DPRINT("ExAllocatePoolWithTag() failed\n");
171 Status
= STATUS_NO_MEMORY
;
174 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
175 if (!RtlCreateUnicodeString(&Device
->DeviceID
, DevicePath
))
177 Status
= STATUS_NO_MEMORY
;
180 if (!RtlCreateUnicodeString(&Device
->InstanceID
, InstancePath
))
182 Status
= STATUS_NO_MEMORY
;
186 if (FullInstancePath
)
188 FullInstancePath
->MaximumLength
= Device
->DeviceID
.Length
+ PathSep
.Length
+ Device
->InstanceID
.Length
;
189 FullInstancePath
->Length
= 0;
190 FullInstancePath
->Buffer
= ExAllocatePool(PagedPool
, FullInstancePath
->MaximumLength
);
191 if (!FullInstancePath
->Buffer
)
193 Status
= STATUS_NO_MEMORY
;
197 RtlAppendUnicodeStringToString(FullInstancePath
, &Device
->DeviceID
);
198 RtlAppendUnicodeStringToString(FullInstancePath
, &PathSep
);
199 RtlAppendUnicodeStringToString(FullInstancePath
, &Device
->InstanceID
);
202 /* Initialize a device object */
203 Status
= IoCreateDevice(
204 PnpRootDeviceObject
->DriverObject
,
205 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
207 FILE_DEVICE_CONTROLLER
,
208 FILE_AUTOGENERATED_DEVICE_NAME
,
211 if (!NT_SUCCESS(Status
))
213 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
214 Status
= STATUS_NO_MEMORY
;
218 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
219 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
220 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
221 PdoDeviceExtension
->DeviceInfo
= Device
;
223 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
224 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
227 &DeviceExtension
->DeviceListHead
,
229 DeviceExtension
->DeviceListCount
++;
231 *PhysicalDeviceObject
= Device
->Pdo
;
232 DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject
, &Device
->DeviceID
, &Device
->InstanceID
);
234 Status
= STATUS_SUCCESS
;
237 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
241 IoDeleteDevice(Device
->Pdo
);
242 RtlFreeUnicodeString(&Device
->DeviceID
);
243 RtlFreeUnicodeString(&Device
->InstanceID
);
244 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
249 static NTSTATUS NTAPI
254 IN ULONG ValueLength
,
256 IN PVOID EntryContext
)
258 PUNICODE_STRING Destination
= (PUNICODE_STRING
)EntryContext
;
259 UNICODE_STRING Source
;
261 if (ValueType
!= REG_SZ
|| ValueLength
== 0 || ValueLength
% sizeof(WCHAR
) != 0)
262 return STATUS_SUCCESS
;
264 Source
.MaximumLength
= Source
.Length
= ValueLength
;
265 Source
.Buffer
= ValueData
;
266 if (Source
.Length
> 0 && Source
.Buffer
[Source
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
267 Source
.Length
-= sizeof(WCHAR
);
268 return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &Source
, Destination
);
271 static NTSTATUS NTAPI
272 QueryBinaryValueCallback(
276 IN ULONG ValueLength
,
278 IN PVOID EntryContext
)
280 PBUFFER Buffer
= (PBUFFER
)EntryContext
;
283 if (ValueLength
== 0)
285 *Buffer
->Data
= NULL
;
286 return STATUS_SUCCESS
;
289 BinaryValue
= ExAllocatePoolWithTag(PagedPool
, ValueLength
, TAG_PNP_ROOT
);
290 if (BinaryValue
== NULL
)
291 return STATUS_NO_MEMORY
;
292 RtlCopyMemory(BinaryValue
, ValueData
, ValueLength
);
293 *Buffer
->Data
= BinaryValue
;
294 if (Buffer
->Length
) *Buffer
->Length
= ValueLength
;
295 return STATUS_SUCCESS
;
300 IN PDEVICE_OBJECT DeviceObject
)
302 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
303 PKEY_BASIC_INFORMATION KeyInfo
= NULL
, SubKeyInfo
= NULL
;
304 UNICODE_STRING LegacyU
= RTL_CONSTANT_STRING(L
"LEGACY_");
305 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L
"\\" REGSTR_KEY_ROOTENUM
);
306 UNICODE_STRING SubKeyName
;
307 WCHAR DevicePath
[MAX_PATH
+ 1];
308 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
309 PPNPROOT_DEVICE Device
= NULL
;
310 HANDLE KeyHandle
= INVALID_HANDLE_VALUE
;
311 HANDLE SubKeyHandle
= INVALID_HANDLE_VALUE
;
312 HANDLE DeviceKeyHandle
= INVALID_HANDLE_VALUE
;
315 ULONG Index1
, Index2
;
316 BUFFER Buffer1
, Buffer2
;
317 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
319 DPRINT("EnumerateDevices(FDO %p)\n", DeviceObject
);
321 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
322 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
324 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + (MAX_PATH
+ 1) * sizeof(WCHAR
);
325 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
328 DPRINT("ExAllocatePoolWithTag() failed\n");
329 Status
= STATUS_NO_MEMORY
;
332 SubKeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
335 DPRINT("ExAllocatePoolWithTag() failed\n");
336 Status
= STATUS_NO_MEMORY
;
340 Status
= IopOpenRegistryKeyEx(&KeyHandle
, NULL
, &KeyName
, KEY_ENUMERATE_SUB_KEYS
);
341 if (!NT_SUCCESS(Status
))
343 DPRINT("IopOpenRegistryKeyEx(%wZ) failed with status 0x%08lx\n", &KeyName
, Status
);
347 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
348 * KeyHandle. We'll first do a first enumeration to have first level keys,
349 * and an inner one to have the real devices list.
354 Status
= ZwEnumerateKey(
361 if (Status
== STATUS_NO_MORE_ENTRIES
)
363 Status
= STATUS_SUCCESS
;
366 else if (!NT_SUCCESS(Status
))
368 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
372 /* Terminate the string */
373 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
375 /* Check if it is a legacy driver */
376 RtlInitUnicodeString(&SubKeyName
, KeyInfo
->Name
);
377 if (RtlPrefixUnicodeString(&LegacyU
, &SubKeyName
, FALSE
))
379 DPRINT("Ignoring legacy driver '%wZ'\n", &SubKeyName
);
385 Status
= IopOpenRegistryKeyEx(&SubKeyHandle
, KeyHandle
, &SubKeyName
, KEY_ENUMERATE_SUB_KEYS
);
386 if (!NT_SUCCESS(Status
))
388 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status
);
392 /* Enumerate the sub-keys */
396 Status
= ZwEnumerateKey(
403 if (Status
== STATUS_NO_MORE_ENTRIES
)
405 else if (!NT_SUCCESS(Status
))
407 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
411 /* Terminate the string */
412 SubKeyInfo
->Name
[SubKeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
416 sizeof(DevicePath
) / sizeof(WCHAR
),
417 L
"%s\\%s", REGSTR_KEY_ROOTENUM
, KeyInfo
->Name
);
418 DPRINT("Found device %S\\%s!\n", DevicePath
, SubKeyInfo
->Name
);
419 if (LocateChildDevice(DeviceExtension
, DevicePath
, SubKeyInfo
->Name
, &Device
) == STATUS_NO_SUCH_DEVICE
)
421 /* Create a PPNPROOT_DEVICE object, and add if in the list of known devices */
422 Device
= (PPNPROOT_DEVICE
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
425 DPRINT("ExAllocatePoolWithTag() failed\n");
426 Status
= STATUS_NO_MEMORY
;
429 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
431 /* Fill device ID and instance ID */
432 if (!RtlCreateUnicodeString(&Device
->DeviceID
, DevicePath
))
434 DPRINT("RtlCreateUnicodeString() failed\n");
435 Status
= STATUS_NO_MEMORY
;
439 if (!RtlCreateUnicodeString(&Device
->InstanceID
, SubKeyInfo
->Name
))
441 DPRINT("RtlCreateUnicodeString() failed\n");
442 Status
= STATUS_NO_MEMORY
;
446 /* Open registry key to fill other informations */
447 Status
= IopOpenRegistryKeyEx(&DeviceKeyHandle
, SubKeyHandle
, &Device
->InstanceID
, KEY_READ
);
448 if (!NT_SUCCESS(Status
))
450 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status
);
454 /* Fill other informations */
455 Buffer1
.Data
= (PVOID
*)&Device
->ResourceRequirementsList
;
456 Buffer1
.Length
= NULL
;
457 Buffer2
.Data
= (PVOID
*)&Device
->ResourceList
;
458 Buffer2
.Length
= &Device
->ResourceListSize
;
459 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
460 QueryTable
[0].QueryRoutine
= QueryStringCallback
;
461 QueryTable
[0].Name
= L
"DeviceDesc";
462 QueryTable
[0].EntryContext
= &Device
->DeviceDescription
;
463 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_SUBKEY
;
464 QueryTable
[1].Name
= L
"LogConf";
465 QueryTable
[2].QueryRoutine
= QueryBinaryValueCallback
;
466 QueryTable
[2].Name
= L
"BasicConfigVector";
467 QueryTable
[2].EntryContext
= &Buffer1
;
468 QueryTable
[3].QueryRoutine
= QueryBinaryValueCallback
;
469 QueryTable
[3].Name
= L
"BootConfig";
470 QueryTable
[3].EntryContext
= &Buffer2
;
472 Status
= RtlQueryRegistryValues(
474 (PCWSTR
)DeviceKeyHandle
,
478 if (!NT_SUCCESS(Status
))
480 DPRINT("RtlQueryRegistryValues() failed with status 0x%08lx\n", Status
);
484 ZwClose(DeviceKeyHandle
);
485 DeviceKeyHandle
= INVALID_HANDLE_VALUE
;
487 /* Insert the newly created device into the list */
489 &DeviceExtension
->DeviceListHead
,
491 DeviceExtension
->DeviceListCount
++;
498 ZwClose(SubKeyHandle
);
499 SubKeyHandle
= INVALID_HANDLE_VALUE
;
506 /* We have a device that has not been added to device list. We need to clean it up */
508 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
510 if (DeviceKeyHandle
!= INVALID_HANDLE_VALUE
)
511 ZwClose(DeviceKeyHandle
);
512 if (SubKeyHandle
!= INVALID_HANDLE_VALUE
)
513 ZwClose(SubKeyHandle
);
514 if (KeyHandle
!= INVALID_HANDLE_VALUE
)
517 ExFreePoolWithTag(KeyInfo
, TAG_PNP_ROOT
);
519 ExFreePoolWithTag(SubKeyInfo
, TAG_PNP_ROOT
);
520 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
524 /* FUNCTION: Handle IRP_MN_QUERY_DEVICE_RELATIONS IRPs for the root bus device object
526 * DeviceObject = Pointer to functional device object of the root bus driver
527 * Irp = Pointer to IRP that should be handled
532 PnpRootQueryDeviceRelations(
533 IN PDEVICE_OBJECT DeviceObject
,
536 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
537 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
538 PDEVICE_RELATIONS Relations
= NULL
, OtherRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
539 PPNPROOT_DEVICE Device
= NULL
;
542 PLIST_ENTRY NextEntry
;
544 DPRINT("PnpRootQueryDeviceRelations(FDO %p, Irp %p)\n", DeviceObject
, Irp
);
546 Status
= EnumerateDevices(DeviceObject
);
547 if (!NT_SUCCESS(Status
))
549 DPRINT("EnumerateDevices() failed with status 0x%08lx\n", Status
);
553 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
555 Size
= FIELD_OFFSET(DEVICE_RELATIONS
, Objects
) + sizeof(PDEVICE_OBJECT
) * DeviceExtension
->DeviceListCount
;
558 /* Another bus driver has already created a DEVICE_RELATIONS
559 * structure so we must merge this structure with our own */
561 Size
+= sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
;
563 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, Size
);
566 DPRINT("ExAllocatePoolWithTag() failed\n");
567 Status
= STATUS_NO_MEMORY
;
570 RtlZeroMemory(Relations
, Size
);
573 Relations
->Count
= OtherRelations
->Count
;
574 RtlCopyMemory(Relations
->Objects
, OtherRelations
->Objects
, sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
);
577 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
580 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
581 NextEntry
!= &DeviceExtension
->DeviceListHead
;
582 NextEntry
= NextEntry
->Flink
)
585 Device
= CONTAINING_RECORD(NextEntry
, PNPROOT_DEVICE
, ListEntry
);
589 /* Create a physical device object for the
590 * device as it does not already have one */
591 Status
= IoCreateDevice(
592 DeviceObject
->DriverObject
,
593 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
595 FILE_DEVICE_CONTROLLER
,
596 FILE_AUTOGENERATED_DEVICE_NAME
,
599 if (!NT_SUCCESS(Status
))
601 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
605 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
606 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
607 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
608 PdoDeviceExtension
->DeviceInfo
= Device
;
610 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
611 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
614 /* Reference the physical device object. The PnP manager
615 will dereference it again when it is no longer needed */
616 ObReferenceObject(Device
->Pdo
);
618 Relations
->Objects
[Relations
->Count
++] = Device
->Pdo
;
620 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
622 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
625 if (!NT_SUCCESS(Status
))
628 ExFreePool(OtherRelations
);
630 ExFreePool(Relations
);
631 if (Device
&& Device
->Pdo
)
633 IoDeleteDevice(Device
->Pdo
);
642 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
644 * DeviceObject = Pointer to functional device object of the root bus driver
645 * Irp = Pointer to IRP that should be handled
650 PnpRootFdoPnpControl(
651 IN PDEVICE_OBJECT DeviceObject
,
654 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
655 PIO_STACK_LOCATION IrpSp
;
658 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
659 Status
= Irp
->IoStatus
.Status
;
660 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
662 switch (IrpSp
->MinorFunction
)
664 case IRP_MN_QUERY_DEVICE_RELATIONS
:
665 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
666 Status
= PnpRootQueryDeviceRelations(DeviceObject
, Irp
);
669 case IRP_MN_START_DEVICE
:
670 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
671 if (!IoForwardIrpSynchronously(DeviceExtension
->Ldo
, Irp
))
672 Status
= STATUS_UNSUCCESSFUL
;
675 Status
= Irp
->IoStatus
.Status
;
676 if (NT_SUCCESS(Status
))
677 DeviceExtension
->State
= dsStarted
;
680 Irp
->IoStatus
.Status
= Status
;
681 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
684 case IRP_MN_STOP_DEVICE
:
685 DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
686 /* Root device cannot be stopped */
687 Irp
->IoStatus
.Status
= Status
= STATUS_INVALID_DEVICE_REQUEST
;
688 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
692 DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
696 if (Status
!= STATUS_PENDING
)
698 Irp
->IoStatus
.Status
= Status
;
699 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
706 PdoQueryDeviceRelations(
707 IN PDEVICE_OBJECT DeviceObject
,
709 IN PIO_STACK_LOCATION IrpSp
)
711 PDEVICE_RELATIONS Relations
;
712 NTSTATUS Status
= Irp
->IoStatus
.Status
;
714 if (IrpSp
->Parameters
.QueryDeviceRelations
.Type
!= TargetDeviceRelation
)
717 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
718 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
));
721 DPRINT("ExAllocatePoolWithTag() failed\n");
722 Status
= STATUS_NO_MEMORY
;
726 ObReferenceObject(DeviceObject
);
727 Relations
->Count
= 1;
728 Relations
->Objects
[0] = DeviceObject
;
729 Status
= STATUS_SUCCESS
;
730 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
737 PdoQueryCapabilities(
738 IN PDEVICE_OBJECT DeviceObject
,
740 IN PIO_STACK_LOCATION IrpSp
)
742 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
743 PDEVICE_CAPABILITIES DeviceCapabilities
;
745 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
746 DeviceCapabilities
= IrpSp
->Parameters
.DeviceCapabilities
.Capabilities
;
748 if (DeviceCapabilities
->Version
!= 1)
749 return STATUS_REVISION_MISMATCH
;
751 DeviceCapabilities
->UniqueID
= TRUE
;
752 /* FIXME: Fill other fields */
754 return STATUS_SUCCESS
;
759 IN PDEVICE_OBJECT DeviceObject
,
761 IN PIO_STACK_LOCATION IrpSp
)
763 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
764 PCM_RESOURCE_LIST ResourceList
;
766 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
768 if (DeviceExtension
->DeviceInfo
->ResourceList
)
770 /* Copy existing resource requirement list */
771 ResourceList
= ExAllocatePool(
773 DeviceExtension
->DeviceInfo
->ResourceListSize
);
775 return STATUS_NO_MEMORY
;
779 DeviceExtension
->DeviceInfo
->ResourceList
,
780 DeviceExtension
->DeviceInfo
->ResourceListSize
);
782 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
784 return STATUS_SUCCESS
;
788 /* No resources so just return without changing the status */
789 return Irp
->IoStatus
.Status
;
794 PdoQueryResourceRequirements(
795 IN PDEVICE_OBJECT DeviceObject
,
797 IN PIO_STACK_LOCATION IrpSp
)
799 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
800 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList
;
802 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
804 if (DeviceExtension
->DeviceInfo
->ResourceRequirementsList
)
806 /* Copy existing resource requirement list */
807 ResourceList
= ExAllocatePool(PagedPool
, DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
809 return STATUS_NO_MEMORY
;
813 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
,
814 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
816 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
818 return STATUS_SUCCESS
;
822 /* No resource requirements so just return without changing the status */
823 return Irp
->IoStatus
.Status
;
829 IN PDEVICE_OBJECT DeviceObject
,
831 IN PIO_STACK_LOCATION IrpSp
)
833 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
834 DEVICE_TEXT_TYPE DeviceTextType
;
835 NTSTATUS Status
= Irp
->IoStatus
.Status
;
837 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
838 DeviceTextType
= IrpSp
->Parameters
.QueryDeviceText
.DeviceTextType
;
840 switch (DeviceTextType
)
842 case DeviceTextDescription
:
844 UNICODE_STRING String
;
845 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
847 Status
= RtlDuplicateUnicodeString(
848 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
849 &DeviceExtension
->DeviceInfo
->DeviceDescription
,
851 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
855 case DeviceTextLocationInformation
:
857 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
858 Status
= STATUS_NOT_SUPPORTED
;
864 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown query id type 0x%lx\n", DeviceTextType
);
873 IN PDEVICE_OBJECT DeviceObject
,
875 IN PIO_STACK_LOCATION IrpSp
)
877 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
878 BUS_QUERY_ID_TYPE IdType
;
879 NTSTATUS Status
= Irp
->IoStatus
.Status
;
881 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
882 IdType
= IrpSp
->Parameters
.QueryId
.IdType
;
886 case BusQueryDeviceID
:
888 UNICODE_STRING String
;
889 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
891 Status
= RtlDuplicateUnicodeString(
892 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
893 &DeviceExtension
->DeviceInfo
->DeviceID
,
895 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
899 case BusQueryHardwareIDs
:
900 case BusQueryCompatibleIDs
:
902 /* Optional, do nothing */
906 case BusQueryInstanceID
:
908 UNICODE_STRING String
;
909 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
911 Status
= RtlDuplicateUnicodeString(
912 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
913 &DeviceExtension
->DeviceInfo
->InstanceID
,
915 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
921 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
929 PdoQueryBusInformation(
930 IN PDEVICE_OBJECT DeviceObject
,
932 IN PIO_STACK_LOCATION IrpSp
)
934 PPNP_BUS_INFORMATION BusInfo
;
937 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNP_BUS_INFORMATION
), TAG_PNP_ROOT
);
939 Status
= STATUS_NO_MEMORY
;
943 &BusInfo
->BusTypeGuid
,
944 &GUID_BUS_TYPE_INTERNAL
,
945 sizeof(BusInfo
->BusTypeGuid
));
946 BusInfo
->LegacyBusType
= PNPBus
;
947 /* We're the only root bus enumerator on the computer */
948 BusInfo
->BusNumber
= 0;
949 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInfo
;
950 Status
= STATUS_SUCCESS
;
957 * FUNCTION: Handle Plug and Play IRPs for the child device
959 * DeviceObject = Pointer to physical device object of the child device
960 * Irp = Pointer to IRP that should be handled
965 PnpRootPdoPnpControl(
966 IN PDEVICE_OBJECT DeviceObject
,
969 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
970 PIO_STACK_LOCATION IrpSp
;
973 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
974 Status
= Irp
->IoStatus
.Status
;
975 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
977 switch (IrpSp
->MinorFunction
)
979 case IRP_MN_START_DEVICE
: /* 0x00 */
980 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
981 Status
= STATUS_SUCCESS
;
984 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x07 */
985 Status
= PdoQueryDeviceRelations(DeviceObject
, Irp
, IrpSp
);
988 case IRP_MN_QUERY_CAPABILITIES
: /* 0x09 */
989 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
990 Status
= PdoQueryCapabilities(DeviceObject
, Irp
, IrpSp
);
993 case IRP_MN_QUERY_RESOURCES
: /* 0x0a */
994 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
995 Status
= PdoQueryResources(DeviceObject
, Irp
, IrpSp
);
998 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
: /* 0x0b */
999 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1000 Status
= PdoQueryResourceRequirements(DeviceObject
, Irp
, IrpSp
);
1003 case IRP_MN_QUERY_DEVICE_TEXT
: /* 0x0c */
1004 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1005 Status
= PdoQueryDeviceText(DeviceObject
, Irp
, IrpSp
);
1008 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0x0d */
1009 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1012 case IRP_MN_QUERY_ID
: /* 0x13 */
1013 Status
= PdoQueryId(DeviceObject
, Irp
, IrpSp
);
1016 case IRP_MN_QUERY_BUS_INFORMATION
: /* 0x15 */
1017 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
1018 Status
= PdoQueryBusInformation(DeviceObject
, Irp
, IrpSp
);
1022 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
1023 Status
= STATUS_NOT_IMPLEMENTED
;
1027 if (Status
!= STATUS_PENDING
)
1029 Irp
->IoStatus
.Status
= Status
;
1030 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1037 * FUNCTION: Handle Plug and Play IRPs
1039 * DeviceObject = Pointer to PDO or FDO
1040 * Irp = Pointer to IRP that should be handled
1044 static NTSTATUS NTAPI
1046 IN PDEVICE_OBJECT DeviceObject
,
1049 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension
;
1052 DeviceExtension
= (PPNPROOT_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1054 if (DeviceExtension
->IsFDO
)
1055 Status
= PnpRootFdoPnpControl(DeviceObject
, Irp
);
1057 Status
= PnpRootPdoPnpControl(DeviceObject
, Irp
);
1065 IN PDRIVER_OBJECT DriverObject
,
1066 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1068 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
1071 DPRINT("PnpRootAddDevice(DriverObject %p, Pdo %p)\n", DriverObject
, PhysicalDeviceObject
);
1073 if (!PhysicalDeviceObject
)
1075 DPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject
);
1076 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1077 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1080 Status
= IoCreateDevice(
1082 sizeof(PNPROOT_FDO_DEVICE_EXTENSION
),
1084 FILE_DEVICE_BUS_EXTENDER
,
1085 FILE_DEVICE_SECURE_OPEN
,
1087 &PnpRootDeviceObject
);
1088 if (!NT_SUCCESS(Status
))
1090 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
1091 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1093 DPRINT("Created FDO %p\n", PnpRootDeviceObject
);
1095 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)PnpRootDeviceObject
->DeviceExtension
;
1096 RtlZeroMemory(DeviceExtension
, sizeof(PNPROOT_FDO_DEVICE_EXTENSION
));
1098 DeviceExtension
->Common
.IsFDO
= TRUE
;
1099 DeviceExtension
->State
= dsStopped
;
1100 InitializeListHead(&DeviceExtension
->DeviceListHead
);
1101 DeviceExtension
->DeviceListCount
= 0;
1102 KeInitializeGuardedMutex(&DeviceExtension
->DeviceListLock
);
1104 Status
= IoAttachDeviceToDeviceStackSafe(
1105 PnpRootDeviceObject
,
1106 PhysicalDeviceObject
,
1107 &DeviceExtension
->Ldo
);
1108 if (!NT_SUCCESS(Status
))
1110 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
1111 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1114 PnpRootDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1116 DPRINT("Done AddDevice()\n");
1118 return STATUS_SUCCESS
;
1123 IN PDRIVER_OBJECT DriverObject
,
1124 IN PUNICODE_STRING RegistryPath
)
1126 DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject
, RegistryPath
);
1128 DriverObject
->DriverExtension
->AddDevice
= PnpRootAddDevice
;
1130 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = PnpRootPnpControl
;
1131 //DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl;
1133 return STATUS_SUCCESS
;