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 OUT PDEVICE_OBJECT
*PhysicalDeviceObject
,
135 OUT OPTIONAL PUNICODE_STRING FullInstancePath
)
137 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
138 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
139 WCHAR DevicePath
[MAX_PATH
+ 1];
140 WCHAR InstancePath
[5];
141 PPNPROOT_DEVICE Device
= NULL
;
144 UNICODE_STRING PathSep
= RTL_CONSTANT_STRING(L
"\\");
146 DeviceExtension
= PnpRootDeviceObject
->DeviceExtension
;
147 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
149 DPRINT("Creating a PnP root device for service '%wZ'\n", ServiceName
);
151 /* Search for a free instance ID */
152 _snwprintf(DevicePath
, sizeof(DevicePath
) / sizeof(WCHAR
), L
"%s\\%wZ", REGSTR_KEY_ROOTENUM
, ServiceName
);
153 for (i
= 0; i
< 9999; i
++)
155 _snwprintf(InstancePath
, sizeof(InstancePath
) / sizeof(WCHAR
), L
"%04lu", i
);
156 Status
= LocateChildDevice(DeviceExtension
, DevicePath
, InstancePath
, &Device
);
157 if (Status
== STATUS_NO_SUCH_DEVICE
)
162 DPRINT1("Too much legacy devices reported for service '%wZ'\n", ServiceName
);
163 Status
= STATUS_INSUFFICIENT_RESOURCES
;
167 /* Initialize a PNPROOT_DEVICE structure */
168 Device
= ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
171 DPRINT("ExAllocatePoolWithTag() failed\n");
172 Status
= STATUS_NO_MEMORY
;
175 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
176 if (!RtlCreateUnicodeString(&Device
->DeviceID
, DevicePath
))
178 Status
= STATUS_NO_MEMORY
;
181 if (!RtlCreateUnicodeString(&Device
->InstanceID
, InstancePath
))
183 Status
= STATUS_NO_MEMORY
;
187 if (FullInstancePath
)
189 FullInstancePath
->MaximumLength
= Device
->DeviceID
.Length
+ PathSep
.Length
+ Device
->InstanceID
.Length
;
190 FullInstancePath
->Length
= 0;
191 FullInstancePath
->Buffer
= ExAllocatePool(PagedPool
, FullInstancePath
->MaximumLength
);
192 if (!FullInstancePath
->Buffer
)
194 Status
= STATUS_NO_MEMORY
;
198 RtlAppendUnicodeStringToString(FullInstancePath
, &Device
->DeviceID
);
199 RtlAppendUnicodeStringToString(FullInstancePath
, &PathSep
);
200 RtlAppendUnicodeStringToString(FullInstancePath
, &Device
->InstanceID
);
203 /* Initialize a device object */
204 Status
= IoCreateDevice(
205 PnpRootDeviceObject
->DriverObject
,
206 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
208 FILE_DEVICE_CONTROLLER
,
209 FILE_AUTOGENERATED_DEVICE_NAME
,
212 if (!NT_SUCCESS(Status
))
214 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
215 Status
= STATUS_NO_MEMORY
;
219 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
220 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
221 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
222 PdoDeviceExtension
->DeviceInfo
= Device
;
224 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
225 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
228 &DeviceExtension
->DeviceListHead
,
230 DeviceExtension
->DeviceListCount
++;
232 *PhysicalDeviceObject
= Device
->Pdo
;
233 DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject
, &Device
->DeviceID
, &Device
->InstanceID
);
235 Status
= STATUS_SUCCESS
;
238 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
242 IoDeleteDevice(Device
->Pdo
);
243 RtlFreeUnicodeString(&Device
->DeviceID
);
244 RtlFreeUnicodeString(&Device
->InstanceID
);
245 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
250 static NTSTATUS NTAPI
255 IN ULONG ValueLength
,
257 IN PVOID EntryContext
)
259 PUNICODE_STRING Destination
= (PUNICODE_STRING
)EntryContext
;
260 UNICODE_STRING Source
;
262 if (ValueType
!= REG_SZ
|| ValueLength
== 0 || ValueLength
% sizeof(WCHAR
) != 0)
263 return STATUS_SUCCESS
;
265 Source
.MaximumLength
= Source
.Length
= ValueLength
;
266 Source
.Buffer
= ValueData
;
267 if (Source
.Length
> 0 && Source
.Buffer
[Source
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
268 Source
.Length
-= sizeof(WCHAR
);
269 return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &Source
, Destination
);
272 static NTSTATUS NTAPI
273 QueryBinaryValueCallback(
277 IN ULONG ValueLength
,
279 IN PVOID EntryContext
)
281 PBUFFER Buffer
= (PBUFFER
)EntryContext
;
284 if (ValueLength
== 0)
286 *Buffer
->Data
= NULL
;
287 return STATUS_SUCCESS
;
290 BinaryValue
= ExAllocatePoolWithTag(PagedPool
, ValueLength
, TAG_PNP_ROOT
);
291 if (BinaryValue
== NULL
)
292 return STATUS_NO_MEMORY
;
293 RtlCopyMemory(BinaryValue
, ValueData
, ValueLength
);
294 *Buffer
->Data
= BinaryValue
;
295 if (Buffer
->Length
) *Buffer
->Length
= ValueLength
;
296 return STATUS_SUCCESS
;
301 IN PDEVICE_OBJECT DeviceObject
)
303 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
304 PKEY_BASIC_INFORMATION KeyInfo
= NULL
, SubKeyInfo
= NULL
;
305 UNICODE_STRING LegacyU
= RTL_CONSTANT_STRING(L
"LEGACY_");
306 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L
"\\" REGSTR_KEY_ROOTENUM
);
307 UNICODE_STRING SubKeyName
;
308 WCHAR DevicePath
[MAX_PATH
+ 1];
309 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
310 PPNPROOT_DEVICE Device
= NULL
;
311 HANDLE KeyHandle
= INVALID_HANDLE_VALUE
;
312 HANDLE SubKeyHandle
= INVALID_HANDLE_VALUE
;
313 HANDLE DeviceKeyHandle
= INVALID_HANDLE_VALUE
;
316 ULONG Index1
, Index2
;
317 BUFFER Buffer1
, Buffer2
;
318 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
320 DPRINT("EnumerateDevices(FDO %p)\n", DeviceObject
);
322 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
323 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
325 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + (MAX_PATH
+ 1) * sizeof(WCHAR
);
326 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
329 DPRINT("ExAllocatePoolWithTag() failed\n");
330 Status
= STATUS_NO_MEMORY
;
333 SubKeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
336 DPRINT("ExAllocatePoolWithTag() failed\n");
337 Status
= STATUS_NO_MEMORY
;
341 Status
= IopOpenRegistryKeyEx(&KeyHandle
, NULL
, &KeyName
, KEY_ENUMERATE_SUB_KEYS
);
342 if (!NT_SUCCESS(Status
))
344 DPRINT("IopOpenRegistryKeyEx(%wZ) failed with status 0x%08lx\n", &KeyName
, Status
);
348 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
349 * KeyHandle. We'll first do a first enumeration to have first level keys,
350 * and an inner one to have the real devices list.
355 Status
= ZwEnumerateKey(
362 if (Status
== STATUS_NO_MORE_ENTRIES
)
364 Status
= STATUS_SUCCESS
;
367 else if (!NT_SUCCESS(Status
))
369 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
373 /* Terminate the string */
374 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
376 /* Check if it is a legacy driver */
377 RtlInitUnicodeString(&SubKeyName
, KeyInfo
->Name
);
378 if (RtlPrefixUnicodeString(&LegacyU
, &SubKeyName
, FALSE
))
380 DPRINT("Ignoring legacy driver '%wZ'\n", &SubKeyName
);
386 Status
= IopOpenRegistryKeyEx(&SubKeyHandle
, KeyHandle
, &SubKeyName
, KEY_ENUMERATE_SUB_KEYS
);
387 if (!NT_SUCCESS(Status
))
389 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status
);
393 /* Enumerate the sub-keys */
397 Status
= ZwEnumerateKey(
404 if (Status
== STATUS_NO_MORE_ENTRIES
)
406 else if (!NT_SUCCESS(Status
))
408 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
412 /* Terminate the string */
413 SubKeyInfo
->Name
[SubKeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
417 sizeof(DevicePath
) / sizeof(WCHAR
),
418 L
"%s\\%s", REGSTR_KEY_ROOTENUM
, KeyInfo
->Name
);
419 DPRINT("Found device %S\\%s!\n", DevicePath
, SubKeyInfo
->Name
);
420 if (LocateChildDevice(DeviceExtension
, DevicePath
, SubKeyInfo
->Name
, &Device
) == STATUS_NO_SUCH_DEVICE
)
422 /* Create a PPNPROOT_DEVICE object, and add if in the list of known devices */
423 Device
= (PPNPROOT_DEVICE
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
426 DPRINT("ExAllocatePoolWithTag() failed\n");
427 Status
= STATUS_NO_MEMORY
;
430 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
432 /* Fill device ID and instance ID */
433 if (!RtlCreateUnicodeString(&Device
->DeviceID
, DevicePath
))
435 DPRINT("RtlCreateUnicodeString() failed\n");
436 Status
= STATUS_NO_MEMORY
;
440 if (!RtlCreateUnicodeString(&Device
->InstanceID
, SubKeyInfo
->Name
))
442 DPRINT("RtlCreateUnicodeString() failed\n");
443 Status
= STATUS_NO_MEMORY
;
447 /* Open registry key to fill other informations */
448 Status
= IopOpenRegistryKeyEx(&DeviceKeyHandle
, SubKeyHandle
, &Device
->InstanceID
, KEY_READ
);
449 if (!NT_SUCCESS(Status
))
451 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status
);
455 /* Fill other informations */
456 Buffer1
.Data
= (PVOID
*)&Device
->ResourceRequirementsList
;
457 Buffer1
.Length
= NULL
;
458 Buffer2
.Data
= (PVOID
*)&Device
->ResourceList
;
459 Buffer2
.Length
= &Device
->ResourceListSize
;
460 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
461 QueryTable
[0].QueryRoutine
= QueryStringCallback
;
462 QueryTable
[0].Name
= L
"DeviceDesc";
463 QueryTable
[0].EntryContext
= &Device
->DeviceDescription
;
464 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_SUBKEY
;
465 QueryTable
[1].Name
= L
"LogConf";
466 QueryTable
[2].QueryRoutine
= QueryBinaryValueCallback
;
467 QueryTable
[2].Name
= L
"BasicConfigVector";
468 QueryTable
[2].EntryContext
= &Buffer1
;
469 QueryTable
[3].QueryRoutine
= QueryBinaryValueCallback
;
470 QueryTable
[3].Name
= L
"BootConfig";
471 QueryTable
[3].EntryContext
= &Buffer2
;
473 Status
= RtlQueryRegistryValues(
475 (PCWSTR
)DeviceKeyHandle
,
479 if (!NT_SUCCESS(Status
))
481 DPRINT("RtlQueryRegistryValues() failed with status 0x%08lx\n", Status
);
485 ZwClose(DeviceKeyHandle
);
486 DeviceKeyHandle
= INVALID_HANDLE_VALUE
;
488 /* Insert the newly created device into the list */
490 &DeviceExtension
->DeviceListHead
,
492 DeviceExtension
->DeviceListCount
++;
499 ZwClose(SubKeyHandle
);
500 SubKeyHandle
= INVALID_HANDLE_VALUE
;
507 /* We have a device that has not been added to device list. We need to clean it up */
509 ExFreePoolWithTag(Device
, TAG_PNP_ROOT
);
511 if (DeviceKeyHandle
!= INVALID_HANDLE_VALUE
)
512 ZwClose(DeviceKeyHandle
);
513 if (SubKeyHandle
!= INVALID_HANDLE_VALUE
)
514 ZwClose(SubKeyHandle
);
515 if (KeyHandle
!= INVALID_HANDLE_VALUE
)
518 ExFreePoolWithTag(KeyInfo
, TAG_PNP_ROOT
);
520 ExFreePoolWithTag(SubKeyInfo
, TAG_PNP_ROOT
);
521 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
525 /* FUNCTION: Handle IRP_MN_QUERY_DEVICE_RELATIONS IRPs for the root bus device object
527 * DeviceObject = Pointer to functional device object of the root bus driver
528 * Irp = Pointer to IRP that should be handled
533 PnpRootQueryDeviceRelations(
534 IN PDEVICE_OBJECT DeviceObject
,
537 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
538 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
539 PDEVICE_RELATIONS Relations
= NULL
, OtherRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
540 PPNPROOT_DEVICE Device
= NULL
;
543 PLIST_ENTRY NextEntry
;
545 DPRINT("PnpRootQueryDeviceRelations(FDO %p, Irp %p)\n", DeviceObject
, Irp
);
547 Status
= EnumerateDevices(DeviceObject
);
548 if (!NT_SUCCESS(Status
))
550 DPRINT("EnumerateDevices() failed with status 0x%08lx\n", Status
);
554 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
556 Size
= FIELD_OFFSET(DEVICE_RELATIONS
, Objects
) + sizeof(PDEVICE_OBJECT
) * DeviceExtension
->DeviceListCount
;
559 /* Another bus driver has already created a DEVICE_RELATIONS
560 * structure so we must merge this structure with our own */
562 Size
+= sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
;
564 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, Size
);
567 DPRINT("ExAllocatePoolWithTag() failed\n");
568 Status
= STATUS_NO_MEMORY
;
571 RtlZeroMemory(Relations
, Size
);
574 Relations
->Count
= OtherRelations
->Count
;
575 RtlCopyMemory(Relations
->Objects
, OtherRelations
->Objects
, sizeof(PDEVICE_OBJECT
) * OtherRelations
->Count
);
578 KeAcquireGuardedMutex(&DeviceExtension
->DeviceListLock
);
581 for (NextEntry
= DeviceExtension
->DeviceListHead
.Flink
;
582 NextEntry
!= &DeviceExtension
->DeviceListHead
;
583 NextEntry
= NextEntry
->Flink
)
586 Device
= CONTAINING_RECORD(NextEntry
, PNPROOT_DEVICE
, ListEntry
);
590 /* Create a physical device object for the
591 * device as it does not already have one */
592 Status
= IoCreateDevice(
593 DeviceObject
->DriverObject
,
594 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
596 FILE_DEVICE_CONTROLLER
,
597 FILE_AUTOGENERATED_DEVICE_NAME
,
600 if (!NT_SUCCESS(Status
))
602 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
606 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
607 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
608 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
609 PdoDeviceExtension
->DeviceInfo
= Device
;
611 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
612 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
615 /* Reference the physical device object. The PnP manager
616 will dereference it again when it is no longer needed */
617 ObReferenceObject(Device
->Pdo
);
619 Relations
->Objects
[Relations
->Count
++] = Device
->Pdo
;
621 KeReleaseGuardedMutex(&DeviceExtension
->DeviceListLock
);
623 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
626 if (!NT_SUCCESS(Status
))
629 ExFreePool(OtherRelations
);
631 ExFreePool(Relations
);
632 if (Device
&& Device
->Pdo
)
634 IoDeleteDevice(Device
->Pdo
);
643 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
645 * DeviceObject = Pointer to functional device object of the root bus driver
646 * Irp = Pointer to IRP that should be handled
651 PnpRootFdoPnpControl(
652 IN PDEVICE_OBJECT DeviceObject
,
655 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
656 PIO_STACK_LOCATION IrpSp
;
659 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
660 Status
= Irp
->IoStatus
.Status
;
661 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
663 switch (IrpSp
->MinorFunction
)
665 case IRP_MN_QUERY_DEVICE_RELATIONS
:
666 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n");
667 Status
= PnpRootQueryDeviceRelations(DeviceObject
, Irp
);
670 case IRP_MN_START_DEVICE
:
671 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
672 if (!IoForwardIrpSynchronously(DeviceExtension
->Ldo
, Irp
))
673 Status
= STATUS_UNSUCCESSFUL
;
676 Status
= Irp
->IoStatus
.Status
;
677 if (NT_SUCCESS(Status
))
678 DeviceExtension
->State
= dsStarted
;
682 case IRP_MN_STOP_DEVICE
:
683 DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
684 /* Root device cannot be stopped */
685 Status
= STATUS_NOT_SUPPORTED
;
689 DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
690 Status
= STATUS_NOT_IMPLEMENTED
;
694 if (Status
!= STATUS_PENDING
)
696 Irp
->IoStatus
.Status
= Status
;
697 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
704 PdoQueryDeviceRelations(
705 IN PDEVICE_OBJECT DeviceObject
,
707 IN PIO_STACK_LOCATION IrpSp
)
709 PDEVICE_RELATIONS Relations
;
710 DEVICE_RELATION_TYPE RelationType
;
711 NTSTATUS Status
= Irp
->IoStatus
.Status
;
713 RelationType
= IrpSp
->Parameters
.QueryDeviceRelations
.Type
;
715 switch (RelationType
)
720 if (IoGetAttachedDevice(DeviceObject
) != DeviceObject
)
722 /* We're not alone in the stack */
723 DPRINT1("PnP is misbehaving ; don't know how to handle IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
728 case TargetDeviceRelation
:
730 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
731 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, sizeof(DEVICE_RELATIONS
));
734 DPRINT("ExAllocatePoolWithTag() failed\n");
735 Status
= STATUS_NO_MEMORY
;
739 ObReferenceObject(DeviceObject
);
740 Relations
->Count
= 1;
741 Relations
->Objects
[0] = DeviceObject
;
742 Status
= STATUS_SUCCESS
;
743 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
750 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / unknown relation type 0x%lx\n", RelationType
);
758 PdoQueryCapabilities(
759 IN PDEVICE_OBJECT DeviceObject
,
761 IN PIO_STACK_LOCATION IrpSp
)
763 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
764 PDEVICE_CAPABILITIES DeviceCapabilities
;
766 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
767 DeviceCapabilities
= IrpSp
->Parameters
.DeviceCapabilities
.Capabilities
;
769 if (DeviceCapabilities
->Version
!= 1)
770 return STATUS_REVISION_MISMATCH
;
772 DeviceCapabilities
->UniqueID
= TRUE
;
773 /* FIXME: Fill other fields */
775 return STATUS_SUCCESS
;
780 IN PDEVICE_OBJECT DeviceObject
,
782 IN PIO_STACK_LOCATION IrpSp
)
784 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
785 PCM_RESOURCE_LIST ResourceList
;
787 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
789 if (DeviceExtension
->DeviceInfo
->ResourceList
== NULL
)
791 /* Create an empty resource list */
792 ResourceList
= ExAllocatePool(PagedPool
, sizeof(CM_RESOURCE_LIST
));
794 return STATUS_NO_MEMORY
;
796 ResourceList
->Count
= 0;
798 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
802 /* Copy existing resource requirement list */
803 ResourceList
= ExAllocatePool(
805 FIELD_OFFSET(CM_RESOURCE_LIST
, List
) + DeviceExtension
->DeviceInfo
->ResourceListSize
);
807 return STATUS_NO_MEMORY
;
809 ResourceList
->Count
= 1;
812 DeviceExtension
->DeviceInfo
->ResourceList
,
813 DeviceExtension
->DeviceInfo
->ResourceListSize
);
814 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
817 return STATUS_SUCCESS
;
821 PdoQueryResourceRequirements(
822 IN PDEVICE_OBJECT DeviceObject
,
824 IN PIO_STACK_LOCATION IrpSp
)
826 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
827 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList
;
828 ULONG ResourceListSize
= FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST
, List
);
830 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
832 if (DeviceExtension
->DeviceInfo
->ResourceRequirementsList
== NULL
)
834 /* Create an empty resource list */
835 ResourceList
= ExAllocatePool(PagedPool
, ResourceListSize
);
837 return STATUS_NO_MEMORY
;
839 RtlZeroMemory(ResourceList
, ResourceListSize
);
840 ResourceList
->ListSize
= ResourceListSize
;
842 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
846 /* Copy existing resource requirement list */
847 ResourceList
= ExAllocatePool(PagedPool
, DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
849 return STATUS_NO_MEMORY
;
853 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
,
854 DeviceExtension
->DeviceInfo
->ResourceRequirementsList
->ListSize
);
855 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
858 return STATUS_SUCCESS
;
863 IN PDEVICE_OBJECT DeviceObject
,
865 IN PIO_STACK_LOCATION IrpSp
)
867 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
868 DEVICE_TEXT_TYPE DeviceTextType
;
869 NTSTATUS Status
= Irp
->IoStatus
.Status
;
871 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
872 DeviceTextType
= IrpSp
->Parameters
.QueryDeviceText
.DeviceTextType
;
874 switch (DeviceTextType
)
876 case DeviceTextDescription
:
878 UNICODE_STRING String
;
879 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
881 Status
= RtlDuplicateUnicodeString(
882 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
883 &DeviceExtension
->DeviceInfo
->DeviceDescription
,
885 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
889 case DeviceTextLocationInformation
:
891 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n");
892 Status
= STATUS_NOT_SUPPORTED
;
898 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown query id type 0x%lx\n", DeviceTextType
);
907 IN PDEVICE_OBJECT DeviceObject
,
909 IN PIO_STACK_LOCATION IrpSp
)
911 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
912 BUS_QUERY_ID_TYPE IdType
;
913 NTSTATUS Status
= Irp
->IoStatus
.Status
;
915 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
916 IdType
= IrpSp
->Parameters
.QueryId
.IdType
;
920 case BusQueryDeviceID
:
922 UNICODE_STRING String
;
923 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
925 Status
= RtlDuplicateUnicodeString(
926 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
927 &DeviceExtension
->DeviceInfo
->DeviceID
,
929 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
933 case BusQueryHardwareIDs
:
934 case BusQueryCompatibleIDs
:
936 /* Optional, do nothing */
940 case BusQueryInstanceID
:
942 UNICODE_STRING String
;
943 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
945 Status
= RtlDuplicateUnicodeString(
946 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
947 &DeviceExtension
->DeviceInfo
->InstanceID
,
949 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
955 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType
);
963 PdoQueryBusInformation(
964 IN PDEVICE_OBJECT DeviceObject
,
966 IN PIO_STACK_LOCATION IrpSp
)
968 PPNP_BUS_INFORMATION BusInfo
;
971 BusInfo
= (PPNP_BUS_INFORMATION
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNP_BUS_INFORMATION
), TAG_PNP_ROOT
);
973 Status
= STATUS_NO_MEMORY
;
977 &BusInfo
->BusTypeGuid
,
978 &GUID_BUS_TYPE_INTERNAL
,
979 sizeof(BusInfo
->BusTypeGuid
));
980 BusInfo
->LegacyBusType
= PNPBus
;
981 /* We're the only root bus enumerator on the computer */
982 BusInfo
->BusNumber
= 0;
983 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInfo
;
984 Status
= STATUS_SUCCESS
;
991 * FUNCTION: Handle Plug and Play IRPs for the child device
993 * DeviceObject = Pointer to physical device object of the child device
994 * Irp = Pointer to IRP that should be handled
999 PnpRootPdoPnpControl(
1000 IN PDEVICE_OBJECT DeviceObject
,
1003 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
1004 PIO_STACK_LOCATION IrpSp
;
1007 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1008 Status
= Irp
->IoStatus
.Status
;
1009 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1011 switch (IrpSp
->MinorFunction
)
1013 case IRP_MN_START_DEVICE
: /* 0x00 */
1014 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
1015 Status
= STATUS_SUCCESS
;
1018 case IRP_MN_QUERY_DEVICE_RELATIONS
: /* 0x07 */
1019 Status
= PdoQueryDeviceRelations(DeviceObject
, Irp
, IrpSp
);
1022 case IRP_MN_QUERY_CAPABILITIES
: /* 0x09 */
1023 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
1024 Status
= PdoQueryCapabilities(DeviceObject
, Irp
, IrpSp
);
1027 case IRP_MN_QUERY_RESOURCES
: /* 0x0a */
1028 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
1029 Status
= PdoQueryResources(DeviceObject
, Irp
, IrpSp
);
1032 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
: /* 0x0b */
1033 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1034 Status
= PdoQueryResourceRequirements(DeviceObject
, Irp
, IrpSp
);
1037 case IRP_MN_QUERY_DEVICE_TEXT
: /* 0x0c */
1038 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1039 Status
= PdoQueryDeviceText(DeviceObject
, Irp
, IrpSp
);
1042 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS
: /* 0x0d */
1043 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1046 case IRP_MN_QUERY_ID
: /* 0x13 */
1047 Status
= PdoQueryId(DeviceObject
, Irp
, IrpSp
);
1050 case IRP_MN_QUERY_BUS_INFORMATION
: /* 0x15 */
1051 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
1052 Status
= PdoQueryBusInformation(DeviceObject
, Irp
, IrpSp
);
1056 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp
->MinorFunction
);
1057 Status
= STATUS_NOT_IMPLEMENTED
;
1061 if (Status
!= STATUS_PENDING
)
1063 Irp
->IoStatus
.Status
= Status
;
1064 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1071 * FUNCTION: Handle Plug and Play IRPs
1073 * DeviceObject = Pointer to PDO or FDO
1074 * Irp = Pointer to IRP that should be handled
1078 static NTSTATUS NTAPI
1080 IN PDEVICE_OBJECT DeviceObject
,
1083 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension
;
1086 DeviceExtension
= (PPNPROOT_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1088 if (DeviceExtension
->IsFDO
)
1089 Status
= PnpRootFdoPnpControl(DeviceObject
, Irp
);
1091 Status
= PnpRootPdoPnpControl(DeviceObject
, Irp
);
1099 IN PDRIVER_OBJECT DriverObject
,
1100 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1102 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
1105 DPRINT("PnpRootAddDevice(DriverObject %p, Pdo %p)\n", DriverObject
, PhysicalDeviceObject
);
1107 if (!PhysicalDeviceObject
)
1109 DPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject
);
1110 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1111 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1114 Status
= IoCreateDevice(
1116 sizeof(PNPROOT_FDO_DEVICE_EXTENSION
),
1118 FILE_DEVICE_BUS_EXTENDER
,
1119 FILE_DEVICE_SECURE_OPEN
,
1121 &PnpRootDeviceObject
);
1122 if (!NT_SUCCESS(Status
))
1124 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status
);
1125 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1127 DPRINT("Created FDO %p\n", PnpRootDeviceObject
);
1129 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)PnpRootDeviceObject
->DeviceExtension
;
1130 RtlZeroMemory(DeviceExtension
, sizeof(PNPROOT_FDO_DEVICE_EXTENSION
));
1132 DeviceExtension
->Common
.IsFDO
= TRUE
;
1133 DeviceExtension
->State
= dsStopped
;
1134 InitializeListHead(&DeviceExtension
->DeviceListHead
);
1135 DeviceExtension
->DeviceListCount
= 0;
1136 KeInitializeGuardedMutex(&DeviceExtension
->DeviceListLock
);
1138 Status
= IoAttachDeviceToDeviceStackSafe(
1139 PnpRootDeviceObject
,
1140 PhysicalDeviceObject
,
1141 &DeviceExtension
->Ldo
);
1142 if (!NT_SUCCESS(Status
))
1144 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status
);
1145 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1148 PnpRootDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1150 DPRINT("Done AddDevice()\n");
1152 return STATUS_SUCCESS
;
1157 IN PDRIVER_OBJECT DriverObject
,
1158 IN PUNICODE_STRING RegistryPath
)
1160 DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject
, RegistryPath
);
1162 DriverObject
->DriverExtension
->AddDevice
= PnpRootAddDevice
;
1164 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = PnpRootPnpControl
;
1165 //DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl;
1167 return STATUS_SUCCESS
;