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 ******************************************************************/
14 #include <internal/debug.h>
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
;
103 RtlInitUnicodeString(&DeviceIdU
, DeviceId
);
104 RtlInitUnicodeString(&InstanceIdU
, InstanceId
);
106 LIST_FOR_EACH(Device
, &DeviceExtension
->DeviceListHead
, PNPROOT_DEVICE
, ListEntry
)
108 if (RtlEqualUnicodeString(&DeviceIdU
, &Device
->DeviceID
, TRUE
)
109 && RtlEqualUnicodeString(&InstanceIdU
, &Device
->InstanceID
, TRUE
))
111 *ChildDevice
= Device
;
112 return STATUS_SUCCESS
;
116 return STATUS_NO_SUCH_DEVICE
;
119 /* Creates a new PnP device for a legacy driver */
122 IN PUNICODE_STRING ServiceName
,
123 IN PDEVICE_OBJECT
*PhysicalDeviceObject
)
125 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
126 UNICODE_STRING UnknownServiceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
127 PUNICODE_STRING LocalServiceName
;
128 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
129 WCHAR DevicePath
[MAX_PATH
+ 1];
130 WCHAR InstancePath
[5];
131 PPNPROOT_DEVICE Device
= NULL
;
135 DeviceExtension
= PnpRootDeviceObject
->DeviceExtension
;
136 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
139 LocalServiceName
= ServiceName
;
141 LocalServiceName
= &UnknownServiceName
;
143 DPRINT("Creating a PnP root device for service '%wZ'\n", LocalServiceName
);
145 /* Search for a free instance ID */
146 _snwprintf(DevicePath
, sizeof(DevicePath
) / sizeof(WCHAR
), L
"%s\\LEGACY_%wZ", REGSTR_KEY_ROOTENUM
, LocalServiceName
);
147 for (i
= 0; i
< 9999; i
++)
149 _snwprintf(InstancePath
, sizeof(InstancePath
) / sizeof(WCHAR
), L
"%04lu", i
);
150 Status
= LocateChildDevice(DeviceExtension
, DevicePath
, InstancePath
, &Device
);
151 if (Status
== STATUS_NO_SUCH_DEVICE
)
156 DPRINT1("Too much legacy devices reported for service '%wZ'\n", &LocalServiceName
);
157 Status
= STATUS_INSUFFICIENT_RESOURCES
;
161 /* Initialize a PNPROOT_DEVICE structure */
162 Device
= ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
165 DPRINT("ExAllocatePoolWithTag() failed\n");
166 Status
= STATUS_NO_MEMORY
;
169 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
170 if (!RtlCreateUnicodeString(&Device
->DeviceID
, DevicePath
))
172 Status
= STATUS_NO_MEMORY
;
175 if (!RtlCreateUnicodeString(&Device
->InstanceID
, InstancePath
))
177 Status
= STATUS_NO_MEMORY
;
181 /* Initialize a device object */
182 Status
= IoCreateDevice(
183 PnpRootDeviceObject
->DriverObject
,
184 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
186 FILE_DEVICE_CONTROLLER
,
187 FILE_AUTOGENERATED_DEVICE_NAME
,
190 if (!NT_SUCCESS(Status
))
192 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
193 Status
= STATUS_NO_MEMORY
;
197 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
198 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
199 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
200 PdoDeviceExtension
->DeviceInfo
= Device
;
202 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
203 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
206 &DeviceExtension
->DeviceListHead
,
208 DeviceExtension
->DeviceListCount
++;
210 *PhysicalDeviceObject
= Device
->Pdo
;
211 DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject
, &Device
->DeviceID
, &Device
->InstanceID
);
213 Status
= STATUS_SUCCESS
;
216 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
220 IoDeleteDevice(Device
->Pdo
);
221 RtlFreeUnicodeString(&Device
->DeviceID
);
222 RtlFreeUnicodeString(&Device
->InstanceID
);
223 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
228 static NTSTATUS NTAPI
233 IN ULONG ValueLength
,
235 IN PVOID EntryContext
)
237 PUNICODE_STRING Destination
= (PUNICODE_STRING
)EntryContext
;
238 UNICODE_STRING Source
;
240 if (ValueType
!= REG_SZ
|| ValueLength
== 0 || ValueLength
% sizeof(WCHAR
) != 0)
241 return STATUS_SUCCESS
;
243 Source
.MaximumLength
= Source
.Length
= ValueLength
;
244 Source
.Buffer
= ValueData
;
245 if (Source
.Length
> 0 && Source
.Buffer
[Source
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
246 Source
.Length
-= sizeof(WCHAR
);
247 return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &Source
, Destination
);
250 static NTSTATUS NTAPI
251 QueryBinaryValueCallback(
255 IN ULONG ValueLength
,
257 IN PVOID EntryContext
)
259 PBUFFER Buffer
= (PBUFFER
)EntryContext
;
262 if (ValueLength
== 0)
264 *Buffer
->Data
= NULL
;
265 return STATUS_SUCCESS
;
268 BinaryValue
= ExAllocatePoolWithTag(PagedPool
, ValueLength
, TAG_PNP_ROOT
);
269 if (BinaryValue
== NULL
)
270 return STATUS_NO_MEMORY
;
271 RtlCopyMemory(BinaryValue
, ValueData
, ValueLength
);
272 *Buffer
->Data
= BinaryValue
;
273 if (Buffer
->Length
) *Buffer
->Length
= ValueLength
;
274 return STATUS_SUCCESS
;
279 IN PDEVICE_OBJECT DeviceObject
)
281 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
282 PKEY_BASIC_INFORMATION KeyInfo
= NULL
, SubKeyInfo
= NULL
;
283 UNICODE_STRING LegacyU
= RTL_CONSTANT_STRING(L
"LEGACY_");
284 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L
"\\" REGSTR_KEY_ROOTENUM
);
285 UNICODE_STRING SubKeyName
;
286 WCHAR DevicePath
[MAX_PATH
+ 1];
287 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
288 PPNPROOT_DEVICE Device
= NULL
;
289 HANDLE KeyHandle
= INVALID_HANDLE_VALUE
;
290 HANDLE SubKeyHandle
= INVALID_HANDLE_VALUE
;
291 HANDLE DeviceKeyHandle
= INVALID_HANDLE_VALUE
;
294 ULONG Index1
, Index2
;
295 BUFFER Buffer1
, Buffer2
;
296 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
298 DPRINT("EnumerateDevices(FDO %p)\n", DeviceObject
);
300 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
301 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
303 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + (MAX_PATH
+ 1) * sizeof(WCHAR
);
304 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
307 DPRINT("ExAllocatePoolWithTag() failed\n");
308 Status
= STATUS_NO_MEMORY
;
311 SubKeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
314 DPRINT("ExAllocatePoolWithTag() failed\n");
315 Status
= STATUS_NO_MEMORY
;
319 Status
= IopOpenRegistryKeyEx(&KeyHandle
, NULL
, &KeyName
, KEY_ENUMERATE_SUB_KEYS
);
320 if (!NT_SUCCESS(Status
))
322 DPRINT("IopOpenRegistryKeyEx(%wZ) failed with status 0x%08lx\n", &KeyName
, Status
);
326 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
327 * KeyHandle. We'll first do a first enumeration to have first level keys,
328 * and an inner one to have the real devices list.
333 Status
= ZwEnumerateKey(
340 if (Status
== STATUS_NO_MORE_ENTRIES
)
342 Status
= STATUS_SUCCESS
;
345 else if (!NT_SUCCESS(Status
))
347 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
351 /* Terminate the string */
352 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
354 /* Check if it is a legacy driver */
355 RtlInitUnicodeString(&SubKeyName
, KeyInfo
->Name
);
356 if (RtlPrefixUnicodeString(&LegacyU
, &SubKeyName
, FALSE
))
358 DPRINT("Ignoring legacy driver '%wZ'\n", &SubKeyName
);
364 Status
= IopOpenRegistryKeyEx(&SubKeyHandle
, KeyHandle
, &SubKeyName
, KEY_ENUMERATE_SUB_KEYS
);
365 if (!NT_SUCCESS(Status
))
367 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status
);
371 /* Enumerate the sub-keys */
375 Status
= ZwEnumerateKey(
382 if (Status
== STATUS_NO_MORE_ENTRIES
)
384 else if (!NT_SUCCESS(Status
))
386 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
390 /* Terminate the string */
391 SubKeyInfo
->Name
[SubKeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
395 sizeof(DevicePath
) / sizeof(WCHAR
),
396 L
"%s\\%s", REGSTR_KEY_ROOTENUM
, KeyInfo
->Name
);
397 DPRINT("Found device %S\\%s!\n", DevicePath
, SubKeyInfo
->Name
);
398 if (LocateChildDevice(DeviceExtension
, DevicePath
, SubKeyInfo
->Name
, &Device
) == STATUS_NO_SUCH_DEVICE
)
400 /* Create a PPNPROOT_DEVICE object, and add if in the list of known devices */
401 Device
= (PPNPROOT_DEVICE
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
404 DPRINT("ExAllocatePoolWithTag() failed\n");
405 Status
= STATUS_NO_MEMORY
;
408 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
410 /* Fill device ID and instance ID */
411 if (!RtlCreateUnicodeString(&Device
->DeviceID
, DevicePath
))
413 DPRINT("RtlCreateUnicodeString() failed\n");
414 Status
= STATUS_NO_MEMORY
;
418 if (!RtlCreateUnicodeString(&Device
->InstanceID
, SubKeyInfo
->Name
))
420 DPRINT("RtlCreateUnicodeString() failed\n");
421 Status
= STATUS_NO_MEMORY
;
425 /* Open registry key to fill other informations */
426 Status
= IopOpenRegistryKeyEx(&DeviceKeyHandle
, SubKeyHandle
, &Device
->InstanceID
, KEY_READ
);
427 if (!NT_SUCCESS(Status
))
429 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status
);
433 /* Fill other informations */
434 Buffer1
.Data
= (PVOID
*)&Device
->ResourceRequirementsList
;
435 Buffer1
.Length
= NULL
;
436 Buffer2
.Data
= (PVOID
*)&Device
->ResourceList
;
437 Buffer2
.Length
= &Device
->ResourceListSize
;
438 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
439 QueryTable
[0].QueryRoutine
= QueryStringCallback
;
440 QueryTable
[0].Name
= L
"DeviceDesc";
441 QueryTable
[0].EntryContext
= &Device
->DeviceDescription
;
442 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_SUBKEY
;
443 QueryTable
[1].Name
= L
"LogConf";
444 QueryTable
[2].QueryRoutine
= QueryBinaryValueCallback
;
445 QueryTable
[2].Name
= L
"BasicConfigVector";
446 QueryTable
[2].EntryContext
= &Buffer1
;
447 QueryTable
[3].QueryRoutine
= QueryBinaryValueCallback
;
448 QueryTable
[3].Name
= L
"BootConfig";
449 QueryTable
[3].EntryContext
= &Buffer2
;
451 Status
= RtlQueryRegistryValues(
453 (PCWSTR
)DeviceKeyHandle
,
457 if (!NT_SUCCESS(Status
))
459 DPRINT("RtlQueryRegistryValues() failed with status 0x%08lx\n", Status
);
463 ZwClose(DeviceKeyHandle
);
464 DeviceKeyHandle
= INVALID_HANDLE_VALUE
;
466 /* Insert the newly created device into the list */
468 &DeviceExtension
->DeviceListHead
,
470 DeviceExtension
->DeviceListCount
++;
477 ZwClose(SubKeyHandle
);
478 SubKeyHandle
= INVALID_HANDLE_VALUE
;
485 /* We have a device that has not been added to device list. We need to clean it up */
487 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
489 if (DeviceKeyHandle
!= INVALID_HANDLE_VALUE
)
490 ZwClose(DeviceKeyHandle
);
491 if (SubKeyHandle
!= INVALID_HANDLE_VALUE
)
492 ZwClose(SubKeyHandle
);
493 if (KeyHandle
!= INVALID_HANDLE_VALUE
)
495 ExFreePoolWithTag(KeyInfo
, TAG_PNP_ROOT
);
496 ExFreePoolWithTag(SubKeyInfo
, TAG_PNP_ROOT
);
497 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
501 /* FUNCTION: Handle IRP_MN_QUERY_DEVICE_RELATIONS IRPs for the root bus device object
503 * DeviceObject = Pointer to functional device object of the root bus driver
504 * Irp = Pointer to IRP that should be handled
509 PnpRootQueryDeviceRelations(
510 IN PDEVICE_OBJECT DeviceObject
,
513 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
514 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
515 PDEVICE_RELATIONS Relations
= NULL
, OtherRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
516 PPNPROOT_DEVICE Device
= NULL
;
520 DPRINT("PnpRootQueryDeviceRelations(FDO %p, Irp %p)\n", DeviceObject
, Irp
);
522 Status
= EnumerateDevices(DeviceObject
);
523 if (!NT_SUCCESS(Status
))
525 DPRINT("EnumerateDevices() failed with status 0x%08lx\n", Status
);
529 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
531 Size
= FIELD_OFFSET(DEVICE_RELATIONS
, Objects
) + sizeof(PDEVICE_OBJECT
) * DeviceExtension
->DeviceListCount
;
534 /* Another bus driver has already created a DEVICE_RELATIONS
535 * structure so we must merge this structure with our own */
537 Size
+= sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
;
539 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, Size
);
542 DPRINT("ExAllocatePoolWithTag() failed\n");
543 Status
= STATUS_NO_MEMORY
;
546 RtlZeroMemory(Relations
, Size
);
549 Relations
->Count
= OtherRelations
->Count
;
550 RtlCopyMemory(Relations
->Objects
, OtherRelations
->Objects
, sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
);
553 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
554 LIST_FOR_EACH(Device
, &DeviceExtension
->DeviceListHead
, PNPROOT_DEVICE
, ListEntry
)
558 /* Create a physical device object for the
559 * device as it does not already have one */
560 Status
= IoCreateDevice(
561 DeviceObject
->DriverObject
,
562 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
564 FILE_DEVICE_CONTROLLER
,
565 FILE_AUTOGENERATED_DEVICE_NAME
,
568 if (!NT_SUCCESS(Status
))
570 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
574 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
575 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
576 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
577 PdoDeviceExtension
->DeviceInfo
= Device
;
579 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
580 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
583 /* Reference the physical device object. The PnP manager
584 will dereference it again when it is no longer needed */
585 ObReferenceObject(Device
->Pdo
);
587 Relations
->Objects
[Relations
->Count
++] = Device
->Pdo
;
589 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
591 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
594 if (!NT_SUCCESS(Status
))
597 ExFreePool(OtherRelations
);
599 ExFreePool(Relations
);
600 if (Device
&& Device
->Pdo
)
602 IoDeleteDevice(Device
->Pdo
);
611 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
613 * DeviceObject = Pointer to functional device object of the root bus driver
614 * Irp = Pointer to IRP that should be handled
619 PnpRootFdoPnpControl(
620 IN PDEVICE_OBJECT DeviceObject
,
623 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
624 PIO_STACK_LOCATION IrpSp
;
627 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
628 Status
= Irp
->IoStatus
.Status
;
629 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
631 switch (IrpSp
->MinorFunction
)
633 case IRP_MN_QUERY_DEVICE_RELATIONS
:
634 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
635 Status
= PnpRootQueryDeviceRelations(DeviceObject
, Irp
);
638 case IRP_MN_START_DEVICE
:
639 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
640 if (!IoForwardIrpSynchronously(DeviceExtension
->Ldo
, Irp
))
641 Status
= STATUS_UNSUCCESSFUL
;
644 Status
= Irp
->IoStatus
.Status
;
645 if (NT_SUCCESS(Status
))
646 DeviceExtension
->State
= dsStarted
;
650 case IRP_MN_STOP_DEVICE
:
651 DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
652 /* Root device cannot be stopped */
653 Status
= STATUS_NOT_SUPPORTED
;
657 DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
658 Status
= STATUS_NOT_IMPLEMENTED
;
662 if (Status
!= STATUS_PENDING
)
664 Irp
->IoStatus
.Status
= Status
;
665 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
672 PdoQueryDeviceRelations(
673 IN PDEVICE_OBJECT DeviceObject
,
675 IN PIO_STACK_LOCATION IrpSp
)
677 PDEVICE_RELATIONS Relations
;
678 DEVICE_RELATION_TYPE RelationType
;
679 NTSTATUS Status
= Irp
->IoStatus
.Status
;
681 RelationType
= IrpSp
->Parameters
.QueryDeviceRelations
.Type
;
683 switch (RelationType
)
688 if (IoGetAttachedDevice(DeviceObject
) != DeviceObject
)
690 /* We're not alone in the stack */
691 DPRINT1("PnP is misbehaving ; don't know how to handle IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
696 case TargetDeviceRelation
:
698 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
699 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
));
702 DPRINT("ExAllocatePoolWithTag() failed\n");
703 Status
= STATUS_NO_MEMORY
;
707 ObReferenceObject(DeviceObject
);
708 Relations
->Count
= 1;
709 Relations
->Objects
[0] = DeviceObject
;
710 Status
= STATUS_SUCCESS
;
711 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
718 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / unknown relation type 0x%lx\n", RelationType
);
726 PdoQueryCapabilities(
727 IN PDEVICE_OBJECT DeviceObject
,
729 IN PIO_STACK_LOCATION IrpSp
)
731 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
732 PDEVICE_CAPABILITIES DeviceCapabilities
;
734 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
735 DeviceCapabilities
= IrpSp
->Parameters
.DeviceCapabilities
.Capabilities
;
737 if (DeviceCapabilities
->Version
!= 1)
738 return STATUS_REVISION_MISMATCH
;
740 DeviceCapabilities
->UniqueID
= TRUE
;
741 /* FIXME: Fill other fields */
743 return STATUS_SUCCESS
;
748 IN PDEVICE_OBJECT DeviceObject
,
750 IN PIO_STACK_LOCATION IrpSp
)
752 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
753 PCM_RESOURCE_LIST ResourceList
;
755 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
757 if (DeviceExtension
->DeviceInfo
->ResourceList
== NULL
)
759 /* Create an empty resource list */
760 ResourceList
= ExAllocatePool(PagedPool
, sizeof(CM_RESOURCE_LIST
));
762 return STATUS_NO_MEMORY
;
764 ResourceList
->Count
= 0;
766 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
770 /* Copy existing resource requirement list */
771 ResourceList
= ExAllocatePool(
773 FIELD_OFFSET(CM_RESOURCE_LIST
, List
) + DeviceExtension
->DeviceInfo
->ResourceListSize
);
775 return STATUS_NO_MEMORY
;
777 ResourceList
->Count
= 1;
780 DeviceExtension
->DeviceInfo
->ResourceList
,
781 DeviceExtension
->DeviceInfo
->ResourceListSize
);
782 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
785 return STATUS_SUCCESS
;
789 PdoQueryResourceRequirements(
790 IN PDEVICE_OBJECT DeviceObject
,
792 IN PIO_STACK_LOCATION IrpSp
)
794 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
795 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList
;
796 ULONG ResourceListSize
= FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST
, List
);
798 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
800 if (DeviceExtension
->DeviceInfo
->ResourceRequirementsList
== NULL
)
802 /* Create an empty resource list */
803 ResourceList
= ExAllocatePool(PagedPool
, ResourceListSize
);
805 return STATUS_NO_MEMORY
;
807 RtlZeroMemory(ResourceList
, ResourceListSize
);
808 ResourceList
->ListSize
= ResourceListSize
;
810 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
814 /* Copy existing resource requirement list */
815 ResourceList
= ExAllocatePool(PagedPool
, DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
817 return STATUS_NO_MEMORY
;
821 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
,
822 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
823 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
826 return STATUS_SUCCESS
;
831 IN PDEVICE_OBJECT DeviceObject
,
833 IN PIO_STACK_LOCATION IrpSp
)
835 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
836 DEVICE_TEXT_TYPE DeviceTextType
;
837 NTSTATUS Status
= Irp
->IoStatus
.Status
;
839 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
840 DeviceTextType
= IrpSp
->Parameters
.QueryDeviceText
.DeviceTextType
;
842 switch (DeviceTextType
)
844 case DeviceTextDescription
:
846 UNICODE_STRING String
;
847 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
849 Status
= RtlDuplicateUnicodeString(
850 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
851 &DeviceExtension
->DeviceInfo
->DeviceDescription
,
853 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
857 case DeviceTextLocationInformation
:
859 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
860 Status
= STATUS_NOT_SUPPORTED
;
866 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown query id type 0x%lx\n", DeviceTextType
);
875 IN PDEVICE_OBJECT DeviceObject
,
877 IN PIO_STACK_LOCATION IrpSp
)
879 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
880 BUS_QUERY_ID_TYPE IdType
;
881 NTSTATUS Status
= Irp
->IoStatus
.Status
;
883 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
884 IdType
= IrpSp
->Parameters
.QueryId
.IdType
;
888 case BusQueryDeviceID
:
890 UNICODE_STRING String
;
891 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
893 Status
= RtlDuplicateUnicodeString(
894 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
895 &DeviceExtension
->DeviceInfo
->DeviceID
,
897 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
901 case BusQueryHardwareIDs
:
902 case BusQueryCompatibleIDs
:
904 /* Optional, do nothing */
908 case BusQueryInstanceID
:
910 UNICODE_STRING String
;
911 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
913 Status
= RtlDuplicateUnicodeString(
914 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
915 &DeviceExtension
->DeviceInfo
->InstanceID
,
917 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
923 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
931 PdoQueryBusInformation(
932 IN PDEVICE_OBJECT DeviceObject
,
934 IN PIO_STACK_LOCATION IrpSp
)
936 PPNP_BUS_INFORMATION BusInfo
;
939 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNP_BUS_INFORMATION
), TAG_PNP_ROOT
);
941 Status
= STATUS_NO_MEMORY
;
945 &BusInfo
->BusTypeGuid
,
946 &GUID_BUS_TYPE_INTERNAL
,
947 sizeof(BusInfo
->BusTypeGuid
));
948 BusInfo
->LegacyBusType
= PNPBus
;
949 /* We're the only root bus enumerator on the computer */
950 BusInfo
->BusNumber
= 0;
951 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInfo
;
952 Status
= STATUS_SUCCESS
;
959 * FUNCTION: Handle Plug and Play IRPs for the child device
961 * DeviceObject = Pointer to physical device object of the child device
962 * Irp = Pointer to IRP that should be handled
967 PnpRootPdoPnpControl(
968 IN PDEVICE_OBJECT DeviceObject
,
971 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
972 PIO_STACK_LOCATION IrpSp
;
975 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
976 Status
= Irp
->IoStatus
.Status
;
977 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
979 switch (IrpSp
->MinorFunction
)
981 case IRP_MN_START_DEVICE
: /* 0x00 */
982 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
983 Status
= STATUS_SUCCESS
;
986 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x07 */
987 Status
= PdoQueryDeviceRelations(DeviceObject
, Irp
, IrpSp
);
990 case IRP_MN_QUERY_CAPABILITIES
: /* 0x09 */
991 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
992 Status
= PdoQueryCapabilities(DeviceObject
, Irp
, IrpSp
);
995 case IRP_MN_QUERY_RESOURCES
: /* 0x0a */
996 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
997 Status
= PdoQueryResources(DeviceObject
, Irp
, IrpSp
);
1000 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
: /* 0x0b */
1001 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1002 Status
= PdoQueryResourceRequirements(DeviceObject
, Irp
, IrpSp
);
1005 case IRP_MN_QUERY_DEVICE_TEXT
: /* 0x0c */
1006 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1007 Status
= PdoQueryDeviceText(DeviceObject
, Irp
, IrpSp
);
1010 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0x0d */
1011 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1014 case IRP_MN_QUERY_ID
: /* 0x13 */
1015 Status
= PdoQueryId(DeviceObject
, Irp
, IrpSp
);
1018 case IRP_MN_QUERY_BUS_INFORMATION
: /* 0x15 */
1019 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
1020 Status
= PdoQueryBusInformation(DeviceObject
, Irp
, IrpSp
);
1024 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
1025 Status
= STATUS_NOT_IMPLEMENTED
;
1029 if (Status
!= STATUS_PENDING
)
1031 Irp
->IoStatus
.Status
= Status
;
1032 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1039 * FUNCTION: Handle Plug and Play IRPs
1041 * DeviceObject = Pointer to PDO or FDO
1042 * Irp = Pointer to IRP that should be handled
1046 static NTSTATUS NTAPI
1048 IN PDEVICE_OBJECT DeviceObject
,
1051 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension
;
1054 DeviceExtension
= (PPNPROOT_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1056 if (DeviceExtension
->IsFDO
)
1057 Status
= PnpRootFdoPnpControl(DeviceObject
, Irp
);
1059 Status
= PnpRootPdoPnpControl(DeviceObject
, Irp
);
1067 IN PDRIVER_OBJECT DriverObject
,
1068 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1070 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
1073 DPRINT("PnpRootAddDevice(DriverObject %p, Pdo %p)\n", DriverObject
, PhysicalDeviceObject
);
1075 if (!PhysicalDeviceObject
)
1077 DPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject
);
1078 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1079 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1082 Status
= IoCreateDevice(
1084 sizeof(PNPROOT_FDO_DEVICE_EXTENSION
),
1086 FILE_DEVICE_BUS_EXTENDER
,
1087 FILE_DEVICE_SECURE_OPEN
,
1089 &PnpRootDeviceObject
);
1090 if (!NT_SUCCESS(Status
))
1092 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
1093 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1095 DPRINT("Created FDO %p\n", PnpRootDeviceObject
);
1097 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)PnpRootDeviceObject
->DeviceExtension
;
1098 RtlZeroMemory(DeviceExtension
, sizeof(PNPROOT_FDO_DEVICE_EXTENSION
));
1100 DeviceExtension
->Common
.IsFDO
= TRUE
;
1101 DeviceExtension
->State
= dsStopped
;
1102 InitializeListHead(&DeviceExtension
->DeviceListHead
);
1103 DeviceExtension
->DeviceListCount
= 0;
1104 KeInitializeGuardedMutex(&DeviceExtension
->DeviceListLock
);
1106 Status
= IoAttachDeviceToDeviceStackSafe(
1107 PnpRootDeviceObject
,
1108 PhysicalDeviceObject
,
1109 &DeviceExtension
->Ldo
);
1110 if (!NT_SUCCESS(Status
))
1112 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
1113 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1116 PnpRootDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1118 DPRINT("Done AddDevice()\n");
1120 return STATUS_SUCCESS
;
1125 IN PDRIVER_OBJECT DriverObject
,
1126 IN PUNICODE_STRING RegistryPath
)
1128 DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject
, RegistryPath
);
1130 DriverObject
->DriverExtension
->AddDevice
= PnpRootAddDevice
;
1132 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = PnpRootPnpControl
;
1133 //DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl;
1135 return STATUS_SUCCESS
;