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 PnpSystemInit
;
27 /* DATA **********************************************************************/
29 PDRIVER_OBJECT IopRootDriverObject
;
30 PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList
= NULL
;
32 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
34 PDEVICE_OBJECT DeviceObject
;
35 DEVICE_RELATION_TYPE Type
;
36 PIO_WORKITEM WorkItem
;
37 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
39 /* FUNCTIONS *****************************************************************/
42 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
43 IN ULONG CreateOptions
,
47 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
);
50 IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
);
54 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
56 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
61 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
62 PDRIVER_OBJECT DriverObject
)
69 /* Special case for bus driven devices */
70 DeviceNode
->Flags
|= DNF_ADDED
;
71 return STATUS_SUCCESS
;
74 if (!DriverObject
->DriverExtension
->AddDevice
)
76 DeviceNode
->Flags
|= DNF_LEGACY_DRIVER
;
79 if (DeviceNode
->Flags
& DNF_LEGACY_DRIVER
)
81 DeviceNode
->Flags
|= DNF_ADDED
+ DNF_STARTED
;
82 return STATUS_SUCCESS
;
85 /* This is a Plug and Play driver */
86 DPRINT("Plug and Play driver found\n");
87 ASSERT(DeviceNode
->PhysicalDeviceObject
);
89 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
90 &DriverObject
->DriverName
,
91 &DeviceNode
->InstancePath
);
92 Status
= DriverObject
->DriverExtension
->AddDevice(
93 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
94 if (!NT_SUCCESS(Status
))
96 DPRINT1("%wZ->AddDevice(%wZ) failed with status 0x%x\n",
97 &DriverObject
->DriverName
,
98 &DeviceNode
->InstancePath
,
100 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
104 /* Check if driver added a FDO above the PDO */
105 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
106 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
108 /* FIXME: What do we do? Unload the driver or just disable the device? */
109 DPRINT1("An FDO was not attached\n");
110 ObDereferenceObject(Fdo
);
111 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
112 return STATUS_UNSUCCESSFUL
;
115 /* Check if we have a ACPI device (needed for power management) */
116 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
118 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
120 /* There can be only one system power device */
121 if (!SystemPowerDeviceNodeCreated
)
123 PopSystemPowerDeviceNode
= DeviceNode
;
124 ObReferenceObject(PopSystemPowerDeviceNode
);
125 SystemPowerDeviceNodeCreated
= TRUE
;
129 ObDereferenceObject(Fdo
);
131 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
133 return STATUS_SUCCESS
;
139 IopSendEject(IN PDEVICE_OBJECT DeviceObject
)
141 IO_STACK_LOCATION Stack
;
144 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
145 Stack
.MajorFunction
= IRP_MJ_PNP
;
146 Stack
.MinorFunction
= IRP_MN_EJECT
;
148 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
154 IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject
)
156 IO_STACK_LOCATION Stack
;
159 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
160 Stack
.MajorFunction
= IRP_MJ_PNP
;
161 Stack
.MinorFunction
= IRP_MN_SURPRISE_REMOVAL
;
163 /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
164 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
170 IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
172 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
173 IO_STACK_LOCATION Stack
;
179 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING
,
180 &DeviceNode
->InstancePath
);
182 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
183 Stack
.MajorFunction
= IRP_MJ_PNP
;
184 Stack
.MinorFunction
= IRP_MN_QUERY_REMOVE_DEVICE
;
186 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
188 IopNotifyPlugPlayNotification(DeviceObject
,
189 EventCategoryTargetDeviceChange
,
190 &GUID_TARGET_DEVICE_QUERY_REMOVE
,
194 if (!NT_SUCCESS(Status
))
196 DPRINT1("Removal vetoed by %wZ\n", &DeviceNode
->InstancePath
);
197 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED
,
198 &DeviceNode
->InstancePath
);
207 IopQueryStopDevice(IN PDEVICE_OBJECT DeviceObject
)
209 IO_STACK_LOCATION Stack
;
212 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
213 Stack
.MajorFunction
= IRP_MJ_PNP
;
214 Stack
.MinorFunction
= IRP_MN_QUERY_STOP_DEVICE
;
216 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
222 IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
224 IO_STACK_LOCATION Stack
;
227 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
228 Stack
.MajorFunction
= IRP_MJ_PNP
;
229 Stack
.MinorFunction
= IRP_MN_REMOVE_DEVICE
;
231 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
232 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
234 IopNotifyPlugPlayNotification(DeviceObject
,
235 EventCategoryTargetDeviceChange
,
236 &GUID_TARGET_DEVICE_REMOVE_COMPLETE
,
244 IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
246 IO_STACK_LOCATION Stack
;
249 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
250 Stack
.MajorFunction
= IRP_MJ_PNP
;
251 Stack
.MinorFunction
= IRP_MN_CANCEL_REMOVE_DEVICE
;
253 /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
254 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
256 IopNotifyPlugPlayNotification(DeviceObject
,
257 EventCategoryTargetDeviceChange
,
258 &GUID_TARGET_DEVICE_REMOVE_CANCELLED
,
266 IopSendStopDevice(IN PDEVICE_OBJECT DeviceObject
)
268 IO_STACK_LOCATION Stack
;
271 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
272 Stack
.MajorFunction
= IRP_MJ_PNP
;
273 Stack
.MinorFunction
= IRP_MN_STOP_DEVICE
;
275 /* Drivers should never fail a IRP_MN_STOP_DEVICE request */
276 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
281 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject
)
283 IO_STACK_LOCATION Stack
;
284 PDEVICE_NODE DeviceNode
;
287 DEVICE_CAPABILITIES DeviceCapabilities
;
289 /* Get the device node */
290 DeviceNode
= IopGetDeviceNode(DeviceObject
);
292 ASSERT(!(DeviceNode
->Flags
& DNF_DISABLED
));
294 /* Build the I/O stack locaiton */
295 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
296 Stack
.MajorFunction
= IRP_MJ_PNP
;
297 Stack
.MinorFunction
= IRP_MN_START_DEVICE
;
299 Stack
.Parameters
.StartDevice
.AllocatedResources
=
300 DeviceNode
->ResourceList
;
301 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
=
302 DeviceNode
->ResourceListTranslated
;
305 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
306 if (!NT_SUCCESS(Status
))
308 /* Send an IRP_MN_REMOVE_DEVICE request */
309 IopRemoveDevice(DeviceNode
);
311 /* Set the appropriate flag */
312 DeviceNode
->Flags
|= DNF_START_FAILED
;
314 DPRINT1("Warning: PnP Start failed (%wZ) [Status: 0x%x]\n", &DeviceNode
->InstancePath
, Status
);
318 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
320 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
321 if (!NT_SUCCESS(Status
))
323 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
326 /* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
327 IoInvalidateDeviceState(DeviceObject
);
329 /* Otherwise, mark us as started */
330 DeviceNode
->Flags
|= DNF_STARTED
;
331 DeviceNode
->Flags
&= ~DNF_STOPPED
;
333 /* We now need enumeration */
334 DeviceNode
->Flags
|= DNF_NEED_ENUMERATION_ONLY
;
339 IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode
)
341 PDEVICE_OBJECT DeviceObject
;
346 ASSERT((DeviceNode
->Flags
& DNF_ADDED
));
347 ASSERT((DeviceNode
->Flags
& (DNF_RESOURCE_ASSIGNED
|
348 DNF_RESOURCE_REPORTED
|
349 DNF_NO_RESOURCE_REQUIRED
)));
351 /* Get the device object */
352 DeviceObject
= DeviceNode
->PhysicalDeviceObject
;
354 /* Check if we're not started yet */
355 if (!(DeviceNode
->Flags
& DNF_STARTED
))
358 IopStartDevice2(DeviceObject
);
361 /* Do we need to query IDs? This happens in the case of manual reporting */
363 if (DeviceNode
->Flags
& DNF_NEED_QUERY_IDS
)
365 DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
366 /* And that case shouldn't happen yet */
371 /* Make sure we're started, and check if we need enumeration */
372 if ((DeviceNode
->Flags
& DNF_STARTED
) &&
373 (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
))
376 IoSynchronousInvalidateDeviceRelations(DeviceObject
, BusRelations
);
377 Status
= STATUS_SUCCESS
;
382 Status
= STATUS_SUCCESS
;
391 PDEVICE_NODE DeviceNode
)
395 DPRINT("Stopping device: %wZ\n", &DeviceNode
->InstancePath
);
397 Status
= IopQueryStopDevice(DeviceNode
->PhysicalDeviceObject
);
398 if (NT_SUCCESS(Status
))
400 IopSendStopDevice(DeviceNode
->PhysicalDeviceObject
);
402 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
403 DeviceNode
->Flags
|= DNF_STOPPED
;
405 return STATUS_SUCCESS
;
413 PDEVICE_NODE DeviceNode
)
416 HANDLE InstanceHandle
= INVALID_HANDLE_VALUE
, ControlHandle
= INVALID_HANDLE_VALUE
;
417 UNICODE_STRING KeyName
;
418 OBJECT_ATTRIBUTES ObjectAttributes
;
420 if (DeviceNode
->Flags
& DNF_DISABLED
)
421 return STATUS_SUCCESS
;
423 Status
= IopAssignDeviceResources(DeviceNode
);
424 if (!NT_SUCCESS(Status
))
428 IopStartAndEnumerateDevice(DeviceNode
);
430 /* FIX: Should be done in new device instance code */
431 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceHandle
);
432 if (!NT_SUCCESS(Status
))
435 /* FIX: Should be done in IoXxxPrepareDriverLoading */
437 RtlInitUnicodeString(&KeyName
, L
"Control");
438 InitializeObjectAttributes(&ObjectAttributes
,
440 OBJ_CASE_INSENSITIVE
,
443 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
444 if (!NT_SUCCESS(Status
))
447 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
448 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
452 if (ControlHandle
!= INVALID_HANDLE_VALUE
)
453 ZwClose(ControlHandle
);
455 if (InstanceHandle
!= INVALID_HANDLE_VALUE
)
456 ZwClose(InstanceHandle
);
463 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
464 PDEVICE_CAPABILITIES DeviceCaps
)
466 IO_STATUS_BLOCK StatusBlock
;
467 IO_STACK_LOCATION Stack
;
470 UNICODE_STRING ValueName
;
472 /* Set up the Header */
473 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
474 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
475 DeviceCaps
->Version
= 1;
476 DeviceCaps
->Address
= -1;
477 DeviceCaps
->UINumber
= -1;
479 /* Set up the Stack */
480 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
481 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
484 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
486 IRP_MN_QUERY_CAPABILITIES
,
488 if (!NT_SUCCESS(Status
))
490 DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%x\n", Status
);
494 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCaps
->Version
+ sizeof(DeviceCaps
->Version
));
496 if (DeviceCaps
->NoDisplayInUI
)
497 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
499 DeviceNode
->UserFlags
&= ~DNUF_DONT_SHOW_IN_UI
;
501 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
502 if (NT_SUCCESS(Status
))
504 /* Set 'Capabilities' value */
505 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
506 Status
= ZwSetValueKey(InstanceKey
,
510 (PVOID
)&DeviceNode
->CapabilityFlags
,
513 /* Set 'UINumber' value */
514 if (DeviceCaps
->UINumber
!= MAXULONG
)
516 RtlInitUnicodeString(&ValueName
, L
"UINumber");
517 Status
= ZwSetValueKey(InstanceKey
,
521 &DeviceCaps
->UINumber
,
530 IopAsynchronousInvalidateDeviceRelations(
531 IN PDEVICE_OBJECT DeviceObject
,
532 IN PVOID InvalidateContext
)
534 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
536 IoSynchronousInvalidateDeviceRelations(
540 ObDereferenceObject(Data
->DeviceObject
);
541 IoFreeWorkItem(Data
->WorkItem
);
546 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
550 if (PopSystemPowerDeviceNode
)
552 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
553 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
554 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
556 return STATUS_SUCCESS
;
559 return STATUS_UNSUCCESSFUL
;
564 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
566 USHORT i
= 0, FoundIndex
= 0xFFFF;
570 /* Acquire the lock */
571 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
573 /* Loop all entries */
574 while (i
< PnpBusTypeGuidList
->GuidCount
)
576 /* Try to find a match */
577 if (RtlCompareMemory(BusTypeGuid
,
578 &PnpBusTypeGuidList
->Guids
[i
],
579 sizeof(GUID
)) == sizeof(GUID
))
588 /* Check if we have to grow the list */
589 if (PnpBusTypeGuidList
->GuidCount
)
591 /* Calculate the new size */
592 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
593 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
595 /* Allocate the new copy */
596 NewList
= ExAllocatePool(PagedPool
, NewSize
);
600 ExFreePool(PnpBusTypeGuidList
);
604 /* Now copy them, decrease the size too */
605 NewSize
-= sizeof(GUID
);
606 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
608 /* Free the old list */
609 ExFreePool(PnpBusTypeGuidList
);
611 /* Use the new buffer */
612 PnpBusTypeGuidList
= NewList
;
615 /* Copy the new GUID */
616 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
620 /* The new entry is the index */
621 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
622 PnpBusTypeGuidList
->GuidCount
++;
625 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
631 * Creates a device node
634 * ParentNode = Pointer to parent device node
635 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
636 * to have the root device node create one
637 * (eg. for legacy drivers)
638 * DeviceNode = Pointer to storage for created device node
644 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
645 PDEVICE_OBJECT PhysicalDeviceObject
,
646 PUNICODE_STRING ServiceName
,
647 PDEVICE_NODE
*DeviceNode
)
652 UNICODE_STRING FullServiceName
;
653 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
654 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
655 UNICODE_STRING KeyName
, ClassName
;
656 PUNICODE_STRING ServiceName1
;
659 UNICODE_STRING ClassGUID
;
661 HANDLE InstanceHandle
;
663 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
664 ParentNode
, PhysicalDeviceObject
, ServiceName
);
666 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
669 return STATUS_INSUFFICIENT_RESOURCES
;
672 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
675 ServiceName1
= &UnknownDeviceName
;
677 ServiceName1
= ServiceName
;
679 if (!PhysicalDeviceObject
)
681 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
682 FullServiceName
.Length
= 0;
683 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
684 if (!FullServiceName
.Buffer
)
687 return STATUS_INSUFFICIENT_RESOURCES
;
690 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
691 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
693 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
694 if (!NT_SUCCESS(Status
))
696 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
701 /* Create the device key for legacy drivers */
702 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
703 if (!NT_SUCCESS(Status
))
705 ZwClose(InstanceHandle
);
707 ExFreePool(FullServiceName
.Buffer
);
711 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
712 if (!Node
->ServiceName
.Buffer
)
714 ZwClose(InstanceHandle
);
716 ExFreePool(FullServiceName
.Buffer
);
720 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
721 Node
->ServiceName
.Length
= 0;
723 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
727 RtlInitUnicodeString(&KeyName
, L
"Service");
728 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
731 if (NT_SUCCESS(Status
))
733 RtlInitUnicodeString(&KeyName
, L
"Legacy");
736 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
737 if (NT_SUCCESS(Status
))
739 RtlInitUnicodeString(&KeyName
, L
"Class");
741 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
742 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
);
744 if (NT_SUCCESS(Status
))
746 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
748 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
749 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
);
755 ZwClose(InstanceHandle
);
756 ExFreePool(FullServiceName
.Buffer
);
758 if (!NT_SUCCESS(Status
))
764 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
765 IopDeviceNodeSetFlag(Node
, DNF_ADDED
);
766 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
769 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
771 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
775 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
776 Node
->Parent
= ParentNode
;
777 Node
->Sibling
= ParentNode
->Child
;
778 ParentNode
->Child
= Node
;
779 if (ParentNode
->LastChild
== NULL
)
780 ParentNode
->LastChild
= Node
;
781 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
782 Node
->Level
= ParentNode
->Level
+ 1;
785 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
789 return STATUS_SUCCESS
;
793 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
796 PDEVICE_NODE PrevSibling
= NULL
;
798 /* All children must be deleted before a parent is deleted */
799 ASSERT(!DeviceNode
->Child
);
801 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
803 ASSERT(DeviceNode
->PhysicalDeviceObject
);
805 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
807 /* Get previous sibling */
808 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
810 PrevSibling
= DeviceNode
->Parent
->Child
;
811 while (PrevSibling
->Sibling
!= DeviceNode
)
812 PrevSibling
= PrevSibling
->Sibling
;
815 /* Unlink from parent if it exists */
816 if (DeviceNode
->Parent
)
818 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
820 DeviceNode
->Parent
->LastChild
= PrevSibling
;
822 PrevSibling
->Sibling
= NULL
;
824 if (DeviceNode
->Parent
->Child
== DeviceNode
)
825 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
828 /* Unlink from sibling list */
830 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
832 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
834 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
836 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
838 if (DeviceNode
->ResourceList
)
840 ExFreePool(DeviceNode
->ResourceList
);
843 if (DeviceNode
->ResourceListTranslated
)
845 ExFreePool(DeviceNode
->ResourceListTranslated
);
848 if (DeviceNode
->ResourceRequirements
)
850 ExFreePool(DeviceNode
->ResourceRequirements
);
853 if (DeviceNode
->BootResources
)
855 ExFreePool(DeviceNode
->BootResources
);
858 ExFreePool(DeviceNode
);
860 return STATUS_SUCCESS
;
865 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
866 IN PIO_STACK_LOCATION IoStackLocation
,
867 OUT PVOID
*Information
)
870 PIO_STACK_LOCATION IrpStack
;
871 IO_STATUS_BLOCK IoStatusBlock
;
874 PDEVICE_OBJECT TopDeviceObject
;
877 /* Call the top of the device stack */
878 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
880 /* Allocate an IRP */
881 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
882 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
884 /* Initialize to failure */
885 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
886 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
888 /* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */
889 if (IoStackLocation
->MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
891 /* Copy the resource requirements list into the IOSB */
892 Irp
->IoStatus
.Information
=
893 IoStatusBlock
.Information
= (ULONG_PTR
)IoStackLocation
->Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
896 /* Initialize the event */
897 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
900 Irp
->UserIosb
= &IoStatusBlock
;
901 Irp
->UserEvent
= &Event
;
904 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
905 IoQueueThreadIrp(Irp
);
907 /* Copy-in the stack */
908 IrpStack
= IoGetNextIrpStackLocation(Irp
);
909 *IrpStack
= *IoStackLocation
;
911 /* Call the driver */
912 Status
= IoCallDriver(TopDeviceObject
, Irp
);
913 if (Status
== STATUS_PENDING
)
916 KeWaitForSingleObject(&Event
,
921 Status
= IoStatusBlock
.Status
;
924 /* Return the information */
925 *Information
= (PVOID
)IoStatusBlock
.Information
;
931 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
932 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
933 IN ULONG MinorFunction
,
934 IN PIO_STACK_LOCATION Stack OPTIONAL
)
936 IO_STACK_LOCATION IoStackLocation
;
938 /* Fill out the stack information */
939 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
940 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
941 IoStackLocation
.MinorFunction
= MinorFunction
;
945 RtlCopyMemory(&IoStackLocation
.Parameters
,
947 sizeof(Stack
->Parameters
));
950 /* Do the PnP call */
951 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
953 (PVOID
)&IoStatusBlock
->Information
);
954 return IoStatusBlock
->Status
;
958 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
960 PDEVICE_NODE ParentDeviceNode
;
961 PDEVICE_NODE ChildDeviceNode
;
964 /* Copy context data so we don't overwrite it in subsequent calls to this function */
965 ParentDeviceNode
= Context
->DeviceNode
;
967 /* Call the action routine */
968 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
969 if (!NT_SUCCESS(Status
))
974 /* Traversal of all children nodes */
975 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
976 ChildDeviceNode
!= NULL
;
977 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
979 /* Pass the current device node to the action routine */
980 Context
->DeviceNode
= ChildDeviceNode
;
982 Status
= IopTraverseDeviceTreeNode(Context
);
983 if (!NT_SUCCESS(Status
))
994 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
998 DPRINT("Context 0x%p\n", Context
);
1000 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1001 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1003 /* Start from the specified device node */
1004 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1006 /* Recursively traverse the device tree */
1007 Status
= IopTraverseDeviceTreeNode(Context
);
1008 if (Status
== STATUS_UNSUCCESSFUL
)
1010 /* The action routine just wanted to terminate the traversal with status
1011 code STATUS_SUCCESS */
1012 Status
= STATUS_SUCCESS
;
1020 * IopCreateDeviceKeyPath
1022 * Creates a registry key
1026 * Name of the key to be created.
1028 * Handle to the newly created key
1031 * This method can create nested trees, so parent of RegistryPath can
1032 * be not existant, and will be created if needed.
1036 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
1037 IN ULONG CreateOptions
,
1040 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
1041 HANDLE hParent
= NULL
, hKey
;
1042 OBJECT_ATTRIBUTES ObjectAttributes
;
1043 UNICODE_STRING KeyName
;
1044 LPCWSTR Current
, Last
;
1048 /* Assume failure */
1051 /* Open root key for device instances */
1052 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
1053 if (!NT_SUCCESS(Status
))
1055 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
1059 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
1060 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
1062 /* Go up to the end of the string */
1063 while (Current
<= Last
)
1065 if (Current
!= Last
&& *Current
!= '\\')
1067 /* Not the end of the string and not a separator */
1072 /* Prepare relative key name */
1073 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
1074 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
1075 DPRINT("Create '%wZ'\n", &KeyName
);
1078 InitializeObjectAttributes(&ObjectAttributes
,
1080 OBJ_CASE_INSENSITIVE
,
1083 Status
= ZwCreateKey(&hKey
,
1084 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
1091 /* Close parent key handle, we don't need it anymore */
1095 /* Key opening/creating failed? */
1096 if (!NT_SUCCESS(Status
))
1098 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
1102 /* Check if it is the end of the string */
1103 if (Current
== Last
)
1105 /* Yes, return success */
1107 return STATUS_SUCCESS
;
1110 /* Start with this new parent key */
1113 KeyName
.Buffer
= (LPWSTR
)Current
;
1116 return STATUS_UNSUCCESSFUL
;
1120 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1121 PDEVICE_NODE DeviceNode
)
1123 OBJECT_ATTRIBUTES ObjectAttributes
;
1124 UNICODE_STRING KeyName
;
1129 HANDLE ControlHandle
;
1131 DPRINT("IopSetDeviceInstanceData() called\n");
1133 /* Create the 'LogConf' key */
1134 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1135 InitializeObjectAttributes(&ObjectAttributes
,
1137 OBJ_CASE_INSENSITIVE
,
1140 Status
= ZwCreateKey(&LogConfKey
,
1147 if (NT_SUCCESS(Status
))
1149 /* Set 'BootConfig' value */
1150 if (DeviceNode
->BootResources
!= NULL
)
1152 ResCount
= DeviceNode
->BootResources
->Count
;
1155 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1156 Status
= ZwSetValueKey(LogConfKey
,
1160 DeviceNode
->BootResources
,
1161 PnpDetermineResourceListSize(DeviceNode
->BootResources
));
1165 /* Set 'BasicConfigVector' value */
1166 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1167 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1169 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1170 Status
= ZwSetValueKey(LogConfKey
,
1173 REG_RESOURCE_REQUIREMENTS_LIST
,
1174 DeviceNode
->ResourceRequirements
,
1175 DeviceNode
->ResourceRequirements
->ListSize
);
1178 ZwClose(LogConfKey
);
1181 /* Set the 'ConfigFlags' value */
1182 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1183 Status
= ZwQueryValueKey(InstanceKey
,
1185 KeyValueBasicInformation
,
1189 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1191 /* Write the default value */
1192 ULONG DefaultConfigFlags
= 0;
1193 Status
= ZwSetValueKey(InstanceKey
,
1197 &DefaultConfigFlags
,
1198 sizeof(DefaultConfigFlags
));
1201 /* Create the 'Control' key */
1202 RtlInitUnicodeString(&KeyName
, L
"Control");
1203 InitializeObjectAttributes(&ObjectAttributes
,
1205 OBJ_CASE_INSENSITIVE
,
1208 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1210 if (NT_SUCCESS(Status
))
1211 ZwClose(ControlHandle
);
1213 DPRINT("IopSetDeviceInstanceData() done\n");
1219 * IopGetParentIdPrefix
1221 * Retrieve (or create) a string which identifies a device.
1225 * Pointer to device node.
1227 * Pointer to the string where is returned the parent node identifier
1230 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1231 * valid and its Buffer field is NULL-terminated. The caller needs to
1232 * to free the string with RtlFreeUnicodeString when it is no longer
1237 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1238 PUNICODE_STRING ParentIdPrefix
)
1240 ULONG KeyNameBufferLength
;
1241 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1242 UNICODE_STRING KeyName
;
1243 UNICODE_STRING KeyValue
;
1244 UNICODE_STRING ValueName
;
1249 /* HACK: As long as some devices have a NULL device
1250 * instance path, the following test is required :(
1252 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1254 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1255 &DeviceNode
->InstancePath
);
1256 return STATUS_UNSUCCESSFUL
;
1259 /* 1. Try to retrieve ParentIdPrefix from registry */
1260 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1261 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1262 if (!ParentIdPrefixInformation
)
1264 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1269 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1270 if (!KeyName
.Buffer
)
1272 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1276 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1278 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1279 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1281 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1282 if (!NT_SUCCESS(Status
))
1284 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1285 Status
= ZwQueryValueKey(
1287 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1288 KeyNameBufferLength
, &KeyNameBufferLength
);
1289 if (NT_SUCCESS(Status
))
1291 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1292 Status
= STATUS_UNSUCCESSFUL
;
1295 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1296 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1300 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1302 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1303 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1307 /* 2. Create the ParentIdPrefix value */
1308 crc32
= RtlComputeCrc32(0,
1309 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1310 DeviceNode
->Parent
->InstancePath
.Length
);
1312 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1313 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1315 /* 3. Try to write the ParentIdPrefix to registry */
1316 Status
= ZwSetValueKey(hKey
,
1320 (PVOID
)KeyValue
.Buffer
,
1321 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1324 if (NT_SUCCESS(Status
))
1326 /* Duplicate the string to return it */
1327 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1329 ExFreePool(ParentIdPrefixInformation
);
1330 RtlFreeUnicodeString(&KeyName
);
1338 * IopActionInterrogateDeviceStack
1340 * Retrieve information for all (direct) child nodes of a parent node.
1344 * Pointer to device node.
1346 * Pointer to parent node to retrieve child node information for.
1349 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1350 * when we reach a device node which is not a direct child of the device
1351 * node for which we retrieve information of child nodes for. Any errors
1352 * that occur is logged instead so that all child services have a chance
1353 * of being interrogated.
1357 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1360 IO_STATUS_BLOCK IoStatusBlock
;
1361 PDEVICE_NODE ParentDeviceNode
;
1362 WCHAR InstancePath
[MAX_PATH
];
1363 IO_STACK_LOCATION Stack
;
1368 ULONG RequiredLength
;
1370 HANDLE InstanceKey
= NULL
;
1371 UNICODE_STRING ValueName
;
1372 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1373 DEVICE_CAPABILITIES DeviceCapabilities
;
1375 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1376 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1378 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1381 * We are called for the parent too, but we don't need to do special
1382 * handling for this node
1385 if (DeviceNode
== ParentDeviceNode
)
1387 DPRINT("Success\n");
1388 return STATUS_SUCCESS
;
1392 * Make sure this device node is a direct child of the parent device node
1393 * that is given as an argument
1396 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1398 /* Stop the traversal immediately and indicate successful operation */
1400 return STATUS_UNSUCCESSFUL
;
1403 /* Skip processing if it was already completed before */
1404 if (DeviceNode
->Flags
& DNF_PROCESSED
)
1407 return STATUS_SUCCESS
;
1411 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1412 if (!NT_SUCCESS(Status
))
1414 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1419 * FIXME: For critical errors, cleanup and disable device, but always
1420 * return STATUS_SUCCESS.
1423 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1425 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1426 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1430 if (NT_SUCCESS(Status
))
1432 /* Copy the device id string */
1433 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1436 * FIXME: Check for valid characters, if there is invalid characters
1442 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1445 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
1447 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1448 if (!NT_SUCCESS(Status
))
1450 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1453 /* This bit is only check after enumeration */
1454 if (DeviceCapabilities
.HardwareDisabled
)
1456 /* FIXME: Cleanup device */
1457 DeviceNode
->Flags
|= DNF_DISABLED
;
1458 return STATUS_SUCCESS
;
1461 DeviceNode
->Flags
&= ~DNF_DISABLED
;
1463 if (!DeviceCapabilities
.UniqueID
)
1465 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1466 DPRINT("Instance ID is not unique\n");
1467 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1468 if (!NT_SUCCESS(Status
))
1470 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1474 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1476 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1477 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1481 if (NT_SUCCESS(Status
))
1483 /* Append the instance id string */
1484 wcscat(InstancePath
, L
"\\");
1485 if (ParentIdPrefix
.Length
> 0)
1487 /* Add information from parent bus device to InstancePath */
1488 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1489 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1490 wcscat(InstancePath
, L
"&");
1492 if (IoStatusBlock
.Information
)
1493 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1496 * FIXME: Check for valid characters, if there is invalid characters
1502 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1504 RtlFreeUnicodeString(&ParentIdPrefix
);
1506 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1508 DPRINT("No resources\n");
1509 /* FIXME: Cleanup and disable device */
1512 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1515 * Create registry key for the instance id, if it doesn't exist yet
1517 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
1518 if (!NT_SUCCESS(Status
))
1520 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1523 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1525 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1526 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1530 if (NT_SUCCESS(Status
))
1533 * FIXME: Check for valid characters, if there is invalid characters
1537 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1538 DPRINT("Hardware IDs:\n");
1541 DPRINT(" %S\n", Ptr
);
1542 Length
= wcslen(Ptr
) + 1;
1545 TotalLength
+= Length
;
1547 DPRINT("TotalLength: %hu\n", TotalLength
);
1550 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1551 Status
= ZwSetValueKey(InstanceKey
,
1555 (PVOID
)IoStatusBlock
.Information
,
1556 (TotalLength
+ 1) * sizeof(WCHAR
));
1557 if (!NT_SUCCESS(Status
))
1559 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1564 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1567 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1569 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1570 Status
= IopInitiatePnpIrp(
1571 DeviceNode
->PhysicalDeviceObject
,
1575 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1578 * FIXME: Check for valid characters, if there is invalid characters
1582 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1583 DPRINT("Compatible IDs:\n");
1586 DPRINT(" %S\n", Ptr
);
1587 Length
= wcslen(Ptr
) + 1;
1590 TotalLength
+= Length
;
1592 DPRINT("TotalLength: %hu\n", TotalLength
);
1595 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1596 Status
= ZwSetValueKey(InstanceKey
,
1600 (PVOID
)IoStatusBlock
.Information
,
1601 (TotalLength
+ 1) * sizeof(WCHAR
));
1602 if (!NT_SUCCESS(Status
))
1604 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1609 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1612 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1614 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1615 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1616 Status
= IopInitiatePnpIrp(
1617 DeviceNode
->PhysicalDeviceObject
,
1619 IRP_MN_QUERY_DEVICE_TEXT
,
1621 /* This key is mandatory, so even if the Irp fails, we still write it */
1622 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1623 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1625 if (NT_SUCCESS(Status
) &&
1626 IoStatusBlock
.Information
&&
1627 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1629 /* This key is overriden when a driver is installed. Don't write the
1630 * new description if another one already exists */
1631 Status
= ZwSetValueKey(InstanceKey
,
1635 (PVOID
)IoStatusBlock
.Information
,
1636 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1640 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1641 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1643 Status
= ZwSetValueKey(InstanceKey
,
1648 DeviceDesc
.MaximumLength
);
1650 if (!NT_SUCCESS(Status
))
1652 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1658 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1660 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1661 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1662 Status
= IopInitiatePnpIrp(
1663 DeviceNode
->PhysicalDeviceObject
,
1665 IRP_MN_QUERY_DEVICE_TEXT
,
1667 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1669 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1670 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1671 Status
= ZwSetValueKey(InstanceKey
,
1675 (PVOID
)IoStatusBlock
.Information
,
1676 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1677 if (!NT_SUCCESS(Status
))
1679 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1684 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1687 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1689 Status
= IopInitiatePnpIrp(
1690 DeviceNode
->PhysicalDeviceObject
,
1692 IRP_MN_QUERY_BUS_INFORMATION
,
1694 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1696 PPNP_BUS_INFORMATION BusInformation
=
1697 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1699 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1700 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1701 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1702 ExFreePool(BusInformation
);
1706 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1708 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1709 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1710 DeviceNode
->ChildBusTypeIndex
= -1;
1713 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1715 Status
= IopInitiatePnpIrp(
1716 DeviceNode
->PhysicalDeviceObject
,
1718 IRP_MN_QUERY_RESOURCES
,
1720 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1722 DeviceNode
->BootResources
=
1723 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1724 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
1728 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1729 DeviceNode
->BootResources
= NULL
;
1732 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1734 Status
= IopInitiatePnpIrp(
1735 DeviceNode
->PhysicalDeviceObject
,
1737 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1739 if (NT_SUCCESS(Status
))
1741 DeviceNode
->ResourceRequirements
=
1742 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1746 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1747 DeviceNode
->ResourceRequirements
= NULL
;
1750 if (InstanceKey
!= NULL
)
1752 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1755 ZwClose(InstanceKey
);
1757 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1759 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1761 /* Report the device to the user-mode pnp manager */
1762 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1763 &DeviceNode
->InstancePath
);
1766 return STATUS_SUCCESS
;
1771 IopHandleDeviceRemoval(
1772 IN PDEVICE_NODE DeviceNode
,
1773 IN PDEVICE_RELATIONS DeviceRelations
)
1775 PDEVICE_NODE Child
= DeviceNode
->Child
, NextChild
;
1779 while (Child
!= NULL
)
1781 NextChild
= Child
->Sibling
;
1784 for (i
= 0; DeviceRelations
&& i
< DeviceRelations
->Count
; i
++)
1786 if (IopGetDeviceNode(DeviceRelations
->Objects
[i
]) == Child
)
1795 IopSendSurpriseRemoval(Child
->PhysicalDeviceObject
);
1797 /* Tell the user-mode PnP manager that a device was removed */
1798 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
1799 &Child
->InstancePath
);
1801 IopSendRemoveDevice(Child
->PhysicalDeviceObject
);
1810 IN PDEVICE_OBJECT DeviceObject
)
1812 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1813 DEVICETREE_TRAVERSE_CONTEXT Context
;
1814 PDEVICE_RELATIONS DeviceRelations
;
1815 PDEVICE_OBJECT ChildDeviceObject
;
1816 IO_STATUS_BLOCK IoStatusBlock
;
1817 PDEVICE_NODE ChildDeviceNode
;
1818 IO_STACK_LOCATION Stack
;
1822 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1824 if (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
)
1826 DeviceNode
->Flags
&= ~DNF_NEED_ENUMERATION_ONLY
;
1828 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1829 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1830 &DeviceNode
->InstancePath
);
1833 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1835 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1837 Status
= IopInitiatePnpIrp(
1840 IRP_MN_QUERY_DEVICE_RELATIONS
,
1842 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1844 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1848 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1851 * Send removal IRPs for devices that have disappeared
1852 * NOTE: This code handles the case where no relations are specified
1854 IopHandleDeviceRemoval(DeviceNode
, DeviceRelations
);
1856 /* Now we bail if nothing was returned */
1857 if (!DeviceRelations
)
1859 /* We're all done */
1860 DPRINT("No PDOs\n");
1861 return STATUS_SUCCESS
;
1864 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1867 * Create device nodes for all discovered devices
1869 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1871 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1872 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1874 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1875 if (!ChildDeviceNode
)
1877 /* One doesn't exist, create it */
1878 Status
= IopCreateDeviceNode(
1883 if (NT_SUCCESS(Status
))
1885 /* Mark the node as enumerated */
1886 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1888 /* Mark the DO as bus enumerated */
1889 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1893 /* Ignore this DO */
1894 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1895 ObDereferenceObject(ChildDeviceNode
);
1900 /* Mark it as enumerated */
1901 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1902 ObDereferenceObject(ChildDeviceObject
);
1905 ExFreePool(DeviceRelations
);
1908 * Retrieve information about all discovered children from the bus driver
1910 IopInitDeviceTreeTraverseContext(
1913 IopActionInterrogateDeviceStack
,
1916 Status
= IopTraverseDeviceTree(&Context
);
1917 if (!NT_SUCCESS(Status
))
1919 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1924 * Retrieve configuration from the registry for discovered children
1926 IopInitDeviceTreeTraverseContext(
1929 IopActionConfigureChildServices
,
1932 Status
= IopTraverseDeviceTree(&Context
);
1933 if (!NT_SUCCESS(Status
))
1935 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1940 * Initialize services for discovered children.
1942 Status
= IopInitializePnpServices(DeviceNode
);
1943 if (!NT_SUCCESS(Status
))
1945 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1949 DPRINT("IopEnumerateDevice() finished\n");
1950 return STATUS_SUCCESS
;
1955 * IopActionConfigureChildServices
1957 * Retrieve configuration for all (direct) child nodes of a parent node.
1961 * Pointer to device node.
1963 * Pointer to parent node to retrieve child node configuration for.
1966 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1967 * when we reach a device node which is not a direct child of the device
1968 * node for which we configure child services for. Any errors that occur is
1969 * logged instead so that all child services have a chance of beeing
1974 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1977 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1978 PDEVICE_NODE ParentDeviceNode
;
1979 PUNICODE_STRING Service
;
1980 UNICODE_STRING ClassGUID
;
1982 DEVICE_CAPABILITIES DeviceCaps
;
1984 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1986 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1989 * We are called for the parent too, but we don't need to do special
1990 * handling for this node
1992 if (DeviceNode
== ParentDeviceNode
)
1994 DPRINT("Success\n");
1995 return STATUS_SUCCESS
;
1999 * Make sure this device node is a direct child of the parent device node
2000 * that is given as an argument
2002 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2004 /* Stop the traversal immediately and indicate successful operation */
2006 return STATUS_UNSUCCESSFUL
;
2009 if (!(DeviceNode
->Flags
& (DNF_DISABLED
| DNF_STARTED
| DNF_ADDED
)))
2011 WCHAR RegKeyBuffer
[MAX_PATH
];
2012 UNICODE_STRING RegKey
;
2015 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2016 RegKey
.Buffer
= RegKeyBuffer
;
2019 * Retrieve configuration from Enum key
2022 Service
= &DeviceNode
->ServiceName
;
2024 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2025 RtlInitUnicodeString(Service
, NULL
);
2026 RtlInitUnicodeString(&ClassGUID
, NULL
);
2028 QueryTable
[0].Name
= L
"Service";
2029 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2030 QueryTable
[0].EntryContext
= Service
;
2032 QueryTable
[1].Name
= L
"ClassGUID";
2033 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2034 QueryTable
[1].EntryContext
= &ClassGUID
;
2035 QueryTable
[1].DefaultType
= REG_SZ
;
2036 QueryTable
[1].DefaultData
= L
"";
2037 QueryTable
[1].DefaultLength
= 0;
2039 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2040 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2042 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2043 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2045 if (!NT_SUCCESS(Status
))
2047 /* FIXME: Log the error */
2048 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2049 &DeviceNode
->InstancePath
, Status
);
2050 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2051 return STATUS_SUCCESS
;
2054 if (Service
->Buffer
== NULL
)
2056 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
2057 DeviceCaps
.RawDeviceOK
)
2059 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
2061 DeviceNode
->ServiceName
.Length
= 0;
2062 DeviceNode
->ServiceName
.MaximumLength
= 0;
2063 DeviceNode
->ServiceName
.Buffer
= NULL
;
2065 else if (ClassGUID
.Length
!= 0)
2067 /* Device has a ClassGUID value, but no Service value.
2068 * Suppose it is using the NULL driver, so state the
2069 * device is started */
2070 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2071 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2075 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2077 return STATUS_SUCCESS
;
2080 DPRINT("Got Service %S\n", Service
->Buffer
);
2083 return STATUS_SUCCESS
;
2087 * IopActionInitChildServices
2089 * Initialize the service for all (direct) child nodes of a parent node
2093 * Pointer to device node.
2095 * Pointer to parent node to initialize child node services for.
2098 * If the driver image for a service is not loaded and initialized
2099 * it is done here too. We only return a status code indicating an
2100 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2101 * not a direct child of the device node for which we initialize
2102 * child services for. Any errors that occur is logged instead so
2103 * that all child services have a chance of being initialized.
2107 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2110 PDEVICE_NODE ParentDeviceNode
;
2112 BOOLEAN BootDrivers
= !PnpSystemInit
;
2114 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2116 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2119 * We are called for the parent too, but we don't need to do special
2120 * handling for this node
2122 if (DeviceNode
== ParentDeviceNode
)
2124 DPRINT("Success\n");
2125 return STATUS_SUCCESS
;
2129 * Make sure this device node is a direct child of the parent device node
2130 * that is given as an argument
2133 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2136 * Stop the traversal immediately and indicate unsuccessful operation
2139 return STATUS_UNSUCCESSFUL
;
2142 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
2143 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
2144 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2145 return STATUS_SUCCESS
;
2147 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
2149 /* We don't need to worry about loading the driver because we're
2150 * being driven in raw mode so our parent must be loaded to get here */
2151 Status
= IopInitializeDevice(DeviceNode
, NULL
);
2152 if (NT_SUCCESS(Status
))
2154 Status
= IopStartDevice(DeviceNode
);
2155 if (!NT_SUCCESS(Status
))
2157 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
2158 &DeviceNode
->InstancePath
, Status
);
2164 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2165 PDRIVER_OBJECT DriverObject
;
2167 /* Get existing DriverObject pointer (in case the driver has
2168 already been loaded and initialized) */
2169 Status
= IopGetDriverObject(
2171 &DeviceNode
->ServiceName
,
2174 if (!NT_SUCCESS(Status
))
2176 /* Driver is not initialized, try to load it */
2177 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2179 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2181 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2182 was loaded by the bootloader */
2183 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2184 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2186 /* Initialize the driver */
2187 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2188 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2192 Status
= STATUS_SUCCESS
;
2197 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2198 &DeviceNode
->ServiceName
, Status
);
2202 /* Driver is loaded and initialized at this point */
2203 if (NT_SUCCESS(Status
))
2205 /* Initialize the device, including all filters */
2206 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
2211 * Don't disable when trying to load only boot drivers
2215 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2216 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2217 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2218 DPRINT1("Initialization of service %S failed (Status %x)\n",
2219 DeviceNode
->ServiceName
.Buffer
, Status
);
2224 return STATUS_SUCCESS
;
2228 * IopInitializePnpServices
2230 * Initialize services for discovered children
2234 * Top device node to start initializing services.
2240 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2242 DEVICETREE_TRAVERSE_CONTEXT Context
;
2244 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2246 IopInitDeviceTreeTraverseContext(
2249 IopActionInitChildServices
,
2252 return IopTraverseDeviceTree(&Context
);
2255 static NTSTATUS INIT_FUNCTION
2256 IopEnumerateDetectedDevices(
2258 IN PUNICODE_STRING RelativePath OPTIONAL
,
2260 IN BOOLEAN EnumerateSubKeys
,
2261 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2262 IN ULONG ParentBootResourcesLength
)
2264 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2265 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2266 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2267 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2268 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2269 OBJECT_ATTRIBUTES ObjectAttributes
;
2270 HANDLE hDevicesKey
= NULL
;
2271 HANDLE hDeviceKey
= NULL
;
2272 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2273 UNICODE_STRING Level2NameU
;
2274 WCHAR Level2Name
[5];
2275 ULONG IndexDevice
= 0;
2277 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2278 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2279 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2280 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2281 UNICODE_STRING DeviceName
, ValueName
;
2283 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2284 ULONG BootResourcesLength
;
2287 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2288 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2289 static ULONG DeviceIndexPci
= 0;
2290 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2291 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2292 static ULONG DeviceIndexSerial
= 0;
2293 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2294 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2295 static ULONG DeviceIndexKeyboard
= 0;
2296 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2297 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2298 static ULONG DeviceIndexMouse
= 0;
2299 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2300 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2301 static ULONG DeviceIndexParallel
= 0;
2302 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2303 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2304 static ULONG DeviceIndexFloppy
= 0;
2305 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2306 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2307 static ULONG DeviceIndexIsa
= 0;
2308 UNICODE_STRING HardwareIdKey
;
2309 PUNICODE_STRING pHardwareId
;
2310 ULONG DeviceIndex
= 0;
2311 PUCHAR CmResourceList
;
2316 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2317 if (!NT_SUCCESS(Status
))
2319 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2324 hDevicesKey
= hBaseKey
;
2326 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2327 if (!pDeviceInformation
)
2329 DPRINT("ExAllocatePool() failed\n");
2330 Status
= STATUS_NO_MEMORY
;
2334 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2335 if (!pValueInformation
)
2337 DPRINT("ExAllocatePool() failed\n");
2338 Status
= STATUS_NO_MEMORY
;
2344 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2345 if (Status
== STATUS_NO_MORE_ENTRIES
)
2347 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2349 ExFreePool(pDeviceInformation
);
2350 DeviceInfoLength
= RequiredSize
;
2351 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2352 if (!pDeviceInformation
)
2354 DPRINT("ExAllocatePool() failed\n");
2355 Status
= STATUS_NO_MEMORY
;
2358 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2360 if (!NT_SUCCESS(Status
))
2362 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2367 /* Open device key */
2368 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2369 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2371 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2372 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2373 if (!NT_SUCCESS(Status
))
2375 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2379 /* Read boot resources, and add then to parent ones */
2380 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2381 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2383 ExFreePool(pValueInformation
);
2384 ValueInfoLength
= RequiredSize
;
2385 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2386 if (!pValueInformation
)
2388 DPRINT("ExAllocatePool() failed\n");
2389 ZwDeleteKey(hLevel2Key
);
2390 Status
= STATUS_NO_MEMORY
;
2393 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2395 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2397 BootResources
= ParentBootResources
;
2398 BootResourcesLength
= ParentBootResourcesLength
;
2400 else if (!NT_SUCCESS(Status
))
2402 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2405 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2407 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2412 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2414 /* Concatenate current resources and parent ones */
2415 if (ParentBootResourcesLength
== 0)
2416 BootResourcesLength
= pValueInformation
->DataLength
;
2418 BootResourcesLength
= ParentBootResourcesLength
2419 + pValueInformation
->DataLength
2421 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2424 DPRINT("ExAllocatePool() failed\n");
2427 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2429 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2431 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2433 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2435 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2436 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2437 ParentBootResourcesLength
- Header
);
2438 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2442 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2444 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2445 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2446 ParentBootResourcesLength
- Header
);
2448 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2449 pValueInformation
->Data
+ Header
,
2450 pValueInformation
->DataLength
- Header
);
2451 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2455 if (EnumerateSubKeys
)
2460 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2461 if (Status
== STATUS_NO_MORE_ENTRIES
)
2463 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2465 ExFreePool(pDeviceInformation
);
2466 DeviceInfoLength
= RequiredSize
;
2467 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2468 if (!pDeviceInformation
)
2470 DPRINT("ExAllocatePool() failed\n");
2471 Status
= STATUS_NO_MEMORY
;
2474 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2476 if (!NT_SUCCESS(Status
))
2478 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2482 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2483 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2485 Status
= IopEnumerateDetectedDevices(
2491 BootResourcesLength
);
2492 if (!NT_SUCCESS(Status
))
2497 /* Read identifier */
2498 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2499 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2501 ExFreePool(pValueInformation
);
2502 ValueInfoLength
= RequiredSize
;
2503 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2504 if (!pValueInformation
)
2506 DPRINT("ExAllocatePool() failed\n");
2507 Status
= STATUS_NO_MEMORY
;
2510 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2512 if (!NT_SUCCESS(Status
))
2514 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2516 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2519 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2521 else if (pValueInformation
->Type
!= REG_SZ
)
2523 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2528 /* Assign hardware id to this device */
2529 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2530 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2531 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2532 ValueName
.Length
-= sizeof(WCHAR
);
2535 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2537 pHardwareId
= &HardwareIdSerial
;
2538 DeviceIndex
= DeviceIndexSerial
++;
2540 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2542 pHardwareId
= &HardwareIdKeyboard
;
2543 DeviceIndex
= DeviceIndexKeyboard
++;
2545 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2547 pHardwareId
= &HardwareIdMouse
;
2548 DeviceIndex
= DeviceIndexMouse
++;
2550 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
2552 pHardwareId
= &HardwareIdParallel
;
2553 DeviceIndex
= DeviceIndexParallel
++;
2555 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
2557 pHardwareId
= &HardwareIdFloppy
;
2558 DeviceIndex
= DeviceIndexFloppy
++;
2560 else if (NT_SUCCESS(Status
))
2562 /* Try to also match the device identifier */
2563 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2565 pHardwareId
= &HardwareIdPci
;
2566 DeviceIndex
= DeviceIndexPci
++;
2568 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
2570 pHardwareId
= &HardwareIdIsa
;
2571 DeviceIndex
= DeviceIndexIsa
++;
2575 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2581 /* Unknown key path */
2582 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2586 /* Prepare hardware id key (hardware id value without final \0) */
2587 HardwareIdKey
= *pHardwareId
;
2588 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2590 /* Add the detected device to Root key */
2591 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2592 Status
= ZwCreateKey(
2598 REG_OPTION_NON_VOLATILE
,
2600 if (!NT_SUCCESS(Status
))
2602 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2605 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2606 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2607 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2608 Status
= ZwCreateKey(
2610 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2614 REG_OPTION_NON_VOLATILE
,
2616 ZwClose(hLevel1Key
);
2617 if (!NT_SUCCESS(Status
))
2619 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2622 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
2623 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2624 if (!NT_SUCCESS(Status
))
2626 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2627 ZwDeleteKey(hLevel2Key
);
2630 /* Create 'LogConf' subkey */
2631 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2632 Status
= ZwCreateKey(
2638 REG_OPTION_VOLATILE
,
2640 if (!NT_SUCCESS(Status
))
2642 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2643 ZwDeleteKey(hLevel2Key
);
2646 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2648 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
2649 if (!CmResourceList
)
2652 ZwDeleteKey(hLevel2Key
);
2656 /* Add the list count (1st member of CM_RESOURCE_LIST) */
2658 RtlCopyMemory(CmResourceList
,
2662 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
2663 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
2665 BootResourcesLength
);
2667 /* Save boot resources to 'LogConf\BootConfig' */
2668 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
2669 if (!NT_SUCCESS(Status
))
2671 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2673 ZwDeleteKey(hLevel2Key
);
2680 if (BootResources
&& BootResources
!= ParentBootResources
)
2682 ExFreePool(BootResources
);
2683 BootResources
= NULL
;
2687 ZwClose(hLevel2Key
);
2692 ZwClose(hDeviceKey
);
2697 Status
= STATUS_SUCCESS
;
2700 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2701 ZwClose(hDevicesKey
);
2703 ZwClose(hDeviceKey
);
2704 if (pDeviceInformation
)
2705 ExFreePool(pDeviceInformation
);
2706 if (pValueInformation
)
2707 ExFreePool(pValueInformation
);
2711 static BOOLEAN INIT_FUNCTION
2712 IopIsFirmwareMapperDisabled(VOID
)
2714 UNICODE_STRING KeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CURRENTCONTROLSET\\Control\\Pnp");
2715 UNICODE_STRING KeyNameU
= RTL_CONSTANT_STRING(L
"DisableFirmwareMapper");
2716 OBJECT_ATTRIBUTES ObjectAttributes
;
2718 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
;
2719 ULONG DesiredLength
, Length
, KeyValue
;
2722 InitializeObjectAttributes(&ObjectAttributes
, &KeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2723 Status
= ZwOpenKey(&hPnpKey
, KEY_QUERY_VALUE
, &ObjectAttributes
);
2724 if (NT_SUCCESS(Status
))
2726 Status
= ZwQueryValueKey(hPnpKey
,
2728 KeyValuePartialInformation
,
2732 if ((Status
== STATUS_BUFFER_TOO_SMALL
) ||
2733 (Status
== STATUS_BUFFER_OVERFLOW
))
2735 Length
= DesiredLength
;
2736 KeyInformation
= ExAllocatePool(PagedPool
, Length
);
2739 Status
= ZwQueryValueKey(hPnpKey
,
2741 KeyValuePartialInformation
,
2745 if (NT_SUCCESS(Status
) && KeyInformation
->DataLength
== sizeof(ULONG
))
2747 KeyValue
= (ULONG
)(*KeyInformation
->Data
);
2751 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed\n", &KeyPathU
, &KeyNameU
);
2755 ExFreePool(KeyInformation
);
2759 DPRINT1("Failed to allocate memory for registry query\n");
2765 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed with status 0x%08lx\n", &KeyPathU
, &KeyNameU
, Status
);
2773 DPRINT1("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyPathU
, Status
);
2776 DPRINT1("Firmware mapper is %s\n", KeyValue
!= 0 ? "disabled" : "enabled");
2778 return (KeyValue
!= 0) ? TRUE
: FALSE
;
2784 IopUpdateRootKey(VOID
)
2786 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2787 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2788 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2789 OBJECT_ATTRIBUTES ObjectAttributes
;
2790 HANDLE hEnum
, hRoot
;
2793 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2794 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2795 if (!NT_SUCCESS(Status
))
2797 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2801 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2802 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2804 if (!NT_SUCCESS(Status
))
2806 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2810 if (!IopIsFirmwareMapperDisabled())
2812 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2813 if (!NT_SUCCESS(Status
))
2815 /* Nothing to do, don't return with an error status */
2816 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2818 return STATUS_SUCCESS
;
2820 Status
= IopEnumerateDetectedDevices(
2831 /* Enumeration is disabled */
2832 Status
= STATUS_SUCCESS
;
2842 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2844 PUNICODE_STRING Name
,
2845 ACCESS_MASK DesiredAccess
)
2847 OBJECT_ATTRIBUTES ObjectAttributes
;
2854 InitializeObjectAttributes(&ObjectAttributes
,
2856 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2860 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2867 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
2868 IN HANDLE RootHandle OPTIONAL
,
2869 IN PUNICODE_STRING KeyName
,
2870 IN ACCESS_MASK DesiredAccess
,
2871 IN ULONG CreateOptions
,
2872 OUT PULONG Disposition OPTIONAL
)
2874 OBJECT_ATTRIBUTES ObjectAttributes
;
2875 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0, Length
;
2876 HANDLE HandleArray
[2];
2877 BOOLEAN Recursing
= TRUE
;
2879 UNICODE_STRING KeyString
;
2880 NTSTATUS Status
= STATUS_SUCCESS
;
2883 /* P1 is start, pp is end */
2884 p1
= KeyName
->Buffer
;
2885 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
2887 /* Create the target key */
2888 InitializeObjectAttributes(&ObjectAttributes
,
2890 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2893 Status
= ZwCreateKey(&HandleArray
[i
],
2901 /* Now we check if this failed */
2902 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
2904 /* Target key failed, so we'll need to create its parent. Setup array */
2905 HandleArray
[0] = NULL
;
2906 HandleArray
[1] = RootHandle
;
2908 /* Keep recursing for each missing parent */
2911 /* And if we're deep enough, close the last handle */
2912 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2914 /* We're setup to ping-pong between the two handle array entries */
2915 RootHandleIndex
= i
;
2918 /* Clear the one we're attempting to open now */
2919 HandleArray
[i
] = NULL
;
2921 /* Process the parent key name */
2922 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
2923 Length
= (p
- p1
) * sizeof(WCHAR
);
2925 /* Is there a parent name? */
2928 /* Build the unicode string for it */
2929 KeyString
.Buffer
= p1
;
2930 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
2932 /* Now try opening the parent */
2933 InitializeObjectAttributes(&ObjectAttributes
,
2935 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2936 HandleArray
[RootHandleIndex
],
2938 Status
= ZwCreateKey(&HandleArray
[i
],
2945 if (NT_SUCCESS(Status
))
2947 /* It worked, we have one more handle */
2952 /* Parent key creation failed, abandon loop */
2959 /* We don't have a parent name, probably corrupted key name */
2960 Status
= STATUS_INVALID_PARAMETER
;
2965 /* Now see if there's more parents to create */
2967 if ((p
== pp
) || (p1
== pp
))
2969 /* We're done, hopefully successfully, so stop */
2974 /* Outer loop check for handle nesting that requires closing the top handle */
2975 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2978 /* Check if we broke out of the loop due to success */
2979 if (NT_SUCCESS(Status
))
2981 /* Return the target handle (we closed all the parent ones) and disposition */
2982 *Handle
= HandleArray
[i
];
2983 if (Disposition
) *Disposition
= KeyDisposition
;
2986 /* Return the success state */
2992 IopGetRegistryValue(IN HANDLE Handle
,
2994 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
2996 UNICODE_STRING ValueString
;
2998 PKEY_VALUE_FULL_INFORMATION FullInformation
;
3002 RtlInitUnicodeString(&ValueString
, ValueName
);
3004 Status
= ZwQueryValueKey(Handle
,
3006 KeyValueFullInformation
,
3010 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
3011 (Status
!= STATUS_BUFFER_TOO_SMALL
))
3016 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
3017 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
3019 Status
= ZwQueryValueKey(Handle
,
3021 KeyValueFullInformation
,
3025 if (!NT_SUCCESS(Status
))
3027 ExFreePool(FullInformation
);
3031 *Information
= FullInformation
;
3032 return STATUS_SUCCESS
;
3035 RTL_GENERIC_COMPARE_RESULTS
3037 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3038 IN PVOID FirstStruct
,
3039 IN PVOID SecondStruct
)
3047 // The allocation function is called by the generic table package whenever
3048 // it needs to allocate memory for the table.
3053 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3063 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3072 PpInitializeDeviceReferenceTable(VOID
)
3074 /* Setup the guarded mutex and AVL table */
3075 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3076 RtlInitializeGenericTableAvl(
3077 &PpDeviceReferenceTable
,
3078 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3079 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3080 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3088 /* Initialize the resource when accessing device registry data */
3089 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3091 /* Setup the device reference AVL table */
3092 PpInitializeDeviceReferenceTable();
3100 /* Check the initialization phase */
3101 switch (ExpInitializationPhase
)
3106 return PiInitPhase0();
3112 //return PiInitPhase1();
3116 /* Don't know any other phase! Bugcheck! */
3117 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3122 LONG IopNumberDeviceNodes
;
3126 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3128 PDEVICE_NODE DeviceNode
;
3132 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), 'donD');
3133 if (!DeviceNode
) return DeviceNode
;
3136 InterlockedIncrement(&IopNumberDeviceNodes
);
3139 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
3140 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
3141 DeviceNode
->BusNumber
= -1;
3142 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
3143 DeviceNode
->ChildBusNumber
= -1;
3144 DeviceNode
->ChildBusTypeIndex
= -1;
3145 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
3146 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
3147 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
3148 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
3149 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
3150 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
3152 /* Check if there is a PDO */
3153 if (PhysicalDeviceObject
)
3155 /* Link it and remove the init flag */
3156 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
3157 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
3158 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3161 /* Return the node */
3165 /* PUBLIC FUNCTIONS **********************************************************/
3169 PnpBusTypeGuidGet(IN USHORT Index
,
3170 IN LPGUID BusTypeGuid
)
3172 NTSTATUS Status
= STATUS_SUCCESS
;
3174 /* Acquire the lock */
3175 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
3178 if (Index
< PnpBusTypeGuidList
->GuidCount
)
3181 RtlCopyMemory(BusTypeGuid
, &PnpBusTypeGuidList
->Guids
[Index
], sizeof(GUID
));
3186 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
3189 /* Release lock and return status */
3190 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
3196 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject
,
3197 IN PHANDLE DeviceInstanceHandle
,
3198 IN ACCESS_MASK DesiredAccess
)
3202 PDEVICE_NODE DeviceNode
;
3203 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
3206 /* Open the enum key */
3207 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
3211 if (!NT_SUCCESS(Status
)) return Status
;
3213 /* Make sure we have an instance path */
3214 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3215 if ((DeviceNode
) && (DeviceNode
->InstancePath
.Length
))
3217 /* Get the instance key */
3218 Status
= IopOpenRegistryKeyEx(DeviceInstanceHandle
,
3220 &DeviceNode
->InstancePath
,
3226 Status
= STATUS_INVALID_DEVICE_REQUEST
;
3229 /* Close the handle and return status */
3236 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList
)
3238 ULONG FinalSize
, PartialSize
, EntrySize
, i
, j
;
3239 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
3240 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
3242 /* If we don't have one, that's easy */
3243 if (!ResourceList
) return 0;
3245 /* Start with the minimum size possible */
3246 FinalSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
3248 /* Loop each full descriptor */
3249 FullDescriptor
= ResourceList
->List
;
3250 for (i
= 0; i
< ResourceList
->Count
; i
++)
3252 /* Start with the minimum size possible */
3253 PartialSize
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
) +
3254 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
);
3256 /* Loop each partial descriptor */
3257 PartialDescriptor
= FullDescriptor
->PartialResourceList
.PartialDescriptors
;
3258 for (j
= 0; j
< FullDescriptor
->PartialResourceList
.Count
; j
++)
3260 /* Start with the minimum size possible */
3261 EntrySize
= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
3263 /* Check if there is extra data */
3264 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
3267 EntrySize
+= PartialDescriptor
->u
.DeviceSpecificData
.DataSize
;
3270 /* The size of partial descriptors is bigger */
3271 PartialSize
+= EntrySize
;
3273 /* Go to the next partial descriptor */
3274 PartialDescriptor
= (PVOID
)((ULONG_PTR
)PartialDescriptor
+ EntrySize
);
3277 /* The size of full descriptors is bigger */
3278 FinalSize
+= PartialSize
;
3280 /* Go to the next full descriptor */
3281 FullDescriptor
= (PVOID
)((ULONG_PTR
)FullDescriptor
+ PartialSize
);
3284 /* Return the final size */
3290 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject
,
3295 IN PULONG BufferLength
)
3298 HANDLE KeyHandle
, SubHandle
;
3299 UNICODE_STRING KeyString
;
3300 PKEY_VALUE_FULL_INFORMATION KeyValueInfo
= NULL
;
3304 /* Find the instance key */
3305 Status
= PnpDeviceObjectToDeviceInstance(DeviceObject
, &KeyHandle
, KEY_READ
);
3306 if (NT_SUCCESS(Status
))
3308 /* Check for name given by caller */
3312 RtlInitUnicodeString(&KeyString
, KeyName
);
3313 Status
= IopOpenRegistryKeyEx(&SubHandle
,
3317 if (NT_SUCCESS(Status
))
3319 /* And use this handle instead */
3321 KeyHandle
= SubHandle
;
3325 /* Check if sub-key handle succeeded (or no-op if no key name given) */
3326 if (NT_SUCCESS(Status
))
3328 /* Now get the size of the property */
3329 Status
= IopGetRegistryValue(KeyHandle
,
3338 /* Fail if any of the registry operations failed */
3339 if (!NT_SUCCESS(Status
)) return Status
;
3341 /* Check how much data we have to copy */
3342 Length
= KeyValueInfo
->DataLength
;
3343 if (*BufferLength
>= Length
)
3345 /* Check for a match in the value type */
3346 if (KeyValueInfo
->Type
== ValueType
)
3349 RtlCopyMemory(Buffer
,
3350 (PVOID
)((ULONG_PTR
)KeyValueInfo
+
3351 KeyValueInfo
->DataOffset
),
3356 /* Invalid registry property type, fail */
3357 Status
= STATUS_INVALID_PARAMETER_2
;
3362 /* Buffer is too small to hold data */
3363 Status
= STATUS_BUFFER_TOO_SMALL
;
3366 /* Return the required buffer length, free the buffer, and return status */
3367 *BufferLength
= Length
;
3368 ExFreePool(KeyValueInfo
);
3372 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
3373 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
3374 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED; while(TRUE); break;}
3381 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3382 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3383 IN ULONG BufferLength
,
3384 OUT PVOID PropertyBuffer
,
3385 OUT PULONG ResultLength
)
3387 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3388 DEVICE_CAPABILITIES DeviceCaps
;
3389 ULONG ReturnLength
= 0, Length
= 0, ValueType
;
3390 PWCHAR ValueName
= NULL
, EnumeratorNameEnd
, DeviceInstanceName
;
3392 NTSTATUS Status
= STATUS_BUFFER_TOO_SMALL
;
3394 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
3395 BOOLEAN NullTerminate
= FALSE
;
3397 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3399 /* Assume failure */
3402 /* Only PDOs can call this */
3403 if (!DeviceNode
) return STATUS_INVALID_DEVICE_REQUEST
;
3405 /* Handle all properties */
3406 switch (DeviceProperty
)
3408 case DevicePropertyBusTypeGuid
:
3410 /* Get the GUID from the internal cache */
3411 Status
= PnpBusTypeGuidGet(DeviceNode
->ChildBusTypeIndex
, &BusTypeGuid
);
3412 if (!NT_SUCCESS(Status
)) return Status
;
3414 /* This is the format of the returned data */
3415 PIP_RETURN_DATA(sizeof(GUID
), &BusTypeGuid
);
3417 case DevicePropertyLegacyBusType
:
3419 /* Validate correct interface type */
3420 if (DeviceNode
->ChildInterfaceType
== InterfaceTypeUndefined
)
3421 return STATUS_OBJECT_NAME_NOT_FOUND
;
3423 /* This is the format of the returned data */
3424 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE
), &DeviceNode
->ChildInterfaceType
);
3426 case DevicePropertyBusNumber
:
3428 /* Validate correct bus number */
3429 if ((DeviceNode
->ChildBusNumber
& 0x80000000) == 0x80000000)
3430 return STATUS_OBJECT_NAME_NOT_FOUND
;
3432 /* This is the format of the returned data */
3433 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceNode
->ChildBusNumber
);
3435 case DevicePropertyEnumeratorName
:
3437 /* Get the instance path */
3438 DeviceInstanceName
= DeviceNode
->InstancePath
.Buffer
;
3441 ASSERT((BufferLength
& 1) == 0);
3442 ASSERT(DeviceInstanceName
!= NULL
);
3444 /* Get the name from the path */
3445 EnumeratorNameEnd
= wcschr(DeviceInstanceName
, OBJ_NAME_PATH_SEPARATOR
);
3446 ASSERT(EnumeratorNameEnd
);
3448 /* This string needs to be NULL-terminated */
3449 NullTerminate
= TRUE
;
3451 /* This is the format of the returned data */
3452 PIP_RETURN_DATA((EnumeratorNameEnd
- DeviceInstanceName
) * sizeof(WCHAR
),
3453 DeviceInstanceName
);
3455 case DevicePropertyAddress
:
3457 /* Query the device caps */
3458 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3459 if (!NT_SUCCESS(Status
) || (DeviceCaps
.Address
== MAXULONG
))
3460 return STATUS_OBJECT_NAME_NOT_FOUND
;
3462 /* This is the format of the returned data */
3463 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceCaps
.Address
);
3465 case DevicePropertyBootConfigurationTranslated
:
3467 /* Validate we have resources */
3468 if (!DeviceNode
->BootResources
)
3469 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
3471 /* No resources will still fake success, but with 0 bytes */
3473 return STATUS_SUCCESS
;
3476 /* This is the format of the returned data */
3477 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode
->BootResources
), // FIXFIX: Should use BootResourcesTranslated
3478 DeviceNode
->BootResources
); // FIXFIX: Should use BootResourcesTranslated
3480 case DevicePropertyPhysicalDeviceObjectName
:
3482 /* Sanity check for Unicode-sized string */
3483 ASSERT((BufferLength
& 1) == 0);
3485 /* Allocate name buffer */
3486 Length
= BufferLength
+ sizeof(OBJECT_NAME_INFORMATION
);
3487 ObjectNameInfo
= ExAllocatePool(PagedPool
, Length
);
3488 if (!ObjectNameInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
3490 /* Query the PDO name */
3491 Status
= ObQueryNameString(DeviceObject
,
3495 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
3497 /* It's up to the caller to try again */
3498 Status
= STATUS_BUFFER_TOO_SMALL
;
3501 /* This string needs to be NULL-terminated */
3502 NullTerminate
= TRUE
;
3504 /* Return if successful */
3505 if (NT_SUCCESS(Status
)) PIP_RETURN_DATA(ObjectNameInfo
->Name
.Length
,
3506 ObjectNameInfo
->Name
.Buffer
);
3508 /* Let the caller know how big the name is */
3509 *ResultLength
-= sizeof(OBJECT_NAME_INFORMATION
);
3512 /* Handle the registry-based properties */
3513 case DevicePropertyUINumber
:
3514 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER
, REG_DWORD
);
3515 case DevicePropertyLocationInformation
:
3516 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION
, REG_SZ
);
3517 case DevicePropertyDeviceDescription
:
3518 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC
, REG_SZ
);
3519 case DevicePropertyHardwareID
:
3520 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID
, REG_MULTI_SZ
);
3521 case DevicePropertyCompatibleIDs
:
3522 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS
, REG_MULTI_SZ
);
3523 case DevicePropertyBootConfiguration
:
3524 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG
, REG_RESOURCE_LIST
);
3525 case DevicePropertyClassName
:
3526 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS
, REG_SZ
);
3527 case DevicePropertyClassGuid
:
3528 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID
, REG_SZ
);
3529 case DevicePropertyDriverKeyName
:
3530 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER
, REG_SZ
);
3531 case DevicePropertyManufacturer
:
3532 PIP_REGISTRY_DATA(REGSTR_VAL_MFG
, REG_SZ
);
3533 case DevicePropertyFriendlyName
:
3534 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME
, REG_SZ
);
3535 case DevicePropertyContainerID
:
3536 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
3537 PIP_UNIMPLEMENTED();
3538 case DevicePropertyRemovalPolicy
:
3539 PIP_UNIMPLEMENTED();
3540 case DevicePropertyInstallState
:
3541 PIP_UNIMPLEMENTED();
3542 case DevicePropertyResourceRequirements
:
3543 PIP_UNIMPLEMENTED();
3544 case DevicePropertyAllocatedResources
:
3545 PIP_UNIMPLEMENTED();
3547 return STATUS_INVALID_PARAMETER_2
;
3550 /* Having a registry value name implies registry data */
3553 /* We know up-front how much data to expect */
3554 *ResultLength
= BufferLength
;
3556 /* Go get the data, use the LogConf subkey if necessary */
3557 Status
= PiGetDeviceRegistryProperty(DeviceObject
,
3561 DevicePropertyBootConfiguration
) ?
3566 else if (NT_SUCCESS(Status
))
3568 /* We know up-front how much data to expect, check the caller's buffer */
3569 *ResultLength
= ReturnLength
+ (NullTerminate
? sizeof(UNICODE_NULL
) : 0);
3570 if (*ResultLength
<= BufferLength
)
3572 /* Buffer is all good, copy the data */
3573 RtlCopyMemory(PropertyBuffer
, Data
, ReturnLength
);
3575 /* Check if we need to NULL-terminate the string */
3578 /* Terminate the string */
3579 ((PWCHAR
)PropertyBuffer
)[ReturnLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3582 /* This is the success path */
3583 Status
= STATUS_SUCCESS
;
3588 Status
= STATUS_BUFFER_TOO_SMALL
;
3592 /* Free any allocation we may have made, and return the status code */
3593 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
3602 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3604 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
3605 IO_STACK_LOCATION Stack
;
3608 IO_STATUS_BLOCK IoStatusBlock
;
3610 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
3611 Stack
.MajorFunction
= IRP_MJ_PNP
;
3612 Stack
.MinorFunction
= IRP_MN_QUERY_PNP_DEVICE_STATE
;
3614 Status
= IopSynchronousCall(PhysicalDeviceObject
, &Stack
, (PVOID
*)&PnPFlags
);
3615 if (!NT_SUCCESS(Status
))
3617 DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%x\n", Status
);
3621 if (PnPFlags
& PNP_DEVICE_NOT_DISABLEABLE
)
3622 DeviceNode
->UserFlags
|= DNUF_NOT_DISABLEABLE
;
3624 DeviceNode
->UserFlags
&= ~DNUF_NOT_DISABLEABLE
;
3626 if (PnPFlags
& PNP_DEVICE_DONT_DISPLAY_IN_UI
)
3627 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
3629 DeviceNode
->UserFlags
&= ~DNUF_DONT_SHOW_IN_UI
;
3631 if ((PnPFlags
& PNP_DEVICE_REMOVED
) ||
3632 ((PnPFlags
& PNP_DEVICE_FAILED
) && !(PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)))
3634 /* Surprise removal */
3636 IopSendSurpriseRemoval(PhysicalDeviceObject
);
3638 /* Tell the user-mode PnP manager that a device was removed */
3639 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
3640 &DeviceNode
->InstancePath
);
3642 IopSendRemoveDevice(PhysicalDeviceObject
);
3644 else if ((PnPFlags
& PNP_DEVICE_FAILED
) && (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
))
3646 /* Stop for resource rebalance */
3648 Status
= IopStopDevice(DeviceNode
);
3649 if (!NT_SUCCESS(Status
))
3651 DPRINT1("Failed to stop device for rebalancing\n");
3653 /* Stop failed so don't rebalance */
3654 PnPFlags
&= ~PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
;
3658 /* Resource rebalance */
3659 if (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)
3661 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
3663 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
3665 IRP_MN_QUERY_RESOURCES
,
3667 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
3669 DeviceNode
->BootResources
=
3670 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
3671 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
3675 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
3676 DeviceNode
->BootResources
= NULL
;
3679 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
3681 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
3683 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
3685 if (NT_SUCCESS(Status
))
3687 DeviceNode
->ResourceRequirements
=
3688 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
3692 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
3693 DeviceNode
->ResourceRequirements
= NULL
;
3696 /* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
3697 if (IopStartDevice(DeviceNode
) != STATUS_SUCCESS
)
3699 DPRINT1("Restart after resource rebalance failed\n");
3701 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
3702 DeviceNode
->Flags
|= DNF_START_FAILED
;
3704 IopRemoveDevice(DeviceNode
);
3710 * @name IoOpenDeviceRegistryKey
3712 * Open a registry key unique for a specified driver or device instance.
3714 * @param DeviceObject Device to get the registry key for.
3715 * @param DevInstKeyType Type of the key to return.
3716 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
3717 * @param DevInstRegKey Handle to the opened registry key on
3718 * successful return.
3726 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
3727 IN ULONG DevInstKeyType
,
3728 IN ACCESS_MASK DesiredAccess
,
3729 OUT PHANDLE DevInstRegKey
)
3731 static WCHAR RootKeyName
[] =
3732 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
3733 static WCHAR ProfileKeyName
[] =
3734 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
3735 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
3736 static WCHAR EnumKeyName
[] = L
"Enum\\";
3737 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
3738 ULONG KeyNameLength
;
3739 LPWSTR KeyNameBuffer
;
3740 UNICODE_STRING KeyName
;
3741 ULONG DriverKeyLength
;
3742 OBJECT_ATTRIBUTES ObjectAttributes
;
3743 PDEVICE_NODE DeviceNode
= NULL
;
3746 DPRINT("IoOpenDeviceRegistryKey() called\n");
3748 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
3750 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
3751 return STATUS_INVALID_PARAMETER
;
3754 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
3755 return STATUS_INVALID_DEVICE_REQUEST
;
3756 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3759 * Calculate the length of the base key name. This is the full
3760 * name for driver key or the name excluding "Device Parameters"
3761 * subkey for device key.
3764 KeyNameLength
= sizeof(RootKeyName
);
3765 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3766 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
3767 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3769 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
3770 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3771 0, NULL
, &DriverKeyLength
);
3772 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
3774 KeyNameLength
+= DriverKeyLength
;
3778 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
3779 DeviceNode
->InstancePath
.Length
;
3783 * Now allocate the buffer for the key name...
3786 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
3787 if (KeyNameBuffer
== NULL
)
3788 return STATUS_INSUFFICIENT_RESOURCES
;
3791 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
3792 KeyName
.Buffer
= KeyNameBuffer
;
3795 * ...and build the key name.
3798 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
3799 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
3801 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3802 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
3804 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3806 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
3807 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3808 DriverKeyLength
, KeyNameBuffer
+
3809 (KeyName
.Length
/ sizeof(WCHAR
)),
3811 if (!NT_SUCCESS(Status
))
3813 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
3814 ExFreePool(KeyNameBuffer
);
3817 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
3821 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
3822 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
3823 if (DeviceNode
->InstancePath
.Length
== 0)
3825 ExFreePool(KeyNameBuffer
);
3831 * Open the base key.
3833 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
3834 if (!NT_SUCCESS(Status
))
3836 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
3837 ExFreePool(KeyNameBuffer
);
3840 ExFreePool(KeyNameBuffer
);
3843 * For driver key we're done now.
3846 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3850 * Let's go further. For device key we must open "Device Parameters"
3851 * subkey and create it if it doesn't exist yet.
3854 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
3855 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
3856 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
3857 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
3858 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
3859 ZwClose(ObjectAttributes
.RootDirectory
);
3866 IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
3868 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
, FailedRemoveDevice
;
3872 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3873 ChildDeviceNode
= ParentDeviceNode
->Child
;
3874 while (ChildDeviceNode
!= NULL
)
3876 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3877 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3879 Status
= IopPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
3880 if (!NT_SUCCESS(Status
))
3882 FailedRemoveDevice
= ChildDeviceNode
;
3886 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3887 ChildDeviceNode
= NextDeviceNode
;
3889 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3891 return STATUS_SUCCESS
;
3894 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3895 ChildDeviceNode
= ParentDeviceNode
->Child
;
3896 while (ChildDeviceNode
!= NULL
)
3898 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3899 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3901 IopCancelPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
3903 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
3904 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
3905 if (ChildDeviceNode
== FailedRemoveDevice
)
3908 ChildDeviceNode
= NextDeviceNode
;
3910 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3912 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3919 IopSendRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
3921 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
;
3924 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3925 ChildDeviceNode
= ParentDeviceNode
->Child
;
3926 while (ChildDeviceNode
!= NULL
)
3928 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3929 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3931 IopSendRemoveDevice(ChildDeviceNode
->PhysicalDeviceObject
);
3933 ChildDeviceNode
= NextDeviceNode
;
3935 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3937 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3942 IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
3944 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
;
3947 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3948 ChildDeviceNode
= ParentDeviceNode
->Child
;
3949 while (ChildDeviceNode
!= NULL
)
3951 NextDeviceNode
= ChildDeviceNode
->Sibling
;
3952 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3954 IopCancelPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
3956 ChildDeviceNode
= NextDeviceNode
;
3958 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
3960 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
3965 IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
3967 /* This function DOES NOT dereference the device objects on SUCCESS
3968 * but it DOES dereference device objects on FAILURE */
3973 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
3975 Status
= IopPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
3976 if (!NT_SUCCESS(Status
))
3983 return STATUS_SUCCESS
;
3986 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
3987 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
3988 for (i
= 0; i
<= j
; i
++)
3990 IopCancelPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
3991 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
3992 DeviceRelations
->Objects
[i
] = NULL
;
3994 for (; i
< DeviceRelations
->Count
; i
++)
3996 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
3997 DeviceRelations
->Objects
[i
] = NULL
;
3999 ExFreePool(DeviceRelations
);
4006 IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4008 /* This function DOES dereference the device objects in all cases */
4012 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4014 IopSendRemoveDevice(DeviceRelations
->Objects
[i
]);
4015 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4016 DeviceRelations
->Objects
[i
] = NULL
;
4019 ExFreePool(DeviceRelations
);
4024 IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4026 /* This function DOES dereference the device objects in all cases */
4030 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4032 IopCancelPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4033 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4034 DeviceRelations
->Objects
[i
] = NULL
;
4037 ExFreePool(DeviceRelations
);
4041 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
)
4043 IO_STACK_LOCATION Stack
;
4044 IO_STATUS_BLOCK IoStatusBlock
;
4045 PDEVICE_RELATIONS DeviceRelations
;
4048 IopCancelRemoveDevice(DeviceObject
);
4050 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
4052 Status
= IopInitiatePnpIrp(DeviceObject
,
4054 IRP_MN_QUERY_DEVICE_RELATIONS
,
4056 if (!NT_SUCCESS(Status
))
4058 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4059 DeviceRelations
= NULL
;
4063 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4066 if (DeviceRelations
)
4067 IopCancelRemoveDeviceRelations(DeviceRelations
);
4071 IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject
)
4073 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
4074 IO_STACK_LOCATION Stack
;
4075 IO_STATUS_BLOCK IoStatusBlock
;
4076 PDEVICE_RELATIONS DeviceRelations
;
4079 if (DeviceNode
->UserFlags
& DNUF_NOT_DISABLEABLE
)
4081 DPRINT1("Removal not allowed for %wZ\n", &DeviceNode
->InstancePath
);
4082 return STATUS_UNSUCCESSFUL
;
4085 if (IopQueryRemoveDevice(DeviceObject
) != STATUS_SUCCESS
)
4087 DPRINT1("Removal vetoed by failing the query remove request\n");
4089 IopCancelRemoveDevice(DeviceObject
);
4091 return STATUS_UNSUCCESSFUL
;
4094 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
4096 Status
= IopInitiatePnpIrp(DeviceObject
,
4098 IRP_MN_QUERY_DEVICE_RELATIONS
,
4100 if (!NT_SUCCESS(Status
))
4102 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4103 DeviceRelations
= NULL
;
4107 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4110 if (DeviceRelations
)
4112 Status
= IopQueryRemoveDeviceRelations(DeviceRelations
);
4113 if (!NT_SUCCESS(Status
))
4117 Status
= IopQueryRemoveChildDevices(DeviceNode
);
4118 if (!NT_SUCCESS(Status
))
4120 if (DeviceRelations
)
4121 IopCancelRemoveDeviceRelations(DeviceRelations
);
4125 if (DeviceRelations
)
4126 IopSendRemoveDeviceRelations(DeviceRelations
);
4127 IopSendRemoveChildDevices(DeviceNode
);
4129 return STATUS_SUCCESS
;
4133 IopRemoveDevice(PDEVICE_NODE DeviceNode
)
4137 DPRINT("Removing device: %wZ\n", &DeviceNode
->InstancePath
);
4139 Status
= IopPrepareDeviceForRemoval(DeviceNode
->PhysicalDeviceObject
);
4140 if (NT_SUCCESS(Status
))
4142 IopSendRemoveDevice(DeviceNode
->PhysicalDeviceObject
);
4143 IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL
,
4144 &DeviceNode
->InstancePath
);
4145 DeviceNode
->Flags
|= DNF_WILL_BE_REMOVED
;
4146 return STATUS_SUCCESS
;
4157 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4159 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
4160 PDEVICE_RELATIONS DeviceRelations
;
4161 IO_STATUS_BLOCK IoStatusBlock
;
4162 IO_STACK_LOCATION Stack
;
4163 DEVICE_CAPABILITIES Capabilities
;
4166 IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT
,
4167 &DeviceNode
->InstancePath
);
4169 if (IopQueryDeviceCapabilities(DeviceNode
, &Capabilities
) != STATUS_SUCCESS
)
4174 Stack
.Parameters
.QueryDeviceRelations
.Type
= EjectionRelations
;
4176 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
4178 IRP_MN_QUERY_DEVICE_RELATIONS
,
4180 if (!NT_SUCCESS(Status
))
4182 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4183 DeviceRelations
= NULL
;
4187 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4190 if (DeviceRelations
)
4192 Status
= IopQueryRemoveDeviceRelations(DeviceRelations
);
4193 if (!NT_SUCCESS(Status
))
4197 Status
= IopQueryRemoveChildDevices(DeviceNode
);
4198 if (!NT_SUCCESS(Status
))
4200 if (DeviceRelations
)
4201 IopCancelRemoveDeviceRelations(DeviceRelations
);
4205 if (IopPrepareDeviceForRemoval(PhysicalDeviceObject
) != STATUS_SUCCESS
)
4207 if (DeviceRelations
)
4208 IopCancelRemoveDeviceRelations(DeviceRelations
);
4209 IopCancelRemoveChildDevices(DeviceNode
);
4213 if (DeviceRelations
)
4214 IopSendRemoveDeviceRelations(DeviceRelations
);
4215 IopSendRemoveChildDevices(DeviceNode
);
4217 if (Capabilities
.EjectSupported
)
4219 if (IopSendEject(PhysicalDeviceObject
) != STATUS_SUCCESS
)
4226 DeviceNode
->Flags
|= DNF_DISABLED
;
4229 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT
,
4230 &DeviceNode
->InstancePath
);
4235 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED
,
4236 &DeviceNode
->InstancePath
);
4244 IoInvalidateDeviceRelations(
4245 IN PDEVICE_OBJECT DeviceObject
,
4246 IN DEVICE_RELATION_TYPE Type
)
4248 PIO_WORKITEM WorkItem
;
4249 PINVALIDATE_DEVICE_RELATION_DATA Data
;
4251 Data
= ExAllocatePool(NonPagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
4254 WorkItem
= IoAllocateWorkItem(DeviceObject
);
4261 ObReferenceObject(DeviceObject
);
4262 Data
->DeviceObject
= DeviceObject
;
4264 Data
->WorkItem
= WorkItem
;
4268 IopAsynchronousInvalidateDeviceRelations
,
4278 IoSynchronousInvalidateDeviceRelations(
4279 IN PDEVICE_OBJECT DeviceObject
,
4280 IN DEVICE_RELATION_TYPE Type
)
4287 /* Enumerate the device */
4288 return IopEnumerateDevice(DeviceObject
);
4289 case PowerRelations
:
4290 /* Not handled yet */
4291 return STATUS_NOT_IMPLEMENTED
;
4292 case TargetDeviceRelation
:
4294 return STATUS_SUCCESS
;
4296 /* Ejection relations are not supported */
4297 return STATUS_NOT_SUPPORTED
;
4306 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
4308 IN PHYSICAL_ADDRESS BusAddress
,
4309 IN OUT PULONG AddressSpace
,
4310 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
4312 /* FIXME: Notify the resource arbiter */
4314 return HalTranslateBusAddress(InterfaceType
,