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
,
49 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
);
52 IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
);
56 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
58 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
63 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
64 PDRIVER_OBJECT DriverObject
)
71 /* Special case for bus driven devices */
72 DeviceNode
->Flags
|= DNF_ADDED
;
73 return STATUS_SUCCESS
;
76 if (!DriverObject
->DriverExtension
->AddDevice
)
78 DeviceNode
->Flags
|= DNF_LEGACY_DRIVER
;
81 if (DeviceNode
->Flags
& DNF_LEGACY_DRIVER
)
83 DeviceNode
->Flags
|= DNF_ADDED
+ DNF_STARTED
;
84 return STATUS_SUCCESS
;
87 /* This is a Plug and Play driver */
88 DPRINT("Plug and Play driver found\n");
89 ASSERT(DeviceNode
->PhysicalDeviceObject
);
91 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
92 &DriverObject
->DriverName
,
93 &DeviceNode
->InstancePath
);
94 Status
= DriverObject
->DriverExtension
->AddDevice(
95 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
96 if (!NT_SUCCESS(Status
))
98 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
102 /* Check if driver added a FDO above the PDO */
103 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
104 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
106 /* FIXME: What do we do? Unload the driver or just disable the device? */
107 DPRINT1("An FDO was not attached\n");
108 ObDereferenceObject(Fdo
);
109 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
110 return STATUS_UNSUCCESSFUL
;
113 /* Check if we have a ACPI device (needed for power management) */
114 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
116 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
118 /* There can be only one system power device */
119 if (!SystemPowerDeviceNodeCreated
)
121 PopSystemPowerDeviceNode
= DeviceNode
;
122 ObReferenceObject(PopSystemPowerDeviceNode
);
123 SystemPowerDeviceNodeCreated
= TRUE
;
127 ObDereferenceObject(Fdo
);
129 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
131 return STATUS_SUCCESS
;
137 IopSendEject(IN PDEVICE_OBJECT DeviceObject
)
139 IO_STACK_LOCATION Stack
;
142 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
143 Stack
.MajorFunction
= IRP_MJ_PNP
;
144 Stack
.MinorFunction
= IRP_MN_EJECT
;
146 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
152 IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject
)
154 IO_STACK_LOCATION Stack
;
157 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
158 Stack
.MajorFunction
= IRP_MJ_PNP
;
159 Stack
.MinorFunction
= IRP_MN_SURPRISE_REMOVAL
;
161 /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
162 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
168 IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
170 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
171 IO_STACK_LOCATION Stack
;
177 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING
,
178 &DeviceNode
->InstancePath
);
180 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
181 Stack
.MajorFunction
= IRP_MJ_PNP
;
182 Stack
.MinorFunction
= IRP_MN_QUERY_REMOVE_DEVICE
;
184 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
186 IopNotifyPlugPlayNotification(DeviceObject
,
187 EventCategoryTargetDeviceChange
,
188 &GUID_TARGET_DEVICE_QUERY_REMOVE
,
192 if (!NT_SUCCESS(Status
))
194 DPRINT1("Removal vetoed by %wZ\n", &DeviceNode
->InstancePath
);
195 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED
,
196 &DeviceNode
->InstancePath
);
205 IopQueryStopDevice(IN PDEVICE_OBJECT DeviceObject
)
207 IO_STACK_LOCATION Stack
;
210 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
211 Stack
.MajorFunction
= IRP_MJ_PNP
;
212 Stack
.MinorFunction
= IRP_MN_QUERY_STOP_DEVICE
;
214 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
220 IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
222 IO_STACK_LOCATION Stack
;
225 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
226 Stack
.MajorFunction
= IRP_MJ_PNP
;
227 Stack
.MinorFunction
= IRP_MN_REMOVE_DEVICE
;
229 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
230 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
232 IopNotifyPlugPlayNotification(DeviceObject
,
233 EventCategoryTargetDeviceChange
,
234 &GUID_TARGET_DEVICE_REMOVE_COMPLETE
,
242 IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
244 IO_STACK_LOCATION Stack
;
247 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
248 Stack
.MajorFunction
= IRP_MJ_PNP
;
249 Stack
.MinorFunction
= IRP_MN_CANCEL_REMOVE_DEVICE
;
251 /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
252 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
254 IopNotifyPlugPlayNotification(DeviceObject
,
255 EventCategoryTargetDeviceChange
,
256 &GUID_TARGET_DEVICE_REMOVE_CANCELLED
,
264 IopSendStopDevice(IN PDEVICE_OBJECT DeviceObject
)
266 IO_STACK_LOCATION Stack
;
269 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
270 Stack
.MajorFunction
= IRP_MJ_PNP
;
271 Stack
.MinorFunction
= IRP_MN_STOP_DEVICE
;
273 /* Drivers should never fail a IRP_MN_STOP_DEVICE request */
274 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
279 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject
)
281 IO_STACK_LOCATION Stack
;
282 PDEVICE_NODE DeviceNode
;
285 DEVICE_CAPABILITIES DeviceCapabilities
;
287 /* Get the device node */
288 DeviceNode
= IopGetDeviceNode(DeviceObject
);
290 ASSERT(!(DeviceNode
->Flags
& DNF_DISABLED
));
292 /* Build the I/O stack locaiton */
293 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
294 Stack
.MajorFunction
= IRP_MJ_PNP
;
295 Stack
.MinorFunction
= IRP_MN_START_DEVICE
;
297 Stack
.Parameters
.StartDevice
.AllocatedResources
=
298 DeviceNode
->ResourceList
;
299 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
=
300 DeviceNode
->ResourceListTranslated
;
303 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
304 if (!NT_SUCCESS(Status
))
306 /* Send an IRP_MN_REMOVE_DEVICE request */
307 IopRemoveDevice(DeviceNode
);
309 /* Set the appropriate flag */
310 DeviceNode
->Flags
|= DNF_START_FAILED
;
312 DPRINT1("Warning: PnP Start failed (%wZ)\n", &DeviceNode
->InstancePath
);
316 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
318 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
319 if (!NT_SUCCESS(Status
))
321 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
324 /* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
325 IoInvalidateDeviceState(DeviceObject
);
327 /* Otherwise, mark us as started */
328 DeviceNode
->Flags
|= DNF_STARTED
;
329 DeviceNode
->Flags
&= ~DNF_STOPPED
;
331 /* We now need enumeration */
332 DeviceNode
->Flags
|= DNF_NEED_ENUMERATION_ONLY
;
337 IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode
)
339 PDEVICE_OBJECT DeviceObject
;
344 ASSERT((DeviceNode
->Flags
& DNF_ADDED
));
345 ASSERT((DeviceNode
->Flags
& (DNF_RESOURCE_ASSIGNED
|
346 DNF_RESOURCE_REPORTED
|
347 DNF_NO_RESOURCE_REQUIRED
)));
349 /* Get the device object */
350 DeviceObject
= DeviceNode
->PhysicalDeviceObject
;
352 /* Check if we're not started yet */
353 if (!(DeviceNode
->Flags
& DNF_STARTED
))
356 IopStartDevice2(DeviceObject
);
359 /* Do we need to query IDs? This happens in the case of manual reporting */
361 if (DeviceNode
->Flags
& DNF_NEED_QUERY_IDS
)
363 DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
364 /* And that case shouldn't happen yet */
369 /* Make sure we're started, and check if we need enumeration */
370 if ((DeviceNode
->Flags
& DNF_STARTED
) &&
371 (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
))
374 IoSynchronousInvalidateDeviceRelations(DeviceObject
, BusRelations
);
375 Status
= STATUS_SUCCESS
;
380 Status
= STATUS_SUCCESS
;
389 PDEVICE_NODE DeviceNode
)
393 DPRINT("Stopping device: %wZ\n", &DeviceNode
->InstancePath
);
395 Status
= IopQueryStopDevice(DeviceNode
->PhysicalDeviceObject
);
396 if (!NT_SUCCESS(Status
))
398 IopSendStopDevice(DeviceNode
->PhysicalDeviceObject
);
399 return STATUS_SUCCESS
;
407 PDEVICE_NODE DeviceNode
)
410 HANDLE InstanceHandle
= INVALID_HANDLE_VALUE
, ControlHandle
= INVALID_HANDLE_VALUE
;
411 UNICODE_STRING KeyName
;
412 OBJECT_ATTRIBUTES ObjectAttributes
;
414 if (DeviceNode
->Flags
& DNF_DISABLED
)
415 return STATUS_SUCCESS
;
417 Status
= IopAssignDeviceResources(DeviceNode
);
418 if (!NT_SUCCESS(Status
))
422 IopStartAndEnumerateDevice(DeviceNode
);
424 /* FIX: Should be done in new device instance code */
425 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceHandle
);
426 if (!NT_SUCCESS(Status
))
429 /* FIX: Should be done in IoXxxPrepareDriverLoading */
431 RtlInitUnicodeString(&KeyName
, L
"Control");
432 InitializeObjectAttributes(&ObjectAttributes
,
434 OBJ_CASE_INSENSITIVE
,
437 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
438 if (!NT_SUCCESS(Status
))
441 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
442 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
446 if (ControlHandle
!= INVALID_HANDLE_VALUE
)
447 ZwClose(ControlHandle
);
449 if (InstanceHandle
!= INVALID_HANDLE_VALUE
)
450 ZwClose(InstanceHandle
);
457 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
458 PDEVICE_CAPABILITIES DeviceCaps
)
460 IO_STATUS_BLOCK StatusBlock
;
461 IO_STACK_LOCATION Stack
;
464 UNICODE_STRING ValueName
;
466 /* Set up the Header */
467 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
468 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
469 DeviceCaps
->Version
= 1;
470 DeviceCaps
->Address
= -1;
471 DeviceCaps
->UINumber
= -1;
473 /* Set up the Stack */
474 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
475 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
478 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
480 IRP_MN_QUERY_CAPABILITIES
,
482 if (!NT_SUCCESS(Status
))
484 DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%x\n", Status
);
488 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCaps
->Version
+ sizeof(DeviceCaps
->Version
));
490 if (DeviceCaps
->NoDisplayInUI
)
491 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
493 DeviceNode
->UserFlags
&= DNUF_DONT_SHOW_IN_UI
;
495 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
496 if (NT_SUCCESS(Status
))
498 /* Set 'Capabilities' value */
499 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
500 Status
= ZwSetValueKey(InstanceKey
,
504 (PVOID
)&DeviceNode
->CapabilityFlags
,
507 /* Set 'UINumber' value */
508 if (DeviceCaps
->UINumber
!= MAXULONG
)
510 RtlInitUnicodeString(&ValueName
, L
"UINumber");
511 Status
= ZwSetValueKey(InstanceKey
,
515 &DeviceCaps
->UINumber
,
524 IopAsynchronousInvalidateDeviceRelations(
525 IN PDEVICE_OBJECT DeviceObject
,
526 IN PVOID InvalidateContext
)
528 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
530 IoSynchronousInvalidateDeviceRelations(
534 ObDereferenceObject(Data
->DeviceObject
);
535 IoFreeWorkItem(Data
->WorkItem
);
540 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
544 if (PopSystemPowerDeviceNode
)
546 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
547 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
548 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
550 return STATUS_SUCCESS
;
553 return STATUS_UNSUCCESSFUL
;
558 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
560 USHORT i
= 0, FoundIndex
= 0xFFFF;
564 /* Acquire the lock */
565 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
567 /* Loop all entries */
568 while (i
< PnpBusTypeGuidList
->GuidCount
)
570 /* Try to find a match */
571 if (RtlCompareMemory(BusTypeGuid
,
572 &PnpBusTypeGuidList
->Guids
[i
],
573 sizeof(GUID
)) == sizeof(GUID
))
582 /* Check if we have to grow the list */
583 if (PnpBusTypeGuidList
->GuidCount
)
585 /* Calculate the new size */
586 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
587 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
589 /* Allocate the new copy */
590 NewList
= ExAllocatePool(PagedPool
, NewSize
);
594 ExFreePool(PnpBusTypeGuidList
);
598 /* Now copy them, decrease the size too */
599 NewSize
-= sizeof(GUID
);
600 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
602 /* Free the old list */
603 ExFreePool(PnpBusTypeGuidList
);
605 /* Use the new buffer */
606 PnpBusTypeGuidList
= NewList
;
609 /* Copy the new GUID */
610 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
614 /* The new entry is the index */
615 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
616 PnpBusTypeGuidList
->GuidCount
++;
619 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
625 * Creates a device node
628 * ParentNode = Pointer to parent device node
629 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
630 * to have the root device node create one
631 * (eg. for legacy drivers)
632 * DeviceNode = Pointer to storage for created device node
638 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
639 PDEVICE_OBJECT PhysicalDeviceObject
,
640 PUNICODE_STRING ServiceName
,
641 PDEVICE_NODE
*DeviceNode
)
646 UNICODE_STRING FullServiceName
;
647 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
648 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
649 UNICODE_STRING KeyName
, ClassName
;
650 PUNICODE_STRING ServiceName1
;
653 UNICODE_STRING ClassGUID
;
655 HANDLE InstanceHandle
;
657 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
658 ParentNode
, PhysicalDeviceObject
, ServiceName
);
660 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
663 return STATUS_INSUFFICIENT_RESOURCES
;
666 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
669 ServiceName1
= &UnknownDeviceName
;
671 ServiceName1
= ServiceName
;
673 if (!PhysicalDeviceObject
)
675 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
676 FullServiceName
.Length
= 0;
677 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
678 if (!FullServiceName
.Buffer
)
681 return STATUS_INSUFFICIENT_RESOURCES
;
684 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
685 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
687 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
688 if (!NT_SUCCESS(Status
))
690 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
695 /* Create the device key for legacy drivers */
696 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
697 if (!NT_SUCCESS(Status
))
699 ZwClose(InstanceHandle
);
701 ExFreePool(FullServiceName
.Buffer
);
705 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
706 if (!Node
->ServiceName
.Buffer
)
708 ZwClose(InstanceHandle
);
710 ExFreePool(FullServiceName
.Buffer
);
714 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
715 Node
->ServiceName
.Length
= 0;
717 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
721 RtlInitUnicodeString(&KeyName
, L
"Service");
722 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
725 if (NT_SUCCESS(Status
))
727 RtlInitUnicodeString(&KeyName
, L
"Legacy");
730 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
731 if (NT_SUCCESS(Status
))
733 RtlInitUnicodeString(&KeyName
, L
"Class");
735 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
736 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
);
738 if (NT_SUCCESS(Status
))
740 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
742 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
743 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
);
749 ZwClose(InstanceHandle
);
750 ExFreePool(FullServiceName
.Buffer
);
752 if (!NT_SUCCESS(Status
))
758 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
759 IopDeviceNodeSetFlag(Node
, DNF_ADDED
);
760 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
763 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
765 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
769 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
770 Node
->Parent
= ParentNode
;
771 Node
->Sibling
= ParentNode
->Child
;
772 ParentNode
->Child
= Node
;
773 if (ParentNode
->LastChild
== NULL
)
774 ParentNode
->LastChild
= Node
;
775 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
776 Node
->Level
= ParentNode
->Level
+ 1;
779 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
783 return STATUS_SUCCESS
;
787 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
790 PDEVICE_NODE PrevSibling
= NULL
;
792 /* All children must be deleted before a parent is deleted */
793 ASSERT(!DeviceNode
->Child
);
795 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
797 ASSERT(DeviceNode
->PhysicalDeviceObject
);
799 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
801 /* Get previous sibling */
802 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
804 PrevSibling
= DeviceNode
->Parent
->Child
;
805 while (PrevSibling
->Sibling
!= DeviceNode
)
806 PrevSibling
= PrevSibling
->Sibling
;
809 /* Unlink from parent if it exists */
810 if (DeviceNode
->Parent
)
812 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
814 DeviceNode
->Parent
->LastChild
= PrevSibling
;
816 PrevSibling
->Sibling
= NULL
;
818 if (DeviceNode
->Parent
->Child
== DeviceNode
)
819 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
822 /* Unlink from sibling list */
824 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
826 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
828 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
830 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
832 if (DeviceNode
->ResourceList
)
834 ExFreePool(DeviceNode
->ResourceList
);
837 if (DeviceNode
->ResourceListTranslated
)
839 ExFreePool(DeviceNode
->ResourceListTranslated
);
842 if (DeviceNode
->ResourceRequirements
)
844 ExFreePool(DeviceNode
->ResourceRequirements
);
847 if (DeviceNode
->BootResources
)
849 ExFreePool(DeviceNode
->BootResources
);
852 ExFreePool(DeviceNode
);
854 return STATUS_SUCCESS
;
859 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
860 IN PIO_STACK_LOCATION IoStackLocation
,
861 OUT PVOID
*Information
)
864 PIO_STACK_LOCATION IrpStack
;
865 IO_STATUS_BLOCK IoStatusBlock
;
868 PDEVICE_OBJECT TopDeviceObject
;
871 /* Call the top of the device stack */
872 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
874 /* Allocate an IRP */
875 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
876 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
878 /* Initialize to failure */
879 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
880 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
882 /* Initialize the event */
883 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
886 Irp
->UserIosb
= &IoStatusBlock
;
887 Irp
->UserEvent
= &Event
;
890 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
891 IoQueueThreadIrp(Irp
);
893 /* Copy-in the stack */
894 IrpStack
= IoGetNextIrpStackLocation(Irp
);
895 *IrpStack
= *IoStackLocation
;
897 /* Call the driver */
898 Status
= IoCallDriver(TopDeviceObject
, Irp
);
899 if (Status
== STATUS_PENDING
)
902 KeWaitForSingleObject(&Event
,
907 Status
= IoStatusBlock
.Status
;
910 /* Return the information */
911 *Information
= (PVOID
)IoStatusBlock
.Information
;
917 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
918 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
919 IN ULONG MinorFunction
,
920 IN PIO_STACK_LOCATION Stack OPTIONAL
)
922 IO_STACK_LOCATION IoStackLocation
;
924 /* Fill out the stack information */
925 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
926 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
927 IoStackLocation
.MinorFunction
= MinorFunction
;
931 RtlCopyMemory(&IoStackLocation
.Parameters
,
933 sizeof(Stack
->Parameters
));
936 /* Do the PnP call */
937 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
939 (PVOID
)&IoStatusBlock
->Information
);
940 return IoStatusBlock
->Status
;
944 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
946 PDEVICE_NODE ParentDeviceNode
;
947 PDEVICE_NODE ChildDeviceNode
;
950 /* Copy context data so we don't overwrite it in subsequent calls to this function */
951 ParentDeviceNode
= Context
->DeviceNode
;
953 /* Call the action routine */
954 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
955 if (!NT_SUCCESS(Status
))
960 /* Traversal of all children nodes */
961 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
962 ChildDeviceNode
!= NULL
;
963 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
965 /* Pass the current device node to the action routine */
966 Context
->DeviceNode
= ChildDeviceNode
;
968 Status
= IopTraverseDeviceTreeNode(Context
);
969 if (!NT_SUCCESS(Status
))
980 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
984 DPRINT("Context 0x%p\n", Context
);
986 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
987 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
989 /* Start from the specified device node */
990 Context
->DeviceNode
= Context
->FirstDeviceNode
;
992 /* Recursively traverse the device tree */
993 Status
= IopTraverseDeviceTreeNode(Context
);
994 if (Status
== STATUS_UNSUCCESSFUL
)
996 /* The action routine just wanted to terminate the traversal with status
997 code STATUS_SUCCESS */
998 Status
= STATUS_SUCCESS
;
1006 * IopCreateDeviceKeyPath
1008 * Creates a registry key
1012 * Name of the key to be created.
1014 * Handle to the newly created key
1017 * This method can create nested trees, so parent of RegistryPath can
1018 * be not existant, and will be created if needed.
1022 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
1023 IN ULONG CreateOptions
,
1026 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
1027 HANDLE hParent
= NULL
, hKey
;
1028 OBJECT_ATTRIBUTES ObjectAttributes
;
1029 UNICODE_STRING KeyName
;
1030 LPCWSTR Current
, Last
;
1034 /* Assume failure */
1037 /* Open root key for device instances */
1038 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
1039 if (!NT_SUCCESS(Status
))
1041 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
1045 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
1046 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
1048 /* Go up to the end of the string */
1049 while (Current
<= Last
)
1051 if (Current
!= Last
&& *Current
!= '\\')
1053 /* Not the end of the string and not a separator */
1058 /* Prepare relative key name */
1059 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
1060 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
1061 DPRINT("Create '%wZ'\n", &KeyName
);
1064 InitializeObjectAttributes(&ObjectAttributes
,
1066 OBJ_CASE_INSENSITIVE
,
1069 Status
= ZwCreateKey(&hKey
,
1070 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
1077 /* Close parent key handle, we don't need it anymore */
1081 /* Key opening/creating failed? */
1082 if (!NT_SUCCESS(Status
))
1084 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
1088 /* Check if it is the end of the string */
1089 if (Current
== Last
)
1091 /* Yes, return success */
1093 return STATUS_SUCCESS
;
1096 /* Start with this new parent key */
1099 KeyName
.Buffer
= (LPWSTR
)Current
;
1102 return STATUS_UNSUCCESSFUL
;
1106 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1107 PDEVICE_NODE DeviceNode
)
1109 OBJECT_ATTRIBUTES ObjectAttributes
;
1110 UNICODE_STRING KeyName
;
1115 HANDLE ControlHandle
;
1117 DPRINT("IopSetDeviceInstanceData() called\n");
1119 /* Create the 'LogConf' key */
1120 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1121 InitializeObjectAttributes(&ObjectAttributes
,
1123 OBJ_CASE_INSENSITIVE
,
1126 Status
= ZwCreateKey(&LogConfKey
,
1133 if (NT_SUCCESS(Status
))
1135 /* Set 'BootConfig' value */
1136 if (DeviceNode
->BootResources
!= NULL
)
1138 ResCount
= DeviceNode
->BootResources
->Count
;
1141 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1142 Status
= ZwSetValueKey(LogConfKey
,
1146 DeviceNode
->BootResources
,
1147 PnpDetermineResourceListSize(DeviceNode
->BootResources
));
1151 /* Set 'BasicConfigVector' value */
1152 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1153 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1155 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1156 Status
= ZwSetValueKey(LogConfKey
,
1159 REG_RESOURCE_REQUIREMENTS_LIST
,
1160 DeviceNode
->ResourceRequirements
,
1161 DeviceNode
->ResourceRequirements
->ListSize
);
1164 ZwClose(LogConfKey
);
1167 /* Set the 'ConfigFlags' value */
1168 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1169 Status
= ZwQueryValueKey(InstanceKey
,
1171 KeyValueBasicInformation
,
1175 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1177 /* Write the default value */
1178 ULONG DefaultConfigFlags
= 0;
1179 Status
= ZwSetValueKey(InstanceKey
,
1183 &DefaultConfigFlags
,
1184 sizeof(DefaultConfigFlags
));
1187 /* Create the 'Control' key */
1188 RtlInitUnicodeString(&KeyName
, L
"Control");
1189 InitializeObjectAttributes(&ObjectAttributes
,
1191 OBJ_CASE_INSENSITIVE
,
1194 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1196 if (NT_SUCCESS(Status
))
1197 ZwClose(ControlHandle
);
1199 DPRINT("IopSetDeviceInstanceData() done\n");
1205 * IopGetParentIdPrefix
1207 * Retrieve (or create) a string which identifies a device.
1211 * Pointer to device node.
1213 * Pointer to the string where is returned the parent node identifier
1216 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1217 * valid and its Buffer field is NULL-terminated. The caller needs to
1218 * to free the string with RtlFreeUnicodeString when it is no longer
1223 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1224 PUNICODE_STRING ParentIdPrefix
)
1226 ULONG KeyNameBufferLength
;
1227 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1228 UNICODE_STRING KeyName
;
1229 UNICODE_STRING KeyValue
;
1230 UNICODE_STRING ValueName
;
1235 /* HACK: As long as some devices have a NULL device
1236 * instance path, the following test is required :(
1238 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1240 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1241 &DeviceNode
->InstancePath
);
1242 return STATUS_UNSUCCESSFUL
;
1245 /* 1. Try to retrieve ParentIdPrefix from registry */
1246 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1247 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1248 if (!ParentIdPrefixInformation
)
1250 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1255 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1256 if (!KeyName
.Buffer
)
1258 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1262 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1264 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1265 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1267 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1268 if (!NT_SUCCESS(Status
))
1270 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1271 Status
= ZwQueryValueKey(
1273 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1274 KeyNameBufferLength
, &KeyNameBufferLength
);
1275 if (NT_SUCCESS(Status
))
1277 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1278 Status
= STATUS_UNSUCCESSFUL
;
1281 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1282 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1286 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1288 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1289 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1293 /* 2. Create the ParentIdPrefix value */
1294 crc32
= RtlComputeCrc32(0,
1295 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1296 DeviceNode
->Parent
->InstancePath
.Length
);
1298 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1299 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1301 /* 3. Try to write the ParentIdPrefix to registry */
1302 Status
= ZwSetValueKey(hKey
,
1306 (PVOID
)KeyValue
.Buffer
,
1307 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1310 if (NT_SUCCESS(Status
))
1312 /* Duplicate the string to return it */
1313 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1315 ExFreePool(ParentIdPrefixInformation
);
1316 RtlFreeUnicodeString(&KeyName
);
1324 * IopActionInterrogateDeviceStack
1326 * Retrieve information for all (direct) child nodes of a parent node.
1330 * Pointer to device node.
1332 * Pointer to parent node to retrieve child node information for.
1335 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1336 * when we reach a device node which is not a direct child of the device
1337 * node for which we retrieve information of child nodes for. Any errors
1338 * that occur is logged instead so that all child services have a chance
1339 * of being interrogated.
1343 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1346 IO_STATUS_BLOCK IoStatusBlock
;
1347 PDEVICE_NODE ParentDeviceNode
;
1348 WCHAR InstancePath
[MAX_PATH
];
1349 IO_STACK_LOCATION Stack
;
1354 ULONG RequiredLength
;
1356 HANDLE InstanceKey
= NULL
;
1357 UNICODE_STRING ValueName
;
1358 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1359 DEVICE_CAPABILITIES DeviceCapabilities
;
1361 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1362 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1364 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1367 * We are called for the parent too, but we don't need to do special
1368 * handling for this node
1371 if (DeviceNode
== ParentDeviceNode
)
1373 DPRINT("Success\n");
1374 return STATUS_SUCCESS
;
1378 * Make sure this device node is a direct child of the parent device node
1379 * that is given as an argument
1382 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1384 /* Stop the traversal immediately and indicate successful operation */
1386 return STATUS_UNSUCCESSFUL
;
1390 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1391 if (!NT_SUCCESS(Status
))
1393 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1398 * FIXME: For critical errors, cleanup and disable device, but always
1399 * return STATUS_SUCCESS.
1402 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1404 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1405 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1409 if (NT_SUCCESS(Status
))
1411 /* Copy the device id string */
1412 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1415 * FIXME: Check for valid characters, if there is invalid characters
1421 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1424 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
1426 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1427 if (!NT_SUCCESS(Status
))
1429 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1432 /* This bit is only check after enumeration */
1433 if (DeviceCapabilities
.HardwareDisabled
)
1435 /* FIXME: Cleanup device */
1436 DeviceNode
->Flags
|= DNF_DISABLED
;
1437 return STATUS_SUCCESS
;
1440 DeviceNode
->Flags
&= ~DNF_DISABLED
;
1442 if (!DeviceCapabilities
.UniqueID
)
1444 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1445 DPRINT("Instance ID is not unique\n");
1446 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1447 if (!NT_SUCCESS(Status
))
1449 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1453 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1455 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1456 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1460 if (NT_SUCCESS(Status
))
1462 /* Append the instance id string */
1463 wcscat(InstancePath
, L
"\\");
1464 if (ParentIdPrefix
.Length
> 0)
1466 /* Add information from parent bus device to InstancePath */
1467 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1468 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1469 wcscat(InstancePath
, L
"&");
1471 if (IoStatusBlock
.Information
)
1472 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1475 * FIXME: Check for valid characters, if there is invalid characters
1481 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1483 RtlFreeUnicodeString(&ParentIdPrefix
);
1485 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1487 DPRINT("No resources\n");
1488 /* FIXME: Cleanup and disable device */
1491 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1494 * Create registry key for the instance id, if it doesn't exist yet
1496 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
1497 if (!NT_SUCCESS(Status
))
1499 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1502 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1504 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1505 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1509 if (NT_SUCCESS(Status
))
1512 * FIXME: Check for valid characters, if there is invalid characters
1516 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1517 DPRINT("Hardware IDs:\n");
1520 DPRINT(" %S\n", Ptr
);
1521 Length
= wcslen(Ptr
) + 1;
1524 TotalLength
+= Length
;
1526 DPRINT("TotalLength: %hu\n", TotalLength
);
1529 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1530 Status
= ZwSetValueKey(InstanceKey
,
1534 (PVOID
)IoStatusBlock
.Information
,
1535 (TotalLength
+ 1) * sizeof(WCHAR
));
1536 if (!NT_SUCCESS(Status
))
1538 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1543 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1546 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1548 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1549 Status
= IopInitiatePnpIrp(
1550 DeviceNode
->PhysicalDeviceObject
,
1554 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1557 * FIXME: Check for valid characters, if there is invalid characters
1561 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1562 DPRINT("Compatible IDs:\n");
1565 DPRINT(" %S\n", Ptr
);
1566 Length
= wcslen(Ptr
) + 1;
1569 TotalLength
+= Length
;
1571 DPRINT("TotalLength: %hu\n", TotalLength
);
1574 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1575 Status
= ZwSetValueKey(InstanceKey
,
1579 (PVOID
)IoStatusBlock
.Information
,
1580 (TotalLength
+ 1) * sizeof(WCHAR
));
1581 if (!NT_SUCCESS(Status
))
1583 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1588 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1591 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1593 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1594 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1595 Status
= IopInitiatePnpIrp(
1596 DeviceNode
->PhysicalDeviceObject
,
1598 IRP_MN_QUERY_DEVICE_TEXT
,
1600 /* This key is mandatory, so even if the Irp fails, we still write it */
1601 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1602 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1604 if (NT_SUCCESS(Status
) &&
1605 IoStatusBlock
.Information
&&
1606 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1608 /* This key is overriden when a driver is installed. Don't write the
1609 * new description if another one already exists */
1610 Status
= ZwSetValueKey(InstanceKey
,
1614 (PVOID
)IoStatusBlock
.Information
,
1615 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1619 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1620 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1622 Status
= ZwSetValueKey(InstanceKey
,
1627 DeviceDesc
.MaximumLength
);
1629 if (!NT_SUCCESS(Status
))
1631 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1637 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1639 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1640 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1641 Status
= IopInitiatePnpIrp(
1642 DeviceNode
->PhysicalDeviceObject
,
1644 IRP_MN_QUERY_DEVICE_TEXT
,
1646 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1648 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1649 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1650 Status
= ZwSetValueKey(InstanceKey
,
1654 (PVOID
)IoStatusBlock
.Information
,
1655 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1656 if (!NT_SUCCESS(Status
))
1658 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1663 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1666 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1668 Status
= IopInitiatePnpIrp(
1669 DeviceNode
->PhysicalDeviceObject
,
1671 IRP_MN_QUERY_BUS_INFORMATION
,
1673 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1675 PPNP_BUS_INFORMATION BusInformation
=
1676 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1678 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1679 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1680 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1681 ExFreePool(BusInformation
);
1685 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1687 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1688 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1689 DeviceNode
->ChildBusTypeIndex
= -1;
1692 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1694 Status
= IopInitiatePnpIrp(
1695 DeviceNode
->PhysicalDeviceObject
,
1697 IRP_MN_QUERY_RESOURCES
,
1699 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1701 DeviceNode
->BootResources
=
1702 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1703 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
1707 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1708 DeviceNode
->BootResources
= NULL
;
1711 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1713 Status
= IopInitiatePnpIrp(
1714 DeviceNode
->PhysicalDeviceObject
,
1716 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1718 if (NT_SUCCESS(Status
))
1720 DeviceNode
->ResourceRequirements
=
1721 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1725 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1726 DeviceNode
->ResourceRequirements
= NULL
;
1729 if (InstanceKey
!= NULL
)
1731 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1734 ZwClose(InstanceKey
);
1736 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1738 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1740 /* Report the device to the user-mode pnp manager */
1741 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1742 &DeviceNode
->InstancePath
);
1745 return STATUS_SUCCESS
;
1750 IopHandleDeviceRemoval(
1751 IN PDEVICE_NODE DeviceNode
,
1752 IN PDEVICE_RELATIONS DeviceRelations
)
1754 PDEVICE_NODE Child
= DeviceNode
->Child
, NextChild
;
1758 while (Child
!= NULL
)
1760 NextChild
= Child
->Sibling
;
1763 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1765 if (IopGetDeviceNode(DeviceRelations
->Objects
[i
]) == Child
)
1774 IopSendSurpriseRemoval(Child
->PhysicalDeviceObject
);
1776 /* Tell the user-mode PnP manager that a device was removed */
1777 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
1778 &Child
->InstancePath
);
1780 IopSendRemoveDevice(Child
->PhysicalDeviceObject
);
1789 IN PDEVICE_OBJECT DeviceObject
)
1791 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1792 DEVICETREE_TRAVERSE_CONTEXT Context
;
1793 PDEVICE_RELATIONS DeviceRelations
;
1794 PDEVICE_OBJECT ChildDeviceObject
;
1795 IO_STATUS_BLOCK IoStatusBlock
;
1796 PDEVICE_NODE ChildDeviceNode
;
1797 IO_STACK_LOCATION Stack
;
1801 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1803 if (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
)
1805 DeviceNode
->Flags
&= ~DNF_NEED_ENUMERATION_ONLY
;
1807 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1808 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1809 &DeviceNode
->InstancePath
);
1812 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1814 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1816 Status
= IopInitiatePnpIrp(
1819 IRP_MN_QUERY_DEVICE_RELATIONS
,
1821 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1823 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1827 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1829 if (!DeviceRelations
)
1831 DPRINT("No PDOs\n");
1832 return STATUS_UNSUCCESSFUL
;
1835 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1838 * Send removal IRPs for devices that have disappeared
1840 IopHandleDeviceRemoval(DeviceNode
, DeviceRelations
);
1843 * Create device nodes for all discovered devices
1845 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1847 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1848 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1850 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1851 if (!ChildDeviceNode
)
1853 /* One doesn't exist, create it */
1854 Status
= IopCreateDeviceNode(
1859 if (NT_SUCCESS(Status
))
1861 /* Mark the node as enumerated */
1862 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1864 /* Mark the DO as bus enumerated */
1865 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1869 /* Ignore this DO */
1870 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1871 ObDereferenceObject(ChildDeviceNode
);
1876 /* Mark it as enumerated */
1877 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1878 ObDereferenceObject(ChildDeviceObject
);
1881 ExFreePool(DeviceRelations
);
1884 * Retrieve information about all discovered children from the bus driver
1886 IopInitDeviceTreeTraverseContext(
1889 IopActionInterrogateDeviceStack
,
1892 Status
= IopTraverseDeviceTree(&Context
);
1893 if (!NT_SUCCESS(Status
))
1895 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1900 * Retrieve configuration from the registry for discovered children
1902 IopInitDeviceTreeTraverseContext(
1905 IopActionConfigureChildServices
,
1908 Status
= IopTraverseDeviceTree(&Context
);
1909 if (!NT_SUCCESS(Status
))
1911 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1916 * Initialize services for discovered children.
1918 Status
= IopInitializePnpServices(DeviceNode
);
1919 if (!NT_SUCCESS(Status
))
1921 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1925 DPRINT("IopEnumerateDevice() finished\n");
1926 return STATUS_SUCCESS
;
1931 * IopActionConfigureChildServices
1933 * Retrieve configuration for all (direct) child nodes of a parent node.
1937 * Pointer to device node.
1939 * Pointer to parent node to retrieve child node configuration for.
1942 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1943 * when we reach a device node which is not a direct child of the device
1944 * node for which we configure child services for. Any errors that occur is
1945 * logged instead so that all child services have a chance of beeing
1950 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1953 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1954 PDEVICE_NODE ParentDeviceNode
;
1955 PUNICODE_STRING Service
;
1956 UNICODE_STRING ClassGUID
;
1958 DEVICE_CAPABILITIES DeviceCaps
;
1960 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1962 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1965 * We are called for the parent too, but we don't need to do special
1966 * handling for this node
1968 if (DeviceNode
== ParentDeviceNode
)
1970 DPRINT("Success\n");
1971 return STATUS_SUCCESS
;
1975 * Make sure this device node is a direct child of the parent device node
1976 * that is given as an argument
1978 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1980 /* Stop the traversal immediately and indicate successful operation */
1982 return STATUS_UNSUCCESSFUL
;
1985 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1987 WCHAR RegKeyBuffer
[MAX_PATH
];
1988 UNICODE_STRING RegKey
;
1991 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1992 RegKey
.Buffer
= RegKeyBuffer
;
1995 * Retrieve configuration from Enum key
1998 Service
= &DeviceNode
->ServiceName
;
2000 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2001 RtlInitUnicodeString(Service
, NULL
);
2002 RtlInitUnicodeString(&ClassGUID
, NULL
);
2004 QueryTable
[0].Name
= L
"Service";
2005 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2006 QueryTable
[0].EntryContext
= Service
;
2008 QueryTable
[1].Name
= L
"ClassGUID";
2009 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2010 QueryTable
[1].EntryContext
= &ClassGUID
;
2011 QueryTable
[1].DefaultType
= REG_SZ
;
2012 QueryTable
[1].DefaultData
= L
"";
2013 QueryTable
[1].DefaultLength
= 0;
2015 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2016 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2018 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2019 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2021 if (!NT_SUCCESS(Status
))
2023 /* FIXME: Log the error */
2024 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2025 &DeviceNode
->InstancePath
, Status
);
2026 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2027 return STATUS_SUCCESS
;
2030 if (Service
->Buffer
== NULL
)
2032 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
2033 DeviceCaps
.RawDeviceOK
)
2035 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
2037 DeviceNode
->ServiceName
.Length
= 0;
2038 DeviceNode
->ServiceName
.MaximumLength
= 0;
2039 DeviceNode
->ServiceName
.Buffer
= NULL
;
2041 else if (ClassGUID
.Length
!= 0)
2043 /* Device has a ClassGUID value, but no Service value.
2044 * Suppose it is using the NULL driver, so state the
2045 * device is started */
2046 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2047 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2051 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2053 return STATUS_SUCCESS
;
2056 DPRINT("Got Service %S\n", Service
->Buffer
);
2059 return STATUS_SUCCESS
;
2063 * IopActionInitChildServices
2065 * Initialize the service for all (direct) child nodes of a parent node
2069 * Pointer to device node.
2071 * Pointer to parent node to initialize child node services for.
2074 * If the driver image for a service is not loaded and initialized
2075 * it is done here too. We only return a status code indicating an
2076 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2077 * not a direct child of the device node for which we initialize
2078 * child services for. Any errors that occur is logged instead so
2079 * that all child services have a chance of being initialized.
2083 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2086 PDEVICE_NODE ParentDeviceNode
;
2088 BOOLEAN BootDrivers
= !PnpSystemInit
;
2090 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2092 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2095 * We are called for the parent too, but we don't need to do special
2096 * handling for this node
2098 if (DeviceNode
== ParentDeviceNode
)
2100 DPRINT("Success\n");
2101 return STATUS_SUCCESS
;
2105 * Make sure this device node is a direct child of the parent device node
2106 * that is given as an argument
2109 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2112 * Stop the traversal immediately and indicate unsuccessful operation
2115 return STATUS_UNSUCCESSFUL
;
2118 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
2119 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
2120 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2121 return STATUS_SUCCESS
;
2123 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
2125 /* We don't need to worry about loading the driver because we're
2126 * being driven in raw mode so our parent must be loaded to get here */
2127 Status
= IopInitializeDevice(DeviceNode
, NULL
);
2128 if (NT_SUCCESS(Status
))
2130 Status
= IopStartDevice(DeviceNode
);
2131 if (!NT_SUCCESS(Status
))
2133 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
2134 &DeviceNode
->InstancePath
, Status
);
2140 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2141 PDRIVER_OBJECT DriverObject
;
2143 /* Get existing DriverObject pointer (in case the driver has
2144 already been loaded and initialized) */
2145 Status
= IopGetDriverObject(
2147 &DeviceNode
->ServiceName
,
2150 if (!NT_SUCCESS(Status
))
2152 /* Driver is not initialized, try to load it */
2153 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2155 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2157 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2158 was loaded by the bootloader */
2159 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2160 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2162 /* Initialize the driver */
2163 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2164 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2168 Status
= STATUS_SUCCESS
;
2173 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2174 &DeviceNode
->ServiceName
, Status
);
2178 /* Driver is loaded and initialized at this point */
2179 if (NT_SUCCESS(Status
))
2181 /* Initialize the device, including all filters */
2182 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
2187 * Don't disable when trying to load only boot drivers
2191 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2192 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2193 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2194 DPRINT1("Initialization of service %S failed (Status %x)\n",
2195 DeviceNode
->ServiceName
.Buffer
, Status
);
2200 return STATUS_SUCCESS
;
2204 * IopInitializePnpServices
2206 * Initialize services for discovered children
2210 * Top device node to start initializing services.
2216 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2218 DEVICETREE_TRAVERSE_CONTEXT Context
;
2220 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2222 IopInitDeviceTreeTraverseContext(
2225 IopActionInitChildServices
,
2228 return IopTraverseDeviceTree(&Context
);
2231 static NTSTATUS INIT_FUNCTION
2232 IopEnumerateDetectedDevices(
2234 IN PUNICODE_STRING RelativePath OPTIONAL
,
2236 IN BOOLEAN EnumerateSubKeys
,
2237 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2238 IN ULONG ParentBootResourcesLength
)
2240 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2241 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2242 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2243 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2244 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2245 OBJECT_ATTRIBUTES ObjectAttributes
;
2246 HANDLE hDevicesKey
= NULL
;
2247 HANDLE hDeviceKey
= NULL
;
2248 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2249 UNICODE_STRING Level2NameU
;
2250 WCHAR Level2Name
[5];
2251 ULONG IndexDevice
= 0;
2253 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2254 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2255 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2256 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2257 UNICODE_STRING DeviceName
, ValueName
;
2259 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2260 ULONG BootResourcesLength
;
2263 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2264 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2265 static ULONG DeviceIndexPci
= 0;
2266 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2267 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2268 static ULONG DeviceIndexSerial
= 0;
2269 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2270 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2271 static ULONG DeviceIndexKeyboard
= 0;
2272 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2273 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2274 static ULONG DeviceIndexMouse
= 0;
2275 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2276 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2277 static ULONG DeviceIndexParallel
= 0;
2278 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2279 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2280 static ULONG DeviceIndexFloppy
= 0;
2281 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2282 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2283 static ULONG DeviceIndexIsa
= 0;
2284 UNICODE_STRING HardwareIdKey
;
2285 PUNICODE_STRING pHardwareId
;
2286 ULONG DeviceIndex
= 0;
2287 PUCHAR CmResourceList
;
2292 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2293 if (!NT_SUCCESS(Status
))
2295 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2300 hDevicesKey
= hBaseKey
;
2302 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2303 if (!pDeviceInformation
)
2305 DPRINT("ExAllocatePool() failed\n");
2306 Status
= STATUS_NO_MEMORY
;
2310 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2311 if (!pValueInformation
)
2313 DPRINT("ExAllocatePool() failed\n");
2314 Status
= STATUS_NO_MEMORY
;
2320 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2321 if (Status
== STATUS_NO_MORE_ENTRIES
)
2323 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2325 ExFreePool(pDeviceInformation
);
2326 DeviceInfoLength
= RequiredSize
;
2327 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2328 if (!pDeviceInformation
)
2330 DPRINT("ExAllocatePool() failed\n");
2331 Status
= STATUS_NO_MEMORY
;
2334 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2336 if (!NT_SUCCESS(Status
))
2338 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2343 /* Open device key */
2344 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2345 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2347 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2348 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2349 if (!NT_SUCCESS(Status
))
2351 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2355 /* Read boot resources, and add then to parent ones */
2356 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2357 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2359 ExFreePool(pValueInformation
);
2360 ValueInfoLength
= RequiredSize
;
2361 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2362 if (!pValueInformation
)
2364 DPRINT("ExAllocatePool() failed\n");
2365 ZwDeleteKey(hLevel2Key
);
2366 Status
= STATUS_NO_MEMORY
;
2369 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2371 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2373 BootResources
= ParentBootResources
;
2374 BootResourcesLength
= ParentBootResourcesLength
;
2376 else if (!NT_SUCCESS(Status
))
2378 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2381 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2383 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2388 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2390 /* Concatenate current resources and parent ones */
2391 if (ParentBootResourcesLength
== 0)
2392 BootResourcesLength
= pValueInformation
->DataLength
;
2394 BootResourcesLength
= ParentBootResourcesLength
2395 + pValueInformation
->DataLength
2397 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2400 DPRINT("ExAllocatePool() failed\n");
2403 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2405 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2407 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2409 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2411 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2412 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2413 ParentBootResourcesLength
- Header
);
2414 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2418 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2420 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2421 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2422 ParentBootResourcesLength
- Header
);
2424 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2425 pValueInformation
->Data
+ Header
,
2426 pValueInformation
->DataLength
- Header
);
2427 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2431 if (EnumerateSubKeys
)
2436 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2437 if (Status
== STATUS_NO_MORE_ENTRIES
)
2439 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2441 ExFreePool(pDeviceInformation
);
2442 DeviceInfoLength
= RequiredSize
;
2443 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2444 if (!pDeviceInformation
)
2446 DPRINT("ExAllocatePool() failed\n");
2447 Status
= STATUS_NO_MEMORY
;
2450 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2452 if (!NT_SUCCESS(Status
))
2454 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2458 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2459 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2461 Status
= IopEnumerateDetectedDevices(
2467 BootResourcesLength
);
2468 if (!NT_SUCCESS(Status
))
2473 /* Read identifier */
2474 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2475 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2477 ExFreePool(pValueInformation
);
2478 ValueInfoLength
= RequiredSize
;
2479 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2480 if (!pValueInformation
)
2482 DPRINT("ExAllocatePool() failed\n");
2483 Status
= STATUS_NO_MEMORY
;
2486 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2488 if (!NT_SUCCESS(Status
))
2490 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2492 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2495 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2497 else if (pValueInformation
->Type
!= REG_SZ
)
2499 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2504 /* Assign hardware id to this device */
2505 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2506 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2507 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2508 ValueName
.Length
-= sizeof(WCHAR
);
2511 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2513 pHardwareId
= &HardwareIdSerial
;
2514 DeviceIndex
= DeviceIndexSerial
++;
2516 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2518 pHardwareId
= &HardwareIdKeyboard
;
2519 DeviceIndex
= DeviceIndexKeyboard
++;
2521 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2523 pHardwareId
= &HardwareIdMouse
;
2524 DeviceIndex
= DeviceIndexMouse
++;
2526 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
2528 pHardwareId
= &HardwareIdParallel
;
2529 DeviceIndex
= DeviceIndexParallel
++;
2531 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
2533 pHardwareId
= &HardwareIdFloppy
;
2534 DeviceIndex
= DeviceIndexFloppy
++;
2536 else if (NT_SUCCESS(Status
))
2538 /* Try to also match the device identifier */
2539 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2541 pHardwareId
= &HardwareIdPci
;
2542 DeviceIndex
= DeviceIndexPci
++;
2544 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
2546 pHardwareId
= &HardwareIdIsa
;
2547 DeviceIndex
= DeviceIndexIsa
++;
2551 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2557 /* Unknown key path */
2558 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2562 /* Prepare hardware id key (hardware id value without final \0) */
2563 HardwareIdKey
= *pHardwareId
;
2564 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2566 /* Add the detected device to Root key */
2567 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2568 Status
= ZwCreateKey(
2574 REG_OPTION_NON_VOLATILE
,
2576 if (!NT_SUCCESS(Status
))
2578 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2581 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2582 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2583 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2584 Status
= ZwCreateKey(
2586 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2590 REG_OPTION_NON_VOLATILE
,
2592 ZwClose(hLevel1Key
);
2593 if (!NT_SUCCESS(Status
))
2595 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2598 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
2599 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2600 if (!NT_SUCCESS(Status
))
2602 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2603 ZwDeleteKey(hLevel2Key
);
2606 /* Create 'LogConf' subkey */
2607 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2608 Status
= ZwCreateKey(
2614 REG_OPTION_VOLATILE
,
2616 if (!NT_SUCCESS(Status
))
2618 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2619 ZwDeleteKey(hLevel2Key
);
2622 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2624 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
2625 if (!CmResourceList
)
2628 ZwDeleteKey(hLevel2Key
);
2632 /* Add the list count (1st member of CM_RESOURCE_LIST) */
2634 RtlCopyMemory(CmResourceList
,
2638 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
2639 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
2641 BootResourcesLength
);
2643 /* Save boot resources to 'LogConf\BootConfig' */
2644 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
2645 if (!NT_SUCCESS(Status
))
2647 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2649 ZwDeleteKey(hLevel2Key
);
2656 if (BootResources
&& BootResources
!= ParentBootResources
)
2658 ExFreePool(BootResources
);
2659 BootResources
= NULL
;
2663 ZwClose(hLevel2Key
);
2668 ZwClose(hDeviceKey
);
2673 Status
= STATUS_SUCCESS
;
2676 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2677 ZwClose(hDevicesKey
);
2679 ZwClose(hDeviceKey
);
2680 if (pDeviceInformation
)
2681 ExFreePool(pDeviceInformation
);
2682 if (pValueInformation
)
2683 ExFreePool(pValueInformation
);
2687 static BOOLEAN INIT_FUNCTION
2688 IopIsAcpiComputer(VOID
)
2693 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2694 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2695 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2696 OBJECT_ATTRIBUTES ObjectAttributes
;
2697 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2698 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2699 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2700 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2702 ULONG IndexDevice
= 0;
2703 UNICODE_STRING DeviceName
, ValueName
;
2704 HANDLE hDevicesKey
= NULL
;
2705 HANDLE hDeviceKey
= NULL
;
2707 BOOLEAN ret
= FALSE
;
2709 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2710 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2711 if (!NT_SUCCESS(Status
))
2713 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2717 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2718 if (!pDeviceInformation
)
2720 DPRINT("ExAllocatePool() failed\n");
2721 Status
= STATUS_NO_MEMORY
;
2725 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2726 if (!pDeviceInformation
)
2728 DPRINT("ExAllocatePool() failed\n");
2729 Status
= STATUS_NO_MEMORY
;
2735 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2736 if (Status
== STATUS_NO_MORE_ENTRIES
)
2738 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2740 ExFreePool(pDeviceInformation
);
2741 DeviceInfoLength
= RequiredSize
;
2742 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2743 if (!pDeviceInformation
)
2745 DPRINT("ExAllocatePool() failed\n");
2746 Status
= STATUS_NO_MEMORY
;
2749 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2751 if (!NT_SUCCESS(Status
))
2753 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2758 /* Open device key */
2759 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2760 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2761 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2766 if (!NT_SUCCESS(Status
))
2768 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2772 /* Read identifier */
2773 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2774 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2776 ExFreePool(pValueInformation
);
2777 ValueInfoLength
= RequiredSize
;
2778 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2779 if (!pValueInformation
)
2781 DPRINT("ExAllocatePool() failed\n");
2782 Status
= STATUS_NO_MEMORY
;
2785 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2787 if (!NT_SUCCESS(Status
))
2789 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2792 else if (pValueInformation
->Type
!= REG_SZ
)
2794 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2798 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2799 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2800 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2801 ValueName
.Length
-= sizeof(WCHAR
);
2802 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
2804 DPRINT("Found ACPI BIOS\n");
2810 ZwClose(hDeviceKey
);
2815 if (pDeviceInformation
)
2816 ExFreePool(pDeviceInformation
);
2817 if (pValueInformation
)
2818 ExFreePool(pValueInformation
);
2820 ZwClose(hDevicesKey
);
2822 ZwClose(hDeviceKey
);
2830 IopUpdateRootKey(VOID
)
2832 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2833 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2834 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2835 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2836 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2837 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2838 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
2839 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
2840 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
2841 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2842 OBJECT_ATTRIBUTES ObjectAttributes
;
2843 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
2847 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2848 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2849 if (!NT_SUCCESS(Status
))
2851 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2855 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2856 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2858 if (!NT_SUCCESS(Status
))
2860 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2864 if (IopIsAcpiComputer())
2866 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
2867 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2869 if (!NT_SUCCESS(Status
))
2871 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
2872 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, 0, &Disposition
);
2873 ZwClose(hHalAcpiDevice
);
2874 if (!NT_SUCCESS(Status
))
2876 if (Disposition
== REG_CREATED_NEW_KEY
)
2878 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
2879 if (NT_SUCCESS(Status
))
2880 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
2882 if (NT_SUCCESS(Status
))
2884 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
2885 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2886 if (NT_SUCCESS(Status
))
2889 ZwClose(hHalAcpiId
);
2894 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2895 if (!NT_SUCCESS(Status
))
2897 /* Nothing to do, don't return with an error status */
2898 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2900 return STATUS_SUCCESS
;
2902 Status
= IopEnumerateDetectedDevices(
2917 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2919 PUNICODE_STRING Name
,
2920 ACCESS_MASK DesiredAccess
)
2922 OBJECT_ATTRIBUTES ObjectAttributes
;
2929 InitializeObjectAttributes(&ObjectAttributes
,
2931 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2935 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2942 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
2943 IN HANDLE RootHandle OPTIONAL
,
2944 IN PUNICODE_STRING KeyName
,
2945 IN ACCESS_MASK DesiredAccess
,
2946 IN ULONG CreateOptions
,
2947 OUT PULONG Disposition OPTIONAL
)
2949 OBJECT_ATTRIBUTES ObjectAttributes
;
2950 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0, Length
;
2951 HANDLE HandleArray
[2];
2952 BOOLEAN Recursing
= TRUE
;
2954 UNICODE_STRING KeyString
;
2955 NTSTATUS Status
= STATUS_SUCCESS
;
2958 /* P1 is start, pp is end */
2959 p1
= KeyName
->Buffer
;
2960 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
2962 /* Create the target key */
2963 InitializeObjectAttributes(&ObjectAttributes
,
2965 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2968 Status
= ZwCreateKey(&HandleArray
[i
],
2976 /* Now we check if this failed */
2977 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
2979 /* Target key failed, so we'll need to create its parent. Setup array */
2980 HandleArray
[0] = NULL
;
2981 HandleArray
[1] = RootHandle
;
2983 /* Keep recursing for each missing parent */
2986 /* And if we're deep enough, close the last handle */
2987 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2989 /* We're setup to ping-pong between the two handle array entries */
2990 RootHandleIndex
= i
;
2993 /* Clear the one we're attempting to open now */
2994 HandleArray
[i
] = NULL
;
2996 /* Process the parent key name */
2997 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
2998 Length
= (p
- p1
) * sizeof(WCHAR
);
3000 /* Is there a parent name? */
3003 /* Build the unicode string for it */
3004 KeyString
.Buffer
= p1
;
3005 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
3007 /* Now try opening the parent */
3008 InitializeObjectAttributes(&ObjectAttributes
,
3010 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3011 HandleArray
[RootHandleIndex
],
3013 Status
= ZwCreateKey(&HandleArray
[i
],
3020 if (NT_SUCCESS(Status
))
3022 /* It worked, we have one more handle */
3027 /* Parent key creation failed, abandon loop */
3034 /* We don't have a parent name, probably corrupted key name */
3035 Status
= STATUS_INVALID_PARAMETER
;
3040 /* Now see if there's more parents to create */
3042 if ((p
== pp
) || (p1
== pp
))
3044 /* We're done, hopefully successfully, so stop */
3049 /* Outer loop check for handle nesting that requires closing the top handle */
3050 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3053 /* Check if we broke out of the loop due to success */
3054 if (NT_SUCCESS(Status
))
3056 /* Return the target handle (we closed all the parent ones) and disposition */
3057 *Handle
= HandleArray
[i
];
3058 if (Disposition
) *Disposition
= KeyDisposition
;
3061 /* Return the success state */
3067 IopGetRegistryValue(IN HANDLE Handle
,
3069 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
3071 UNICODE_STRING ValueString
;
3073 PKEY_VALUE_FULL_INFORMATION FullInformation
;
3077 RtlInitUnicodeString(&ValueString
, ValueName
);
3079 Status
= ZwQueryValueKey(Handle
,
3081 KeyValueFullInformation
,
3085 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
3086 (Status
!= STATUS_BUFFER_TOO_SMALL
))
3091 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
3092 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
3094 Status
= ZwQueryValueKey(Handle
,
3096 KeyValueFullInformation
,
3100 if (!NT_SUCCESS(Status
))
3102 ExFreePool(FullInformation
);
3106 *Information
= FullInformation
;
3107 return STATUS_SUCCESS
;
3110 RTL_GENERIC_COMPARE_RESULTS
3112 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3113 IN PVOID FirstStruct
,
3114 IN PVOID SecondStruct
)
3122 // The allocation function is called by the generic table package whenever
3123 // it needs to allocate memory for the table.
3128 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3138 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3147 PpInitializeDeviceReferenceTable(VOID
)
3149 /* Setup the guarded mutex and AVL table */
3150 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3151 RtlInitializeGenericTableAvl(
3152 &PpDeviceReferenceTable
,
3153 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3154 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3155 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3163 /* Initialize the resource when accessing device registry data */
3164 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3166 /* Setup the device reference AVL table */
3167 PpInitializeDeviceReferenceTable();
3175 /* Check the initialization phase */
3176 switch (ExpInitializationPhase
)
3181 return PiInitPhase0();
3187 //return PiInitPhase1();
3191 /* Don't know any other phase! Bugcheck! */
3192 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3197 LONG IopNumberDeviceNodes
;
3201 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3203 PDEVICE_NODE DeviceNode
;
3207 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), 'donD');
3208 if (!DeviceNode
) return DeviceNode
;
3211 InterlockedIncrement(&IopNumberDeviceNodes
);
3214 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
3215 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
3216 DeviceNode
->BusNumber
= -1;
3217 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
3218 DeviceNode
->ChildBusNumber
= -1;
3219 DeviceNode
->ChildBusTypeIndex
= -1;
3220 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
3221 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
3222 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
3223 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
3224 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
3225 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
3227 /* Check if there is a PDO */
3228 if (PhysicalDeviceObject
)
3230 /* Link it and remove the init flag */
3231 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
3232 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
3233 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3236 /* Return the node */
3240 /* PUBLIC FUNCTIONS **********************************************************/
3244 PnpBusTypeGuidGet(IN USHORT Index
,
3245 IN LPGUID BusTypeGuid
)
3247 NTSTATUS Status
= STATUS_SUCCESS
;
3249 /* Acquire the lock */
3250 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
3253 if (Index
< PnpBusTypeGuidList
->GuidCount
)
3256 RtlCopyMemory(BusTypeGuid
, &PnpBusTypeGuidList
->Guids
[Index
], sizeof(GUID
));
3261 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
3264 /* Release lock and return status */
3265 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
3271 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject
,
3272 IN PHANDLE DeviceInstanceHandle
,
3273 IN ACCESS_MASK DesiredAccess
)
3277 PDEVICE_NODE DeviceNode
;
3278 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
3281 /* Open the enum key */
3282 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
3286 if (!NT_SUCCESS(Status
)) return Status
;
3288 /* Make sure we have an instance path */
3289 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3290 if ((DeviceNode
) && (DeviceNode
->InstancePath
.Length
))
3292 /* Get the instance key */
3293 Status
= IopOpenRegistryKeyEx(DeviceInstanceHandle
,
3295 &DeviceNode
->InstancePath
,
3301 Status
= STATUS_INVALID_DEVICE_REQUEST
;
3304 /* Close the handle and return status */
3311 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList
)
3313 ULONG FinalSize
, PartialSize
, EntrySize
, i
, j
;
3314 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
3315 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
3317 /* If we don't have one, that's easy */
3318 if (!ResourceList
) return 0;
3320 /* Start with the minimum size possible */
3321 FinalSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
3323 /* Loop each full descriptor */
3324 FullDescriptor
= ResourceList
->List
;
3325 for (i
= 0; i
< ResourceList
->Count
; i
++)
3327 /* Start with the minimum size possible */
3328 PartialSize
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
) +
3329 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
);
3331 /* Loop each partial descriptor */
3332 PartialDescriptor
= FullDescriptor
->PartialResourceList
.PartialDescriptors
;
3333 for (j
= 0; j
< FullDescriptor
->PartialResourceList
.Count
; j
++)
3335 /* Start with the minimum size possible */
3336 EntrySize
= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
3338 /* Check if there is extra data */
3339 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
3342 EntrySize
+= PartialDescriptor
->u
.DeviceSpecificData
.DataSize
;
3345 /* The size of partial descriptors is bigger */
3346 PartialSize
+= EntrySize
;
3348 /* Go to the next partial descriptor */
3349 PartialDescriptor
= (PVOID
)((ULONG_PTR
)PartialDescriptor
+ EntrySize
);
3352 /* The size of full descriptors is bigger */
3353 FinalSize
+= PartialSize
;
3355 /* Go to the next full descriptor */
3356 FullDescriptor
= (PVOID
)((ULONG_PTR
)FullDescriptor
+ PartialSize
);
3359 /* Return the final size */
3365 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject
,
3370 IN PULONG BufferLength
)
3373 HANDLE KeyHandle
, SubHandle
;
3374 UNICODE_STRING KeyString
;
3375 PKEY_VALUE_FULL_INFORMATION KeyValueInfo
= NULL
;
3379 /* Find the instance key */
3380 Status
= PnpDeviceObjectToDeviceInstance(DeviceObject
, &KeyHandle
, KEY_READ
);
3381 if (NT_SUCCESS(Status
))
3383 /* Check for name given by caller */
3387 RtlInitUnicodeString(&KeyString
, KeyName
);
3388 Status
= IopOpenRegistryKeyEx(&SubHandle
,
3392 if (NT_SUCCESS(Status
))
3394 /* And use this handle instead */
3396 KeyHandle
= SubHandle
;
3400 /* Check if sub-key handle succeeded (or no-op if no key name given) */
3401 if (NT_SUCCESS(Status
))
3403 /* Now get the size of the property */
3404 Status
= IopGetRegistryValue(KeyHandle
,
3413 /* Fail if any of the registry operations failed */
3414 if (!NT_SUCCESS(Status
)) return Status
;
3416 /* Check how much data we have to copy */
3417 Length
= KeyValueInfo
->DataLength
;
3418 if (*BufferLength
>= Length
)
3420 /* Check for a match in the value type */
3421 if (KeyValueInfo
->Type
== ValueType
)
3424 RtlCopyMemory(Buffer
,
3425 (PVOID
)((ULONG_PTR
)KeyValueInfo
+
3426 KeyValueInfo
->DataOffset
),
3431 /* Invalid registry property type, fail */
3432 Status
= STATUS_INVALID_PARAMETER_2
;
3437 /* Buffer is too small to hold data */
3438 Status
= STATUS_BUFFER_TOO_SMALL
;
3441 /* Return the required buffer length, free the buffer, and return status */
3442 *BufferLength
= Length
;
3443 ExFreePool(KeyValueInfo
);
3447 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
3448 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
3449 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED; while(TRUE); break;}
3456 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3457 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3458 IN ULONG BufferLength
,
3459 OUT PVOID PropertyBuffer
,
3460 OUT PULONG ResultLength
)
3462 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3463 DEVICE_CAPABILITIES DeviceCaps
;
3464 ULONG ReturnLength
= 0, Length
= 0, ValueType
;
3465 PWCHAR ValueName
= NULL
, EnumeratorNameEnd
, DeviceInstanceName
;
3467 NTSTATUS Status
= STATUS_BUFFER_TOO_SMALL
;
3469 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
3470 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3472 /* Assume failure */
3475 /* Only PDOs can call this */
3476 if (!DeviceNode
) return STATUS_INVALID_DEVICE_REQUEST
;
3478 /* Handle all properties */
3479 switch (DeviceProperty
)
3481 case DevicePropertyBusTypeGuid
:
3483 /* Get the GUID from the internal cache */
3484 Status
= PnpBusTypeGuidGet(DeviceNode
->ChildBusTypeIndex
, &BusTypeGuid
);
3485 if (!NT_SUCCESS(Status
)) return Status
;
3487 /* This is the format of the returned data */
3488 PIP_RETURN_DATA(sizeof(GUID
), &BusTypeGuid
);
3490 case DevicePropertyLegacyBusType
:
3492 /* Validate correct interface type */
3493 if (DeviceNode
->ChildInterfaceType
== InterfaceTypeUndefined
)
3494 return STATUS_OBJECT_NAME_NOT_FOUND
;
3496 /* This is the format of the returned data */
3497 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE
), &DeviceNode
->ChildInterfaceType
);
3499 case DevicePropertyBusNumber
:
3501 /* Validate correct bus number */
3502 if ((DeviceNode
->ChildBusNumber
& 0x80000000) == 0x80000000)
3503 return STATUS_OBJECT_NAME_NOT_FOUND
;
3505 /* This is the format of the returned data */
3506 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceNode
->ChildBusNumber
);
3508 case DevicePropertyEnumeratorName
:
3510 /* Get the instance path */
3511 DeviceInstanceName
= DeviceNode
->InstancePath
.Buffer
;
3514 ASSERT((BufferLength
& 1) == 0);
3515 ASSERT(DeviceInstanceName
!= NULL
);
3517 /* Get the name from the path */
3518 EnumeratorNameEnd
= wcschr(DeviceInstanceName
, OBJ_NAME_PATH_SEPARATOR
);
3519 ASSERT(EnumeratorNameEnd
);
3521 /* This is the format of the returned data */
3522 PIP_RETURN_DATA((EnumeratorNameEnd
- DeviceInstanceName
) * sizeof(WCHAR
),
3523 DeviceInstanceName
);
3525 case DevicePropertyAddress
:
3527 /* Query the device caps */
3528 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3529 if (!NT_SUCCESS(Status
) || (DeviceCaps
.Address
== MAXULONG
))
3530 return STATUS_OBJECT_NAME_NOT_FOUND
;
3532 /* This is the format of the returned data */
3533 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceCaps
.Address
);
3535 case DevicePropertyBootConfigurationTranslated
:
3537 /* Validate we have resources */
3538 if (!DeviceNode
->BootResources
)
3539 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
3541 /* No resources will still fake success, but with 0 bytes */
3543 return STATUS_SUCCESS
;
3546 /* This is the format of the returned data */
3547 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode
->BootResources
), // FIXFIX: Should use BootResourcesTranslated
3548 DeviceNode
->BootResources
); // FIXFIX: Should use BootResourcesTranslated
3550 case DevicePropertyPhysicalDeviceObjectName
:
3552 /* Sanity check for Unicode-sized string */
3553 ASSERT((BufferLength
& 1) == 0);
3555 /* Allocate name buffer */
3556 Length
= BufferLength
+ sizeof(OBJECT_NAME_INFORMATION
);
3557 ObjectNameInfo
= ExAllocatePool(PagedPool
, Length
);
3558 if (!ObjectNameInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
3560 /* Query the PDO name */
3561 Status
= ObQueryNameString(DeviceObject
,
3565 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
3567 /* It's up to the caller to try again */
3568 Status
= STATUS_BUFFER_TOO_SMALL
;
3571 /* Return if successful */
3572 if (NT_SUCCESS(Status
)) PIP_RETURN_DATA(ObjectNameInfo
->Name
.Length
,
3573 ObjectNameInfo
->Name
.Buffer
);
3575 /* Let the caller know how big the name is */
3576 *ResultLength
-= sizeof(OBJECT_NAME_INFORMATION
);
3579 /* Handle the registry-based properties */
3580 case DevicePropertyUINumber
:
3581 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER
, REG_DWORD
);
3582 case DevicePropertyLocationInformation
:
3583 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION
, REG_SZ
);
3584 case DevicePropertyDeviceDescription
:
3585 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC
, REG_SZ
);
3586 case DevicePropertyHardwareID
:
3587 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID
, REG_MULTI_SZ
);
3588 case DevicePropertyCompatibleIDs
:
3589 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS
, REG_MULTI_SZ
);
3590 case DevicePropertyBootConfiguration
:
3591 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG
, REG_RESOURCE_LIST
);
3592 case DevicePropertyClassName
:
3593 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS
, REG_SZ
);
3594 case DevicePropertyClassGuid
:
3595 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID
, REG_SZ
);
3596 case DevicePropertyDriverKeyName
:
3597 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER
, REG_SZ
);
3598 case DevicePropertyManufacturer
:
3599 PIP_REGISTRY_DATA(REGSTR_VAL_MFG
, REG_SZ
);
3600 case DevicePropertyFriendlyName
:
3601 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME
, REG_SZ
);
3602 case DevicePropertyContainerID
:
3603 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
3604 PIP_UNIMPLEMENTED();
3605 case DevicePropertyRemovalPolicy
:
3606 PIP_UNIMPLEMENTED();
3607 case DevicePropertyInstallState
:
3608 PIP_UNIMPLEMENTED();
3609 case DevicePropertyResourceRequirements
:
3610 PIP_UNIMPLEMENTED();
3611 case DevicePropertyAllocatedResources
:
3612 PIP_UNIMPLEMENTED();
3614 return STATUS_INVALID_PARAMETER_2
;
3617 /* Having a registry value name implies registry data */
3620 /* We know up-front how much data to expect */
3621 *ResultLength
= BufferLength
;
3623 /* Go get the data, use the LogConf subkey if necessary */
3624 Status
= PiGetDeviceRegistryProperty(DeviceObject
,
3628 DevicePropertyBootConfiguration
) ?
3633 else if (NT_SUCCESS(Status
))
3635 /* We know up-front how much data to expect, check the caller's buffer */
3636 *ResultLength
= ReturnLength
;
3637 if (ReturnLength
<= BufferLength
)
3639 /* Buffer is all good, copy the data */
3640 RtlCopyMemory(PropertyBuffer
, Data
, ReturnLength
);
3642 /* Check for properties that require a null-terminated string */
3643 if ((DeviceProperty
== DevicePropertyEnumeratorName
) ||
3644 (DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
))
3646 /* Terminate the string */
3647 ((PWCHAR
)PropertyBuffer
)[ReturnLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3650 /* This is the success path */
3651 Status
= STATUS_SUCCESS
;
3656 Status
= STATUS_BUFFER_TOO_SMALL
;
3660 /* Free any allocation we may have made, and return the status code */
3661 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
3670 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3672 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
3673 IO_STACK_LOCATION Stack
;
3676 IO_STATUS_BLOCK IoStatusBlock
;
3678 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
3679 Stack
.MajorFunction
= IRP_MJ_PNP
;
3680 Stack
.MinorFunction
= IRP_MN_QUERY_PNP_DEVICE_STATE
;
3682 Status
= IopSynchronousCall(PhysicalDeviceObject
, &Stack
, (PVOID
*)&PnPFlags
);
3683 if (!NT_SUCCESS(Status
))
3685 DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%x\n", Status
);
3689 if (PnPFlags
& PNP_DEVICE_NOT_DISABLEABLE
)
3690 DeviceNode
->UserFlags
|= DNUF_NOT_DISABLEABLE
;
3692 DeviceNode
->UserFlags
&= ~DNUF_NOT_DISABLEABLE
;
3694 if (PnPFlags
& PNP_DEVICE_DONT_DISPLAY_IN_UI
)
3695 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
3697 DeviceNode
->UserFlags
&= ~DNUF_DONT_SHOW_IN_UI
;
3699 if ((PnPFlags
& PNP_DEVICE_REMOVED
) ||
3700 ((PnPFlags
& PNP_DEVICE_FAILED
) && !(PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)))
3702 /* Surprise removal */
3704 IopSendSurpriseRemoval(PhysicalDeviceObject
);
3706 /* Tell the user-mode PnP manager that a device was removed */
3707 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
3708 &DeviceNode
->InstancePath
);
3710 IopSendRemoveDevice(PhysicalDeviceObject
);
3712 else if ((PnPFlags
& PNP_DEVICE_FAILED
) && (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
))
3714 /* Stop for resource rebalance */
3716 if (NT_SUCCESS(IopQueryStopDevice(PhysicalDeviceObject
)))
3718 IopSendStopDevice(PhysicalDeviceObject
);
3720 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
3721 DeviceNode
->Flags
|= DNF_STOPPED
;
3725 /* Resource rebalance */
3726 if (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)
3728 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
3730 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
3732 IRP_MN_QUERY_RESOURCES
,
3734 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
3736 DeviceNode
->BootResources
=
3737 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
3738 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
3742 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
3743 DeviceNode
->BootResources
= NULL
;
3746 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
3748 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
3750 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
3752 if (NT_SUCCESS(Status
))
3754 DeviceNode
->ResourceRequirements
=
3755 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
3759 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
3760 DeviceNode
->ResourceRequirements
= NULL
;
3763 /* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
3764 if (IopStartDevice(DeviceNode
) != STATUS_SUCCESS
)
3766 DPRINT1("Restart after resource rebalance failed\n");
3768 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
3769 DeviceNode
->Flags
|= DNF_START_FAILED
;
3771 IopRemoveDevice(DeviceNode
);
3777 * @name IoOpenDeviceRegistryKey
3779 * Open a registry key unique for a specified driver or device instance.
3781 * @param DeviceObject Device to get the registry key for.
3782 * @param DevInstKeyType Type of the key to return.
3783 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
3784 * @param DevInstRegKey Handle to the opened registry key on
3785 * successful return.
3793 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
3794 IN ULONG DevInstKeyType
,
3795 IN ACCESS_MASK DesiredAccess
,
3796 OUT PHANDLE DevInstRegKey
)
3798 static WCHAR RootKeyName
[] =
3799 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
3800 static WCHAR ProfileKeyName
[] =
3801 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
3802 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
3803 static WCHAR EnumKeyName
[] = L
"Enum\\";
3804 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
3805 ULONG KeyNameLength
;
3806 LPWSTR KeyNameBuffer
;
3807 UNICODE_STRING KeyName
;
3808 ULONG DriverKeyLength
;
3809 OBJECT_ATTRIBUTES ObjectAttributes
;
3810 PDEVICE_NODE DeviceNode
= NULL
;
3813 DPRINT("IoOpenDeviceRegistryKey() called\n");
3815 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
3817 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
3818 return STATUS_INVALID_PARAMETER
;
3821 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
3822 return STATUS_INVALID_DEVICE_REQUEST
;
3823 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3826 * Calculate the length of the base key name. This is the full
3827 * name for driver key or the name excluding "Device Parameters"
3828 * subkey for device key.
3831 KeyNameLength
= sizeof(RootKeyName
);
3832 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3833 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
3834 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3836 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
3837 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3838 0, NULL
, &DriverKeyLength
);
3839 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
3841 KeyNameLength
+= DriverKeyLength
;
3845 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
3846 DeviceNode
->InstancePath
.Length
;
3850 * Now allocate the buffer for the key name...
3853 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
3854 if (KeyNameBuffer
== NULL
)
3855 return STATUS_INSUFFICIENT_RESOURCES
;
3858 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
3859 KeyName
.Buffer
= KeyNameBuffer
;
3862 * ...and build the key name.
3865 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
3866 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
3868 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3869 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
3871 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3873 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
3874 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3875 DriverKeyLength
, KeyNameBuffer
+
3876 (KeyName
.Length
/ sizeof(WCHAR
)),
3878 if (!NT_SUCCESS(Status
))
3880 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
3881 ExFreePool(KeyNameBuffer
);
3884 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
3888 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
3889 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
3890 if (DeviceNode
->InstancePath
.Length
== 0)
3892 ExFreePool(KeyNameBuffer
);
3898 * Open the base key.
3900 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
3901 if (!NT_SUCCESS(Status
))
3903 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
3904 ExFreePool(KeyNameBuffer
);
3907 ExFreePool(KeyNameBuffer
);
3910 * For driver key we're done now.
3913 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3917 * Let's go further. For device key we must open "Device Parameters"
3918 * subkey and create it if it doesn't exist yet.
3921 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
3922 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
3923 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
3924 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
3925 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
3926 ZwClose(ObjectAttributes
.RootDirectory
);
3933 IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
3935 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
, FailedRemoveDevice
;
3939 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3940 ChildDeviceNode
= ParentDeviceNode
->Child
;
3941 while (ChildDeviceNode
!= NULL
)
3943 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3944 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3946 Status
= IopPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
3947 if (!NT_SUCCESS(Status
))
3949 FailedRemoveDevice
= ChildDeviceNode
;
3953 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3954 ChildDeviceNode
= NextDeviceNode
;
3956 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3958 return STATUS_SUCCESS
;
3961 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3962 ChildDeviceNode
= ParentDeviceNode
->Child
;
3963 while (ChildDeviceNode
!= NULL
)
3965 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3966 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3968 IopCancelPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
3970 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
3971 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
3972 if (ChildDeviceNode
== FailedRemoveDevice
)
3975 ChildDeviceNode
= NextDeviceNode
;
3977 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3979 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3986 IopSendRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
3988 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
;
3991 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3992 ChildDeviceNode
= ParentDeviceNode
->Child
;
3993 while (ChildDeviceNode
!= NULL
)
3995 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3996 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3998 IopSendRemoveDevice(ChildDeviceNode
->PhysicalDeviceObject
);
4000 ChildDeviceNode
= NextDeviceNode
;
4002 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4004 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4009 IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
4011 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
;
4014 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4015 ChildDeviceNode
= ParentDeviceNode
->Child
;
4016 while (ChildDeviceNode
!= NULL
)
4018 NextDeviceNode
= ChildDeviceNode
->Sibling
;
4019 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4021 IopCancelPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
4023 ChildDeviceNode
= NextDeviceNode
;
4025 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4027 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4032 IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4034 /* This function DOES NOT dereference the device objects on SUCCESS
4035 * but it DOES dereference device objects on FAILURE */
4040 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4042 Status
= IopPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4043 if (!NT_SUCCESS(Status
))
4050 return STATUS_SUCCESS
;
4053 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
4054 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
4055 for (i
= 0; i
<= j
; i
++)
4057 IopCancelPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4058 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4059 DeviceRelations
->Objects
[i
] = NULL
;
4061 for (; i
< DeviceRelations
->Count
; i
++)
4063 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4064 DeviceRelations
->Objects
[i
] = NULL
;
4066 ExFreePool(DeviceRelations
);
4073 IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4075 /* This function DOES dereference the device objects in all cases */
4079 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4081 IopSendRemoveDevice(DeviceRelations
->Objects
[i
]);
4082 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4083 DeviceRelations
->Objects
[i
] = NULL
;
4086 ExFreePool(DeviceRelations
);
4091 IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4093 /* This function DOES dereference the device objects in all cases */
4097 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4099 IopCancelPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4100 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4101 DeviceRelations
->Objects
[i
] = NULL
;
4104 ExFreePool(DeviceRelations
);
4108 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
)
4110 IO_STACK_LOCATION Stack
;
4111 IO_STATUS_BLOCK IoStatusBlock
;
4112 PDEVICE_RELATIONS DeviceRelations
;
4115 IopCancelRemoveDevice(DeviceObject
);
4117 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
4119 Status
= IopInitiatePnpIrp(DeviceObject
,
4121 IRP_MN_QUERY_DEVICE_RELATIONS
,
4123 if (!NT_SUCCESS(Status
))
4125 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4126 DeviceRelations
= NULL
;
4130 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4133 if (DeviceRelations
)
4134 IopCancelRemoveDeviceRelations(DeviceRelations
);
4138 IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject
)
4140 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
4141 IO_STACK_LOCATION Stack
;
4142 IO_STATUS_BLOCK IoStatusBlock
;
4143 PDEVICE_RELATIONS DeviceRelations
;
4146 if (DeviceNode
->UserFlags
& DNUF_NOT_DISABLEABLE
)
4148 DPRINT1("Removal not allowed for %wZ\n", &DeviceNode
->InstancePath
);
4149 return STATUS_UNSUCCESSFUL
;
4152 if (IopQueryRemoveDevice(DeviceObject
) != STATUS_SUCCESS
)
4154 DPRINT1("Removal vetoed by failing the query remove request\n");
4156 IopCancelRemoveDevice(DeviceObject
);
4158 return STATUS_UNSUCCESSFUL
;
4161 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
4163 Status
= IopInitiatePnpIrp(DeviceObject
,
4165 IRP_MN_QUERY_DEVICE_RELATIONS
,
4167 if (!NT_SUCCESS(Status
))
4169 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4170 DeviceRelations
= NULL
;
4174 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4177 if (DeviceRelations
)
4179 Status
= IopQueryRemoveDeviceRelations(DeviceRelations
);
4180 if (!NT_SUCCESS(Status
))
4184 Status
= IopQueryRemoveChildDevices(DeviceNode
);
4185 if (!NT_SUCCESS(Status
))
4187 if (DeviceRelations
)
4188 IopCancelRemoveDeviceRelations(DeviceRelations
);
4192 if (DeviceRelations
)
4193 IopSendRemoveDeviceRelations(DeviceRelations
);
4194 IopSendRemoveChildDevices(DeviceNode
);
4196 return STATUS_SUCCESS
;
4200 IopRemoveDevice(PDEVICE_NODE DeviceNode
)
4204 DPRINT("Removing device: %wZ\n", &DeviceNode
->InstancePath
);
4206 Status
= IopPrepareDeviceForRemoval(DeviceNode
->PhysicalDeviceObject
);
4207 if (NT_SUCCESS(Status
))
4209 IopSendRemoveDevice(DeviceNode
->PhysicalDeviceObject
);
4210 IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL
,
4211 &DeviceNode
->InstancePath
);
4212 DeviceNode
->Flags
|= DNF_WILL_BE_REMOVED
;
4213 return STATUS_SUCCESS
;
4224 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4226 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
4227 PDEVICE_RELATIONS DeviceRelations
;
4228 IO_STATUS_BLOCK IoStatusBlock
;
4229 IO_STACK_LOCATION Stack
;
4230 DEVICE_CAPABILITIES Capabilities
;
4233 IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT
,
4234 &DeviceNode
->InstancePath
);
4236 if (IopQueryDeviceCapabilities(DeviceNode
, &Capabilities
) != STATUS_SUCCESS
)
4241 Stack
.Parameters
.QueryDeviceRelations
.Type
= EjectionRelations
;
4243 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
4245 IRP_MN_QUERY_DEVICE_RELATIONS
,
4247 if (!NT_SUCCESS(Status
))
4249 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4250 DeviceRelations
= NULL
;
4254 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4257 if (DeviceRelations
)
4259 Status
= IopQueryRemoveDeviceRelations(DeviceRelations
);
4260 if (!NT_SUCCESS(Status
))
4264 Status
= IopQueryRemoveChildDevices(DeviceNode
);
4265 if (!NT_SUCCESS(Status
))
4267 if (DeviceRelations
)
4268 IopCancelRemoveDeviceRelations(DeviceRelations
);
4272 if (IopPrepareDeviceForRemoval(PhysicalDeviceObject
) != STATUS_SUCCESS
)
4274 if (DeviceRelations
)
4275 IopCancelRemoveDeviceRelations(DeviceRelations
);
4276 IopCancelRemoveChildDevices(DeviceNode
);
4280 if (DeviceRelations
)
4281 IopSendRemoveDeviceRelations(DeviceRelations
);
4282 IopSendRemoveChildDevices(DeviceNode
);
4284 if (Capabilities
.EjectSupported
)
4286 if (IopSendEject(PhysicalDeviceObject
) != STATUS_SUCCESS
)
4293 DeviceNode
->Flags
|= DNF_DISABLED
;
4296 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT
,
4297 &DeviceNode
->InstancePath
);
4302 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED
,
4303 &DeviceNode
->InstancePath
);
4311 IoInvalidateDeviceRelations(
4312 IN PDEVICE_OBJECT DeviceObject
,
4313 IN DEVICE_RELATION_TYPE Type
)
4315 PIO_WORKITEM WorkItem
;
4316 PINVALIDATE_DEVICE_RELATION_DATA Data
;
4318 Data
= ExAllocatePool(NonPagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
4321 WorkItem
= IoAllocateWorkItem(DeviceObject
);
4328 ObReferenceObject(DeviceObject
);
4329 Data
->DeviceObject
= DeviceObject
;
4331 Data
->WorkItem
= WorkItem
;
4335 IopAsynchronousInvalidateDeviceRelations
,
4345 IoSynchronousInvalidateDeviceRelations(
4346 IN PDEVICE_OBJECT DeviceObject
,
4347 IN DEVICE_RELATION_TYPE Type
)
4354 /* Enumerate the device */
4355 return IopEnumerateDevice(DeviceObject
);
4356 case PowerRelations
:
4357 /* Not handled yet */
4358 return STATUS_NOT_IMPLEMENTED
;
4359 case TargetDeviceRelation
:
4361 return STATUS_SUCCESS
;
4363 /* Ejection relations are not supported */
4364 return STATUS_NOT_SUPPORTED
;
4373 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
4375 IN PHYSICAL_ADDRESS BusAddress
,
4376 IN OUT PULONG AddressSpace
,
4377 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
4379 /* FIXME: Notify the resource arbiter */
4381 return HalTranslateBusAddress(InterfaceType
,