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 ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 PDEVICE_NODE IopRootDeviceNode
;
19 KSPIN_LOCK IopDeviceTreeLock
;
20 ERESOURCE PpRegistryDeviceResource
;
21 KGUARDED_MUTEX PpDeviceReferenceTableLock
;
22 RTL_AVL_TABLE PpDeviceReferenceTable
;
24 extern ULONG ExpInitializationPhase
;
25 extern BOOLEAN ExpInTextModeSetup
;
26 extern BOOLEAN PnpSystemInit
;
28 /* DATA **********************************************************************/
30 PDRIVER_OBJECT IopRootDriverObject
;
31 PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList
= NULL
;
33 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
35 PDEVICE_OBJECT DeviceObject
;
36 DEVICE_RELATION_TYPE Type
;
37 PIO_WORKITEM WorkItem
;
38 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
40 /* FUNCTIONS *****************************************************************/
43 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
44 IN ULONG CreateOptions
,
48 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
);
51 IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
);
55 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
57 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
62 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
63 PDRIVER_OBJECT DriverObject
)
70 /* Special case for bus driven devices */
71 DeviceNode
->Flags
|= DNF_ADDED
;
72 return STATUS_SUCCESS
;
75 if (!DriverObject
->DriverExtension
->AddDevice
)
77 DeviceNode
->Flags
|= DNF_LEGACY_DRIVER
;
80 if (DeviceNode
->Flags
& DNF_LEGACY_DRIVER
)
82 DeviceNode
->Flags
|= DNF_ADDED
+ DNF_STARTED
;
83 return STATUS_SUCCESS
;
86 /* This is a Plug and Play driver */
87 DPRINT("Plug and Play driver found\n");
88 ASSERT(DeviceNode
->PhysicalDeviceObject
);
90 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
91 &DriverObject
->DriverName
,
92 &DeviceNode
->InstancePath
);
93 Status
= DriverObject
->DriverExtension
->AddDevice(
94 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
95 if (!NT_SUCCESS(Status
))
97 DPRINT1("%wZ->AddDevice(%wZ) failed with status 0x%x\n",
98 &DriverObject
->DriverName
,
99 &DeviceNode
->InstancePath
,
101 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
105 /* Check if driver added a FDO above the PDO */
106 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
107 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
109 /* FIXME: What do we do? Unload the driver or just disable the device? */
110 DPRINT1("An FDO was not attached\n");
111 ObDereferenceObject(Fdo
);
112 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
113 return STATUS_UNSUCCESSFUL
;
116 /* Check if we have a ACPI device (needed for power management) */
117 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
119 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
121 /* There can be only one system power device */
122 if (!SystemPowerDeviceNodeCreated
)
124 PopSystemPowerDeviceNode
= DeviceNode
;
125 ObReferenceObject(PopSystemPowerDeviceNode
->PhysicalDeviceObject
);
126 SystemPowerDeviceNodeCreated
= TRUE
;
130 ObDereferenceObject(Fdo
);
132 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
134 return STATUS_SUCCESS
;
140 IopSendEject(IN PDEVICE_OBJECT DeviceObject
)
142 IO_STACK_LOCATION Stack
;
145 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
146 Stack
.MajorFunction
= IRP_MJ_PNP
;
147 Stack
.MinorFunction
= IRP_MN_EJECT
;
149 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
155 IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject
)
157 IO_STACK_LOCATION Stack
;
160 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
161 Stack
.MajorFunction
= IRP_MJ_PNP
;
162 Stack
.MinorFunction
= IRP_MN_SURPRISE_REMOVAL
;
164 /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
165 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
171 IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
173 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
174 IO_STACK_LOCATION Stack
;
180 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING
,
181 &DeviceNode
->InstancePath
);
183 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
184 Stack
.MajorFunction
= IRP_MJ_PNP
;
185 Stack
.MinorFunction
= IRP_MN_QUERY_REMOVE_DEVICE
;
187 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
189 IopNotifyPlugPlayNotification(DeviceObject
,
190 EventCategoryTargetDeviceChange
,
191 &GUID_TARGET_DEVICE_QUERY_REMOVE
,
195 if (!NT_SUCCESS(Status
))
197 DPRINT1("Removal vetoed by %wZ\n", &DeviceNode
->InstancePath
);
198 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED
,
199 &DeviceNode
->InstancePath
);
208 IopQueryStopDevice(IN PDEVICE_OBJECT DeviceObject
)
210 IO_STACK_LOCATION Stack
;
213 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
214 Stack
.MajorFunction
= IRP_MJ_PNP
;
215 Stack
.MinorFunction
= IRP_MN_QUERY_STOP_DEVICE
;
217 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
223 IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
225 IO_STACK_LOCATION Stack
;
228 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
229 Stack
.MajorFunction
= IRP_MJ_PNP
;
230 Stack
.MinorFunction
= IRP_MN_REMOVE_DEVICE
;
232 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
233 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
235 IopNotifyPlugPlayNotification(DeviceObject
,
236 EventCategoryTargetDeviceChange
,
237 &GUID_TARGET_DEVICE_REMOVE_COMPLETE
,
245 IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
247 IO_STACK_LOCATION Stack
;
250 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
251 Stack
.MajorFunction
= IRP_MJ_PNP
;
252 Stack
.MinorFunction
= IRP_MN_CANCEL_REMOVE_DEVICE
;
254 /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
255 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
257 IopNotifyPlugPlayNotification(DeviceObject
,
258 EventCategoryTargetDeviceChange
,
259 &GUID_TARGET_DEVICE_REMOVE_CANCELLED
,
267 IopSendStopDevice(IN PDEVICE_OBJECT DeviceObject
)
269 IO_STACK_LOCATION Stack
;
272 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
273 Stack
.MajorFunction
= IRP_MJ_PNP
;
274 Stack
.MinorFunction
= IRP_MN_STOP_DEVICE
;
276 /* Drivers should never fail a IRP_MN_STOP_DEVICE request */
277 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
282 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject
)
284 IO_STACK_LOCATION Stack
;
285 PDEVICE_NODE DeviceNode
;
288 DEVICE_CAPABILITIES DeviceCapabilities
;
290 /* Get the device node */
291 DeviceNode
= IopGetDeviceNode(DeviceObject
);
293 ASSERT(!(DeviceNode
->Flags
& DNF_DISABLED
));
295 /* Build the I/O stack locaiton */
296 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
297 Stack
.MajorFunction
= IRP_MJ_PNP
;
298 Stack
.MinorFunction
= IRP_MN_START_DEVICE
;
300 Stack
.Parameters
.StartDevice
.AllocatedResources
=
301 DeviceNode
->ResourceList
;
302 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
=
303 DeviceNode
->ResourceListTranslated
;
306 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
307 if (!NT_SUCCESS(Status
))
309 /* Send an IRP_MN_REMOVE_DEVICE request */
310 IopRemoveDevice(DeviceNode
);
312 /* Set the appropriate flag */
313 DeviceNode
->Flags
|= DNF_START_FAILED
;
315 DPRINT1("Warning: PnP Start failed (%wZ) [Status: 0x%x]\n", &DeviceNode
->InstancePath
, Status
);
319 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
321 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
322 if (!NT_SUCCESS(Status
))
324 DPRINT1("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
327 /* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
328 IoInvalidateDeviceState(DeviceObject
);
330 /* Otherwise, mark us as started */
331 DeviceNode
->Flags
|= DNF_STARTED
;
332 DeviceNode
->Flags
&= ~DNF_STOPPED
;
334 /* We now need enumeration */
335 DeviceNode
->Flags
|= DNF_NEED_ENUMERATION_ONLY
;
340 IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode
)
342 PDEVICE_OBJECT DeviceObject
;
347 ASSERT((DeviceNode
->Flags
& DNF_ADDED
));
348 ASSERT((DeviceNode
->Flags
& (DNF_RESOURCE_ASSIGNED
|
349 DNF_RESOURCE_REPORTED
|
350 DNF_NO_RESOURCE_REQUIRED
)));
352 /* Get the device object */
353 DeviceObject
= DeviceNode
->PhysicalDeviceObject
;
355 /* Check if we're not started yet */
356 if (!(DeviceNode
->Flags
& DNF_STARTED
))
359 IopStartDevice2(DeviceObject
);
362 /* Do we need to query IDs? This happens in the case of manual reporting */
364 if (DeviceNode
->Flags
& DNF_NEED_QUERY_IDS
)
366 DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
367 /* And that case shouldn't happen yet */
372 /* Make sure we're started, and check if we need enumeration */
373 if ((DeviceNode
->Flags
& DNF_STARTED
) &&
374 (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
))
377 IoSynchronousInvalidateDeviceRelations(DeviceObject
, BusRelations
);
378 Status
= STATUS_SUCCESS
;
383 Status
= STATUS_SUCCESS
;
392 PDEVICE_NODE DeviceNode
)
396 DPRINT("Stopping device: %wZ\n", &DeviceNode
->InstancePath
);
398 Status
= IopQueryStopDevice(DeviceNode
->PhysicalDeviceObject
);
399 if (NT_SUCCESS(Status
))
401 IopSendStopDevice(DeviceNode
->PhysicalDeviceObject
);
403 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
404 DeviceNode
->Flags
|= DNF_STOPPED
;
406 return STATUS_SUCCESS
;
414 PDEVICE_NODE DeviceNode
)
417 HANDLE InstanceHandle
= INVALID_HANDLE_VALUE
, ControlHandle
= INVALID_HANDLE_VALUE
;
418 UNICODE_STRING KeyName
;
419 OBJECT_ATTRIBUTES ObjectAttributes
;
421 if (DeviceNode
->Flags
& DNF_DISABLED
)
422 return STATUS_SUCCESS
;
424 Status
= IopAssignDeviceResources(DeviceNode
);
425 if (!NT_SUCCESS(Status
))
429 IopStartAndEnumerateDevice(DeviceNode
);
431 /* FIX: Should be done in new device instance code */
432 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceHandle
);
433 if (!NT_SUCCESS(Status
))
436 /* FIX: Should be done in IoXxxPrepareDriverLoading */
438 RtlInitUnicodeString(&KeyName
, L
"Control");
439 InitializeObjectAttributes(&ObjectAttributes
,
441 OBJ_CASE_INSENSITIVE
,
444 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
445 if (!NT_SUCCESS(Status
))
448 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
449 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
453 if (ControlHandle
!= INVALID_HANDLE_VALUE
)
454 ZwClose(ControlHandle
);
456 if (InstanceHandle
!= INVALID_HANDLE_VALUE
)
457 ZwClose(InstanceHandle
);
464 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
465 PDEVICE_CAPABILITIES DeviceCaps
)
467 IO_STATUS_BLOCK StatusBlock
;
468 IO_STACK_LOCATION Stack
;
471 UNICODE_STRING ValueName
;
473 /* Set up the Header */
474 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
475 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
476 DeviceCaps
->Version
= 1;
477 DeviceCaps
->Address
= -1;
478 DeviceCaps
->UINumber
= -1;
480 /* Set up the Stack */
481 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
482 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
485 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
487 IRP_MN_QUERY_CAPABILITIES
,
489 if (!NT_SUCCESS(Status
))
491 DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%x\n", Status
);
495 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCaps
->Version
+ sizeof(DeviceCaps
->Version
));
497 if (DeviceCaps
->NoDisplayInUI
)
498 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
500 DeviceNode
->UserFlags
&= ~DNUF_DONT_SHOW_IN_UI
;
502 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
503 if (NT_SUCCESS(Status
))
505 /* Set 'Capabilities' value */
506 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
507 Status
= ZwSetValueKey(InstanceKey
,
511 (PVOID
)&DeviceNode
->CapabilityFlags
,
514 /* Set 'UINumber' value */
515 if (DeviceCaps
->UINumber
!= MAXULONG
)
517 RtlInitUnicodeString(&ValueName
, L
"UINumber");
518 Status
= ZwSetValueKey(InstanceKey
,
522 &DeviceCaps
->UINumber
,
531 IopAsynchronousInvalidateDeviceRelations(
532 IN PDEVICE_OBJECT DeviceObject
,
533 IN PVOID InvalidateContext
)
535 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
537 IoSynchronousInvalidateDeviceRelations(
541 ObDereferenceObject(Data
->DeviceObject
);
542 IoFreeWorkItem(Data
->WorkItem
);
547 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
551 if (PopSystemPowerDeviceNode
)
553 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
554 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
555 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
557 return STATUS_SUCCESS
;
560 return STATUS_UNSUCCESSFUL
;
565 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
567 USHORT i
= 0, FoundIndex
= 0xFFFF;
571 /* Acquire the lock */
572 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
574 /* Loop all entries */
575 while (i
< PnpBusTypeGuidList
->GuidCount
)
577 /* Try to find a match */
578 if (RtlCompareMemory(BusTypeGuid
,
579 &PnpBusTypeGuidList
->Guids
[i
],
580 sizeof(GUID
)) == sizeof(GUID
))
589 /* Check if we have to grow the list */
590 if (PnpBusTypeGuidList
->GuidCount
)
592 /* Calculate the new size */
593 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
594 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
596 /* Allocate the new copy */
597 NewList
= ExAllocatePool(PagedPool
, NewSize
);
601 ExFreePool(PnpBusTypeGuidList
);
605 /* Now copy them, decrease the size too */
606 NewSize
-= sizeof(GUID
);
607 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
609 /* Free the old list */
610 ExFreePool(PnpBusTypeGuidList
);
612 /* Use the new buffer */
613 PnpBusTypeGuidList
= NewList
;
616 /* Copy the new GUID */
617 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
621 /* The new entry is the index */
622 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
623 PnpBusTypeGuidList
->GuidCount
++;
626 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
632 * Creates a device node
635 * ParentNode = Pointer to parent device node
636 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
637 * to have the root device node create one
638 * (eg. for legacy drivers)
639 * DeviceNode = Pointer to storage for created device node
645 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
646 PDEVICE_OBJECT PhysicalDeviceObject
,
647 PUNICODE_STRING ServiceName
,
648 PDEVICE_NODE
*DeviceNode
)
653 UNICODE_STRING FullServiceName
;
654 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
655 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
656 UNICODE_STRING KeyName
, ClassName
;
657 PUNICODE_STRING ServiceName1
;
660 UNICODE_STRING ClassGUID
;
662 HANDLE InstanceHandle
;
664 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
665 ParentNode
, PhysicalDeviceObject
, ServiceName
);
667 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
670 return STATUS_INSUFFICIENT_RESOURCES
;
673 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
676 ServiceName1
= &UnknownDeviceName
;
678 ServiceName1
= ServiceName
;
680 if (!PhysicalDeviceObject
)
682 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
683 FullServiceName
.Length
= 0;
684 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
685 if (!FullServiceName
.Buffer
)
688 return STATUS_INSUFFICIENT_RESOURCES
;
691 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
692 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
694 Status
= PnpRootCreateDevice(&FullServiceName
, NULL
, &PhysicalDeviceObject
, &Node
->InstancePath
);
695 if (!NT_SUCCESS(Status
))
697 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
702 /* Create the device key for legacy drivers */
703 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
704 if (!NT_SUCCESS(Status
))
706 ZwClose(InstanceHandle
);
708 ExFreePool(FullServiceName
.Buffer
);
712 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
713 if (!Node
->ServiceName
.Buffer
)
715 ZwClose(InstanceHandle
);
717 ExFreePool(FullServiceName
.Buffer
);
721 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
722 Node
->ServiceName
.Length
= 0;
724 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
728 RtlInitUnicodeString(&KeyName
, L
"Service");
729 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
732 if (NT_SUCCESS(Status
))
734 RtlInitUnicodeString(&KeyName
, L
"Legacy");
737 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
738 if (NT_SUCCESS(Status
))
740 RtlInitUnicodeString(&KeyName
, L
"Class");
742 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
743 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
);
745 if (NT_SUCCESS(Status
))
747 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
749 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
750 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
);
756 ZwClose(InstanceHandle
);
757 ExFreePool(FullServiceName
.Buffer
);
759 if (!NT_SUCCESS(Status
))
765 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
766 IopDeviceNodeSetFlag(Node
, DNF_PROCESSED
);
767 IopDeviceNodeSetFlag(Node
, DNF_ADDED
);
768 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
771 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
773 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
777 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
778 Node
->Parent
= ParentNode
;
779 Node
->Sibling
= ParentNode
->Child
;
780 ParentNode
->Child
= Node
;
781 if (ParentNode
->LastChild
== NULL
)
782 ParentNode
->LastChild
= Node
;
783 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
784 Node
->Level
= ParentNode
->Level
+ 1;
787 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
791 return STATUS_SUCCESS
;
795 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
798 PDEVICE_NODE PrevSibling
= NULL
;
800 /* All children must be deleted before a parent is deleted */
801 ASSERT(!DeviceNode
->Child
);
803 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
805 ASSERT(DeviceNode
->PhysicalDeviceObject
);
807 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
809 /* Get previous sibling */
810 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
812 PrevSibling
= DeviceNode
->Parent
->Child
;
813 while (PrevSibling
->Sibling
!= DeviceNode
)
814 PrevSibling
= PrevSibling
->Sibling
;
817 /* Unlink from parent if it exists */
818 if (DeviceNode
->Parent
)
820 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
822 DeviceNode
->Parent
->LastChild
= PrevSibling
;
824 PrevSibling
->Sibling
= NULL
;
826 if (DeviceNode
->Parent
->Child
== DeviceNode
)
827 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
830 /* Unlink from sibling list */
832 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
834 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
836 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
838 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
840 if (DeviceNode
->ResourceList
)
842 ExFreePool(DeviceNode
->ResourceList
);
845 if (DeviceNode
->ResourceListTranslated
)
847 ExFreePool(DeviceNode
->ResourceListTranslated
);
850 if (DeviceNode
->ResourceRequirements
)
852 ExFreePool(DeviceNode
->ResourceRequirements
);
855 if (DeviceNode
->BootResources
)
857 ExFreePool(DeviceNode
->BootResources
);
860 ExFreePool(DeviceNode
);
862 return STATUS_SUCCESS
;
867 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
868 IN PIO_STACK_LOCATION IoStackLocation
,
869 OUT PVOID
*Information
)
872 PIO_STACK_LOCATION IrpStack
;
873 IO_STATUS_BLOCK IoStatusBlock
;
876 PDEVICE_OBJECT TopDeviceObject
;
879 /* Call the top of the device stack */
880 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
882 /* Allocate an IRP */
883 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
884 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
886 /* Initialize to failure */
887 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
888 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
890 /* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */
891 if (IoStackLocation
->MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
893 /* Copy the resource requirements list into the IOSB */
894 Irp
->IoStatus
.Information
=
895 IoStatusBlock
.Information
= (ULONG_PTR
)IoStackLocation
->Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
898 /* Initialize the event */
899 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
902 Irp
->UserIosb
= &IoStatusBlock
;
903 Irp
->UserEvent
= &Event
;
906 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
907 IoQueueThreadIrp(Irp
);
909 /* Copy-in the stack */
910 IrpStack
= IoGetNextIrpStackLocation(Irp
);
911 *IrpStack
= *IoStackLocation
;
913 /* Call the driver */
914 Status
= IoCallDriver(TopDeviceObject
, Irp
);
915 if (Status
== STATUS_PENDING
)
918 KeWaitForSingleObject(&Event
,
923 Status
= IoStatusBlock
.Status
;
926 /* Return the information */
927 *Information
= (PVOID
)IoStatusBlock
.Information
;
933 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
934 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
935 IN UCHAR MinorFunction
,
936 IN PIO_STACK_LOCATION Stack OPTIONAL
)
938 IO_STACK_LOCATION IoStackLocation
;
940 /* Fill out the stack information */
941 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
942 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
943 IoStackLocation
.MinorFunction
= MinorFunction
;
947 RtlCopyMemory(&IoStackLocation
.Parameters
,
949 sizeof(Stack
->Parameters
));
952 /* Do the PnP call */
953 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
955 (PVOID
)&IoStatusBlock
->Information
);
956 return IoStatusBlock
->Status
;
960 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
962 PDEVICE_NODE ParentDeviceNode
;
963 PDEVICE_NODE ChildDeviceNode
;
966 /* Copy context data so we don't overwrite it in subsequent calls to this function */
967 ParentDeviceNode
= Context
->DeviceNode
;
969 /* Call the action routine */
970 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
971 if (!NT_SUCCESS(Status
))
976 /* Traversal of all children nodes */
977 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
978 ChildDeviceNode
!= NULL
;
979 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
981 /* Pass the current device node to the action routine */
982 Context
->DeviceNode
= ChildDeviceNode
;
984 Status
= IopTraverseDeviceTreeNode(Context
);
985 if (!NT_SUCCESS(Status
))
996 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1000 DPRINT("Context 0x%p\n", Context
);
1002 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1003 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1005 /* Start from the specified device node */
1006 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1008 /* Recursively traverse the device tree */
1009 Status
= IopTraverseDeviceTreeNode(Context
);
1010 if (Status
== STATUS_UNSUCCESSFUL
)
1012 /* The action routine just wanted to terminate the traversal with status
1013 code STATUS_SUCCESS */
1014 Status
= STATUS_SUCCESS
;
1022 * IopCreateDeviceKeyPath
1024 * Creates a registry key
1028 * Name of the key to be created.
1030 * Handle to the newly created key
1033 * This method can create nested trees, so parent of RegistryPath can
1034 * be not existant, and will be created if needed.
1038 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
1039 IN ULONG CreateOptions
,
1042 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
1043 HANDLE hParent
= NULL
, hKey
;
1044 OBJECT_ATTRIBUTES ObjectAttributes
;
1045 UNICODE_STRING KeyName
;
1046 LPCWSTR Current
, Last
;
1050 /* Assume failure */
1053 /* Create a volatile device tree in 1st stage so we have a clean slate
1054 * for enumeration using the correct HAL (chosen in 1st stage setup) */
1055 if (ExpInTextModeSetup
) CreateOptions
|= REG_OPTION_VOLATILE
;
1057 /* Open root key for device instances */
1058 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
1059 if (!NT_SUCCESS(Status
))
1061 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
1065 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
1066 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
1068 /* Go up to the end of the string */
1069 while (Current
<= Last
)
1071 if (Current
!= Last
&& *Current
!= '\\')
1073 /* Not the end of the string and not a separator */
1078 /* Prepare relative key name */
1079 Length
= (USHORT
)((ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
);
1080 KeyName
.MaximumLength
= KeyName
.Length
= Length
;
1081 DPRINT("Create '%wZ'\n", &KeyName
);
1084 InitializeObjectAttributes(&ObjectAttributes
,
1086 OBJ_CASE_INSENSITIVE
,
1089 Status
= ZwCreateKey(&hKey
,
1090 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
1097 /* Close parent key handle, we don't need it anymore */
1101 /* Key opening/creating failed? */
1102 if (!NT_SUCCESS(Status
))
1104 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
1108 /* Check if it is the end of the string */
1109 if (Current
== Last
)
1111 /* Yes, return success */
1113 return STATUS_SUCCESS
;
1116 /* Start with this new parent key */
1119 KeyName
.Buffer
= (LPWSTR
)Current
;
1122 return STATUS_UNSUCCESSFUL
;
1126 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1127 PDEVICE_NODE DeviceNode
)
1129 OBJECT_ATTRIBUTES ObjectAttributes
;
1130 UNICODE_STRING KeyName
;
1135 HANDLE ControlHandle
;
1137 DPRINT("IopSetDeviceInstanceData() called\n");
1139 /* Create the 'LogConf' key */
1140 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1141 InitializeObjectAttributes(&ObjectAttributes
,
1143 OBJ_CASE_INSENSITIVE
,
1146 Status
= ZwCreateKey(&LogConfKey
,
1151 REG_OPTION_VOLATILE
,
1153 if (NT_SUCCESS(Status
))
1155 /* Set 'BootConfig' value */
1156 if (DeviceNode
->BootResources
!= NULL
)
1158 ResCount
= DeviceNode
->BootResources
->Count
;
1161 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1162 Status
= ZwSetValueKey(LogConfKey
,
1166 DeviceNode
->BootResources
,
1167 PnpDetermineResourceListSize(DeviceNode
->BootResources
));
1171 /* Set 'BasicConfigVector' value */
1172 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1173 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1175 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1176 Status
= ZwSetValueKey(LogConfKey
,
1179 REG_RESOURCE_REQUIREMENTS_LIST
,
1180 DeviceNode
->ResourceRequirements
,
1181 DeviceNode
->ResourceRequirements
->ListSize
);
1184 ZwClose(LogConfKey
);
1187 /* Set the 'ConfigFlags' value */
1188 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1189 Status
= ZwQueryValueKey(InstanceKey
,
1191 KeyValueBasicInformation
,
1195 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1197 /* Write the default value */
1198 ULONG DefaultConfigFlags
= 0;
1199 Status
= ZwSetValueKey(InstanceKey
,
1203 &DefaultConfigFlags
,
1204 sizeof(DefaultConfigFlags
));
1207 /* Create the 'Control' key */
1208 RtlInitUnicodeString(&KeyName
, L
"Control");
1209 InitializeObjectAttributes(&ObjectAttributes
,
1211 OBJ_CASE_INSENSITIVE
,
1214 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1216 if (NT_SUCCESS(Status
))
1217 ZwClose(ControlHandle
);
1219 DPRINT("IopSetDeviceInstanceData() done\n");
1225 * IopGetParentIdPrefix
1227 * Retrieve (or create) a string which identifies a device.
1231 * Pointer to device node.
1233 * Pointer to the string where is returned the parent node identifier
1236 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1237 * valid and its Buffer field is NULL-terminated. The caller needs to
1238 * to free the string with RtlFreeUnicodeString when it is no longer
1243 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1244 PUNICODE_STRING ParentIdPrefix
)
1246 ULONG KeyNameBufferLength
;
1247 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1248 UNICODE_STRING KeyName
= {0, 0, NULL
};
1249 UNICODE_STRING KeyValue
;
1250 UNICODE_STRING ValueName
;
1255 /* HACK: As long as some devices have a NULL device
1256 * instance path, the following test is required :(
1258 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1260 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1261 &DeviceNode
->InstancePath
);
1262 return STATUS_UNSUCCESSFUL
;
1265 /* 1. Try to retrieve ParentIdPrefix from registry */
1266 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1267 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1268 if (!ParentIdPrefixInformation
)
1270 return STATUS_INSUFFICIENT_RESOURCES
;
1273 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1274 if (!KeyName
.Buffer
)
1276 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1280 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1282 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1283 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1285 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1286 if (!NT_SUCCESS(Status
))
1288 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1289 Status
= ZwQueryValueKey(
1291 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1292 KeyNameBufferLength
, &KeyNameBufferLength
);
1293 if (NT_SUCCESS(Status
))
1295 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1296 Status
= STATUS_UNSUCCESSFUL
;
1299 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1300 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1304 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1306 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1307 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1311 /* 2. Create the ParentIdPrefix value */
1312 crc32
= RtlComputeCrc32(0,
1313 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1314 DeviceNode
->Parent
->InstancePath
.Length
);
1316 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1317 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1319 /* 3. Try to write the ParentIdPrefix to registry */
1320 Status
= ZwSetValueKey(hKey
,
1324 (PVOID
)KeyValue
.Buffer
,
1325 ((ULONG
)wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1328 if (NT_SUCCESS(Status
))
1330 /* Duplicate the string to return it */
1331 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1333 ExFreePool(ParentIdPrefixInformation
);
1334 RtlFreeUnicodeString(&KeyName
);
1341 IopQueryHardwareIds(PDEVICE_NODE DeviceNode
,
1344 IO_STACK_LOCATION Stack
;
1345 IO_STATUS_BLOCK IoStatusBlock
;
1347 UNICODE_STRING ValueName
;
1349 ULONG Length
, TotalLength
;
1351 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1353 RtlZeroMemory(&Stack
, sizeof(Stack
));
1354 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1355 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1359 if (NT_SUCCESS(Status
))
1362 * FIXME: Check for valid characters, if there is invalid characters
1366 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1367 DPRINT("Hardware IDs:\n");
1370 DPRINT(" %S\n", Ptr
);
1371 Length
= (ULONG
)wcslen(Ptr
) + 1;
1374 TotalLength
+= Length
;
1376 DPRINT("TotalLength: %hu\n", TotalLength
);
1379 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1380 Status
= ZwSetValueKey(InstanceKey
,
1384 (PVOID
)IoStatusBlock
.Information
,
1385 (TotalLength
+ 1) * sizeof(WCHAR
));
1386 if (!NT_SUCCESS(Status
))
1388 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1393 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1400 IopQueryCompatibleIds(PDEVICE_NODE DeviceNode
,
1403 IO_STACK_LOCATION Stack
;
1404 IO_STATUS_BLOCK IoStatusBlock
;
1406 UNICODE_STRING ValueName
;
1408 ULONG Length
, TotalLength
;
1410 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1412 RtlZeroMemory(&Stack
, sizeof(Stack
));
1413 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1414 Status
= IopInitiatePnpIrp(
1415 DeviceNode
->PhysicalDeviceObject
,
1419 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1422 * FIXME: Check for valid characters, if there is invalid characters
1426 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1427 DPRINT("Compatible IDs:\n");
1430 DPRINT(" %S\n", Ptr
);
1431 Length
= (ULONG
)wcslen(Ptr
) + 1;
1434 TotalLength
+= Length
;
1436 DPRINT("TotalLength: %hu\n", TotalLength
);
1439 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1440 Status
= ZwSetValueKey(InstanceKey
,
1444 (PVOID
)IoStatusBlock
.Information
,
1445 (TotalLength
+ 1) * sizeof(WCHAR
));
1446 if (!NT_SUCCESS(Status
))
1448 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1453 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1461 * IopActionInterrogateDeviceStack
1463 * Retrieve information for all (direct) child nodes of a parent node.
1467 * Pointer to device node.
1469 * Pointer to parent node to retrieve child node information for.
1472 * Any errors that occur are logged instead so that all child services have a chance
1473 * of being interrogated.
1477 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1480 IO_STATUS_BLOCK IoStatusBlock
;
1481 PDEVICE_NODE ParentDeviceNode
;
1482 WCHAR InstancePath
[MAX_PATH
];
1483 IO_STACK_LOCATION Stack
;
1485 ULONG RequiredLength
;
1487 HANDLE InstanceKey
= NULL
;
1488 UNICODE_STRING ValueName
;
1489 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1490 DEVICE_CAPABILITIES DeviceCapabilities
;
1492 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1493 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1495 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1498 * We are called for the parent too, but we don't need to do special
1499 * handling for this node
1502 if (DeviceNode
== ParentDeviceNode
)
1504 DPRINT("Success\n");
1505 return STATUS_SUCCESS
;
1509 * Make sure this device node is a direct child of the parent device node
1510 * that is given as an argument
1513 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1515 DPRINT("Skipping 2+ level child\n");
1516 return STATUS_SUCCESS
;
1519 /* Skip processing if it was already completed before */
1520 if (DeviceNode
->Flags
& DNF_PROCESSED
)
1523 return STATUS_SUCCESS
;
1527 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1528 if (!NT_SUCCESS(Status
))
1530 DPRINT1("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1535 * FIXME: For critical errors, cleanup and disable device, but always
1536 * return STATUS_SUCCESS.
1539 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1541 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1542 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1546 if (NT_SUCCESS(Status
))
1548 /* Copy the device id string */
1549 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1552 * FIXME: Check for valid characters, if there is invalid characters
1558 DPRINT1("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1560 /* We have to return success otherwise we abort the traverse operation */
1561 return STATUS_SUCCESS
;
1564 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
1566 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1567 if (!NT_SUCCESS(Status
))
1569 DPRINT1("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1571 /* We have to return success otherwise we abort the traverse operation */
1572 return STATUS_SUCCESS
;
1575 /* This bit is only check after enumeration */
1576 if (DeviceCapabilities
.HardwareDisabled
)
1578 /* FIXME: Cleanup device */
1579 DeviceNode
->Flags
|= DNF_DISABLED
;
1580 return STATUS_SUCCESS
;
1583 DeviceNode
->Flags
&= ~DNF_DISABLED
;
1585 if (!DeviceCapabilities
.UniqueID
)
1587 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1588 DPRINT("Instance ID is not unique\n");
1589 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1590 if (!NT_SUCCESS(Status
))
1592 DPRINT1("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1594 /* We have to return success otherwise we abort the traverse operation */
1595 return STATUS_SUCCESS
;
1599 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1601 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1602 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1606 if (NT_SUCCESS(Status
))
1608 /* Append the instance id string */
1609 wcscat(InstancePath
, L
"\\");
1610 if (ParentIdPrefix
.Length
> 0)
1612 /* Add information from parent bus device to InstancePath */
1613 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1614 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1615 wcscat(InstancePath
, L
"&");
1617 if (IoStatusBlock
.Information
)
1618 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1621 * FIXME: Check for valid characters, if there is invalid characters
1627 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1629 RtlFreeUnicodeString(&ParentIdPrefix
);
1631 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1633 DPRINT("No resources\n");
1634 /* FIXME: Cleanup and disable device */
1637 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1640 * Create registry key for the instance id, if it doesn't exist yet
1642 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
1643 if (!NT_SUCCESS(Status
))
1645 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1647 /* We have to return success otherwise we abort the traverse operation */
1648 return STATUS_SUCCESS
;
1651 IopQueryHardwareIds(DeviceNode
, InstanceKey
);
1653 IopQueryCompatibleIds(DeviceNode
, InstanceKey
);
1655 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1657 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1658 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1659 Status
= IopInitiatePnpIrp(
1660 DeviceNode
->PhysicalDeviceObject
,
1662 IRP_MN_QUERY_DEVICE_TEXT
,
1664 /* This key is mandatory, so even if the Irp fails, we still write it */
1665 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1666 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1668 if (NT_SUCCESS(Status
) &&
1669 IoStatusBlock
.Information
&&
1670 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1672 /* This key is overriden when a driver is installed. Don't write the
1673 * new description if another one already exists */
1674 Status
= ZwSetValueKey(InstanceKey
,
1678 (PVOID
)IoStatusBlock
.Information
,
1679 ((ULONG
)wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1683 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1684 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1686 Status
= ZwSetValueKey(InstanceKey
,
1691 DeviceDesc
.MaximumLength
);
1693 if (!NT_SUCCESS(Status
))
1695 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1701 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1703 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1704 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1705 Status
= IopInitiatePnpIrp(
1706 DeviceNode
->PhysicalDeviceObject
,
1708 IRP_MN_QUERY_DEVICE_TEXT
,
1710 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1712 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1713 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1714 Status
= ZwSetValueKey(InstanceKey
,
1718 (PVOID
)IoStatusBlock
.Information
,
1719 ((ULONG
)wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1720 if (!NT_SUCCESS(Status
))
1722 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1727 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1730 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1732 Status
= IopInitiatePnpIrp(
1733 DeviceNode
->PhysicalDeviceObject
,
1735 IRP_MN_QUERY_BUS_INFORMATION
,
1737 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1739 PPNP_BUS_INFORMATION BusInformation
=
1740 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1742 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1743 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1744 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1745 ExFreePool(BusInformation
);
1749 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1751 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1752 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1753 DeviceNode
->ChildBusTypeIndex
= -1;
1756 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1758 Status
= IopInitiatePnpIrp(
1759 DeviceNode
->PhysicalDeviceObject
,
1761 IRP_MN_QUERY_RESOURCES
,
1763 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1765 DeviceNode
->BootResources
=
1766 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1767 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
1771 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1772 DeviceNode
->BootResources
= NULL
;
1775 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1777 Status
= IopInitiatePnpIrp(
1778 DeviceNode
->PhysicalDeviceObject
,
1780 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1782 if (NT_SUCCESS(Status
))
1784 DeviceNode
->ResourceRequirements
=
1785 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1789 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1790 DeviceNode
->ResourceRequirements
= NULL
;
1793 if (InstanceKey
!= NULL
)
1795 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1798 ZwClose(InstanceKey
);
1800 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1802 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1804 /* Report the device to the user-mode pnp manager */
1805 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1806 &DeviceNode
->InstancePath
);
1809 return STATUS_SUCCESS
;
1814 IopHandleDeviceRemoval(
1815 IN PDEVICE_NODE DeviceNode
,
1816 IN PDEVICE_RELATIONS DeviceRelations
)
1818 PDEVICE_NODE Child
= DeviceNode
->Child
, NextChild
;
1822 while (Child
!= NULL
)
1824 NextChild
= Child
->Sibling
;
1827 for (i
= 0; DeviceRelations
&& i
< DeviceRelations
->Count
; i
++)
1829 if (IopGetDeviceNode(DeviceRelations
->Objects
[i
]) == Child
)
1838 IopSendSurpriseRemoval(Child
->PhysicalDeviceObject
);
1840 /* Tell the user-mode PnP manager that a device was removed */
1841 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
1842 &Child
->InstancePath
);
1844 IopSendRemoveDevice(Child
->PhysicalDeviceObject
);
1853 IN PDEVICE_OBJECT DeviceObject
)
1855 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1856 DEVICETREE_TRAVERSE_CONTEXT Context
;
1857 PDEVICE_RELATIONS DeviceRelations
;
1858 PDEVICE_OBJECT ChildDeviceObject
;
1859 IO_STATUS_BLOCK IoStatusBlock
;
1860 PDEVICE_NODE ChildDeviceNode
;
1861 IO_STACK_LOCATION Stack
;
1865 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1867 if (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
)
1869 DeviceNode
->Flags
&= ~DNF_NEED_ENUMERATION_ONLY
;
1871 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1872 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1873 &DeviceNode
->InstancePath
);
1876 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1878 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1880 Status
= IopInitiatePnpIrp(
1883 IRP_MN_QUERY_DEVICE_RELATIONS
,
1885 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1887 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1891 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1894 * Send removal IRPs for devices that have disappeared
1895 * NOTE: This code handles the case where no relations are specified
1897 IopHandleDeviceRemoval(DeviceNode
, DeviceRelations
);
1899 /* Now we bail if nothing was returned */
1900 if (!DeviceRelations
)
1902 /* We're all done */
1903 DPRINT("No PDOs\n");
1904 return STATUS_SUCCESS
;
1907 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1910 * Create device nodes for all discovered devices
1912 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1914 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1915 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1917 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1918 if (!ChildDeviceNode
)
1920 /* One doesn't exist, create it */
1921 Status
= IopCreateDeviceNode(
1926 if (NT_SUCCESS(Status
))
1928 /* Mark the node as enumerated */
1929 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1931 /* Mark the DO as bus enumerated */
1932 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1936 /* Ignore this DO */
1937 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1938 ObDereferenceObject(ChildDeviceObject
);
1943 /* Mark it as enumerated */
1944 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1945 ObDereferenceObject(ChildDeviceObject
);
1948 ExFreePool(DeviceRelations
);
1951 * Retrieve information about all discovered children from the bus driver
1953 IopInitDeviceTreeTraverseContext(
1956 IopActionInterrogateDeviceStack
,
1959 Status
= IopTraverseDeviceTree(&Context
);
1960 if (!NT_SUCCESS(Status
))
1962 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1967 * Retrieve configuration from the registry for discovered children
1969 IopInitDeviceTreeTraverseContext(
1972 IopActionConfigureChildServices
,
1975 Status
= IopTraverseDeviceTree(&Context
);
1976 if (!NT_SUCCESS(Status
))
1978 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1983 * Initialize services for discovered children.
1985 Status
= IopInitializePnpServices(DeviceNode
);
1986 if (!NT_SUCCESS(Status
))
1988 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1992 DPRINT("IopEnumerateDevice() finished\n");
1993 return STATUS_SUCCESS
;
1998 * IopActionConfigureChildServices
2000 * Retrieve configuration for all (direct) child nodes of a parent node.
2004 * Pointer to device node.
2006 * Pointer to parent node to retrieve child node configuration for.
2009 * Any errors that occur are logged instead so that all child services have a chance of beeing
2014 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2017 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2018 PDEVICE_NODE ParentDeviceNode
;
2019 PUNICODE_STRING Service
;
2020 UNICODE_STRING ClassGUID
;
2022 DEVICE_CAPABILITIES DeviceCaps
;
2024 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2026 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2029 * We are called for the parent too, but we don't need to do special
2030 * handling for this node
2032 if (DeviceNode
== ParentDeviceNode
)
2034 DPRINT("Success\n");
2035 return STATUS_SUCCESS
;
2039 * Make sure this device node is a direct child of the parent device node
2040 * that is given as an argument
2043 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2045 DPRINT("Skipping 2+ level child\n");
2046 return STATUS_SUCCESS
;
2049 if (!(DeviceNode
->Flags
& DNF_PROCESSED
))
2051 DPRINT1("Child not ready to be configured\n");
2052 return STATUS_SUCCESS
;
2055 if (!(DeviceNode
->Flags
& (DNF_DISABLED
| DNF_STARTED
| DNF_ADDED
)))
2057 WCHAR RegKeyBuffer
[MAX_PATH
];
2058 UNICODE_STRING RegKey
;
2061 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2062 RegKey
.Buffer
= RegKeyBuffer
;
2065 * Retrieve configuration from Enum key
2068 Service
= &DeviceNode
->ServiceName
;
2070 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2071 RtlInitUnicodeString(Service
, NULL
);
2072 RtlInitUnicodeString(&ClassGUID
, NULL
);
2074 QueryTable
[0].Name
= L
"Service";
2075 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2076 QueryTable
[0].EntryContext
= Service
;
2078 QueryTable
[1].Name
= L
"ClassGUID";
2079 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2080 QueryTable
[1].EntryContext
= &ClassGUID
;
2081 QueryTable
[1].DefaultType
= REG_SZ
;
2082 QueryTable
[1].DefaultData
= L
"";
2083 QueryTable
[1].DefaultLength
= 0;
2085 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2086 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2088 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2089 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2091 if (!NT_SUCCESS(Status
))
2093 /* FIXME: Log the error */
2094 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2095 &DeviceNode
->InstancePath
, Status
);
2096 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2097 return STATUS_SUCCESS
;
2100 if (Service
->Buffer
== NULL
)
2102 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
2103 DeviceCaps
.RawDeviceOK
)
2105 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
2107 DeviceNode
->ServiceName
.Length
= 0;
2108 DeviceNode
->ServiceName
.MaximumLength
= 0;
2109 DeviceNode
->ServiceName
.Buffer
= NULL
;
2111 else if (ClassGUID
.Length
!= 0)
2113 /* Device has a ClassGUID value, but no Service value.
2114 * Suppose it is using the NULL driver, so state the
2115 * device is started */
2116 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2117 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2121 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2123 return STATUS_SUCCESS
;
2126 DPRINT("Got Service %S\n", Service
->Buffer
);
2129 return STATUS_SUCCESS
;
2133 * IopActionInitChildServices
2135 * Initialize the service for all (direct) child nodes of a parent node
2139 * Pointer to device node.
2141 * Pointer to parent node to initialize child node services for.
2144 * If the driver image for a service is not loaded and initialized
2145 * it is done here too. Any errors that occur are logged instead so
2146 * that all child services have a chance of being initialized.
2150 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2153 PDEVICE_NODE ParentDeviceNode
;
2155 BOOLEAN BootDrivers
= !PnpSystemInit
;
2157 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2159 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2162 * We are called for the parent too, but we don't need to do special
2163 * handling for this node
2165 if (DeviceNode
== ParentDeviceNode
)
2167 DPRINT("Success\n");
2168 return STATUS_SUCCESS
;
2172 * Make sure this device node is a direct child of the parent device node
2173 * that is given as an argument
2176 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2178 DPRINT("Skipping 2+ level child\n");
2179 return STATUS_SUCCESS
;
2182 if (!(DeviceNode
->Flags
& DNF_PROCESSED
))
2184 DPRINT1("Child not ready to be added\n");
2185 return STATUS_SUCCESS
;
2188 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
2189 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
2190 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2191 return STATUS_SUCCESS
;
2193 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
2195 /* We don't need to worry about loading the driver because we're
2196 * being driven in raw mode so our parent must be loaded to get here */
2197 Status
= IopInitializeDevice(DeviceNode
, NULL
);
2198 if (NT_SUCCESS(Status
))
2200 Status
= IopStartDevice(DeviceNode
);
2201 if (!NT_SUCCESS(Status
))
2203 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
2204 &DeviceNode
->InstancePath
, Status
);
2210 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2211 PDRIVER_OBJECT DriverObject
;
2213 /* Get existing DriverObject pointer (in case the driver has
2214 already been loaded and initialized) */
2215 Status
= IopGetDriverObject(
2217 &DeviceNode
->ServiceName
,
2220 if (!NT_SUCCESS(Status
))
2222 /* Driver is not initialized, try to load it */
2223 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2225 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2227 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2228 was loaded by the bootloader */
2229 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2230 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2232 /* Initialize the driver */
2233 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2234 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2238 Status
= STATUS_SUCCESS
;
2243 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2244 &DeviceNode
->ServiceName
, Status
);
2248 /* Driver is loaded and initialized at this point */
2249 if (NT_SUCCESS(Status
))
2251 /* Initialize the device, including all filters */
2252 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
2257 * Don't disable when trying to load only boot drivers
2261 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2262 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2263 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2264 DPRINT1("Initialization of service %S failed (Status %x)\n",
2265 DeviceNode
->ServiceName
.Buffer
, Status
);
2270 return STATUS_SUCCESS
;
2274 * IopInitializePnpServices
2276 * Initialize services for discovered children
2280 * Top device node to start initializing services.
2286 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2288 DEVICETREE_TRAVERSE_CONTEXT Context
;
2290 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2292 IopInitDeviceTreeTraverseContext(
2295 IopActionInitChildServices
,
2298 return IopTraverseDeviceTree(&Context
);
2301 static NTSTATUS INIT_FUNCTION
2302 IopEnumerateDetectedDevices(
2304 IN PUNICODE_STRING RelativePath OPTIONAL
,
2306 IN BOOLEAN EnumerateSubKeys
,
2307 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2308 IN ULONG ParentBootResourcesLength
)
2310 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2311 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2312 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2313 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2314 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2315 OBJECT_ATTRIBUTES ObjectAttributes
;
2316 HANDLE hDevicesKey
= NULL
;
2317 HANDLE hDeviceKey
= NULL
;
2318 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2319 UNICODE_STRING Level2NameU
;
2320 WCHAR Level2Name
[5];
2321 ULONG IndexDevice
= 0;
2323 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2324 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2325 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2326 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2327 UNICODE_STRING DeviceName
, ValueName
;
2329 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2330 ULONG BootResourcesLength
;
2333 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2334 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2335 static ULONG DeviceIndexPci
= 0;
2336 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2337 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2338 static ULONG DeviceIndexSerial
= 0;
2339 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2340 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2341 static ULONG DeviceIndexKeyboard
= 0;
2342 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2343 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2344 static ULONG DeviceIndexMouse
= 0;
2345 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2346 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2347 static ULONG DeviceIndexParallel
= 0;
2348 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2349 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2350 static ULONG DeviceIndexFloppy
= 0;
2351 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2352 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2353 static ULONG DeviceIndexIsa
= 0;
2354 UNICODE_STRING HardwareIdKey
;
2355 PUNICODE_STRING pHardwareId
;
2356 ULONG DeviceIndex
= 0;
2357 PUCHAR CmResourceList
;
2362 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2363 if (!NT_SUCCESS(Status
))
2365 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2370 hDevicesKey
= hBaseKey
;
2372 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2373 if (!pDeviceInformation
)
2375 DPRINT("ExAllocatePool() failed\n");
2376 Status
= STATUS_NO_MEMORY
;
2380 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2381 if (!pValueInformation
)
2383 DPRINT("ExAllocatePool() failed\n");
2384 Status
= STATUS_NO_MEMORY
;
2390 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2391 if (Status
== STATUS_NO_MORE_ENTRIES
)
2393 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2395 ExFreePool(pDeviceInformation
);
2396 DeviceInfoLength
= RequiredSize
;
2397 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2398 if (!pDeviceInformation
)
2400 DPRINT("ExAllocatePool() failed\n");
2401 Status
= STATUS_NO_MEMORY
;
2404 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2406 if (!NT_SUCCESS(Status
))
2408 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2413 /* Open device key */
2414 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2415 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2417 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2418 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2419 if (!NT_SUCCESS(Status
))
2421 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2425 /* Read boot resources, and add then to parent ones */
2426 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2427 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2429 ExFreePool(pValueInformation
);
2430 ValueInfoLength
= RequiredSize
;
2431 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2432 if (!pValueInformation
)
2434 DPRINT("ExAllocatePool() failed\n");
2435 ZwDeleteKey(hLevel2Key
);
2436 Status
= STATUS_NO_MEMORY
;
2439 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2441 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2443 BootResources
= ParentBootResources
;
2444 BootResourcesLength
= ParentBootResourcesLength
;
2446 else if (!NT_SUCCESS(Status
))
2448 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2451 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2453 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2458 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2460 /* Concatenate current resources and parent ones */
2461 if (ParentBootResourcesLength
== 0)
2462 BootResourcesLength
= pValueInformation
->DataLength
;
2464 BootResourcesLength
= ParentBootResourcesLength
2465 + pValueInformation
->DataLength
2467 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2470 DPRINT("ExAllocatePool() failed\n");
2473 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2475 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2477 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2479 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2481 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2482 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2483 ParentBootResourcesLength
- Header
);
2484 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2488 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2490 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2491 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2492 ParentBootResourcesLength
- Header
);
2494 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2495 pValueInformation
->Data
+ Header
,
2496 pValueInformation
->DataLength
- Header
);
2497 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2501 if (EnumerateSubKeys
)
2506 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2507 if (Status
== STATUS_NO_MORE_ENTRIES
)
2509 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2511 ExFreePool(pDeviceInformation
);
2512 DeviceInfoLength
= RequiredSize
;
2513 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2514 if (!pDeviceInformation
)
2516 DPRINT("ExAllocatePool() failed\n");
2517 Status
= STATUS_NO_MEMORY
;
2520 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2522 if (!NT_SUCCESS(Status
))
2524 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2528 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2529 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2531 Status
= IopEnumerateDetectedDevices(
2537 BootResourcesLength
);
2538 if (!NT_SUCCESS(Status
))
2543 /* Read identifier */
2544 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2545 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2547 ExFreePool(pValueInformation
);
2548 ValueInfoLength
= RequiredSize
;
2549 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2550 if (!pValueInformation
)
2552 DPRINT("ExAllocatePool() failed\n");
2553 Status
= STATUS_NO_MEMORY
;
2556 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2558 if (!NT_SUCCESS(Status
))
2560 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2562 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2565 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2567 else if (pValueInformation
->Type
!= REG_SZ
)
2569 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2574 /* Assign hardware id to this device */
2575 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2576 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2577 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2578 ValueName
.Length
-= sizeof(WCHAR
);
2581 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2583 pHardwareId
= &HardwareIdSerial
;
2584 DeviceIndex
= DeviceIndexSerial
++;
2586 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2588 pHardwareId
= &HardwareIdKeyboard
;
2589 DeviceIndex
= DeviceIndexKeyboard
++;
2591 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2593 pHardwareId
= &HardwareIdMouse
;
2594 DeviceIndex
= DeviceIndexMouse
++;
2596 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
2598 pHardwareId
= &HardwareIdParallel
;
2599 DeviceIndex
= DeviceIndexParallel
++;
2601 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
2603 pHardwareId
= &HardwareIdFloppy
;
2604 DeviceIndex
= DeviceIndexFloppy
++;
2606 else if (NT_SUCCESS(Status
))
2608 /* Try to also match the device identifier */
2609 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2611 pHardwareId
= &HardwareIdPci
;
2612 DeviceIndex
= DeviceIndexPci
++;
2614 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
2616 pHardwareId
= &HardwareIdIsa
;
2617 DeviceIndex
= DeviceIndexIsa
++;
2621 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2627 /* Unknown key path */
2628 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2632 /* Prepare hardware id key (hardware id value without final \0) */
2633 HardwareIdKey
= *pHardwareId
;
2634 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2636 /* Add the detected device to Root key */
2637 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2638 Status
= ZwCreateKey(
2644 ExpInTextModeSetup
? REG_OPTION_VOLATILE
: 0,
2646 if (!NT_SUCCESS(Status
))
2648 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2651 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2652 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2653 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2654 Status
= ZwCreateKey(
2656 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2660 ExpInTextModeSetup
? REG_OPTION_VOLATILE
: 0,
2662 ZwClose(hLevel1Key
);
2663 if (!NT_SUCCESS(Status
))
2665 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2668 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
2669 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2670 if (!NT_SUCCESS(Status
))
2672 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2673 ZwDeleteKey(hLevel2Key
);
2676 /* Create 'LogConf' subkey */
2677 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2678 Status
= ZwCreateKey(
2684 REG_OPTION_VOLATILE
,
2686 if (!NT_SUCCESS(Status
))
2688 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2689 ZwDeleteKey(hLevel2Key
);
2692 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2694 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
2695 if (!CmResourceList
)
2698 ZwDeleteKey(hLevel2Key
);
2702 /* Add the list count (1st member of CM_RESOURCE_LIST) */
2704 RtlCopyMemory(CmResourceList
,
2708 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
2709 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
2711 BootResourcesLength
);
2713 /* Save boot resources to 'LogConf\BootConfig' */
2714 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
2715 if (!NT_SUCCESS(Status
))
2717 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2719 ZwDeleteKey(hLevel2Key
);
2726 if (BootResources
&& BootResources
!= ParentBootResources
)
2728 ExFreePool(BootResources
);
2729 BootResources
= NULL
;
2733 ZwClose(hLevel2Key
);
2738 ZwClose(hDeviceKey
);
2743 Status
= STATUS_SUCCESS
;
2746 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2747 ZwClose(hDevicesKey
);
2749 ZwClose(hDeviceKey
);
2750 if (pDeviceInformation
)
2751 ExFreePool(pDeviceInformation
);
2752 if (pValueInformation
)
2753 ExFreePool(pValueInformation
);
2757 static BOOLEAN INIT_FUNCTION
2758 IopIsFirmwareMapperDisabled(VOID
)
2760 UNICODE_STRING KeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CURRENTCONTROLSET\\Control\\Pnp");
2761 UNICODE_STRING KeyNameU
= RTL_CONSTANT_STRING(L
"DisableFirmwareMapper");
2762 OBJECT_ATTRIBUTES ObjectAttributes
;
2764 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
;
2765 ULONG DesiredLength
, Length
;
2769 InitializeObjectAttributes(&ObjectAttributes
, &KeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2770 Status
= ZwOpenKey(&hPnpKey
, KEY_QUERY_VALUE
, &ObjectAttributes
);
2771 if (NT_SUCCESS(Status
))
2773 Status
= ZwQueryValueKey(hPnpKey
,
2775 KeyValuePartialInformation
,
2779 if ((Status
== STATUS_BUFFER_TOO_SMALL
) ||
2780 (Status
== STATUS_BUFFER_OVERFLOW
))
2782 Length
= DesiredLength
;
2783 KeyInformation
= ExAllocatePool(PagedPool
, Length
);
2786 Status
= ZwQueryValueKey(hPnpKey
,
2788 KeyValuePartialInformation
,
2792 if (NT_SUCCESS(Status
) && KeyInformation
->DataLength
== sizeof(ULONG
))
2794 KeyValue
= (ULONG
)(*KeyInformation
->Data
);
2798 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed\n", &KeyPathU
, &KeyNameU
);
2801 ExFreePool(KeyInformation
);
2805 DPRINT1("Failed to allocate memory for registry query\n");
2810 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed with status 0x%08lx\n", &KeyPathU
, &KeyNameU
, Status
);
2817 DPRINT1("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyPathU
, Status
);
2820 DPRINT1("Firmware mapper is %s\n", KeyValue
!= 0 ? "disabled" : "enabled");
2822 return (KeyValue
!= 0) ? TRUE
: FALSE
;
2828 IopUpdateRootKey(VOID
)
2830 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2831 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2832 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2833 OBJECT_ATTRIBUTES ObjectAttributes
;
2834 HANDLE hEnum
, hRoot
;
2837 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2838 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2839 if (!NT_SUCCESS(Status
))
2841 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2845 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2846 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2848 if (!NT_SUCCESS(Status
))
2850 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2854 if (!IopIsFirmwareMapperDisabled())
2856 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2857 if (!NT_SUCCESS(Status
))
2859 /* Nothing to do, don't return with an error status */
2860 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2862 return STATUS_SUCCESS
;
2864 Status
= IopEnumerateDetectedDevices(
2875 /* Enumeration is disabled */
2876 Status
= STATUS_SUCCESS
;
2886 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2888 PUNICODE_STRING Name
,
2889 ACCESS_MASK DesiredAccess
)
2891 OBJECT_ATTRIBUTES ObjectAttributes
;
2898 InitializeObjectAttributes(&ObjectAttributes
,
2900 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2904 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2911 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
2912 IN HANDLE RootHandle OPTIONAL
,
2913 IN PUNICODE_STRING KeyName
,
2914 IN ACCESS_MASK DesiredAccess
,
2915 IN ULONG CreateOptions
,
2916 OUT PULONG Disposition OPTIONAL
)
2918 OBJECT_ATTRIBUTES ObjectAttributes
;
2919 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0;
2921 HANDLE HandleArray
[2];
2922 BOOLEAN Recursing
= TRUE
;
2924 UNICODE_STRING KeyString
;
2925 NTSTATUS Status
= STATUS_SUCCESS
;
2928 /* P1 is start, pp is end */
2929 p1
= KeyName
->Buffer
;
2930 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
2932 /* Create the target key */
2933 InitializeObjectAttributes(&ObjectAttributes
,
2935 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2938 Status
= ZwCreateKey(&HandleArray
[i
],
2946 /* Now we check if this failed */
2947 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
2949 /* Target key failed, so we'll need to create its parent. Setup array */
2950 HandleArray
[0] = NULL
;
2951 HandleArray
[1] = RootHandle
;
2953 /* Keep recursing for each missing parent */
2956 /* And if we're deep enough, close the last handle */
2957 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2959 /* We're setup to ping-pong between the two handle array entries */
2960 RootHandleIndex
= i
;
2963 /* Clear the one we're attempting to open now */
2964 HandleArray
[i
] = NULL
;
2966 /* Process the parent key name */
2967 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
2968 Length
= (USHORT
)(p
- p1
) * sizeof(WCHAR
);
2970 /* Is there a parent name? */
2973 /* Build the unicode string for it */
2974 KeyString
.Buffer
= p1
;
2975 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
2977 /* Now try opening the parent */
2978 InitializeObjectAttributes(&ObjectAttributes
,
2980 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2981 HandleArray
[RootHandleIndex
],
2983 Status
= ZwCreateKey(&HandleArray
[i
],
2990 if (NT_SUCCESS(Status
))
2992 /* It worked, we have one more handle */
2997 /* Parent key creation failed, abandon loop */
3004 /* We don't have a parent name, probably corrupted key name */
3005 Status
= STATUS_INVALID_PARAMETER
;
3010 /* Now see if there's more parents to create */
3012 if ((p
== pp
) || (p1
== pp
))
3014 /* We're done, hopefully successfully, so stop */
3019 /* Outer loop check for handle nesting that requires closing the top handle */
3020 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3023 /* Check if we broke out of the loop due to success */
3024 if (NT_SUCCESS(Status
))
3026 /* Return the target handle (we closed all the parent ones) and disposition */
3027 *Handle
= HandleArray
[i
];
3028 if (Disposition
) *Disposition
= KeyDisposition
;
3031 /* Return the success state */
3037 IopGetRegistryValue(IN HANDLE Handle
,
3039 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
3041 UNICODE_STRING ValueString
;
3043 PKEY_VALUE_FULL_INFORMATION FullInformation
;
3047 RtlInitUnicodeString(&ValueString
, ValueName
);
3049 Status
= ZwQueryValueKey(Handle
,
3051 KeyValueFullInformation
,
3055 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
3056 (Status
!= STATUS_BUFFER_TOO_SMALL
))
3061 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
3062 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
3064 Status
= ZwQueryValueKey(Handle
,
3066 KeyValueFullInformation
,
3070 if (!NT_SUCCESS(Status
))
3072 ExFreePool(FullInformation
);
3076 *Information
= FullInformation
;
3077 return STATUS_SUCCESS
;
3080 RTL_GENERIC_COMPARE_RESULTS
3082 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3083 IN PVOID FirstStruct
,
3084 IN PVOID SecondStruct
)
3092 // The allocation function is called by the generic table package whenever
3093 // it needs to allocate memory for the table.
3098 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3108 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3117 PpInitializeDeviceReferenceTable(VOID
)
3119 /* Setup the guarded mutex and AVL table */
3120 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3121 RtlInitializeGenericTableAvl(
3122 &PpDeviceReferenceTable
,
3123 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3124 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3125 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3133 /* Initialize the resource when accessing device registry data */
3134 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3136 /* Setup the device reference AVL table */
3137 PpInitializeDeviceReferenceTable();
3145 /* Check the initialization phase */
3146 switch (ExpInitializationPhase
)
3151 return PiInitPhase0();
3157 //return PiInitPhase1();
3161 /* Don't know any other phase! Bugcheck! */
3162 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3167 LONG IopNumberDeviceNodes
;
3171 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3173 PDEVICE_NODE DeviceNode
;
3177 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), 'donD');
3178 if (!DeviceNode
) return DeviceNode
;
3181 InterlockedIncrement(&IopNumberDeviceNodes
);
3184 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
3185 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
3186 DeviceNode
->BusNumber
= -1;
3187 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
3188 DeviceNode
->ChildBusNumber
= -1;
3189 DeviceNode
->ChildBusTypeIndex
= -1;
3190 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
3191 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
3192 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
3193 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
3194 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
3195 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
3197 /* Check if there is a PDO */
3198 if (PhysicalDeviceObject
)
3200 /* Link it and remove the init flag */
3201 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
3202 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
3203 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3206 /* Return the node */
3210 /* PUBLIC FUNCTIONS **********************************************************/
3214 PnpBusTypeGuidGet(IN USHORT Index
,
3215 IN LPGUID BusTypeGuid
)
3217 NTSTATUS Status
= STATUS_SUCCESS
;
3219 /* Acquire the lock */
3220 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
3223 if (Index
< PnpBusTypeGuidList
->GuidCount
)
3226 RtlCopyMemory(BusTypeGuid
, &PnpBusTypeGuidList
->Guids
[Index
], sizeof(GUID
));
3231 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
3234 /* Release lock and return status */
3235 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
3241 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject
,
3242 IN PHANDLE DeviceInstanceHandle
,
3243 IN ACCESS_MASK DesiredAccess
)
3247 PDEVICE_NODE DeviceNode
;
3248 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
3251 /* Open the enum key */
3252 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
3256 if (!NT_SUCCESS(Status
)) return Status
;
3258 /* Make sure we have an instance path */
3259 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3260 if ((DeviceNode
) && (DeviceNode
->InstancePath
.Length
))
3262 /* Get the instance key */
3263 Status
= IopOpenRegistryKeyEx(DeviceInstanceHandle
,
3265 &DeviceNode
->InstancePath
,
3271 Status
= STATUS_INVALID_DEVICE_REQUEST
;
3274 /* Close the handle and return status */
3281 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList
)
3283 ULONG FinalSize
, PartialSize
, EntrySize
, i
, j
;
3284 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
3285 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
3287 /* If we don't have one, that's easy */
3288 if (!ResourceList
) return 0;
3290 /* Start with the minimum size possible */
3291 FinalSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
3293 /* Loop each full descriptor */
3294 FullDescriptor
= ResourceList
->List
;
3295 for (i
= 0; i
< ResourceList
->Count
; i
++)
3297 /* Start with the minimum size possible */
3298 PartialSize
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
) +
3299 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
);
3301 /* Loop each partial descriptor */
3302 PartialDescriptor
= FullDescriptor
->PartialResourceList
.PartialDescriptors
;
3303 for (j
= 0; j
< FullDescriptor
->PartialResourceList
.Count
; j
++)
3305 /* Start with the minimum size possible */
3306 EntrySize
= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
3308 /* Check if there is extra data */
3309 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
3312 EntrySize
+= PartialDescriptor
->u
.DeviceSpecificData
.DataSize
;
3315 /* The size of partial descriptors is bigger */
3316 PartialSize
+= EntrySize
;
3318 /* Go to the next partial descriptor */
3319 PartialDescriptor
= (PVOID
)((ULONG_PTR
)PartialDescriptor
+ EntrySize
);
3322 /* The size of full descriptors is bigger */
3323 FinalSize
+= PartialSize
;
3325 /* Go to the next full descriptor */
3326 FullDescriptor
= (PVOID
)((ULONG_PTR
)FullDescriptor
+ PartialSize
);
3329 /* Return the final size */
3335 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject
,
3340 IN PULONG BufferLength
)
3343 HANDLE KeyHandle
, SubHandle
;
3344 UNICODE_STRING KeyString
;
3345 PKEY_VALUE_FULL_INFORMATION KeyValueInfo
= NULL
;
3349 /* Find the instance key */
3350 Status
= PnpDeviceObjectToDeviceInstance(DeviceObject
, &KeyHandle
, KEY_READ
);
3351 if (NT_SUCCESS(Status
))
3353 /* Check for name given by caller */
3357 RtlInitUnicodeString(&KeyString
, KeyName
);
3358 Status
= IopOpenRegistryKeyEx(&SubHandle
,
3362 if (NT_SUCCESS(Status
))
3364 /* And use this handle instead */
3366 KeyHandle
= SubHandle
;
3370 /* Check if sub-key handle succeeded (or no-op if no key name given) */
3371 if (NT_SUCCESS(Status
))
3373 /* Now get the size of the property */
3374 Status
= IopGetRegistryValue(KeyHandle
,
3383 /* Fail if any of the registry operations failed */
3384 if (!NT_SUCCESS(Status
)) return Status
;
3386 /* Check how much data we have to copy */
3387 Length
= KeyValueInfo
->DataLength
;
3388 if (*BufferLength
>= Length
)
3390 /* Check for a match in the value type */
3391 if (KeyValueInfo
->Type
== ValueType
)
3394 RtlCopyMemory(Buffer
,
3395 (PVOID
)((ULONG_PTR
)KeyValueInfo
+
3396 KeyValueInfo
->DataOffset
),
3401 /* Invalid registry property type, fail */
3402 Status
= STATUS_INVALID_PARAMETER_2
;
3407 /* Buffer is too small to hold data */
3408 Status
= STATUS_BUFFER_TOO_SMALL
;
3411 /* Return the required buffer length, free the buffer, and return status */
3412 *BufferLength
= Length
;
3413 ExFreePool(KeyValueInfo
);
3417 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
3418 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
3419 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED; while(TRUE); break;}
3426 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3427 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3428 IN ULONG BufferLength
,
3429 OUT PVOID PropertyBuffer
,
3430 OUT PULONG ResultLength
)
3432 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3433 DEVICE_CAPABILITIES DeviceCaps
;
3434 ULONG ReturnLength
= 0, Length
= 0, ValueType
;
3435 PWCHAR ValueName
= NULL
, EnumeratorNameEnd
, DeviceInstanceName
;
3437 NTSTATUS Status
= STATUS_BUFFER_TOO_SMALL
;
3439 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
3440 BOOLEAN NullTerminate
= FALSE
;
3442 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3444 /* Assume failure */
3447 /* Only PDOs can call this */
3448 if (!DeviceNode
) return STATUS_INVALID_DEVICE_REQUEST
;
3450 /* Handle all properties */
3451 switch (DeviceProperty
)
3453 case DevicePropertyBusTypeGuid
:
3455 /* Get the GUID from the internal cache */
3456 Status
= PnpBusTypeGuidGet(DeviceNode
->ChildBusTypeIndex
, &BusTypeGuid
);
3457 if (!NT_SUCCESS(Status
)) return Status
;
3459 /* This is the format of the returned data */
3460 PIP_RETURN_DATA(sizeof(GUID
), &BusTypeGuid
);
3462 case DevicePropertyLegacyBusType
:
3464 /* Validate correct interface type */
3465 if (DeviceNode
->ChildInterfaceType
== InterfaceTypeUndefined
)
3466 return STATUS_OBJECT_NAME_NOT_FOUND
;
3468 /* This is the format of the returned data */
3469 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE
), &DeviceNode
->ChildInterfaceType
);
3471 case DevicePropertyBusNumber
:
3473 /* Validate correct bus number */
3474 if ((DeviceNode
->ChildBusNumber
& 0x80000000) == 0x80000000)
3475 return STATUS_OBJECT_NAME_NOT_FOUND
;
3477 /* This is the format of the returned data */
3478 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceNode
->ChildBusNumber
);
3480 case DevicePropertyEnumeratorName
:
3482 /* Get the instance path */
3483 DeviceInstanceName
= DeviceNode
->InstancePath
.Buffer
;
3486 ASSERT((BufferLength
& 1) == 0);
3487 ASSERT(DeviceInstanceName
!= NULL
);
3489 /* Get the name from the path */
3490 EnumeratorNameEnd
= wcschr(DeviceInstanceName
, OBJ_NAME_PATH_SEPARATOR
);
3491 ASSERT(EnumeratorNameEnd
);
3493 /* This string needs to be NULL-terminated */
3494 NullTerminate
= TRUE
;
3496 /* This is the format of the returned data */
3497 PIP_RETURN_DATA((ULONG
)(EnumeratorNameEnd
- DeviceInstanceName
) * sizeof(WCHAR
),
3498 DeviceInstanceName
);
3500 case DevicePropertyAddress
:
3502 /* Query the device caps */
3503 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3504 if (!NT_SUCCESS(Status
) || (DeviceCaps
.Address
== MAXULONG
))
3505 return STATUS_OBJECT_NAME_NOT_FOUND
;
3507 /* This is the format of the returned data */
3508 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceCaps
.Address
);
3510 case DevicePropertyBootConfigurationTranslated
:
3512 /* Validate we have resources */
3513 if (!DeviceNode
->BootResources
)
3514 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
3516 /* No resources will still fake success, but with 0 bytes */
3518 return STATUS_SUCCESS
;
3521 /* This is the format of the returned data */
3522 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode
->BootResources
), // FIXFIX: Should use BootResourcesTranslated
3523 DeviceNode
->BootResources
); // FIXFIX: Should use BootResourcesTranslated
3525 case DevicePropertyPhysicalDeviceObjectName
:
3527 /* Sanity check for Unicode-sized string */
3528 ASSERT((BufferLength
& 1) == 0);
3530 /* Allocate name buffer */
3531 Length
= BufferLength
+ sizeof(OBJECT_NAME_INFORMATION
);
3532 ObjectNameInfo
= ExAllocatePool(PagedPool
, Length
);
3533 if (!ObjectNameInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
3535 /* Query the PDO name */
3536 Status
= ObQueryNameString(DeviceObject
,
3540 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
3542 /* It's up to the caller to try again */
3543 Status
= STATUS_BUFFER_TOO_SMALL
;
3546 /* This string needs to be NULL-terminated */
3547 NullTerminate
= TRUE
;
3549 /* Return if successful */
3550 if (NT_SUCCESS(Status
)) PIP_RETURN_DATA(ObjectNameInfo
->Name
.Length
,
3551 ObjectNameInfo
->Name
.Buffer
);
3553 /* Let the caller know how big the name is */
3554 *ResultLength
-= sizeof(OBJECT_NAME_INFORMATION
);
3557 /* Handle the registry-based properties */
3558 case DevicePropertyUINumber
:
3559 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER
, REG_DWORD
);
3560 case DevicePropertyLocationInformation
:
3561 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION
, REG_SZ
);
3562 case DevicePropertyDeviceDescription
:
3563 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC
, REG_SZ
);
3564 case DevicePropertyHardwareID
:
3565 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID
, REG_MULTI_SZ
);
3566 case DevicePropertyCompatibleIDs
:
3567 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS
, REG_MULTI_SZ
);
3568 case DevicePropertyBootConfiguration
:
3569 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG
, REG_RESOURCE_LIST
);
3570 case DevicePropertyClassName
:
3571 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS
, REG_SZ
);
3572 case DevicePropertyClassGuid
:
3573 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID
, REG_SZ
);
3574 case DevicePropertyDriverKeyName
:
3575 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER
, REG_SZ
);
3576 case DevicePropertyManufacturer
:
3577 PIP_REGISTRY_DATA(REGSTR_VAL_MFG
, REG_SZ
);
3578 case DevicePropertyFriendlyName
:
3579 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME
, REG_SZ
);
3580 case DevicePropertyContainerID
:
3581 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
3582 PIP_UNIMPLEMENTED();
3583 case DevicePropertyRemovalPolicy
:
3584 PIP_UNIMPLEMENTED();
3585 case DevicePropertyInstallState
:
3586 PIP_UNIMPLEMENTED();
3587 case DevicePropertyResourceRequirements
:
3588 PIP_UNIMPLEMENTED();
3589 case DevicePropertyAllocatedResources
:
3590 PIP_UNIMPLEMENTED();
3592 return STATUS_INVALID_PARAMETER_2
;
3595 /* Having a registry value name implies registry data */
3598 /* We know up-front how much data to expect */
3599 *ResultLength
= BufferLength
;
3601 /* Go get the data, use the LogConf subkey if necessary */
3602 Status
= PiGetDeviceRegistryProperty(DeviceObject
,
3606 DevicePropertyBootConfiguration
) ?
3611 else if (NT_SUCCESS(Status
))
3613 /* We know up-front how much data to expect, check the caller's buffer */
3614 *ResultLength
= ReturnLength
+ (NullTerminate
? sizeof(UNICODE_NULL
) : 0);
3615 if (*ResultLength
<= BufferLength
)
3617 /* Buffer is all good, copy the data */
3618 RtlCopyMemory(PropertyBuffer
, Data
, ReturnLength
);
3620 /* Check if we need to NULL-terminate the string */
3623 /* Terminate the string */
3624 ((PWCHAR
)PropertyBuffer
)[ReturnLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3627 /* This is the success path */
3628 Status
= STATUS_SUCCESS
;
3633 Status
= STATUS_BUFFER_TOO_SMALL
;
3637 /* Free any allocation we may have made, and return the status code */
3638 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
3647 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3649 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
3650 IO_STACK_LOCATION Stack
;
3653 IO_STATUS_BLOCK IoStatusBlock
;
3655 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
3656 Stack
.MajorFunction
= IRP_MJ_PNP
;
3657 Stack
.MinorFunction
= IRP_MN_QUERY_PNP_DEVICE_STATE
;
3659 Status
= IopSynchronousCall(PhysicalDeviceObject
, &Stack
, (PVOID
*)&PnPFlags
);
3660 if (!NT_SUCCESS(Status
))
3662 DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%x\n", Status
);
3666 if (PnPFlags
& PNP_DEVICE_NOT_DISABLEABLE
)
3667 DeviceNode
->UserFlags
|= DNUF_NOT_DISABLEABLE
;
3669 DeviceNode
->UserFlags
&= ~DNUF_NOT_DISABLEABLE
;
3671 if (PnPFlags
& PNP_DEVICE_DONT_DISPLAY_IN_UI
)
3672 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
3674 DeviceNode
->UserFlags
&= ~DNUF_DONT_SHOW_IN_UI
;
3676 if ((PnPFlags
& PNP_DEVICE_REMOVED
) ||
3677 ((PnPFlags
& PNP_DEVICE_FAILED
) && !(PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)))
3679 /* Surprise removal */
3681 IopSendSurpriseRemoval(PhysicalDeviceObject
);
3683 /* Tell the user-mode PnP manager that a device was removed */
3684 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
3685 &DeviceNode
->InstancePath
);
3687 IopSendRemoveDevice(PhysicalDeviceObject
);
3689 else if ((PnPFlags
& PNP_DEVICE_FAILED
) && (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
))
3691 /* Stop for resource rebalance */
3693 Status
= IopStopDevice(DeviceNode
);
3694 if (!NT_SUCCESS(Status
))
3696 DPRINT1("Failed to stop device for rebalancing\n");
3698 /* Stop failed so don't rebalance */
3699 PnPFlags
&= ~PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
;
3703 /* Resource rebalance */
3704 if (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)
3706 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
3708 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
3710 IRP_MN_QUERY_RESOURCES
,
3712 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
3714 DeviceNode
->BootResources
=
3715 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
3716 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
3720 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
3721 DeviceNode
->BootResources
= NULL
;
3724 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
3726 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
3728 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
3730 if (NT_SUCCESS(Status
))
3732 DeviceNode
->ResourceRequirements
=
3733 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
3737 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
3738 DeviceNode
->ResourceRequirements
= NULL
;
3741 /* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
3742 if (IopStartDevice(DeviceNode
) != STATUS_SUCCESS
)
3744 DPRINT1("Restart after resource rebalance failed\n");
3746 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
3747 DeviceNode
->Flags
|= DNF_START_FAILED
;
3749 IopRemoveDevice(DeviceNode
);
3755 * @name IoOpenDeviceRegistryKey
3757 * Open a registry key unique for a specified driver or device instance.
3759 * @param DeviceObject Device to get the registry key for.
3760 * @param DevInstKeyType Type of the key to return.
3761 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
3762 * @param DevInstRegKey Handle to the opened registry key on
3763 * successful return.
3771 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
3772 IN ULONG DevInstKeyType
,
3773 IN ACCESS_MASK DesiredAccess
,
3774 OUT PHANDLE DevInstRegKey
)
3776 static WCHAR RootKeyName
[] =
3777 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
3778 static WCHAR ProfileKeyName
[] =
3779 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
3780 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
3781 static WCHAR EnumKeyName
[] = L
"Enum\\";
3782 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
3783 ULONG KeyNameLength
;
3784 LPWSTR KeyNameBuffer
;
3785 UNICODE_STRING KeyName
;
3786 ULONG DriverKeyLength
;
3787 OBJECT_ATTRIBUTES ObjectAttributes
;
3788 PDEVICE_NODE DeviceNode
= NULL
;
3791 DPRINT("IoOpenDeviceRegistryKey() called\n");
3793 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
3795 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
3796 return STATUS_INVALID_PARAMETER
;
3799 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
3800 return STATUS_INVALID_DEVICE_REQUEST
;
3801 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3804 * Calculate the length of the base key name. This is the full
3805 * name for driver key or the name excluding "Device Parameters"
3806 * subkey for device key.
3809 KeyNameLength
= sizeof(RootKeyName
);
3810 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3811 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
3812 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3814 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
3815 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3816 0, NULL
, &DriverKeyLength
);
3817 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
3819 KeyNameLength
+= DriverKeyLength
;
3823 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
3824 DeviceNode
->InstancePath
.Length
;
3828 * Now allocate the buffer for the key name...
3831 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
3832 if (KeyNameBuffer
== NULL
)
3833 return STATUS_INSUFFICIENT_RESOURCES
;
3836 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
3837 KeyName
.Buffer
= KeyNameBuffer
;
3840 * ...and build the key name.
3843 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
3844 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
3846 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3847 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
3849 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3851 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
3852 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3853 DriverKeyLength
, KeyNameBuffer
+
3854 (KeyName
.Length
/ sizeof(WCHAR
)),
3856 if (!NT_SUCCESS(Status
))
3858 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
3859 ExFreePool(KeyNameBuffer
);
3862 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
3866 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
3867 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
3868 if (DeviceNode
->InstancePath
.Length
== 0)
3870 ExFreePool(KeyNameBuffer
);
3876 * Open the base key.
3878 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
3879 if (!NT_SUCCESS(Status
))
3881 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
3882 ExFreePool(KeyNameBuffer
);
3885 ExFreePool(KeyNameBuffer
);
3888 * For driver key we're done now.
3891 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3895 * Let's go further. For device key we must open "Device Parameters"
3896 * subkey and create it if it doesn't exist yet.
3899 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
3900 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
3901 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
3902 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
3903 0, NULL
, ExpInTextModeSetup
? REG_OPTION_VOLATILE
: 0, NULL
);
3904 ZwClose(ObjectAttributes
.RootDirectory
);
3911 IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
3913 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
, FailedRemoveDevice
;
3917 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3918 ChildDeviceNode
= ParentDeviceNode
->Child
;
3919 while (ChildDeviceNode
!= NULL
)
3921 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3922 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3924 Status
= IopPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
3925 if (!NT_SUCCESS(Status
))
3927 FailedRemoveDevice
= ChildDeviceNode
;
3931 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3932 ChildDeviceNode
= NextDeviceNode
;
3934 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3936 return STATUS_SUCCESS
;
3939 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3940 ChildDeviceNode
= ParentDeviceNode
->Child
;
3941 while (ChildDeviceNode
!= NULL
)
3943 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3944 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3946 IopCancelPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
3948 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
3949 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
3950 if (ChildDeviceNode
== FailedRemoveDevice
)
3953 ChildDeviceNode
= NextDeviceNode
;
3955 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3957 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3964 IopSendRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
3966 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
;
3969 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3970 ChildDeviceNode
= ParentDeviceNode
->Child
;
3971 while (ChildDeviceNode
!= NULL
)
3973 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3974 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3976 IopSendRemoveDevice(ChildDeviceNode
->PhysicalDeviceObject
);
3978 ChildDeviceNode
= NextDeviceNode
;
3980 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3982 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3987 IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
3989 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
;
3992 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3993 ChildDeviceNode
= ParentDeviceNode
->Child
;
3994 while (ChildDeviceNode
!= NULL
)
3996 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3997 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3999 IopCancelPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
4001 ChildDeviceNode
= NextDeviceNode
;
4003 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4005 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4010 IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4012 /* This function DOES NOT dereference the device objects on SUCCESS
4013 * but it DOES dereference device objects on FAILURE */
4018 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4020 Status
= IopPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4021 if (!NT_SUCCESS(Status
))
4028 return STATUS_SUCCESS
;
4031 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
4032 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
4033 for (i
= 0; i
<= j
; i
++)
4035 IopCancelPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4036 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4037 DeviceRelations
->Objects
[i
] = NULL
;
4039 for (; i
< DeviceRelations
->Count
; i
++)
4041 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4042 DeviceRelations
->Objects
[i
] = NULL
;
4044 ExFreePool(DeviceRelations
);
4051 IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4053 /* This function DOES dereference the device objects in all cases */
4057 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4059 IopSendRemoveDevice(DeviceRelations
->Objects
[i
]);
4060 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4061 DeviceRelations
->Objects
[i
] = NULL
;
4064 ExFreePool(DeviceRelations
);
4069 IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4071 /* This function DOES dereference the device objects in all cases */
4075 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4077 IopCancelPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4078 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4079 DeviceRelations
->Objects
[i
] = NULL
;
4082 ExFreePool(DeviceRelations
);
4086 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
)
4088 IO_STACK_LOCATION Stack
;
4089 IO_STATUS_BLOCK IoStatusBlock
;
4090 PDEVICE_RELATIONS DeviceRelations
;
4093 IopCancelRemoveDevice(DeviceObject
);
4095 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
4097 Status
= IopInitiatePnpIrp(DeviceObject
,
4099 IRP_MN_QUERY_DEVICE_RELATIONS
,
4101 if (!NT_SUCCESS(Status
))
4103 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4104 DeviceRelations
= NULL
;
4108 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4111 if (DeviceRelations
)
4112 IopCancelRemoveDeviceRelations(DeviceRelations
);
4116 IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject
)
4118 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
4119 IO_STACK_LOCATION Stack
;
4120 IO_STATUS_BLOCK IoStatusBlock
;
4121 PDEVICE_RELATIONS DeviceRelations
;
4124 if (DeviceNode
->UserFlags
& DNUF_NOT_DISABLEABLE
)
4126 DPRINT1("Removal not allowed for %wZ\n", &DeviceNode
->InstancePath
);
4127 return STATUS_UNSUCCESSFUL
;
4130 if (IopQueryRemoveDevice(DeviceObject
) != STATUS_SUCCESS
)
4132 DPRINT1("Removal vetoed by failing the query remove request\n");
4134 IopCancelRemoveDevice(DeviceObject
);
4136 return STATUS_UNSUCCESSFUL
;
4139 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
4141 Status
= IopInitiatePnpIrp(DeviceObject
,
4143 IRP_MN_QUERY_DEVICE_RELATIONS
,
4145 if (!NT_SUCCESS(Status
))
4147 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4148 DeviceRelations
= NULL
;
4152 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4155 if (DeviceRelations
)
4157 Status
= IopQueryRemoveDeviceRelations(DeviceRelations
);
4158 if (!NT_SUCCESS(Status
))
4162 Status
= IopQueryRemoveChildDevices(DeviceNode
);
4163 if (!NT_SUCCESS(Status
))
4165 if (DeviceRelations
)
4166 IopCancelRemoveDeviceRelations(DeviceRelations
);
4170 if (DeviceRelations
)
4171 IopSendRemoveDeviceRelations(DeviceRelations
);
4172 IopSendRemoveChildDevices(DeviceNode
);
4174 return STATUS_SUCCESS
;
4178 IopRemoveDevice(PDEVICE_NODE DeviceNode
)
4182 DPRINT("Removing device: %wZ\n", &DeviceNode
->InstancePath
);
4184 Status
= IopPrepareDeviceForRemoval(DeviceNode
->PhysicalDeviceObject
);
4185 if (NT_SUCCESS(Status
))
4187 IopSendRemoveDevice(DeviceNode
->PhysicalDeviceObject
);
4188 IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL
,
4189 &DeviceNode
->InstancePath
);
4190 DeviceNode
->Flags
|= DNF_WILL_BE_REMOVED
;
4191 return STATUS_SUCCESS
;
4202 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4204 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
4205 PDEVICE_RELATIONS DeviceRelations
;
4206 IO_STATUS_BLOCK IoStatusBlock
;
4207 IO_STACK_LOCATION Stack
;
4208 DEVICE_CAPABILITIES Capabilities
;
4211 IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT
,
4212 &DeviceNode
->InstancePath
);
4214 if (IopQueryDeviceCapabilities(DeviceNode
, &Capabilities
) != STATUS_SUCCESS
)
4219 Stack
.Parameters
.QueryDeviceRelations
.Type
= EjectionRelations
;
4221 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
4223 IRP_MN_QUERY_DEVICE_RELATIONS
,
4225 if (!NT_SUCCESS(Status
))
4227 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4228 DeviceRelations
= NULL
;
4232 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4235 if (DeviceRelations
)
4237 Status
= IopQueryRemoveDeviceRelations(DeviceRelations
);
4238 if (!NT_SUCCESS(Status
))
4242 Status
= IopQueryRemoveChildDevices(DeviceNode
);
4243 if (!NT_SUCCESS(Status
))
4245 if (DeviceRelations
)
4246 IopCancelRemoveDeviceRelations(DeviceRelations
);
4250 if (IopPrepareDeviceForRemoval(PhysicalDeviceObject
) != STATUS_SUCCESS
)
4252 if (DeviceRelations
)
4253 IopCancelRemoveDeviceRelations(DeviceRelations
);
4254 IopCancelRemoveChildDevices(DeviceNode
);
4258 if (DeviceRelations
)
4259 IopSendRemoveDeviceRelations(DeviceRelations
);
4260 IopSendRemoveChildDevices(DeviceNode
);
4262 if (Capabilities
.EjectSupported
)
4264 if (IopSendEject(PhysicalDeviceObject
) != STATUS_SUCCESS
)
4271 DeviceNode
->Flags
|= DNF_DISABLED
;
4274 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT
,
4275 &DeviceNode
->InstancePath
);
4280 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED
,
4281 &DeviceNode
->InstancePath
);
4289 IoInvalidateDeviceRelations(
4290 IN PDEVICE_OBJECT DeviceObject
,
4291 IN DEVICE_RELATION_TYPE Type
)
4293 PIO_WORKITEM WorkItem
;
4294 PINVALIDATE_DEVICE_RELATION_DATA Data
;
4296 Data
= ExAllocatePool(NonPagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
4299 WorkItem
= IoAllocateWorkItem(DeviceObject
);
4306 ObReferenceObject(DeviceObject
);
4307 Data
->DeviceObject
= DeviceObject
;
4309 Data
->WorkItem
= WorkItem
;
4313 IopAsynchronousInvalidateDeviceRelations
,
4323 IoSynchronousInvalidateDeviceRelations(
4324 IN PDEVICE_OBJECT DeviceObject
,
4325 IN DEVICE_RELATION_TYPE Type
)
4332 /* Enumerate the device */
4333 return IopEnumerateDevice(DeviceObject
);
4334 case PowerRelations
:
4335 /* Not handled yet */
4336 return STATUS_NOT_IMPLEMENTED
;
4337 case TargetDeviceRelation
:
4339 return STATUS_SUCCESS
;
4341 /* Ejection relations are not supported */
4342 return STATUS_NOT_SUPPORTED
;
4351 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
4353 IN PHYSICAL_ADDRESS BusAddress
,
4354 IN OUT PULONG AddressSpace
,
4355 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
4357 /* FIXME: Notify the resource arbiter */
4359 return HalTranslateBusAddress(InterfaceType
,