2 * PROJECT: ReactOS Kernel
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnpmgr.c
5 * PURPOSE: Initializes the PnP manager
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Copyright 2007 Hervé Poussineau (hpoussin@reactos.org)
10 /* INCLUDES ******************************************************************/
18 /* GLOBALS *******************************************************************/
20 PDEVICE_NODE IopRootDeviceNode
;
21 KSPIN_LOCK IopDeviceTreeLock
;
22 ERESOURCE PpRegistryDeviceResource
;
23 KGUARDED_MUTEX PpDeviceReferenceTableLock
;
24 RTL_AVL_TABLE PpDeviceReferenceTable
;
26 extern ULONG ExpInitializationPhase
;
27 extern BOOLEAN PnpSystemInit
;
29 /* DATA **********************************************************************/
31 PDRIVER_OBJECT IopRootDriverObject
;
32 PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList
= NULL
;
34 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
36 PDEVICE_OBJECT DeviceObject
;
37 DEVICE_RELATION_TYPE Type
;
38 PIO_WORKITEM WorkItem
;
39 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
41 /* FUNCTIONS *****************************************************************/
44 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
45 IN ULONG CreateOptions
,
50 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
52 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
57 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
58 PDRIVER_OBJECT DriverObject
)
65 /* Special case for bus driven devices */
66 DeviceNode
->Flags
|= DNF_ADDED
;
67 return STATUS_SUCCESS
;
70 if (!DriverObject
->DriverExtension
->AddDevice
)
72 DeviceNode
->Flags
|= DNF_LEGACY_DRIVER
;
75 if (DeviceNode
->Flags
& DNF_LEGACY_DRIVER
)
77 DeviceNode
->Flags
|= DNF_ADDED
+ DNF_STARTED
;
78 return STATUS_SUCCESS
;
81 /* This is a Plug and Play driver */
82 DPRINT("Plug and Play driver found\n");
83 ASSERT(DeviceNode
->PhysicalDeviceObject
);
85 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
86 &DriverObject
->DriverName
,
87 &DeviceNode
->InstancePath
);
88 Status
= DriverObject
->DriverExtension
->AddDevice(
89 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
90 if (!NT_SUCCESS(Status
))
92 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
96 /* Check if driver added a FDO above the PDO */
97 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
98 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
100 /* FIXME: What do we do? Unload the driver or just disable the device? */
101 DPRINT1("An FDO was not attached\n");
102 ObDereferenceObject(Fdo
);
103 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
104 return STATUS_UNSUCCESSFUL
;
107 /* Check if we have a ACPI device (needed for power management) */
108 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
110 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
112 /* There can be only one system power device */
113 if (!SystemPowerDeviceNodeCreated
)
115 PopSystemPowerDeviceNode
= DeviceNode
;
116 ObReferenceObject(PopSystemPowerDeviceNode
);
117 SystemPowerDeviceNodeCreated
= TRUE
;
121 ObDereferenceObject(Fdo
);
123 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
125 return STATUS_SUCCESS
;
130 IopSendEject(IN PDEVICE_OBJECT DeviceObject
)
132 IO_STACK_LOCATION Stack
;
135 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
136 Stack
.MajorFunction
= IRP_MJ_PNP
;
137 Stack
.MinorFunction
= IRP_MN_EJECT
;
139 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
144 IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject
)
146 IO_STACK_LOCATION Stack
;
149 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
150 Stack
.MajorFunction
= IRP_MJ_PNP
;
151 Stack
.MinorFunction
= IRP_MN_SURPRISE_REMOVAL
;
153 /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
154 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
159 IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
161 IO_STACK_LOCATION Stack
;
165 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
166 Stack
.MajorFunction
= IRP_MJ_PNP
;
167 Stack
.MinorFunction
= IRP_MN_QUERY_REMOVE_DEVICE
;
169 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
171 IopNotifyPlugPlayNotification(DeviceObject
,
172 EventCategoryTargetDeviceChange
,
173 &GUID_TARGET_DEVICE_QUERY_REMOVE
,
182 IopQueryStopDevice(IN PDEVICE_OBJECT DeviceObject
)
184 IO_STACK_LOCATION Stack
;
187 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
188 Stack
.MajorFunction
= IRP_MJ_PNP
;
189 Stack
.MinorFunction
= IRP_MN_QUERY_STOP_DEVICE
;
191 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
196 IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
198 IO_STACK_LOCATION Stack
;
201 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
202 Stack
.MajorFunction
= IRP_MJ_PNP
;
203 Stack
.MinorFunction
= IRP_MN_REMOVE_DEVICE
;
205 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
206 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
208 IopNotifyPlugPlayNotification(DeviceObject
,
209 EventCategoryTargetDeviceChange
,
210 &GUID_TARGET_DEVICE_REMOVE_COMPLETE
,
217 IopSendStopDevice(IN PDEVICE_OBJECT DeviceObject
)
219 IO_STACK_LOCATION Stack
;
222 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
223 Stack
.MajorFunction
= IRP_MJ_PNP
;
224 Stack
.MinorFunction
= IRP_MN_STOP_DEVICE
;
226 /* Drivers should never fail a IRP_MN_STOP_DEVICE request */
227 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
232 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject
)
234 IO_STACK_LOCATION Stack
;
235 PDEVICE_NODE DeviceNode
;
238 DEVICE_CAPABILITIES DeviceCapabilities
;
240 /* Get the device node */
241 DeviceNode
= IopGetDeviceNode(DeviceObject
);
243 ASSERT(!(DeviceNode
->Flags
& DNF_DISABLED
));
245 /* Build the I/O stack locaiton */
246 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
247 Stack
.MajorFunction
= IRP_MJ_PNP
;
248 Stack
.MinorFunction
= IRP_MN_START_DEVICE
;
250 Stack
.Parameters
.StartDevice
.AllocatedResources
=
251 DeviceNode
->ResourceList
;
252 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
=
253 DeviceNode
->ResourceListTranslated
;
256 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
257 if (!NT_SUCCESS(Status
))
259 /* Send an IRP_MN_REMOVE_DEVICE request */
260 IopSendRemoveDevice(DeviceObject
);
262 /* Set the appropriate flag */
263 DeviceNode
->Flags
|= DNF_START_FAILED
;
265 DPRINT1("Warning: PnP Start failed (%wZ)\n", &DeviceNode
->InstancePath
);
269 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
271 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
272 if (!NT_SUCCESS(Status
))
274 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
277 /* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
278 IoInvalidateDeviceState(DeviceObject
);
280 /* Otherwise, mark us as started */
281 DeviceNode
->Flags
|= DNF_STARTED
;
282 DeviceNode
->Flags
&= ~DNF_STOPPED
;
284 /* We now need enumeration */
285 DeviceNode
->Flags
|= DNF_NEED_ENUMERATION_ONLY
;
290 IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode
)
292 PDEVICE_OBJECT DeviceObject
;
297 ASSERT((DeviceNode
->Flags
& DNF_ADDED
));
298 ASSERT((DeviceNode
->Flags
& (DNF_RESOURCE_ASSIGNED
|
299 DNF_RESOURCE_REPORTED
|
300 DNF_NO_RESOURCE_REQUIRED
)));
302 /* Get the device object */
303 DeviceObject
= DeviceNode
->PhysicalDeviceObject
;
305 /* Check if we're not started yet */
306 if (!(DeviceNode
->Flags
& DNF_STARTED
))
309 IopStartDevice2(DeviceObject
);
312 /* Do we need to query IDs? This happens in the case of manual reporting */
314 if (DeviceNode
->Flags
& DNF_NEED_QUERY_IDS
)
316 DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
317 /* And that case shouldn't happen yet */
322 /* Make sure we're started, and check if we need enumeration */
323 if ((DeviceNode
->Flags
& DNF_STARTED
) &&
324 (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
))
327 IoSynchronousInvalidateDeviceRelations(DeviceObject
, BusRelations
);
328 Status
= STATUS_SUCCESS
;
333 Status
= STATUS_SUCCESS
;
342 PDEVICE_NODE DeviceNode
)
346 DPRINT("Stopping device: %wZ\n", &DeviceNode
->InstancePath
);
348 Status
= IopQueryStopDevice(DeviceNode
->PhysicalDeviceObject
);
349 if (!NT_SUCCESS(Status
))
351 IopSendStopDevice(DeviceNode
->PhysicalDeviceObject
);
352 return STATUS_SUCCESS
;
360 PDEVICE_NODE DeviceNode
)
363 HANDLE InstanceHandle
= INVALID_HANDLE_VALUE
, ControlHandle
= INVALID_HANDLE_VALUE
;
364 UNICODE_STRING KeyName
;
365 OBJECT_ATTRIBUTES ObjectAttributes
;
367 if (DeviceNode
->Flags
& DNF_DISABLED
)
368 return STATUS_SUCCESS
;
370 Status
= IopAssignDeviceResources(DeviceNode
);
371 if (!NT_SUCCESS(Status
))
375 IopStartAndEnumerateDevice(DeviceNode
);
377 /* FIX: Should be done in new device instance code */
378 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceHandle
);
379 if (!NT_SUCCESS(Status
))
382 /* FIX: Should be done in IoXxxPrepareDriverLoading */
384 RtlInitUnicodeString(&KeyName
, L
"Control");
385 InitializeObjectAttributes(&ObjectAttributes
,
387 OBJ_CASE_INSENSITIVE
,
390 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
391 if (!NT_SUCCESS(Status
))
394 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
395 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
399 if (ControlHandle
!= INVALID_HANDLE_VALUE
)
400 ZwClose(ControlHandle
);
402 if (InstanceHandle
!= INVALID_HANDLE_VALUE
)
403 ZwClose(InstanceHandle
);
410 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
411 PDEVICE_CAPABILITIES DeviceCaps
)
413 IO_STATUS_BLOCK StatusBlock
;
414 IO_STACK_LOCATION Stack
;
417 UNICODE_STRING ValueName
;
419 /* Set up the Header */
420 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
421 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
422 DeviceCaps
->Version
= 1;
423 DeviceCaps
->Address
= -1;
424 DeviceCaps
->UINumber
= -1;
426 /* Set up the Stack */
427 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
428 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
431 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
433 IRP_MN_QUERY_CAPABILITIES
,
435 if (!NT_SUCCESS(Status
))
437 DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%x\n", Status
);
441 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCaps
->Version
+ sizeof(DeviceCaps
->Version
));
443 if (DeviceCaps
->NoDisplayInUI
)
444 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
446 DeviceNode
->UserFlags
&= DNUF_DONT_SHOW_IN_UI
;
448 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
449 if (NT_SUCCESS(Status
))
451 /* Set 'Capabilities' value */
452 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
453 Status
= ZwSetValueKey(InstanceKey
,
457 (PVOID
)&DeviceNode
->CapabilityFlags
,
460 /* Set 'UINumber' value */
461 if (DeviceCaps
->UINumber
!= MAXULONG
)
463 RtlInitUnicodeString(&ValueName
, L
"UINumber");
464 Status
= ZwSetValueKey(InstanceKey
,
468 &DeviceCaps
->UINumber
,
477 IopAsynchronousInvalidateDeviceRelations(
478 IN PDEVICE_OBJECT DeviceObject
,
479 IN PVOID InvalidateContext
)
481 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
483 IoSynchronousInvalidateDeviceRelations(
487 ObDereferenceObject(Data
->DeviceObject
);
488 IoFreeWorkItem(Data
->WorkItem
);
493 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
497 if (PopSystemPowerDeviceNode
)
499 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
500 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
501 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
503 return STATUS_SUCCESS
;
506 return STATUS_UNSUCCESSFUL
;
511 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
513 USHORT i
= 0, FoundIndex
= 0xFFFF;
517 /* Acquire the lock */
518 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
520 /* Loop all entries */
521 while (i
< PnpBusTypeGuidList
->GuidCount
)
523 /* Try to find a match */
524 if (RtlCompareMemory(BusTypeGuid
,
525 &PnpBusTypeGuidList
->Guids
[i
],
526 sizeof(GUID
)) == sizeof(GUID
))
535 /* Check if we have to grow the list */
536 if (PnpBusTypeGuidList
->GuidCount
)
538 /* Calculate the new size */
539 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
540 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
542 /* Allocate the new copy */
543 NewList
= ExAllocatePool(PagedPool
, NewSize
);
547 ExFreePool(PnpBusTypeGuidList
);
551 /* Now copy them, decrease the size too */
552 NewSize
-= sizeof(GUID
);
553 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
555 /* Free the old list */
556 ExFreePool(PnpBusTypeGuidList
);
558 /* Use the new buffer */
559 PnpBusTypeGuidList
= NewList
;
562 /* Copy the new GUID */
563 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
567 /* The new entry is the index */
568 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
569 PnpBusTypeGuidList
->GuidCount
++;
572 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
578 * Creates a device node
581 * ParentNode = Pointer to parent device node
582 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
583 * to have the root device node create one
584 * (eg. for legacy drivers)
585 * DeviceNode = Pointer to storage for created device node
591 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
592 PDEVICE_OBJECT PhysicalDeviceObject
,
593 PUNICODE_STRING ServiceName
,
594 PDEVICE_NODE
*DeviceNode
)
599 UNICODE_STRING FullServiceName
;
600 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
601 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
602 UNICODE_STRING KeyName
, ClassName
;
603 PUNICODE_STRING ServiceName1
;
606 UNICODE_STRING ClassGUID
;
608 HANDLE InstanceHandle
;
610 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
611 ParentNode
, PhysicalDeviceObject
, ServiceName
);
613 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
616 return STATUS_INSUFFICIENT_RESOURCES
;
619 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
622 ServiceName1
= &UnknownDeviceName
;
624 ServiceName1
= ServiceName
;
626 if (!PhysicalDeviceObject
)
628 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
629 FullServiceName
.Length
= 0;
630 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
631 if (!FullServiceName
.Buffer
)
634 return STATUS_INSUFFICIENT_RESOURCES
;
637 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
638 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
640 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
641 if (!NT_SUCCESS(Status
))
643 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
648 /* Create the device key for legacy drivers */
649 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
650 if (!NT_SUCCESS(Status
))
652 ZwClose(InstanceHandle
);
654 ExFreePool(FullServiceName
.Buffer
);
658 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
659 if (!Node
->ServiceName
.Buffer
)
661 ZwClose(InstanceHandle
);
663 ExFreePool(FullServiceName
.Buffer
);
667 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
668 Node
->ServiceName
.Length
= 0;
670 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
674 RtlInitUnicodeString(&KeyName
, L
"Service");
675 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
678 if (NT_SUCCESS(Status
))
680 RtlInitUnicodeString(&KeyName
, L
"Legacy");
683 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
684 if (NT_SUCCESS(Status
))
686 RtlInitUnicodeString(&KeyName
, L
"Class");
688 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
689 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
);
691 if (NT_SUCCESS(Status
))
693 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
695 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
696 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
);
702 ZwClose(InstanceHandle
);
703 ExFreePool(FullServiceName
.Buffer
);
705 if (!NT_SUCCESS(Status
))
711 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
712 IopDeviceNodeSetFlag(Node
, DNF_ADDED
);
713 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
716 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
718 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
722 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
723 Node
->Parent
= ParentNode
;
724 Node
->Sibling
= ParentNode
->Child
;
725 ParentNode
->Child
= Node
;
726 if (ParentNode
->LastChild
== NULL
)
727 ParentNode
->LastChild
= Node
;
728 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
729 Node
->Level
= ParentNode
->Level
+ 1;
732 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
736 return STATUS_SUCCESS
;
740 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
743 PDEVICE_NODE PrevSibling
= NULL
;
745 /* All children must be deleted before a parent is deleted */
746 ASSERT(!DeviceNode
->Child
);
748 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
750 ASSERT(DeviceNode
->PhysicalDeviceObject
);
752 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
754 /* Get previous sibling */
755 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
757 PrevSibling
= DeviceNode
->Parent
->Child
;
758 while (PrevSibling
->Sibling
!= DeviceNode
)
759 PrevSibling
= PrevSibling
->Sibling
;
762 /* Unlink from parent if it exists */
763 if (DeviceNode
->Parent
)
765 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
767 DeviceNode
->Parent
->LastChild
= PrevSibling
;
769 PrevSibling
->Sibling
= NULL
;
771 if (DeviceNode
->Parent
->Child
== DeviceNode
)
772 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
775 /* Unlink from sibling list */
777 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
779 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
781 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
783 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
785 if (DeviceNode
->ResourceList
)
787 ExFreePool(DeviceNode
->ResourceList
);
790 if (DeviceNode
->ResourceListTranslated
)
792 ExFreePool(DeviceNode
->ResourceListTranslated
);
795 if (DeviceNode
->ResourceRequirements
)
797 ExFreePool(DeviceNode
->ResourceRequirements
);
800 if (DeviceNode
->BootResources
)
802 ExFreePool(DeviceNode
->BootResources
);
805 ExFreePool(DeviceNode
);
807 return STATUS_SUCCESS
;
812 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
813 IN PIO_STACK_LOCATION IoStackLocation
,
814 OUT PVOID
*Information
)
817 PIO_STACK_LOCATION IrpStack
;
818 IO_STATUS_BLOCK IoStatusBlock
;
821 PDEVICE_OBJECT TopDeviceObject
;
824 /* Call the top of the device stack */
825 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
827 /* Allocate an IRP */
828 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
829 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
831 /* Initialize to failure */
832 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
833 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
835 /* Initialize the event */
836 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
839 Irp
->UserIosb
= &IoStatusBlock
;
840 Irp
->UserEvent
= &Event
;
843 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
844 IoQueueThreadIrp(Irp
);
846 /* Copy-in the stack */
847 IrpStack
= IoGetNextIrpStackLocation(Irp
);
848 *IrpStack
= *IoStackLocation
;
850 /* Call the driver */
851 Status
= IoCallDriver(TopDeviceObject
, Irp
);
852 if (Status
== STATUS_PENDING
)
855 KeWaitForSingleObject(&Event
,
860 Status
= IoStatusBlock
.Status
;
863 /* Return the information */
864 *Information
= (PVOID
)IoStatusBlock
.Information
;
870 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
871 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
872 IN ULONG MinorFunction
,
873 IN PIO_STACK_LOCATION Stack OPTIONAL
)
875 IO_STACK_LOCATION IoStackLocation
;
877 /* Fill out the stack information */
878 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
879 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
880 IoStackLocation
.MinorFunction
= MinorFunction
;
884 RtlCopyMemory(&IoStackLocation
.Parameters
,
886 sizeof(Stack
->Parameters
));
889 /* Do the PnP call */
890 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
892 (PVOID
)&IoStatusBlock
->Information
);
893 return IoStatusBlock
->Status
;
897 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
899 PDEVICE_NODE ParentDeviceNode
;
900 PDEVICE_NODE ChildDeviceNode
;
903 /* Copy context data so we don't overwrite it in subsequent calls to this function */
904 ParentDeviceNode
= Context
->DeviceNode
;
906 /* Call the action routine */
907 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
908 if (!NT_SUCCESS(Status
))
913 /* Traversal of all children nodes */
914 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
915 ChildDeviceNode
!= NULL
;
916 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
918 /* Pass the current device node to the action routine */
919 Context
->DeviceNode
= ChildDeviceNode
;
921 Status
= IopTraverseDeviceTreeNode(Context
);
922 if (!NT_SUCCESS(Status
))
933 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
937 DPRINT("Context 0x%p\n", Context
);
939 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
940 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
942 /* Start from the specified device node */
943 Context
->DeviceNode
= Context
->FirstDeviceNode
;
945 /* Recursively traverse the device tree */
946 Status
= IopTraverseDeviceTreeNode(Context
);
947 if (Status
== STATUS_UNSUCCESSFUL
)
949 /* The action routine just wanted to terminate the traversal with status
950 code STATUS_SUCCESS */
951 Status
= STATUS_SUCCESS
;
959 * IopCreateDeviceKeyPath
961 * Creates a registry key
965 * Name of the key to be created.
967 * Handle to the newly created key
970 * This method can create nested trees, so parent of RegistryPath can
971 * be not existant, and will be created if needed.
975 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
976 IN ULONG CreateOptions
,
979 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
980 HANDLE hParent
= NULL
, hKey
;
981 OBJECT_ATTRIBUTES ObjectAttributes
;
982 UNICODE_STRING KeyName
;
983 LPCWSTR Current
, Last
;
990 /* Open root key for device instances */
991 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
992 if (!NT_SUCCESS(Status
))
994 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
998 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
999 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
1001 /* Go up to the end of the string */
1002 while (Current
<= Last
)
1004 if (Current
!= Last
&& *Current
!= '\\')
1006 /* Not the end of the string and not a separator */
1011 /* Prepare relative key name */
1012 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
1013 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
1014 DPRINT("Create '%wZ'\n", &KeyName
);
1017 InitializeObjectAttributes(&ObjectAttributes
,
1019 OBJ_CASE_INSENSITIVE
,
1022 Status
= ZwCreateKey(&hKey
,
1023 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
1030 /* Close parent key handle, we don't need it anymore */
1034 /* Key opening/creating failed? */
1035 if (!NT_SUCCESS(Status
))
1037 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
1041 /* Check if it is the end of the string */
1042 if (Current
== Last
)
1044 /* Yes, return success */
1046 return STATUS_SUCCESS
;
1049 /* Start with this new parent key */
1052 KeyName
.Buffer
= (LPWSTR
)Current
;
1055 return STATUS_UNSUCCESSFUL
;
1059 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1060 PDEVICE_NODE DeviceNode
)
1062 OBJECT_ATTRIBUTES ObjectAttributes
;
1063 UNICODE_STRING KeyName
;
1068 HANDLE ControlHandle
;
1070 DPRINT("IopSetDeviceInstanceData() called\n");
1072 /* Create the 'LogConf' key */
1073 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1074 InitializeObjectAttributes(&ObjectAttributes
,
1076 OBJ_CASE_INSENSITIVE
,
1079 Status
= ZwCreateKey(&LogConfKey
,
1086 if (NT_SUCCESS(Status
))
1088 /* Set 'BootConfig' value */
1089 if (DeviceNode
->BootResources
!= NULL
)
1091 ResCount
= DeviceNode
->BootResources
->Count
;
1094 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1095 Status
= ZwSetValueKey(LogConfKey
,
1099 DeviceNode
->BootResources
,
1100 PnpDetermineResourceListSize(DeviceNode
->BootResources
));
1104 /* Set 'BasicConfigVector' value */
1105 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1106 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1108 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1109 Status
= ZwSetValueKey(LogConfKey
,
1112 REG_RESOURCE_REQUIREMENTS_LIST
,
1113 DeviceNode
->ResourceRequirements
,
1114 DeviceNode
->ResourceRequirements
->ListSize
);
1117 ZwClose(LogConfKey
);
1120 /* Set the 'ConfigFlags' value */
1121 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1122 Status
= ZwQueryValueKey(InstanceKey
,
1124 KeyValueBasicInformation
,
1128 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1130 /* Write the default value */
1131 ULONG DefaultConfigFlags
= 0;
1132 Status
= ZwSetValueKey(InstanceKey
,
1136 &DefaultConfigFlags
,
1137 sizeof(DefaultConfigFlags
));
1140 /* Create the 'Control' key */
1141 RtlInitUnicodeString(&KeyName
, L
"Control");
1142 InitializeObjectAttributes(&ObjectAttributes
,
1144 OBJ_CASE_INSENSITIVE
,
1147 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1149 if (NT_SUCCESS(Status
))
1150 ZwClose(ControlHandle
);
1152 DPRINT("IopSetDeviceInstanceData() done\n");
1158 * IopGetParentIdPrefix
1160 * Retrieve (or create) a string which identifies a device.
1164 * Pointer to device node.
1166 * Pointer to the string where is returned the parent node identifier
1169 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1170 * valid and its Buffer field is NULL-terminated. The caller needs to
1171 * to free the string with RtlFreeUnicodeString when it is no longer
1176 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1177 PUNICODE_STRING ParentIdPrefix
)
1179 ULONG KeyNameBufferLength
;
1180 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1181 UNICODE_STRING KeyName
;
1182 UNICODE_STRING KeyValue
;
1183 UNICODE_STRING ValueName
;
1188 /* HACK: As long as some devices have a NULL device
1189 * instance path, the following test is required :(
1191 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1193 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1194 &DeviceNode
->InstancePath
);
1195 return STATUS_UNSUCCESSFUL
;
1198 /* 1. Try to retrieve ParentIdPrefix from registry */
1199 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1200 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1201 if (!ParentIdPrefixInformation
)
1203 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1208 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1209 if (!KeyName
.Buffer
)
1211 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1215 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1217 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1218 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1220 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1221 if (!NT_SUCCESS(Status
))
1223 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1224 Status
= ZwQueryValueKey(
1226 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1227 KeyNameBufferLength
, &KeyNameBufferLength
);
1228 if (NT_SUCCESS(Status
))
1230 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1231 Status
= STATUS_UNSUCCESSFUL
;
1234 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1235 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1239 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1241 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1242 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1246 /* 2. Create the ParentIdPrefix value */
1247 crc32
= RtlComputeCrc32(0,
1248 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1249 DeviceNode
->Parent
->InstancePath
.Length
);
1251 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1252 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1254 /* 3. Try to write the ParentIdPrefix to registry */
1255 Status
= ZwSetValueKey(hKey
,
1259 (PVOID
)KeyValue
.Buffer
,
1260 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1263 if (NT_SUCCESS(Status
))
1265 /* Duplicate the string to return it */
1266 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1268 ExFreePool(ParentIdPrefixInformation
);
1269 RtlFreeUnicodeString(&KeyName
);
1277 * IopActionInterrogateDeviceStack
1279 * Retrieve information for all (direct) child nodes of a parent node.
1283 * Pointer to device node.
1285 * Pointer to parent node to retrieve child node information for.
1288 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1289 * when we reach a device node which is not a direct child of the device
1290 * node for which we retrieve information of child nodes for. Any errors
1291 * that occur is logged instead so that all child services have a chance
1292 * of being interrogated.
1296 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1299 IO_STATUS_BLOCK IoStatusBlock
;
1300 PDEVICE_NODE ParentDeviceNode
;
1301 WCHAR InstancePath
[MAX_PATH
];
1302 IO_STACK_LOCATION Stack
;
1307 ULONG RequiredLength
;
1309 HANDLE InstanceKey
= NULL
;
1310 UNICODE_STRING ValueName
;
1311 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1312 DEVICE_CAPABILITIES DeviceCapabilities
;
1314 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1315 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1317 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1320 * We are called for the parent too, but we don't need to do special
1321 * handling for this node
1324 if (DeviceNode
== ParentDeviceNode
)
1326 DPRINT("Success\n");
1327 return STATUS_SUCCESS
;
1331 * Make sure this device node is a direct child of the parent device node
1332 * that is given as an argument
1335 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1337 /* Stop the traversal immediately and indicate successful operation */
1339 return STATUS_UNSUCCESSFUL
;
1343 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1344 if (!NT_SUCCESS(Status
))
1346 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1351 * FIXME: For critical errors, cleanup and disable device, but always
1352 * return STATUS_SUCCESS.
1355 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1357 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1358 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1362 if (NT_SUCCESS(Status
))
1364 /* Copy the device id string */
1365 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1368 * FIXME: Check for valid characters, if there is invalid characters
1374 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1377 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
1379 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1380 if (!NT_SUCCESS(Status
))
1382 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1385 /* This bit is only check after enumeration */
1386 if (DeviceCapabilities
.HardwareDisabled
)
1388 /* FIXME: Cleanup device */
1389 DeviceNode
->Flags
|= DNF_DISABLED
;
1390 return STATUS_SUCCESS
;
1393 DeviceNode
->Flags
&= ~DNF_DISABLED
;
1395 if (!DeviceCapabilities
.UniqueID
)
1397 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1398 DPRINT("Instance ID is not unique\n");
1399 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1400 if (!NT_SUCCESS(Status
))
1402 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1406 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1408 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1409 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1413 if (NT_SUCCESS(Status
))
1415 /* Append the instance id string */
1416 wcscat(InstancePath
, L
"\\");
1417 if (ParentIdPrefix
.Length
> 0)
1419 /* Add information from parent bus device to InstancePath */
1420 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1421 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1422 wcscat(InstancePath
, L
"&");
1424 if (IoStatusBlock
.Information
)
1425 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1428 * FIXME: Check for valid characters, if there is invalid characters
1434 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1436 RtlFreeUnicodeString(&ParentIdPrefix
);
1438 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1440 DPRINT("No resources\n");
1441 /* FIXME: Cleanup and disable device */
1444 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1447 * Create registry key for the instance id, if it doesn't exist yet
1449 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
1450 if (!NT_SUCCESS(Status
))
1452 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1455 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1457 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1458 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1462 if (NT_SUCCESS(Status
))
1465 * FIXME: Check for valid characters, if there is invalid characters
1469 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1470 DPRINT("Hardware IDs:\n");
1473 DPRINT(" %S\n", Ptr
);
1474 Length
= wcslen(Ptr
) + 1;
1477 TotalLength
+= Length
;
1479 DPRINT("TotalLength: %hu\n", TotalLength
);
1482 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1483 Status
= ZwSetValueKey(InstanceKey
,
1487 (PVOID
)IoStatusBlock
.Information
,
1488 (TotalLength
+ 1) * sizeof(WCHAR
));
1489 if (!NT_SUCCESS(Status
))
1491 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1496 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1499 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1501 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1502 Status
= IopInitiatePnpIrp(
1503 DeviceNode
->PhysicalDeviceObject
,
1507 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1510 * FIXME: Check for valid characters, if there is invalid characters
1514 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1515 DPRINT("Compatible IDs:\n");
1518 DPRINT(" %S\n", Ptr
);
1519 Length
= wcslen(Ptr
) + 1;
1522 TotalLength
+= Length
;
1524 DPRINT("TotalLength: %hu\n", TotalLength
);
1527 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1528 Status
= ZwSetValueKey(InstanceKey
,
1532 (PVOID
)IoStatusBlock
.Information
,
1533 (TotalLength
+ 1) * sizeof(WCHAR
));
1534 if (!NT_SUCCESS(Status
))
1536 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1541 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1544 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1546 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1547 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1548 Status
= IopInitiatePnpIrp(
1549 DeviceNode
->PhysicalDeviceObject
,
1551 IRP_MN_QUERY_DEVICE_TEXT
,
1553 /* This key is mandatory, so even if the Irp fails, we still write it */
1554 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1555 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1557 if (NT_SUCCESS(Status
) &&
1558 IoStatusBlock
.Information
&&
1559 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1561 /* This key is overriden when a driver is installed. Don't write the
1562 * new description if another one already exists */
1563 Status
= ZwSetValueKey(InstanceKey
,
1567 (PVOID
)IoStatusBlock
.Information
,
1568 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1572 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1573 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1575 Status
= ZwSetValueKey(InstanceKey
,
1580 DeviceDesc
.MaximumLength
);
1582 if (!NT_SUCCESS(Status
))
1584 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1590 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1592 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1593 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1594 Status
= IopInitiatePnpIrp(
1595 DeviceNode
->PhysicalDeviceObject
,
1597 IRP_MN_QUERY_DEVICE_TEXT
,
1599 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1601 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1602 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1603 Status
= ZwSetValueKey(InstanceKey
,
1607 (PVOID
)IoStatusBlock
.Information
,
1608 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1609 if (!NT_SUCCESS(Status
))
1611 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1616 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1619 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1621 Status
= IopInitiatePnpIrp(
1622 DeviceNode
->PhysicalDeviceObject
,
1624 IRP_MN_QUERY_BUS_INFORMATION
,
1626 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1628 PPNP_BUS_INFORMATION BusInformation
=
1629 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1631 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1632 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1633 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1634 ExFreePool(BusInformation
);
1638 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1640 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1641 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1642 DeviceNode
->ChildBusTypeIndex
= -1;
1645 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1647 Status
= IopInitiatePnpIrp(
1648 DeviceNode
->PhysicalDeviceObject
,
1650 IRP_MN_QUERY_RESOURCES
,
1652 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1654 DeviceNode
->BootResources
=
1655 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1656 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
1660 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1661 DeviceNode
->BootResources
= NULL
;
1664 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1666 Status
= IopInitiatePnpIrp(
1667 DeviceNode
->PhysicalDeviceObject
,
1669 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1671 if (NT_SUCCESS(Status
))
1673 DeviceNode
->ResourceRequirements
=
1674 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1678 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1679 DeviceNode
->ResourceRequirements
= NULL
;
1682 if (InstanceKey
!= NULL
)
1684 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1687 ZwClose(InstanceKey
);
1689 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1691 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1693 /* Report the device to the user-mode pnp manager */
1694 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1695 &DeviceNode
->InstancePath
);
1698 return STATUS_SUCCESS
;
1703 IopHandleDeviceRemoval(
1704 IN PDEVICE_NODE DeviceNode
,
1705 IN PDEVICE_RELATIONS DeviceRelations
)
1707 PDEVICE_NODE Child
= DeviceNode
->Child
, NextChild
;
1711 while (Child
!= NULL
)
1713 NextChild
= Child
->Sibling
;
1716 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1718 if (IopGetDeviceNode(DeviceRelations
->Objects
[i
]) == Child
)
1727 IopSendSurpriseRemoval(Child
->PhysicalDeviceObject
);
1729 /* Tell the user-mode PnP manager that a device was removed */
1730 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
1731 &Child
->InstancePath
);
1733 IopSendRemoveDevice(Child
->PhysicalDeviceObject
);
1742 IN PDEVICE_OBJECT DeviceObject
)
1744 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1745 DEVICETREE_TRAVERSE_CONTEXT Context
;
1746 PDEVICE_RELATIONS DeviceRelations
;
1747 PDEVICE_OBJECT ChildDeviceObject
;
1748 IO_STATUS_BLOCK IoStatusBlock
;
1749 PDEVICE_NODE ChildDeviceNode
;
1750 IO_STACK_LOCATION Stack
;
1754 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1756 if (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
)
1758 DeviceNode
->Flags
&= ~DNF_NEED_ENUMERATION_ONLY
;
1760 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1761 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1762 &DeviceNode
->InstancePath
);
1765 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1767 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1769 Status
= IopInitiatePnpIrp(
1772 IRP_MN_QUERY_DEVICE_RELATIONS
,
1774 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1776 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1780 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1782 if (!DeviceRelations
)
1784 DPRINT("No PDOs\n");
1785 return STATUS_UNSUCCESSFUL
;
1788 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1791 * Send removal IRPs for devices that have disappeared
1793 IopHandleDeviceRemoval(DeviceNode
, DeviceRelations
);
1796 * Create device nodes for all discovered devices
1798 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1800 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1801 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1803 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1804 if (!ChildDeviceNode
)
1806 /* One doesn't exist, create it */
1807 Status
= IopCreateDeviceNode(
1812 if (NT_SUCCESS(Status
))
1814 /* Mark the node as enumerated */
1815 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1817 /* Mark the DO as bus enumerated */
1818 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1822 /* Ignore this DO */
1823 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1824 ObDereferenceObject(ChildDeviceNode
);
1829 /* Mark it as enumerated */
1830 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1831 ObDereferenceObject(ChildDeviceObject
);
1834 ExFreePool(DeviceRelations
);
1837 * Retrieve information about all discovered children from the bus driver
1839 IopInitDeviceTreeTraverseContext(
1842 IopActionInterrogateDeviceStack
,
1845 Status
= IopTraverseDeviceTree(&Context
);
1846 if (!NT_SUCCESS(Status
))
1848 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1853 * Retrieve configuration from the registry for discovered children
1855 IopInitDeviceTreeTraverseContext(
1858 IopActionConfigureChildServices
,
1861 Status
= IopTraverseDeviceTree(&Context
);
1862 if (!NT_SUCCESS(Status
))
1864 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1869 * Initialize services for discovered children.
1871 Status
= IopInitializePnpServices(DeviceNode
);
1872 if (!NT_SUCCESS(Status
))
1874 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1878 DPRINT("IopEnumerateDevice() finished\n");
1879 return STATUS_SUCCESS
;
1884 * IopActionConfigureChildServices
1886 * Retrieve configuration for all (direct) child nodes of a parent node.
1890 * Pointer to device node.
1892 * Pointer to parent node to retrieve child node configuration for.
1895 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1896 * when we reach a device node which is not a direct child of the device
1897 * node for which we configure child services for. Any errors that occur is
1898 * logged instead so that all child services have a chance of beeing
1903 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1906 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1907 PDEVICE_NODE ParentDeviceNode
;
1908 PUNICODE_STRING Service
;
1909 UNICODE_STRING ClassGUID
;
1911 DEVICE_CAPABILITIES DeviceCaps
;
1913 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1915 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1918 * We are called for the parent too, but we don't need to do special
1919 * handling for this node
1921 if (DeviceNode
== ParentDeviceNode
)
1923 DPRINT("Success\n");
1924 return STATUS_SUCCESS
;
1928 * Make sure this device node is a direct child of the parent device node
1929 * that is given as an argument
1931 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1933 /* Stop the traversal immediately and indicate successful operation */
1935 return STATUS_UNSUCCESSFUL
;
1938 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1940 WCHAR RegKeyBuffer
[MAX_PATH
];
1941 UNICODE_STRING RegKey
;
1944 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1945 RegKey
.Buffer
= RegKeyBuffer
;
1948 * Retrieve configuration from Enum key
1951 Service
= &DeviceNode
->ServiceName
;
1953 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1954 RtlInitUnicodeString(Service
, NULL
);
1955 RtlInitUnicodeString(&ClassGUID
, NULL
);
1957 QueryTable
[0].Name
= L
"Service";
1958 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1959 QueryTable
[0].EntryContext
= Service
;
1961 QueryTable
[1].Name
= L
"ClassGUID";
1962 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1963 QueryTable
[1].EntryContext
= &ClassGUID
;
1964 QueryTable
[1].DefaultType
= REG_SZ
;
1965 QueryTable
[1].DefaultData
= L
"";
1966 QueryTable
[1].DefaultLength
= 0;
1968 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1969 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1971 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1972 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1974 if (!NT_SUCCESS(Status
))
1976 /* FIXME: Log the error */
1977 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
1978 &DeviceNode
->InstancePath
, Status
);
1979 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1980 return STATUS_SUCCESS
;
1983 if (Service
->Buffer
== NULL
)
1985 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
1986 DeviceCaps
.RawDeviceOK
)
1988 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
1990 DeviceNode
->ServiceName
.Length
= 0;
1991 DeviceNode
->ServiceName
.MaximumLength
= 0;
1992 DeviceNode
->ServiceName
.Buffer
= NULL
;
1994 else if (ClassGUID
.Length
!= 0)
1996 /* Device has a ClassGUID value, but no Service value.
1997 * Suppose it is using the NULL driver, so state the
1998 * device is started */
1999 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2000 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2004 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2006 return STATUS_SUCCESS
;
2009 DPRINT("Got Service %S\n", Service
->Buffer
);
2012 return STATUS_SUCCESS
;
2016 * IopActionInitChildServices
2018 * Initialize the service for all (direct) child nodes of a parent node
2022 * Pointer to device node.
2024 * Pointer to parent node to initialize child node services for.
2027 * If the driver image for a service is not loaded and initialized
2028 * it is done here too. We only return a status code indicating an
2029 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2030 * not a direct child of the device node for which we initialize
2031 * child services for. Any errors that occur is logged instead so
2032 * that all child services have a chance of being initialized.
2036 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2039 PDEVICE_NODE ParentDeviceNode
;
2041 BOOLEAN BootDrivers
= !PnpSystemInit
;
2043 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2045 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2048 * We are called for the parent too, but we don't need to do special
2049 * handling for this node
2051 if (DeviceNode
== ParentDeviceNode
)
2053 DPRINT("Success\n");
2054 return STATUS_SUCCESS
;
2058 * Make sure this device node is a direct child of the parent device node
2059 * that is given as an argument
2062 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2065 * Stop the traversal immediately and indicate unsuccessful operation
2068 return STATUS_UNSUCCESSFUL
;
2071 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
2072 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
2073 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2074 return STATUS_SUCCESS
;
2076 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
2078 /* We don't need to worry about loading the driver because we're
2079 * being driven in raw mode so our parent must be loaded to get here */
2080 Status
= IopInitializeDevice(DeviceNode
, NULL
);
2081 if (NT_SUCCESS(Status
))
2083 Status
= IopStartDevice(DeviceNode
);
2084 if (!NT_SUCCESS(Status
))
2086 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
2087 &DeviceNode
->InstancePath
, Status
);
2093 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2094 PDRIVER_OBJECT DriverObject
;
2096 /* Get existing DriverObject pointer (in case the driver has
2097 already been loaded and initialized) */
2098 Status
= IopGetDriverObject(
2100 &DeviceNode
->ServiceName
,
2103 if (!NT_SUCCESS(Status
))
2105 /* Driver is not initialized, try to load it */
2106 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2108 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2110 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2111 was loaded by the bootloader */
2112 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2113 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2115 /* Initialize the driver */
2116 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2117 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2121 Status
= STATUS_SUCCESS
;
2126 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2127 &DeviceNode
->ServiceName
, Status
);
2131 /* Driver is loaded and initialized at this point */
2132 if (NT_SUCCESS(Status
))
2134 /* Initialize the device, including all filters */
2135 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
2140 * Don't disable when trying to load only boot drivers
2144 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2145 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2146 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2147 DPRINT1("Initialization of service %S failed (Status %x)\n",
2148 DeviceNode
->ServiceName
.Buffer
, Status
);
2153 return STATUS_SUCCESS
;
2157 * IopInitializePnpServices
2159 * Initialize services for discovered children
2163 * Top device node to start initializing services.
2169 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2171 DEVICETREE_TRAVERSE_CONTEXT Context
;
2173 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2175 IopInitDeviceTreeTraverseContext(
2178 IopActionInitChildServices
,
2181 return IopTraverseDeviceTree(&Context
);
2184 static NTSTATUS INIT_FUNCTION
2185 IopEnumerateDetectedDevices(
2187 IN PUNICODE_STRING RelativePath OPTIONAL
,
2189 IN BOOLEAN EnumerateSubKeys
,
2190 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2191 IN ULONG ParentBootResourcesLength
)
2193 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2194 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2195 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2196 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2197 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2198 OBJECT_ATTRIBUTES ObjectAttributes
;
2199 HANDLE hDevicesKey
= NULL
;
2200 HANDLE hDeviceKey
= NULL
;
2201 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2202 UNICODE_STRING Level2NameU
;
2203 WCHAR Level2Name
[5];
2204 ULONG IndexDevice
= 0;
2206 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2207 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2208 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2209 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2210 UNICODE_STRING DeviceName
, ValueName
;
2212 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2213 ULONG BootResourcesLength
;
2216 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2217 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2218 static ULONG DeviceIndexPci
= 0;
2219 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2220 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2221 static ULONG DeviceIndexSerial
= 0;
2222 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2223 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2224 static ULONG DeviceIndexKeyboard
= 0;
2225 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2226 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2227 static ULONG DeviceIndexMouse
= 0;
2228 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2229 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2230 static ULONG DeviceIndexParallel
= 0;
2231 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2232 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2233 static ULONG DeviceIndexFloppy
= 0;
2234 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2235 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2236 static ULONG DeviceIndexIsa
= 0;
2237 UNICODE_STRING HardwareIdKey
;
2238 PUNICODE_STRING pHardwareId
;
2239 ULONG DeviceIndex
= 0;
2240 PUCHAR CmResourceList
;
2245 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2246 if (!NT_SUCCESS(Status
))
2248 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2253 hDevicesKey
= hBaseKey
;
2255 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2256 if (!pDeviceInformation
)
2258 DPRINT("ExAllocatePool() failed\n");
2259 Status
= STATUS_NO_MEMORY
;
2263 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2264 if (!pValueInformation
)
2266 DPRINT("ExAllocatePool() failed\n");
2267 Status
= STATUS_NO_MEMORY
;
2273 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2274 if (Status
== STATUS_NO_MORE_ENTRIES
)
2276 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2278 ExFreePool(pDeviceInformation
);
2279 DeviceInfoLength
= RequiredSize
;
2280 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2281 if (!pDeviceInformation
)
2283 DPRINT("ExAllocatePool() failed\n");
2284 Status
= STATUS_NO_MEMORY
;
2287 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2289 if (!NT_SUCCESS(Status
))
2291 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2296 /* Open device key */
2297 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2298 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2300 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2301 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2302 if (!NT_SUCCESS(Status
))
2304 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2308 /* Read boot resources, and add then to parent ones */
2309 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2310 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2312 ExFreePool(pValueInformation
);
2313 ValueInfoLength
= RequiredSize
;
2314 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2315 if (!pValueInformation
)
2317 DPRINT("ExAllocatePool() failed\n");
2318 ZwDeleteKey(hLevel2Key
);
2319 Status
= STATUS_NO_MEMORY
;
2322 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2324 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2326 BootResources
= ParentBootResources
;
2327 BootResourcesLength
= ParentBootResourcesLength
;
2329 else if (!NT_SUCCESS(Status
))
2331 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2334 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2336 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2341 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2343 /* Concatenate current resources and parent ones */
2344 if (ParentBootResourcesLength
== 0)
2345 BootResourcesLength
= pValueInformation
->DataLength
;
2347 BootResourcesLength
= ParentBootResourcesLength
2348 + pValueInformation
->DataLength
2350 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2353 DPRINT("ExAllocatePool() failed\n");
2356 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2358 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2360 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2362 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2364 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2365 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2366 ParentBootResourcesLength
- Header
);
2367 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2371 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2373 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2374 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2375 ParentBootResourcesLength
- Header
);
2377 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2378 pValueInformation
->Data
+ Header
,
2379 pValueInformation
->DataLength
- Header
);
2380 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2384 if (EnumerateSubKeys
)
2389 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2390 if (Status
== STATUS_NO_MORE_ENTRIES
)
2392 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2394 ExFreePool(pDeviceInformation
);
2395 DeviceInfoLength
= RequiredSize
;
2396 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2397 if (!pDeviceInformation
)
2399 DPRINT("ExAllocatePool() failed\n");
2400 Status
= STATUS_NO_MEMORY
;
2403 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2405 if (!NT_SUCCESS(Status
))
2407 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2411 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2412 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2414 Status
= IopEnumerateDetectedDevices(
2420 BootResourcesLength
);
2421 if (!NT_SUCCESS(Status
))
2426 /* Read identifier */
2427 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2428 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2430 ExFreePool(pValueInformation
);
2431 ValueInfoLength
= RequiredSize
;
2432 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2433 if (!pValueInformation
)
2435 DPRINT("ExAllocatePool() failed\n");
2436 Status
= STATUS_NO_MEMORY
;
2439 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2441 if (!NT_SUCCESS(Status
))
2443 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2445 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2448 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2450 else if (pValueInformation
->Type
!= REG_SZ
)
2452 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2457 /* Assign hardware id to this device */
2458 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2459 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2460 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2461 ValueName
.Length
-= sizeof(WCHAR
);
2464 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2466 pHardwareId
= &HardwareIdSerial
;
2467 DeviceIndex
= DeviceIndexSerial
++;
2469 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2471 pHardwareId
= &HardwareIdKeyboard
;
2472 DeviceIndex
= DeviceIndexKeyboard
++;
2474 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2476 pHardwareId
= &HardwareIdMouse
;
2477 DeviceIndex
= DeviceIndexMouse
++;
2479 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
2481 pHardwareId
= &HardwareIdParallel
;
2482 DeviceIndex
= DeviceIndexParallel
++;
2484 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
2486 pHardwareId
= &HardwareIdFloppy
;
2487 DeviceIndex
= DeviceIndexFloppy
++;
2489 else if (NT_SUCCESS(Status
))
2491 /* Try to also match the device identifier */
2492 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2494 pHardwareId
= &HardwareIdPci
;
2495 DeviceIndex
= DeviceIndexPci
++;
2497 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
2499 pHardwareId
= &HardwareIdIsa
;
2500 DeviceIndex
= DeviceIndexIsa
++;
2504 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2510 /* Unknown key path */
2511 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2515 /* Prepare hardware id key (hardware id value without final \0) */
2516 HardwareIdKey
= *pHardwareId
;
2517 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2519 /* Add the detected device to Root key */
2520 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2521 Status
= ZwCreateKey(
2527 REG_OPTION_NON_VOLATILE
,
2529 if (!NT_SUCCESS(Status
))
2531 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2534 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2535 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2536 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2537 Status
= ZwCreateKey(
2539 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2543 REG_OPTION_NON_VOLATILE
,
2545 ZwClose(hLevel1Key
);
2546 if (!NT_SUCCESS(Status
))
2548 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2551 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
2552 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2553 if (!NT_SUCCESS(Status
))
2555 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2556 ZwDeleteKey(hLevel2Key
);
2559 /* Create 'LogConf' subkey */
2560 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2561 Status
= ZwCreateKey(
2567 REG_OPTION_VOLATILE
,
2569 if (!NT_SUCCESS(Status
))
2571 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2572 ZwDeleteKey(hLevel2Key
);
2575 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2577 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
2578 if (!CmResourceList
)
2581 ZwDeleteKey(hLevel2Key
);
2585 /* Add the list count (1st member of CM_RESOURCE_LIST) */
2587 RtlCopyMemory(CmResourceList
,
2591 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
2592 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
2594 BootResourcesLength
);
2596 /* Save boot resources to 'LogConf\BootConfig' */
2597 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
2598 if (!NT_SUCCESS(Status
))
2600 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2602 ZwDeleteKey(hLevel2Key
);
2609 if (BootResources
&& BootResources
!= ParentBootResources
)
2611 ExFreePool(BootResources
);
2612 BootResources
= NULL
;
2616 ZwClose(hLevel2Key
);
2621 ZwClose(hDeviceKey
);
2626 Status
= STATUS_SUCCESS
;
2629 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2630 ZwClose(hDevicesKey
);
2632 ZwClose(hDeviceKey
);
2633 if (pDeviceInformation
)
2634 ExFreePool(pDeviceInformation
);
2635 if (pValueInformation
)
2636 ExFreePool(pValueInformation
);
2640 static BOOLEAN INIT_FUNCTION
2641 IopIsAcpiComputer(VOID
)
2646 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2647 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2648 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2649 OBJECT_ATTRIBUTES ObjectAttributes
;
2650 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2651 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2652 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2653 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2655 ULONG IndexDevice
= 0;
2656 UNICODE_STRING DeviceName
, ValueName
;
2657 HANDLE hDevicesKey
= NULL
;
2658 HANDLE hDeviceKey
= NULL
;
2660 BOOLEAN ret
= FALSE
;
2662 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2663 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2664 if (!NT_SUCCESS(Status
))
2666 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2670 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2671 if (!pDeviceInformation
)
2673 DPRINT("ExAllocatePool() failed\n");
2674 Status
= STATUS_NO_MEMORY
;
2678 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2679 if (!pDeviceInformation
)
2681 DPRINT("ExAllocatePool() failed\n");
2682 Status
= STATUS_NO_MEMORY
;
2688 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2689 if (Status
== STATUS_NO_MORE_ENTRIES
)
2691 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2693 ExFreePool(pDeviceInformation
);
2694 DeviceInfoLength
= RequiredSize
;
2695 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2696 if (!pDeviceInformation
)
2698 DPRINT("ExAllocatePool() failed\n");
2699 Status
= STATUS_NO_MEMORY
;
2702 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2704 if (!NT_SUCCESS(Status
))
2706 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2711 /* Open device key */
2712 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2713 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2714 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2719 if (!NT_SUCCESS(Status
))
2721 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2725 /* Read identifier */
2726 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2727 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2729 ExFreePool(pValueInformation
);
2730 ValueInfoLength
= RequiredSize
;
2731 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2732 if (!pValueInformation
)
2734 DPRINT("ExAllocatePool() failed\n");
2735 Status
= STATUS_NO_MEMORY
;
2738 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2740 if (!NT_SUCCESS(Status
))
2742 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2745 else if (pValueInformation
->Type
!= REG_SZ
)
2747 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2751 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2752 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2753 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2754 ValueName
.Length
-= sizeof(WCHAR
);
2755 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
2757 DPRINT("Found ACPI BIOS\n");
2763 ZwClose(hDeviceKey
);
2768 if (pDeviceInformation
)
2769 ExFreePool(pDeviceInformation
);
2770 if (pValueInformation
)
2771 ExFreePool(pValueInformation
);
2773 ZwClose(hDevicesKey
);
2775 ZwClose(hDeviceKey
);
2783 IopUpdateRootKey(VOID
)
2785 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2786 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2787 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2788 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2789 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2790 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2791 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
2792 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
2793 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
2794 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2795 OBJECT_ATTRIBUTES ObjectAttributes
;
2796 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
2800 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2801 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2802 if (!NT_SUCCESS(Status
))
2804 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2808 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2809 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2811 if (!NT_SUCCESS(Status
))
2813 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2817 if (IopIsAcpiComputer())
2819 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
2820 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2822 if (!NT_SUCCESS(Status
))
2824 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
2825 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, 0, &Disposition
);
2826 ZwClose(hHalAcpiDevice
);
2827 if (!NT_SUCCESS(Status
))
2829 if (Disposition
== REG_CREATED_NEW_KEY
)
2831 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
2832 if (NT_SUCCESS(Status
))
2833 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
2835 if (NT_SUCCESS(Status
))
2837 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
2838 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2839 if (NT_SUCCESS(Status
))
2842 ZwClose(hHalAcpiId
);
2847 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2848 if (!NT_SUCCESS(Status
))
2850 /* Nothing to do, don't return with an error status */
2851 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2853 return STATUS_SUCCESS
;
2855 Status
= IopEnumerateDetectedDevices(
2870 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2872 PUNICODE_STRING Name
,
2873 ACCESS_MASK DesiredAccess
)
2875 OBJECT_ATTRIBUTES ObjectAttributes
;
2882 InitializeObjectAttributes(&ObjectAttributes
,
2884 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2888 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2895 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
2896 IN HANDLE RootHandle OPTIONAL
,
2897 IN PUNICODE_STRING KeyName
,
2898 IN ACCESS_MASK DesiredAccess
,
2899 IN ULONG CreateOptions
,
2900 OUT PULONG Disposition OPTIONAL
)
2902 OBJECT_ATTRIBUTES ObjectAttributes
;
2903 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0, Length
;
2904 HANDLE HandleArray
[2];
2905 BOOLEAN Recursing
= TRUE
;
2907 UNICODE_STRING KeyString
;
2908 NTSTATUS Status
= STATUS_SUCCESS
;
2911 /* P1 is start, pp is end */
2912 p1
= KeyName
->Buffer
;
2913 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
2915 /* Create the target key */
2916 InitializeObjectAttributes(&ObjectAttributes
,
2918 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2921 Status
= ZwCreateKey(&HandleArray
[i
],
2929 /* Now we check if this failed */
2930 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
2932 /* Target key failed, so we'll need to create its parent. Setup array */
2933 HandleArray
[0] = NULL
;
2934 HandleArray
[1] = RootHandle
;
2936 /* Keep recursing for each missing parent */
2939 /* And if we're deep enough, close the last handle */
2940 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2942 /* We're setup to ping-pong between the two handle array entries */
2943 RootHandleIndex
= i
;
2946 /* Clear the one we're attempting to open now */
2947 HandleArray
[i
] = NULL
;
2949 /* Process the parent key name */
2950 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
2951 Length
= (p
- p1
) * sizeof(WCHAR
);
2953 /* Is there a parent name? */
2956 /* Build the unicode string for it */
2957 KeyString
.Buffer
= p1
;
2958 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
2960 /* Now try opening the parent */
2961 InitializeObjectAttributes(&ObjectAttributes
,
2963 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2964 HandleArray
[RootHandleIndex
],
2966 Status
= ZwCreateKey(&HandleArray
[i
],
2973 if (NT_SUCCESS(Status
))
2975 /* It worked, we have one more handle */
2980 /* Parent key creation failed, abandon loop */
2987 /* We don't have a parent name, probably corrupted key name */
2988 Status
= STATUS_INVALID_PARAMETER
;
2993 /* Now see if there's more parents to create */
2995 if ((p
== pp
) || (p1
== pp
))
2997 /* We're done, hopefully successfully, so stop */
3002 /* Outer loop check for handle nesting that requires closing the top handle */
3003 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3006 /* Check if we broke out of the loop due to success */
3007 if (NT_SUCCESS(Status
))
3009 /* Return the target handle (we closed all the parent ones) and disposition */
3010 *Handle
= HandleArray
[i
];
3011 if (Disposition
) *Disposition
= KeyDisposition
;
3014 /* Return the success state */
3020 IopGetRegistryValue(IN HANDLE Handle
,
3022 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
3024 UNICODE_STRING ValueString
;
3026 PKEY_VALUE_FULL_INFORMATION FullInformation
;
3030 RtlInitUnicodeString(&ValueString
, ValueName
);
3032 Status
= ZwQueryValueKey(Handle
,
3034 KeyValueFullInformation
,
3038 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
3039 (Status
!= STATUS_BUFFER_TOO_SMALL
))
3044 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
3045 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
3047 Status
= ZwQueryValueKey(Handle
,
3049 KeyValueFullInformation
,
3053 if (!NT_SUCCESS(Status
))
3055 ExFreePool(FullInformation
);
3059 *Information
= FullInformation
;
3060 return STATUS_SUCCESS
;
3063 RTL_GENERIC_COMPARE_RESULTS
3065 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3066 IN PVOID FirstStruct
,
3067 IN PVOID SecondStruct
)
3075 // The allocation function is called by the generic table package whenever
3076 // it needs to allocate memory for the table.
3081 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3091 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3100 PpInitializeDeviceReferenceTable(VOID
)
3102 /* Setup the guarded mutex and AVL table */
3103 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3104 RtlInitializeGenericTableAvl(
3105 &PpDeviceReferenceTable
,
3106 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3107 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3108 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3116 /* Initialize the resource when accessing device registry data */
3117 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3119 /* Setup the device reference AVL table */
3120 PpInitializeDeviceReferenceTable();
3128 /* Check the initialization phase */
3129 switch (ExpInitializationPhase
)
3134 return PiInitPhase0();
3140 //return PiInitPhase1();
3144 /* Don't know any other phase! Bugcheck! */
3145 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3150 LONG IopNumberDeviceNodes
;
3154 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3156 PDEVICE_NODE DeviceNode
;
3160 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), 'donD');
3161 if (!DeviceNode
) return DeviceNode
;
3164 InterlockedIncrement(&IopNumberDeviceNodes
);
3167 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
3168 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
3169 DeviceNode
->BusNumber
= -1;
3170 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
3171 DeviceNode
->ChildBusNumber
= -1;
3172 DeviceNode
->ChildBusTypeIndex
= -1;
3173 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
3174 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
3175 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
3176 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
3177 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
3178 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
3180 /* Check if there is a PDO */
3181 if (PhysicalDeviceObject
)
3183 /* Link it and remove the init flag */
3184 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
3185 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
3186 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3189 /* Return the node */
3193 /* PUBLIC FUNCTIONS **********************************************************/
3197 PnpBusTypeGuidGet(IN USHORT Index
,
3198 IN LPGUID BusTypeGuid
)
3200 NTSTATUS Status
= STATUS_SUCCESS
;
3202 /* Acquire the lock */
3203 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
3206 if (Index
< PnpBusTypeGuidList
->GuidCount
)
3209 RtlCopyMemory(BusTypeGuid
, &PnpBusTypeGuidList
->Guids
[Index
], sizeof(GUID
));
3214 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
3217 /* Release lock and return status */
3218 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
3224 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject
,
3225 IN PHANDLE DeviceInstanceHandle
,
3226 IN ACCESS_MASK DesiredAccess
)
3230 PDEVICE_NODE DeviceNode
;
3231 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
3234 /* Open the enum key */
3235 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
3239 if (!NT_SUCCESS(Status
)) return Status
;
3241 /* Make sure we have an instance path */
3242 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3243 if ((DeviceNode
) && (DeviceNode
->InstancePath
.Length
))
3245 /* Get the instance key */
3246 Status
= IopOpenRegistryKeyEx(DeviceInstanceHandle
,
3248 &DeviceNode
->InstancePath
,
3254 Status
= STATUS_INVALID_DEVICE_REQUEST
;
3257 /* Close the handle and return status */
3264 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList
)
3266 ULONG FinalSize
, PartialSize
, EntrySize
, i
, j
;
3267 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
3268 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
3270 /* If we don't have one, that's easy */
3271 if (!ResourceList
) return 0;
3273 /* Start with the minimum size possible */
3274 FinalSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
3276 /* Loop each full descriptor */
3277 FullDescriptor
= ResourceList
->List
;
3278 for (i
= 0; i
< ResourceList
->Count
; i
++)
3280 /* Start with the minimum size possible */
3281 PartialSize
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
) +
3282 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
);
3284 /* Loop each partial descriptor */
3285 PartialDescriptor
= FullDescriptor
->PartialResourceList
.PartialDescriptors
;
3286 for (j
= 0; j
< FullDescriptor
->PartialResourceList
.Count
; j
++)
3288 /* Start with the minimum size possible */
3289 EntrySize
= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
3291 /* Check if there is extra data */
3292 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
3295 EntrySize
+= PartialDescriptor
->u
.DeviceSpecificData
.DataSize
;
3298 /* The size of partial descriptors is bigger */
3299 PartialSize
+= EntrySize
;
3301 /* Go to the next partial descriptor */
3302 PartialDescriptor
= (PVOID
)((ULONG_PTR
)PartialDescriptor
+ EntrySize
);
3305 /* The size of full descriptors is bigger */
3306 FinalSize
+= PartialSize
;
3308 /* Go to the next full descriptor */
3309 FullDescriptor
= (PVOID
)((ULONG_PTR
)FullDescriptor
+ PartialSize
);
3312 /* Return the final size */
3318 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject
,
3323 IN PULONG BufferLength
)
3326 HANDLE KeyHandle
, SubHandle
;
3327 UNICODE_STRING KeyString
;
3328 PKEY_VALUE_FULL_INFORMATION KeyValueInfo
= NULL
;
3332 /* Find the instance key */
3333 Status
= PnpDeviceObjectToDeviceInstance(DeviceObject
, &KeyHandle
, KEY_READ
);
3334 if (NT_SUCCESS(Status
))
3336 /* Check for name given by caller */
3340 RtlInitUnicodeString(&KeyString
, KeyName
);
3341 Status
= IopOpenRegistryKeyEx(&SubHandle
,
3345 if (NT_SUCCESS(Status
))
3347 /* And use this handle instead */
3349 KeyHandle
= SubHandle
;
3353 /* Check if sub-key handle succeeded (or no-op if no key name given) */
3354 if (NT_SUCCESS(Status
))
3356 /* Now get the size of the property */
3357 Status
= IopGetRegistryValue(KeyHandle
,
3366 /* Fail if any of the registry operations failed */
3367 if (!NT_SUCCESS(Status
)) return Status
;
3369 /* Check how much data we have to copy */
3370 Length
= KeyValueInfo
->DataLength
;
3371 if (*BufferLength
>= Length
)
3373 /* Check for a match in the value type */
3374 if (KeyValueInfo
->Type
== ValueType
)
3377 RtlCopyMemory(Buffer
,
3378 (PVOID
)((ULONG_PTR
)KeyValueInfo
+
3379 KeyValueInfo
->DataOffset
),
3384 /* Invalid registry property type, fail */
3385 Status
= STATUS_INVALID_PARAMETER_2
;
3390 /* Buffer is too small to hold data */
3391 Status
= STATUS_BUFFER_TOO_SMALL
;
3394 /* Return the required buffer length, free the buffer, and return status */
3395 *BufferLength
= Length
;
3396 ExFreePool(KeyValueInfo
);
3400 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
3401 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
3402 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED; while(TRUE); break;}
3409 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3410 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3411 IN ULONG BufferLength
,
3412 OUT PVOID PropertyBuffer
,
3413 OUT PULONG ResultLength
)
3415 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3416 DEVICE_CAPABILITIES DeviceCaps
;
3417 ULONG ReturnLength
= 0, Length
= 0, ValueType
;
3418 PWCHAR ValueName
= NULL
, EnumeratorNameEnd
, DeviceInstanceName
;
3420 NTSTATUS Status
= STATUS_BUFFER_TOO_SMALL
;
3422 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
3423 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3425 /* Assume failure */
3428 /* Only PDOs can call this */
3429 if (!DeviceNode
) return STATUS_INVALID_DEVICE_REQUEST
;
3431 /* Handle all properties */
3432 switch (DeviceProperty
)
3434 case DevicePropertyBusTypeGuid
:
3436 /* Get the GUID from the internal cache */
3437 Status
= PnpBusTypeGuidGet(DeviceNode
->ChildBusTypeIndex
, &BusTypeGuid
);
3438 if (!NT_SUCCESS(Status
)) return Status
;
3440 /* This is the format of the returned data */
3441 PIP_RETURN_DATA(sizeof(GUID
), &BusTypeGuid
);
3443 case DevicePropertyLegacyBusType
:
3445 /* Validate correct interface type */
3446 if (DeviceNode
->ChildInterfaceType
== InterfaceTypeUndefined
)
3447 return STATUS_OBJECT_NAME_NOT_FOUND
;
3449 /* This is the format of the returned data */
3450 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE
), &DeviceNode
->ChildInterfaceType
);
3452 case DevicePropertyBusNumber
:
3454 /* Validate correct bus number */
3455 if ((DeviceNode
->ChildBusNumber
& 0x80000000) == 0x80000000)
3456 return STATUS_OBJECT_NAME_NOT_FOUND
;
3458 /* This is the format of the returned data */
3459 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceNode
->ChildBusNumber
);
3461 case DevicePropertyEnumeratorName
:
3463 /* Get the instance path */
3464 DeviceInstanceName
= DeviceNode
->InstancePath
.Buffer
;
3467 ASSERT((BufferLength
& 1) == 0);
3468 ASSERT(DeviceInstanceName
!= NULL
);
3470 /* Get the name from the path */
3471 EnumeratorNameEnd
= wcschr(DeviceInstanceName
, OBJ_NAME_PATH_SEPARATOR
);
3472 ASSERT(EnumeratorNameEnd
);
3474 /* This is the format of the returned data */
3475 PIP_RETURN_DATA((EnumeratorNameEnd
- DeviceInstanceName
) * sizeof(WCHAR
),
3476 DeviceInstanceName
);
3478 case DevicePropertyAddress
:
3480 /* Query the device caps */
3481 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3482 if (!NT_SUCCESS(Status
) || (DeviceCaps
.Address
== MAXULONG
))
3483 return STATUS_OBJECT_NAME_NOT_FOUND
;
3485 /* This is the format of the returned data */
3486 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceCaps
.Address
);
3488 case DevicePropertyBootConfigurationTranslated
:
3490 /* Validate we have resources */
3491 if (!DeviceNode
->BootResources
)
3492 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
3494 /* No resources will still fake success, but with 0 bytes */
3496 return STATUS_SUCCESS
;
3499 /* This is the format of the returned data */
3500 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode
->BootResources
), // FIXFIX: Should use BootResourcesTranslated
3501 DeviceNode
->BootResources
); // FIXFIX: Should use BootResourcesTranslated
3503 case DevicePropertyPhysicalDeviceObjectName
:
3505 /* Sanity check for Unicode-sized string */
3506 ASSERT((BufferLength
& 1) == 0);
3508 /* Allocate name buffer */
3509 Length
= BufferLength
+ sizeof(OBJECT_NAME_INFORMATION
);
3510 ObjectNameInfo
= ExAllocatePool(PagedPool
, Length
);
3511 if (!ObjectNameInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
3513 /* Query the PDO name */
3514 Status
= ObQueryNameString(DeviceObject
,
3518 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
3520 /* It's up to the caller to try again */
3521 Status
= STATUS_BUFFER_TOO_SMALL
;
3524 /* Return if successful */
3525 if (NT_SUCCESS(Status
)) PIP_RETURN_DATA(ObjectNameInfo
->Name
.Length
,
3526 ObjectNameInfo
->Name
.Buffer
);
3528 /* Let the caller know how big the name is */
3529 *ResultLength
-= sizeof(OBJECT_NAME_INFORMATION
);
3532 /* Handle the registry-based properties */
3533 case DevicePropertyUINumber
:
3534 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER
, REG_DWORD
);
3535 case DevicePropertyLocationInformation
:
3536 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION
, REG_SZ
);
3537 case DevicePropertyDeviceDescription
:
3538 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC
, REG_SZ
);
3539 case DevicePropertyHardwareID
:
3540 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID
, REG_MULTI_SZ
);
3541 case DevicePropertyCompatibleIDs
:
3542 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS
, REG_MULTI_SZ
);
3543 case DevicePropertyBootConfiguration
:
3544 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG
, REG_RESOURCE_LIST
);
3545 case DevicePropertyClassName
:
3546 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS
, REG_SZ
);
3547 case DevicePropertyClassGuid
:
3548 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID
, REG_SZ
);
3549 case DevicePropertyDriverKeyName
:
3550 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER
, REG_SZ
);
3551 case DevicePropertyManufacturer
:
3552 PIP_REGISTRY_DATA(REGSTR_VAL_MFG
, REG_SZ
);
3553 case DevicePropertyFriendlyName
:
3554 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME
, REG_SZ
);
3555 case DevicePropertyContainerID
:
3556 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
3557 PIP_UNIMPLEMENTED();
3558 case DevicePropertyRemovalPolicy
:
3559 PIP_UNIMPLEMENTED();
3560 case DevicePropertyInstallState
:
3561 PIP_UNIMPLEMENTED();
3562 case DevicePropertyResourceRequirements
:
3563 PIP_UNIMPLEMENTED();
3564 case DevicePropertyAllocatedResources
:
3565 PIP_UNIMPLEMENTED();
3567 return STATUS_INVALID_PARAMETER_2
;
3570 /* Having a registry value name implies registry data */
3573 /* We know up-front how much data to expect */
3574 *ResultLength
= BufferLength
;
3576 /* Go get the data, use the LogConf subkey if necessary */
3577 Status
= PiGetDeviceRegistryProperty(DeviceObject
,
3581 DevicePropertyBootConfiguration
) ?
3586 else if (NT_SUCCESS(Status
))
3588 /* We know up-front how much data to expect, check the caller's buffer */
3589 *ResultLength
= ReturnLength
;
3590 if (ReturnLength
<= BufferLength
)
3592 /* Buffer is all good, copy the data */
3593 RtlCopyMemory(PropertyBuffer
, Data
, ReturnLength
);
3595 /* Check for properties that require a null-terminated string */
3596 if ((DeviceProperty
== DevicePropertyEnumeratorName
) ||
3597 (DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
))
3599 /* Terminate the string */
3600 ((PWCHAR
)PropertyBuffer
)[ReturnLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3603 /* This is the success path */
3604 Status
= STATUS_SUCCESS
;
3609 Status
= STATUS_BUFFER_TOO_SMALL
;
3613 /* Free any allocation we may have made, and return the status code */
3614 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
3623 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3625 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
3626 IO_STACK_LOCATION Stack
;
3629 IO_STATUS_BLOCK IoStatusBlock
;
3631 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
3632 Stack
.MajorFunction
= IRP_MJ_PNP
;
3633 Stack
.MinorFunction
= IRP_MN_QUERY_PNP_DEVICE_STATE
;
3635 Status
= IopSynchronousCall(PhysicalDeviceObject
, &Stack
, (PVOID
*)&PnPFlags
);
3636 if (!NT_SUCCESS(Status
))
3638 DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%x\n", Status
);
3642 if (PnPFlags
& PNP_DEVICE_NOT_DISABLEABLE
)
3643 DeviceNode
->UserFlags
|= DNUF_NOT_DISABLEABLE
;
3645 DeviceNode
->UserFlags
&= ~DNUF_NOT_DISABLEABLE
;
3647 if (PnPFlags
& PNP_DEVICE_DONT_DISPLAY_IN_UI
)
3648 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
3650 DeviceNode
->UserFlags
&= ~DNUF_DONT_SHOW_IN_UI
;
3652 if ((PnPFlags
& PNP_DEVICE_REMOVED
) ||
3653 ((PnPFlags
& PNP_DEVICE_FAILED
) && !(PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)))
3655 /* Surprise removal */
3657 IopSendSurpriseRemoval(PhysicalDeviceObject
);
3659 /* Tell the user-mode PnP manager that a device was removed */
3660 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
3661 &DeviceNode
->InstancePath
);
3663 IopSendRemoveDevice(PhysicalDeviceObject
);
3665 else if ((PnPFlags
& PNP_DEVICE_FAILED
) && (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
))
3667 /* Stop for resource rebalance */
3669 if (NT_SUCCESS(IopQueryStopDevice(PhysicalDeviceObject
)))
3671 IopSendStopDevice(PhysicalDeviceObject
);
3673 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
3674 DeviceNode
->Flags
|= DNF_STOPPED
;
3678 /* Resource rebalance */
3679 if (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)
3681 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
3683 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
3685 IRP_MN_QUERY_RESOURCES
,
3687 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
3689 DeviceNode
->BootResources
=
3690 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
3691 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
3695 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
3696 DeviceNode
->BootResources
= NULL
;
3699 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
3701 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
3703 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
3705 if (NT_SUCCESS(Status
))
3707 DeviceNode
->ResourceRequirements
=
3708 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
3712 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
3713 DeviceNode
->ResourceRequirements
= NULL
;
3716 /* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
3717 if (IopStartDevice(DeviceNode
) != STATUS_SUCCESS
)
3719 DPRINT1("Restart after resource rebalance failed\n");
3721 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
3722 DeviceNode
->Flags
|= DNF_START_FAILED
;
3724 IopSendRemoveDevice(PhysicalDeviceObject
);
3730 * @name IoOpenDeviceRegistryKey
3732 * Open a registry key unique for a specified driver or device instance.
3734 * @param DeviceObject Device to get the registry key for.
3735 * @param DevInstKeyType Type of the key to return.
3736 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
3737 * @param DevInstRegKey Handle to the opened registry key on
3738 * successful return.
3746 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
3747 IN ULONG DevInstKeyType
,
3748 IN ACCESS_MASK DesiredAccess
,
3749 OUT PHANDLE DevInstRegKey
)
3751 static WCHAR RootKeyName
[] =
3752 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
3753 static WCHAR ProfileKeyName
[] =
3754 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
3755 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
3756 static WCHAR EnumKeyName
[] = L
"Enum\\";
3757 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
3758 ULONG KeyNameLength
;
3759 LPWSTR KeyNameBuffer
;
3760 UNICODE_STRING KeyName
;
3761 ULONG DriverKeyLength
;
3762 OBJECT_ATTRIBUTES ObjectAttributes
;
3763 PDEVICE_NODE DeviceNode
= NULL
;
3766 DPRINT("IoOpenDeviceRegistryKey() called\n");
3768 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
3770 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
3771 return STATUS_INVALID_PARAMETER
;
3774 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
3775 return STATUS_INVALID_DEVICE_REQUEST
;
3776 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3779 * Calculate the length of the base key name. This is the full
3780 * name for driver key or the name excluding "Device Parameters"
3781 * subkey for device key.
3784 KeyNameLength
= sizeof(RootKeyName
);
3785 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3786 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
3787 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3789 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
3790 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3791 0, NULL
, &DriverKeyLength
);
3792 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
3794 KeyNameLength
+= DriverKeyLength
;
3798 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
3799 DeviceNode
->InstancePath
.Length
;
3803 * Now allocate the buffer for the key name...
3806 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
3807 if (KeyNameBuffer
== NULL
)
3808 return STATUS_INSUFFICIENT_RESOURCES
;
3811 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
3812 KeyName
.Buffer
= KeyNameBuffer
;
3815 * ...and build the key name.
3818 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
3819 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
3821 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3822 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
3824 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3826 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
3827 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3828 DriverKeyLength
, KeyNameBuffer
+
3829 (KeyName
.Length
/ sizeof(WCHAR
)),
3831 if (!NT_SUCCESS(Status
))
3833 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
3834 ExFreePool(KeyNameBuffer
);
3837 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
3841 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
3842 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
3843 if (DeviceNode
->InstancePath
.Length
== 0)
3845 ExFreePool(KeyNameBuffer
);
3851 * Open the base key.
3853 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
3854 if (!NT_SUCCESS(Status
))
3856 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
3857 ExFreePool(KeyNameBuffer
);
3860 ExFreePool(KeyNameBuffer
);
3863 * For driver key we're done now.
3866 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3870 * Let's go further. For device key we must open "Device Parameters"
3871 * subkey and create it if it doesn't exist yet.
3874 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
3875 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
3876 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
3877 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
3878 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
3879 ZwClose(ObjectAttributes
.RootDirectory
);
3886 IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject
)
3888 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3889 IO_STACK_LOCATION Stack
;
3890 IO_STATUS_BLOCK IoStatusBlock
;
3891 PDEVICE_RELATIONS DeviceRelations
;
3895 if (DeviceNode
->UserFlags
& DNUF_NOT_DISABLEABLE
)
3897 DPRINT1("Removal not allowed for %wZ\n", &DeviceNode
->InstancePath
);
3898 return STATUS_UNSUCCESSFUL
;
3901 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING
,
3902 &DeviceNode
->InstancePath
);
3904 if (IopQueryRemoveDevice(DeviceObject
) != STATUS_SUCCESS
)
3906 DPRINT1("Removal vetoed by failing the query remove request\n");
3908 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED
,
3909 &DeviceNode
->InstancePath
);
3911 return STATUS_UNSUCCESSFUL
;
3914 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
3916 Status
= IopInitiatePnpIrp(DeviceObject
,
3918 IRP_MN_QUERY_DEVICE_RELATIONS
,
3920 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
3922 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
3926 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
3928 if (DeviceRelations
)
3930 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
3932 PDEVICE_NODE RelationsDeviceNode
= IopGetDeviceNode(DeviceRelations
->Objects
[i
]);
3934 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING
,
3935 &RelationsDeviceNode
->InstancePath
);
3937 if (IopQueryRemoveDevice(DeviceRelations
->Objects
[i
]) != STATUS_SUCCESS
)
3939 DPRINT1("Device removal vetoed by failing a dependent query remove request\n");
3941 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED
,
3942 &RelationsDeviceNode
->InstancePath
);
3944 Status
= STATUS_UNSUCCESSFUL
;
3950 IopSendRemoveDevice(DeviceRelations
->Objects
[i
]);
3952 IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL
,
3953 &RelationsDeviceNode
->InstancePath
);
3955 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
3957 DeviceRelations
->Objects
[i
] = NULL
;
3961 ExFreePool(DeviceRelations
);
3963 DeviceRelations
= NULL
;
3966 Status
= STATUS_SUCCESS
;
3969 if (DeviceRelations
)
3971 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
3973 if (DeviceRelations
->Objects
[i
])
3975 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
3979 ExFreePool(DeviceRelations
);
3986 IopRemoveDevice(PDEVICE_NODE DeviceNode
)
3990 DPRINT("Removing device: %wZ\n", &DeviceNode
->InstancePath
);
3992 Status
= IopPrepareDeviceForRemoval(DeviceNode
->PhysicalDeviceObject
);
3993 if (NT_SUCCESS(Status
))
3995 IopSendRemoveDevice(DeviceNode
->PhysicalDeviceObject
);
3996 return STATUS_SUCCESS
;
4007 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4009 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
4010 PDEVICE_RELATIONS DeviceRelations
;
4011 IO_STATUS_BLOCK IoStatusBlock
;
4012 IO_STACK_LOCATION Stack
;
4013 DEVICE_CAPABILITIES Capabilities
;
4017 IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT
,
4018 &DeviceNode
->InstancePath
);
4020 if (IopQueryDeviceCapabilities(DeviceNode
, &Capabilities
) != STATUS_SUCCESS
)
4022 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED
,
4023 &DeviceNode
->InstancePath
);
4027 Stack
.Parameters
.QueryDeviceRelations
.Type
= EjectionRelations
;
4029 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
4031 IRP_MN_QUERY_DEVICE_RELATIONS
,
4033 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
4035 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4036 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED
,
4037 &DeviceNode
->InstancePath
);
4041 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4043 if (DeviceRelations
)
4045 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4047 PDEVICE_NODE RelationsDeviceNode
= IopGetDeviceNode(DeviceRelations
->Objects
[i
]);
4049 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING
,
4050 &RelationsDeviceNode
->InstancePath
);
4052 if (IopQueryRemoveDevice(DeviceRelations
->Objects
[i
]) != STATUS_SUCCESS
)
4054 DPRINT1("Device removal vetoed by failing a query remove request (ejection relations)\n");
4056 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED
,
4057 &RelationsDeviceNode
->InstancePath
);
4063 IopSendRemoveDevice(DeviceRelations
->Objects
[i
]);
4065 IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL
,
4066 &RelationsDeviceNode
->InstancePath
);
4068 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4070 DeviceRelations
->Objects
[i
] = NULL
;
4074 ExFreePool(DeviceRelations
);
4076 DeviceRelations
= NULL
;
4079 if (IopPrepareDeviceForRemoval(PhysicalDeviceObject
) != STATUS_SUCCESS
)
4081 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED
,
4082 &DeviceNode
->InstancePath
);
4086 if (Capabilities
.EjectSupported
)
4088 if (IopSendEject(PhysicalDeviceObject
) != STATUS_SUCCESS
)
4090 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED
,
4091 &DeviceNode
->InstancePath
);
4098 DeviceNode
->Flags
|= DNF_DISABLED
;
4102 if (DeviceRelations
)
4104 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4106 if (DeviceRelations
->Objects
[i
])
4108 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4112 ExFreePool(DeviceRelations
);
4114 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED
,
4115 &DeviceNode
->InstancePath
);
4119 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT
,
4120 &DeviceNode
->InstancePath
);
4129 IoInvalidateDeviceRelations(
4130 IN PDEVICE_OBJECT DeviceObject
,
4131 IN DEVICE_RELATION_TYPE Type
)
4133 PIO_WORKITEM WorkItem
;
4134 PINVALIDATE_DEVICE_RELATION_DATA Data
;
4136 Data
= ExAllocatePool(NonPagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
4139 WorkItem
= IoAllocateWorkItem(DeviceObject
);
4146 ObReferenceObject(DeviceObject
);
4147 Data
->DeviceObject
= DeviceObject
;
4149 Data
->WorkItem
= WorkItem
;
4153 IopAsynchronousInvalidateDeviceRelations
,
4163 IoSynchronousInvalidateDeviceRelations(
4164 IN PDEVICE_OBJECT DeviceObject
,
4165 IN DEVICE_RELATION_TYPE Type
)
4172 /* Enumerate the device */
4173 return IopEnumerateDevice(DeviceObject
);
4174 case PowerRelations
:
4175 /* Not handled yet */
4176 return STATUS_NOT_IMPLEMENTED
;
4177 case TargetDeviceRelation
:
4179 return STATUS_SUCCESS
;
4181 /* Ejection relations are not supported */
4182 return STATUS_NOT_SUPPORTED
;
4191 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
4193 IN PHYSICAL_ADDRESS BusAddress
,
4194 IN OUT PULONG AddressSpace
,
4195 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
4197 /* FIXME: Notify the resource arbiter */
4199 return HalTranslateBusAddress(InterfaceType
,