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 ULONG ResourceRequirementsListSize
;
37 // Associated resource list
38 PCM_RESOURCE_LIST ResourceList
;
39 ULONG ResourceListSize
;
40 } PNPROOT_DEVICE
, *PPNPROOT_DEVICE
;
49 } PNPROOT_DEVICE_STATE
;
51 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
53 // Wether this device extension is for an FDO or PDO
55 } PNPROOT_COMMON_DEVICE_EXTENSION
, *PPNPROOT_COMMON_DEVICE_EXTENSION
;
57 /* Physical Device Object device extension for a child device */
58 typedef struct _PNPROOT_PDO_DEVICE_EXTENSION
61 PNPROOT_COMMON_DEVICE_EXTENSION Common
;
62 // Informations about the device
63 PPNPROOT_DEVICE DeviceInfo
;
64 } PNPROOT_PDO_DEVICE_EXTENSION
, *PPNPROOT_PDO_DEVICE_EXTENSION
;
66 /* Physical Device Object device extension for the Root bus device object */
67 typedef struct _PNPROOT_FDO_DEVICE_EXTENSION
70 PNPROOT_COMMON_DEVICE_EXTENSION Common
;
71 // Lower device object
73 // Current state of the driver
74 PNPROOT_DEVICE_STATE State
;
75 // Namespace device list
76 LIST_ENTRY DeviceListHead
;
77 // Number of (not removed) devices in device list
78 ULONG DeviceListCount
;
79 // Lock for namespace device list
80 KGUARDED_MUTEX DeviceListLock
;
81 } PNPROOT_FDO_DEVICE_EXTENSION
, *PPNPROOT_FDO_DEVICE_EXTENSION
;
83 typedef struct _BUFFER
89 static PDEVICE_OBJECT PnpRootDeviceObject
= NULL
;
91 /* FUNCTIONS *****************************************************************/
95 IN PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
,
98 OUT PPNPROOT_DEVICE
* ChildDevice
)
100 PPNPROOT_DEVICE Device
;
101 UNICODE_STRING DeviceIdU
, InstanceIdU
;
102 PLIST_ENTRY NextEntry
;
104 /* Initialize the strings to compare */
105 RtlInitUnicodeString(&DeviceIdU
, DeviceId
);
106 RtlInitUnicodeString(&InstanceIdU
, InstanceId
);
109 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
110 NextEntry
!= &DeviceExtension
->DeviceListHead
;
111 NextEntry
= NextEntry
->Flink
)
114 Device
= CONTAINING_RECORD(NextEntry
, PNPROOT_DEVICE
, ListEntry
);
116 /* See if the strings match */
117 if (RtlEqualUnicodeString(&DeviceIdU
, &Device
->DeviceID
, TRUE
) &&
118 RtlEqualUnicodeString(&InstanceIdU
, &Device
->InstanceID
, TRUE
))
120 /* They do, so set the pointer and return success */
121 *ChildDevice
= Device
;
122 return STATUS_SUCCESS
;
126 /* No device found */
127 return STATUS_NO_SUCH_DEVICE
;
130 /* Creates a new PnP device for a legacy driver */
133 IN PUNICODE_STRING ServiceName
,
134 IN PDEVICE_OBJECT
*PhysicalDeviceObject
)
136 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
137 UNICODE_STRING UnknownServiceName
= RTL_CONSTANT_STRING(L
"LEGACY_UNKNOWN");
138 PUNICODE_STRING LocalServiceName
;
139 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
140 WCHAR DevicePath
[MAX_PATH
+ 1];
141 WCHAR InstancePath
[5];
142 PPNPROOT_DEVICE Device
= NULL
;
146 DeviceExtension
= PnpRootDeviceObject
->DeviceExtension
;
147 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
150 LocalServiceName
= ServiceName
;
152 LocalServiceName
= &UnknownServiceName
;
154 DPRINT("Creating a PnP root device for service '%wZ'\n", LocalServiceName
);
156 /* Search for a free instance ID */
157 _snwprintf(DevicePath
, sizeof(DevicePath
) / sizeof(WCHAR
), L
"%s\\%wZ", REGSTR_KEY_ROOTENUM
, LocalServiceName
);
158 for (i
= 0; i
< 9999; i
++)
160 _snwprintf(InstancePath
, sizeof(InstancePath
) / sizeof(WCHAR
), L
"%04lu", i
);
161 Status
= LocateChildDevice(DeviceExtension
, DevicePath
, InstancePath
, &Device
);
162 if (Status
== STATUS_NO_SUCH_DEVICE
)
167 DPRINT1("Too much legacy devices reported for service '%wZ'\n", &LocalServiceName
);
168 Status
= STATUS_INSUFFICIENT_RESOURCES
;
172 /* Initialize a PNPROOT_DEVICE structure */
173 Device
= ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
176 DPRINT("ExAllocatePoolWithTag() failed\n");
177 Status
= STATUS_NO_MEMORY
;
180 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
181 if (!RtlCreateUnicodeString(&Device
->DeviceID
, DevicePath
))
183 Status
= STATUS_NO_MEMORY
;
186 if (!RtlCreateUnicodeString(&Device
->InstanceID
, InstancePath
))
188 Status
= STATUS_NO_MEMORY
;
192 /* Initialize a device object */
193 Status
= IoCreateDevice(
194 PnpRootDeviceObject
->DriverObject
,
195 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
197 FILE_DEVICE_CONTROLLER
,
198 FILE_AUTOGENERATED_DEVICE_NAME
,
201 if (!NT_SUCCESS(Status
))
203 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
204 Status
= STATUS_NO_MEMORY
;
208 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
209 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
210 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
211 PdoDeviceExtension
->DeviceInfo
= Device
;
213 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
214 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
217 &DeviceExtension
->DeviceListHead
,
219 DeviceExtension
->DeviceListCount
++;
221 *PhysicalDeviceObject
= Device
->Pdo
;
222 DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject
, &Device
->DeviceID
, &Device
->InstanceID
);
224 Status
= STATUS_SUCCESS
;
227 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
231 IoDeleteDevice(Device
->Pdo
);
232 RtlFreeUnicodeString(&Device
->DeviceID
);
233 RtlFreeUnicodeString(&Device
->InstanceID
);
234 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
239 static NTSTATUS NTAPI
244 IN ULONG ValueLength
,
246 IN PVOID EntryContext
)
248 PUNICODE_STRING Destination
= (PUNICODE_STRING
)EntryContext
;
249 UNICODE_STRING Source
;
251 if (ValueType
!= REG_SZ
|| ValueLength
== 0 || ValueLength
% sizeof(WCHAR
) != 0)
252 return STATUS_SUCCESS
;
254 Source
.MaximumLength
= Source
.Length
= ValueLength
;
255 Source
.Buffer
= ValueData
;
256 if (Source
.Length
> 0 && Source
.Buffer
[Source
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
257 Source
.Length
-= sizeof(WCHAR
);
258 return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &Source
, Destination
);
261 static NTSTATUS NTAPI
262 QueryBinaryValueCallback(
266 IN ULONG ValueLength
,
268 IN PVOID EntryContext
)
270 PBUFFER Buffer
= (PBUFFER
)EntryContext
;
273 if (ValueLength
== 0)
275 *Buffer
->Data
= NULL
;
276 return STATUS_SUCCESS
;
279 BinaryValue
= ExAllocatePoolWithTag(PagedPool
, ValueLength
, TAG_PNP_ROOT
);
280 if (BinaryValue
== NULL
)
281 return STATUS_NO_MEMORY
;
282 RtlCopyMemory(BinaryValue
, ValueData
, ValueLength
);
283 *Buffer
->Data
= BinaryValue
;
284 if (Buffer
->Length
) *Buffer
->Length
= ValueLength
;
285 return STATUS_SUCCESS
;
290 IN PDEVICE_OBJECT DeviceObject
)
292 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
293 PKEY_BASIC_INFORMATION KeyInfo
= NULL
, SubKeyInfo
= NULL
;
294 UNICODE_STRING LegacyU
= RTL_CONSTANT_STRING(L
"LEGACY_");
295 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L
"\\" REGSTR_KEY_ROOTENUM
);
296 UNICODE_STRING SubKeyName
;
297 WCHAR DevicePath
[MAX_PATH
+ 1];
298 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
299 PPNPROOT_DEVICE Device
= NULL
;
300 HANDLE KeyHandle
= INVALID_HANDLE_VALUE
;
301 HANDLE SubKeyHandle
= INVALID_HANDLE_VALUE
;
302 HANDLE DeviceKeyHandle
= INVALID_HANDLE_VALUE
;
305 ULONG Index1
, Index2
;
306 BUFFER Buffer1
, Buffer2
;
307 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
309 DPRINT("EnumerateDevices(FDO %p)\n", DeviceObject
);
311 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
312 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
314 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + (MAX_PATH
+ 1) * sizeof(WCHAR
);
315 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
318 DPRINT("ExAllocatePoolWithTag() failed\n");
319 Status
= STATUS_NO_MEMORY
;
322 SubKeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
325 DPRINT("ExAllocatePoolWithTag() failed\n");
326 Status
= STATUS_NO_MEMORY
;
330 Status
= IopOpenRegistryKeyEx(&KeyHandle
, NULL
, &KeyName
, KEY_ENUMERATE_SUB_KEYS
);
331 if (!NT_SUCCESS(Status
))
333 DPRINT("IopOpenRegistryKeyEx(%wZ) failed with status 0x%08lx\n", &KeyName
, Status
);
337 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
338 * KeyHandle. We'll first do a first enumeration to have first level keys,
339 * and an inner one to have the real devices list.
344 Status
= ZwEnumerateKey(
351 if (Status
== STATUS_NO_MORE_ENTRIES
)
353 Status
= STATUS_SUCCESS
;
356 else if (!NT_SUCCESS(Status
))
358 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
362 /* Terminate the string */
363 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
365 /* Check if it is a legacy driver */
366 RtlInitUnicodeString(&SubKeyName
, KeyInfo
->Name
);
367 if (RtlPrefixUnicodeString(&LegacyU
, &SubKeyName
, FALSE
))
369 DPRINT("Ignoring legacy driver '%wZ'\n", &SubKeyName
);
375 Status
= IopOpenRegistryKeyEx(&SubKeyHandle
, KeyHandle
, &SubKeyName
, KEY_ENUMERATE_SUB_KEYS
);
376 if (!NT_SUCCESS(Status
))
378 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status
);
382 /* Enumerate the sub-keys */
386 Status
= ZwEnumerateKey(
393 if (Status
== STATUS_NO_MORE_ENTRIES
)
395 else if (!NT_SUCCESS(Status
))
397 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
401 /* Terminate the string */
402 SubKeyInfo
->Name
[SubKeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
406 sizeof(DevicePath
) / sizeof(WCHAR
),
407 L
"%s\\%s", REGSTR_KEY_ROOTENUM
, KeyInfo
->Name
);
408 DPRINT("Found device %S\\%s!\n", DevicePath
, SubKeyInfo
->Name
);
409 if (LocateChildDevice(DeviceExtension
, DevicePath
, SubKeyInfo
->Name
, &Device
) == STATUS_NO_SUCH_DEVICE
)
411 /* Create a PPNPROOT_DEVICE object, and add if in the list of known devices */
412 Device
= (PPNPROOT_DEVICE
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
415 DPRINT("ExAllocatePoolWithTag() failed\n");
416 Status
= STATUS_NO_MEMORY
;
419 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
421 /* Fill device ID and instance ID */
422 if (!RtlCreateUnicodeString(&Device
->DeviceID
, DevicePath
))
424 DPRINT("RtlCreateUnicodeString() failed\n");
425 Status
= STATUS_NO_MEMORY
;
429 if (!RtlCreateUnicodeString(&Device
->InstanceID
, SubKeyInfo
->Name
))
431 DPRINT("RtlCreateUnicodeString() failed\n");
432 Status
= STATUS_NO_MEMORY
;
436 /* Open registry key to fill other informations */
437 Status
= IopOpenRegistryKeyEx(&DeviceKeyHandle
, SubKeyHandle
, &Device
->InstanceID
, KEY_READ
);
438 if (!NT_SUCCESS(Status
))
440 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status
);
444 /* Fill other informations */
445 Buffer1
.Data
= (PVOID
*)&Device
->ResourceRequirementsList
;
446 Buffer1
.Length
= NULL
;
447 Buffer2
.Data
= (PVOID
*)&Device
->ResourceList
;
448 Buffer2
.Length
= &Device
->ResourceListSize
;
449 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
450 QueryTable
[0].QueryRoutine
= QueryStringCallback
;
451 QueryTable
[0].Name
= L
"DeviceDesc";
452 QueryTable
[0].EntryContext
= &Device
->DeviceDescription
;
453 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_SUBKEY
;
454 QueryTable
[1].Name
= L
"LogConf";
455 QueryTable
[2].QueryRoutine
= QueryBinaryValueCallback
;
456 QueryTable
[2].Name
= L
"BasicConfigVector";
457 QueryTable
[2].EntryContext
= &Buffer1
;
458 QueryTable
[3].QueryRoutine
= QueryBinaryValueCallback
;
459 QueryTable
[3].Name
= L
"BootConfig";
460 QueryTable
[3].EntryContext
= &Buffer2
;
462 Status
= RtlQueryRegistryValues(
464 (PCWSTR
)DeviceKeyHandle
,
468 if (!NT_SUCCESS(Status
))
470 DPRINT("RtlQueryRegistryValues() failed with status 0x%08lx\n", Status
);
474 ZwClose(DeviceKeyHandle
);
475 DeviceKeyHandle
= INVALID_HANDLE_VALUE
;
477 /* Insert the newly created device into the list */
479 &DeviceExtension
->DeviceListHead
,
481 DeviceExtension
->DeviceListCount
++;
488 ZwClose(SubKeyHandle
);
489 SubKeyHandle
= INVALID_HANDLE_VALUE
;
496 /* We have a device that has not been added to device list. We need to clean it up */
498 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
500 if (DeviceKeyHandle
!= INVALID_HANDLE_VALUE
)
501 ZwClose(DeviceKeyHandle
);
502 if (SubKeyHandle
!= INVALID_HANDLE_VALUE
)
503 ZwClose(SubKeyHandle
);
504 if (KeyHandle
!= INVALID_HANDLE_VALUE
)
507 ExFreePoolWithTag(KeyInfo
, TAG_PNP_ROOT
);
509 ExFreePoolWithTag(SubKeyInfo
, TAG_PNP_ROOT
);
510 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
514 /* FUNCTION: Handle IRP_MN_QUERY_DEVICE_RELATIONS IRPs for the root bus device object
516 * DeviceObject = Pointer to functional device object of the root bus driver
517 * Irp = Pointer to IRP that should be handled
522 PnpRootQueryDeviceRelations(
523 IN PDEVICE_OBJECT DeviceObject
,
526 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
527 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
528 PDEVICE_RELATIONS Relations
= NULL
, OtherRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
529 PPNPROOT_DEVICE Device
= NULL
;
532 PLIST_ENTRY NextEntry
;
534 DPRINT("PnpRootQueryDeviceRelations(FDO %p, Irp %p)\n", DeviceObject
, Irp
);
536 Status
= EnumerateDevices(DeviceObject
);
537 if (!NT_SUCCESS(Status
))
539 DPRINT("EnumerateDevices() failed with status 0x%08lx\n", Status
);
543 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
545 Size
= FIELD_OFFSET(DEVICE_RELATIONS
, Objects
) + sizeof(PDEVICE_OBJECT
) * DeviceExtension
->DeviceListCount
;
548 /* Another bus driver has already created a DEVICE_RELATIONS
549 * structure so we must merge this structure with our own */
551 Size
+= sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
;
553 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, Size
);
556 DPRINT("ExAllocatePoolWithTag() failed\n");
557 Status
= STATUS_NO_MEMORY
;
560 RtlZeroMemory(Relations
, Size
);
563 Relations
->Count
= OtherRelations
->Count
;
564 RtlCopyMemory(Relations
->Objects
, OtherRelations
->Objects
, sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
);
567 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
570 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
571 NextEntry
!= &DeviceExtension
->DeviceListHead
;
572 NextEntry
= NextEntry
->Flink
)
575 Device
= CONTAINING_RECORD(NextEntry
, PNPROOT_DEVICE
, ListEntry
);
579 /* Create a physical device object for the
580 * device as it does not already have one */
581 Status
= IoCreateDevice(
582 DeviceObject
->DriverObject
,
583 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
585 FILE_DEVICE_CONTROLLER
,
586 FILE_AUTOGENERATED_DEVICE_NAME
,
589 if (!NT_SUCCESS(Status
))
591 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
595 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
596 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
597 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
598 PdoDeviceExtension
->DeviceInfo
= Device
;
600 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
601 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
604 /* Reference the physical device object. The PnP manager
605 will dereference it again when it is no longer needed */
606 ObReferenceObject(Device
->Pdo
);
608 Relations
->Objects
[Relations
->Count
++] = Device
->Pdo
;
610 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
612 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
615 if (!NT_SUCCESS(Status
))
618 ExFreePool(OtherRelations
);
620 ExFreePool(Relations
);
621 if (Device
&& Device
->Pdo
)
623 IoDeleteDevice(Device
->Pdo
);
632 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
634 * DeviceObject = Pointer to functional device object of the root bus driver
635 * Irp = Pointer to IRP that should be handled
640 PnpRootFdoPnpControl(
641 IN PDEVICE_OBJECT DeviceObject
,
644 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
645 PIO_STACK_LOCATION IrpSp
;
648 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
649 Status
= Irp
->IoStatus
.Status
;
650 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
652 switch (IrpSp
->MinorFunction
)
654 case IRP_MN_QUERY_DEVICE_RELATIONS
:
655 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
656 Status
= PnpRootQueryDeviceRelations(DeviceObject
, Irp
);
659 case IRP_MN_START_DEVICE
:
660 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
661 if (!IoForwardIrpSynchronously(DeviceExtension
->Ldo
, Irp
))
662 Status
= STATUS_UNSUCCESSFUL
;
665 Status
= Irp
->IoStatus
.Status
;
666 if (NT_SUCCESS(Status
))
667 DeviceExtension
->State
= dsStarted
;
671 case IRP_MN_STOP_DEVICE
:
672 DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
673 /* Root device cannot be stopped */
674 Status
= STATUS_NOT_SUPPORTED
;
678 DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
679 Status
= STATUS_NOT_IMPLEMENTED
;
683 if (Status
!= STATUS_PENDING
)
685 Irp
->IoStatus
.Status
= Status
;
686 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
693 PdoQueryDeviceRelations(
694 IN PDEVICE_OBJECT DeviceObject
,
696 IN PIO_STACK_LOCATION IrpSp
)
698 PDEVICE_RELATIONS Relations
;
699 DEVICE_RELATION_TYPE RelationType
;
700 NTSTATUS Status
= Irp
->IoStatus
.Status
;
702 RelationType
= IrpSp
->Parameters
.QueryDeviceRelations
.Type
;
704 switch (RelationType
)
709 if (IoGetAttachedDevice(DeviceObject
) != DeviceObject
)
711 /* We're not alone in the stack */
712 DPRINT1("PnP is misbehaving ; don't know how to handle IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
717 case TargetDeviceRelation
:
719 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
720 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
));
723 DPRINT("ExAllocatePoolWithTag() failed\n");
724 Status
= STATUS_NO_MEMORY
;
728 ObReferenceObject(DeviceObject
);
729 Relations
->Count
= 1;
730 Relations
->Objects
[0] = DeviceObject
;
731 Status
= STATUS_SUCCESS
;
732 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
739 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / unknown relation type 0x%lx\n", RelationType
);
747 PdoQueryCapabilities(
748 IN PDEVICE_OBJECT DeviceObject
,
750 IN PIO_STACK_LOCATION IrpSp
)
752 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
753 PDEVICE_CAPABILITIES DeviceCapabilities
;
755 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
756 DeviceCapabilities
= IrpSp
->Parameters
.DeviceCapabilities
.Capabilities
;
758 if (DeviceCapabilities
->Version
!= 1)
759 return STATUS_REVISION_MISMATCH
;
761 DeviceCapabilities
->UniqueID
= TRUE
;
762 /* FIXME: Fill other fields */
764 return STATUS_SUCCESS
;
769 IN PDEVICE_OBJECT DeviceObject
,
771 IN PIO_STACK_LOCATION IrpSp
)
773 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
774 PCM_RESOURCE_LIST ResourceList
;
776 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
778 if (DeviceExtension
->DeviceInfo
->ResourceList
== NULL
)
780 /* Create an empty resource list */
781 ResourceList
= ExAllocatePool(PagedPool
, sizeof(CM_RESOURCE_LIST
));
783 return STATUS_NO_MEMORY
;
785 ResourceList
->Count
= 0;
787 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
791 /* Copy existing resource requirement list */
792 ResourceList
= ExAllocatePool(
794 FIELD_OFFSET(CM_RESOURCE_LIST
, List
) + DeviceExtension
->DeviceInfo
->ResourceListSize
);
796 return STATUS_NO_MEMORY
;
798 ResourceList
->Count
= 1;
801 DeviceExtension
->DeviceInfo
->ResourceList
,
802 DeviceExtension
->DeviceInfo
->ResourceListSize
);
803 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
806 return STATUS_SUCCESS
;
810 PdoQueryResourceRequirements(
811 IN PDEVICE_OBJECT DeviceObject
,
813 IN PIO_STACK_LOCATION IrpSp
)
815 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
816 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList
;
817 ULONG ResourceListSize
= FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST
, List
);
819 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
821 if (DeviceExtension
->DeviceInfo
->ResourceRequirementsList
== NULL
)
823 /* Create an empty resource list */
824 ResourceList
= ExAllocatePool(PagedPool
, ResourceListSize
);
826 return STATUS_NO_MEMORY
;
828 RtlZeroMemory(ResourceList
, ResourceListSize
);
829 ResourceList
->ListSize
= ResourceListSize
;
831 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
835 /* Copy existing resource requirement list */
836 ResourceList
= ExAllocatePool(PagedPool
, DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
838 return STATUS_NO_MEMORY
;
842 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
,
843 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
844 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
847 return STATUS_SUCCESS
;
852 IN PDEVICE_OBJECT DeviceObject
,
854 IN PIO_STACK_LOCATION IrpSp
)
856 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
857 DEVICE_TEXT_TYPE DeviceTextType
;
858 NTSTATUS Status
= Irp
->IoStatus
.Status
;
860 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
861 DeviceTextType
= IrpSp
->Parameters
.QueryDeviceText
.DeviceTextType
;
863 switch (DeviceTextType
)
865 case DeviceTextDescription
:
867 UNICODE_STRING String
;
868 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
870 Status
= RtlDuplicateUnicodeString(
871 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
872 &DeviceExtension
->DeviceInfo
->DeviceDescription
,
874 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
878 case DeviceTextLocationInformation
:
880 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
881 Status
= STATUS_NOT_SUPPORTED
;
887 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown query id type 0x%lx\n", DeviceTextType
);
896 IN PDEVICE_OBJECT DeviceObject
,
898 IN PIO_STACK_LOCATION IrpSp
)
900 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
901 BUS_QUERY_ID_TYPE IdType
;
902 NTSTATUS Status
= Irp
->IoStatus
.Status
;
904 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
905 IdType
= IrpSp
->Parameters
.QueryId
.IdType
;
909 case BusQueryDeviceID
:
911 UNICODE_STRING String
;
912 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
914 Status
= RtlDuplicateUnicodeString(
915 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
916 &DeviceExtension
->DeviceInfo
->DeviceID
,
918 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
922 case BusQueryHardwareIDs
:
923 case BusQueryCompatibleIDs
:
925 /* Optional, do nothing */
929 case BusQueryInstanceID
:
931 UNICODE_STRING String
;
932 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
934 Status
= RtlDuplicateUnicodeString(
935 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
936 &DeviceExtension
->DeviceInfo
->InstanceID
,
938 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
944 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
952 PdoQueryBusInformation(
953 IN PDEVICE_OBJECT DeviceObject
,
955 IN PIO_STACK_LOCATION IrpSp
)
957 PPNP_BUS_INFORMATION BusInfo
;
960 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNP_BUS_INFORMATION
), TAG_PNP_ROOT
);
962 Status
= STATUS_NO_MEMORY
;
966 &BusInfo
->BusTypeGuid
,
967 &GUID_BUS_TYPE_INTERNAL
,
968 sizeof(BusInfo
->BusTypeGuid
));
969 BusInfo
->LegacyBusType
= PNPBus
;
970 /* We're the only root bus enumerator on the computer */
971 BusInfo
->BusNumber
= 0;
972 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInfo
;
973 Status
= STATUS_SUCCESS
;
980 * FUNCTION: Handle Plug and Play IRPs for the child device
982 * DeviceObject = Pointer to physical device object of the child device
983 * Irp = Pointer to IRP that should be handled
988 PnpRootPdoPnpControl(
989 IN PDEVICE_OBJECT DeviceObject
,
992 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
993 PIO_STACK_LOCATION IrpSp
;
996 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
997 Status
= Irp
->IoStatus
.Status
;
998 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1000 switch (IrpSp
->MinorFunction
)
1002 case IRP_MN_START_DEVICE
: /* 0x00 */
1003 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1004 Status
= STATUS_SUCCESS
;
1007 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x07 */
1008 Status
= PdoQueryDeviceRelations(DeviceObject
, Irp
, IrpSp
);
1011 case IRP_MN_QUERY_CAPABILITIES
: /* 0x09 */
1012 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
1013 Status
= PdoQueryCapabilities(DeviceObject
, Irp
, IrpSp
);
1016 case IRP_MN_QUERY_RESOURCES
: /* 0x0a */
1017 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
1018 Status
= PdoQueryResources(DeviceObject
, Irp
, IrpSp
);
1021 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
: /* 0x0b */
1022 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1023 Status
= PdoQueryResourceRequirements(DeviceObject
, Irp
, IrpSp
);
1026 case IRP_MN_QUERY_DEVICE_TEXT
: /* 0x0c */
1027 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1028 Status
= PdoQueryDeviceText(DeviceObject
, Irp
, IrpSp
);
1031 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0x0d */
1032 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1035 case IRP_MN_QUERY_ID
: /* 0x13 */
1036 Status
= PdoQueryId(DeviceObject
, Irp
, IrpSp
);
1039 case IRP_MN_QUERY_BUS_INFORMATION
: /* 0x15 */
1040 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
1041 Status
= PdoQueryBusInformation(DeviceObject
, Irp
, IrpSp
);
1045 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
1046 Status
= STATUS_NOT_IMPLEMENTED
;
1050 if (Status
!= STATUS_PENDING
)
1052 Irp
->IoStatus
.Status
= Status
;
1053 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1060 * FUNCTION: Handle Plug and Play IRPs
1062 * DeviceObject = Pointer to PDO or FDO
1063 * Irp = Pointer to IRP that should be handled
1067 static NTSTATUS NTAPI
1069 IN PDEVICE_OBJECT DeviceObject
,
1072 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension
;
1075 DeviceExtension
= (PPNPROOT_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1077 if (DeviceExtension
->IsFDO
)
1078 Status
= PnpRootFdoPnpControl(DeviceObject
, Irp
);
1080 Status
= PnpRootPdoPnpControl(DeviceObject
, Irp
);
1088 IN PDRIVER_OBJECT DriverObject
,
1089 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1091 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
1094 DPRINT("PnpRootAddDevice(DriverObject %p, Pdo %p)\n", DriverObject
, PhysicalDeviceObject
);
1096 if (!PhysicalDeviceObject
)
1098 DPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject
);
1099 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1100 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1103 Status
= IoCreateDevice(
1105 sizeof(PNPROOT_FDO_DEVICE_EXTENSION
),
1107 FILE_DEVICE_BUS_EXTENDER
,
1108 FILE_DEVICE_SECURE_OPEN
,
1110 &PnpRootDeviceObject
);
1111 if (!NT_SUCCESS(Status
))
1113 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
1114 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1116 DPRINT("Created FDO %p\n", PnpRootDeviceObject
);
1118 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)PnpRootDeviceObject
->DeviceExtension
;
1119 RtlZeroMemory(DeviceExtension
, sizeof(PNPROOT_FDO_DEVICE_EXTENSION
));
1121 DeviceExtension
->Common
.IsFDO
= TRUE
;
1122 DeviceExtension
->State
= dsStopped
;
1123 InitializeListHead(&DeviceExtension
->DeviceListHead
);
1124 DeviceExtension
->DeviceListCount
= 0;
1125 KeInitializeGuardedMutex(&DeviceExtension
->DeviceListLock
);
1127 Status
= IoAttachDeviceToDeviceStackSafe(
1128 PnpRootDeviceObject
,
1129 PhysicalDeviceObject
,
1130 &DeviceExtension
->Ldo
);
1131 if (!NT_SUCCESS(Status
))
1133 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
1134 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1137 PnpRootDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1139 DPRINT("Done AddDevice()\n");
1141 return STATUS_SUCCESS
;
1146 IN PDRIVER_OBJECT DriverObject
,
1147 IN PUNICODE_STRING RegistryPath
)
1149 DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject
, RegistryPath
);
1151 DriverObject
->DriverExtension
->AddDevice
= PnpRootAddDevice
;
1153 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = PnpRootPnpControl
;
1154 //DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl;
1156 return STATUS_SUCCESS
;