2 * PROJECT: ReactOS Kernel
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnpmgr.c
5 * PURPOSE: Initializes the PnP manager
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Copyright 2007 Hervé Poussineau (hpoussin@reactos.org)
10 /* INCLUDES ******************************************************************/
18 /* GLOBALS *******************************************************************/
20 PDEVICE_NODE IopRootDeviceNode
;
21 KSPIN_LOCK IopDeviceTreeLock
;
22 ERESOURCE PpRegistryDeviceResource
;
23 KGUARDED_MUTEX PpDeviceReferenceTableLock
;
24 RTL_AVL_TABLE PpDeviceReferenceTable
;
26 extern ULONG ExpInitializationPhase
;
27 extern BOOLEAN PnpSystemInit
;
29 /* DATA **********************************************************************/
31 PDRIVER_OBJECT IopRootDriverObject
;
32 FAST_MUTEX IopBusTypeGuidListLock
;
33 PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList
= NULL
;
35 #if defined (ALLOC_PRAGMA)
36 #pragma alloc_text(INIT, PnpInit)
37 #pragma alloc_text(INIT, PnpInit2)
40 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
42 PDEVICE_OBJECT DeviceObject
;
43 DEVICE_RELATION_TYPE Type
;
44 PIO_WORKITEM WorkItem
;
45 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
47 /* FUNCTIONS *****************************************************************/
50 IopAssignDeviceResources(
51 IN PDEVICE_NODE DeviceNode
,
52 OUT ULONG
*pRequiredSize
);
55 IopTranslateDeviceResources(
56 IN PDEVICE_NODE DeviceNode
,
57 IN ULONG RequiredSize
);
60 IopUpdateResourceMapForPnPDevice(
61 IN PDEVICE_NODE DeviceNode
);
65 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
70 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
72 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
77 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
78 PDRIVER_OBJECT DriverObject
)
83 if (!DriverObject
->DriverExtension
->AddDevice
)
84 return STATUS_SUCCESS
;
86 /* This is a Plug and Play driver */
87 DPRINT("Plug and Play driver found\n");
88 ASSERT(DeviceNode
->PhysicalDeviceObject
);
90 /* Check if this plug-and-play driver is used as a legacy one for this device node */
91 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
93 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
94 return STATUS_SUCCESS
;
97 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
98 &DriverObject
->DriverName
,
99 &DeviceNode
->InstancePath
);
100 Status
= DriverObject
->DriverExtension
->AddDevice(
101 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
102 if (!NT_SUCCESS(Status
))
104 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
108 /* Check if driver added a FDO above the PDO */
109 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
110 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
112 /* FIXME: What do we do? Unload the driver or just disable the device? */
113 DPRINT1("An FDO was not attached\n");
114 ObDereferenceObject(Fdo
);
115 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
116 return STATUS_UNSUCCESSFUL
;
119 /* Check if we have a ACPI device (needed for power management) */
120 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
122 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
124 /* There can be only one system power device */
125 if (!SystemPowerDeviceNodeCreated
)
127 PopSystemPowerDeviceNode
= DeviceNode
;
128 ObReferenceObject(PopSystemPowerDeviceNode
);
129 SystemPowerDeviceNodeCreated
= TRUE
;
133 ObDereferenceObject(Fdo
);
135 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
136 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
138 return STATUS_SUCCESS
;
143 PDEVICE_NODE DeviceNode
)
145 IO_STATUS_BLOCK IoStatusBlock
;
146 IO_STACK_LOCATION Stack
;
147 ULONG RequiredLength
;
149 HANDLE InstanceHandle
, ControlHandle
;
150 UNICODE_STRING KeyName
;
151 OBJECT_ATTRIBUTES ObjectAttributes
;
153 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
154 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
155 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
156 Status
= IopInitiatePnpIrp(
157 DeviceNode
->PhysicalDeviceObject
,
159 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
161 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
163 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
166 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
168 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
169 if (NT_SUCCESS(Status
))
171 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
172 if (NT_SUCCESS(Status
))
174 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
175 if (!NT_SUCCESS(Status
))
177 DPRINT("IopUpdateResourceMap() failed (Status 0x%08lx)\n", Status
);
182 DPRINT("IopTranslateDeviceResources() failed (Status 0x%08lx)\n", Status
);
187 DPRINT("IopAssignDeviceResources() failed (Status 0x%08lx)\n", Status
);
189 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
191 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
192 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
193 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
196 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and
197 * actually _depend_ on this!. This is because NT will lock the Device Node
198 * with an ERESOURCE, which of course requires APCs to be disabled.
200 KeEnterCriticalRegion();
202 Status
= IopInitiatePnpIrp(
203 DeviceNode
->PhysicalDeviceObject
,
208 KeLeaveCriticalRegion();
210 if (!NT_SUCCESS(Status
))
212 DPRINT("IopInitiatePnpIrp() failed\n");
216 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
218 DPRINT("Device needs enumeration, invalidating bus relations\n");
219 /* Invalidate device relations synchronously
220 (otherwise there will be dirty read of DeviceNode) */
221 IopEnumerateDevice(DeviceNode
->PhysicalDeviceObject
);
222 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
226 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceHandle
);
227 if (!NT_SUCCESS(Status
))
230 RtlInitUnicodeString(&KeyName
, L
"Control");
231 InitializeObjectAttributes(&ObjectAttributes
,
233 OBJ_CASE_INSENSITIVE
,
236 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
237 if (!NT_SUCCESS(Status
))
239 ZwClose(InstanceHandle
);
243 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
244 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
246 if (NT_SUCCESS(Status
))
247 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
249 ZwClose(ControlHandle
);
250 ZwClose(InstanceHandle
);
257 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
258 PDEVICE_CAPABILITIES DeviceCaps
)
260 IO_STATUS_BLOCK StatusBlock
;
261 IO_STACK_LOCATION Stack
;
263 /* Set up the Header */
264 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
265 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
266 DeviceCaps
->Version
= 1;
267 DeviceCaps
->Address
= -1;
268 DeviceCaps
->UINumber
= -1;
270 /* Set up the Stack */
271 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
272 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
275 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
277 IRP_MN_QUERY_CAPABILITIES
,
282 IopAsynchronousInvalidateDeviceRelations(
283 IN PDEVICE_OBJECT DeviceObject
,
284 IN PVOID InvalidateContext
)
286 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
288 IoSynchronousInvalidateDeviceRelations(
292 ObDereferenceObject(Data
->DeviceObject
);
293 IoFreeWorkItem(Data
->WorkItem
);
298 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
302 if (PopSystemPowerDeviceNode
)
304 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
305 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
306 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
308 return STATUS_SUCCESS
;
311 return STATUS_UNSUCCESSFUL
;
316 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
318 USHORT i
= 0, FoundIndex
= 0xFFFF;
322 /* Acquire the lock */
323 ExAcquireFastMutex(&IopBusTypeGuidListLock
);
325 /* Loop all entries */
326 while (i
< IopBusTypeGuidList
->GuidCount
)
328 /* Try to find a match */
329 if (RtlCompareMemory(BusTypeGuid
,
330 &IopBusTypeGuidList
->Guids
[i
],
331 sizeof(GUID
)) == sizeof(GUID
))
340 /* Check if we have to grow the list */
341 if (IopBusTypeGuidList
->GuidCount
)
343 /* Calculate the new size */
344 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
345 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
347 /* Allocate the new copy */
348 NewList
= ExAllocatePool(PagedPool
, NewSize
);
352 ExFreePool(IopBusTypeGuidList
);
356 /* Now copy them, decrease the size too */
357 NewSize
-= sizeof(GUID
);
358 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
360 /* Free the old list */
361 ExFreePool(IopBusTypeGuidList
);
363 /* Use the new buffer */
364 IopBusTypeGuidList
= NewList
;
367 /* Copy the new GUID */
368 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
372 /* The new entry is the index */
373 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
374 IopBusTypeGuidList
->GuidCount
++;
377 ExReleaseFastMutex(&IopBusTypeGuidListLock
);
383 * Creates a device node
386 * ParentNode = Pointer to parent device node
387 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
388 * to have the root device node create one
389 * (eg. for legacy drivers)
390 * DeviceNode = Pointer to storage for created device node
396 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
397 PDEVICE_OBJECT PhysicalDeviceObject
,
398 PUNICODE_STRING ServiceName
,
399 PDEVICE_NODE
*DeviceNode
)
404 UNICODE_STRING FullServiceName
;
405 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
406 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
409 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
410 ParentNode
, PhysicalDeviceObject
, ServiceName
);
412 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
415 return STATUS_INSUFFICIENT_RESOURCES
;
418 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
421 ServiceName
= &UnknownDeviceName
;
423 if (!PhysicalDeviceObject
)
425 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName
->Length
;
426 FullServiceName
.Length
= 0;
427 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
428 if (!FullServiceName
.Buffer
)
431 return STATUS_INSUFFICIENT_RESOURCES
;
434 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
435 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName
);
437 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
438 if (!NT_SUCCESS(Status
))
440 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
445 /* Create the device key for legacy drivers */
446 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, &TempHandle
);
447 if (NT_SUCCESS(Status
))
450 ExFreePool(FullServiceName
.Buffer
);
452 /* This is for drivers passed on the command line to ntoskrnl.exe */
453 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
454 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
457 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
459 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
463 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
464 Node
->Parent
= ParentNode
;
465 Node
->Sibling
= ParentNode
->Child
;
466 ParentNode
->Child
= Node
;
467 if (ParentNode
->LastChild
== NULL
)
468 ParentNode
->LastChild
= Node
;
469 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
470 Node
->Level
= ParentNode
->Level
+ 1;
473 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
477 return STATUS_SUCCESS
;
481 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
484 PDEVICE_NODE PrevSibling
= NULL
;
486 /* All children must be deleted before a parent is deleted */
487 ASSERT(!DeviceNode
->Child
);
489 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
491 ASSERT(DeviceNode
->PhysicalDeviceObject
);
493 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
495 /* Get previous sibling */
496 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
498 PrevSibling
= DeviceNode
->Parent
->Child
;
499 while (PrevSibling
->Sibling
!= DeviceNode
)
500 PrevSibling
= PrevSibling
->Sibling
;
503 /* Unlink from parent if it exists */
504 if (DeviceNode
->Parent
)
506 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
508 DeviceNode
->Parent
->LastChild
= PrevSibling
;
510 PrevSibling
->Sibling
= NULL
;
512 if (DeviceNode
->Parent
->Child
== DeviceNode
)
513 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
516 /* Unlink from sibling list */
518 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
520 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
522 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
524 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
526 if (DeviceNode
->ResourceList
)
528 ExFreePool(DeviceNode
->ResourceList
);
531 if (DeviceNode
->ResourceListTranslated
)
533 ExFreePool(DeviceNode
->ResourceListTranslated
);
536 if (DeviceNode
->ResourceRequirements
)
538 ExFreePool(DeviceNode
->ResourceRequirements
);
541 if (DeviceNode
->BootResources
)
543 ExFreePool(DeviceNode
->BootResources
);
546 ExFreePool(DeviceNode
);
548 return STATUS_SUCCESS
;
552 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
553 PIO_STATUS_BLOCK IoStatusBlock
,
555 PIO_STACK_LOCATION Stack OPTIONAL
)
557 PDEVICE_OBJECT TopDeviceObject
;
558 PIO_STACK_LOCATION IrpSp
;
563 /* Always call the top of the device stack */
564 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
571 Irp
= IoBuildSynchronousFsdRequest(
580 /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */
581 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
582 Irp
->IoStatus
.Information
= 0;
584 if (MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
586 Irp
->IoStatus
.Information
= (ULONG_PTR
)Stack
->Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
589 IrpSp
= IoGetNextIrpStackLocation(Irp
);
590 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
594 RtlCopyMemory(&IrpSp
->Parameters
,
596 sizeof(Stack
->Parameters
));
599 Status
= IoCallDriver(TopDeviceObject
, Irp
);
600 if (Status
== STATUS_PENDING
)
602 KeWaitForSingleObject(&Event
,
607 Status
= IoStatusBlock
->Status
;
610 ObDereferenceObject(TopDeviceObject
);
617 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
619 PDEVICE_NODE ParentDeviceNode
;
620 PDEVICE_NODE ChildDeviceNode
;
623 /* Copy context data so we don't overwrite it in subsequent calls to this function */
624 ParentDeviceNode
= Context
->DeviceNode
;
626 /* Call the action routine */
627 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
628 if (!NT_SUCCESS(Status
))
633 /* Traversal of all children nodes */
634 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
635 ChildDeviceNode
!= NULL
;
636 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
638 /* Pass the current device node to the action routine */
639 Context
->DeviceNode
= ChildDeviceNode
;
641 Status
= IopTraverseDeviceTreeNode(Context
);
642 if (!NT_SUCCESS(Status
))
653 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
657 DPRINT("Context 0x%p\n", Context
);
659 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
660 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
662 /* Start from the specified device node */
663 Context
->DeviceNode
= Context
->FirstDeviceNode
;
665 /* Recursively traverse the device tree */
666 Status
= IopTraverseDeviceTreeNode(Context
);
667 if (Status
== STATUS_UNSUCCESSFUL
)
669 /* The action routine just wanted to terminate the traversal with status
670 code STATUS_SUCCESS */
671 Status
= STATUS_SUCCESS
;
679 * IopCreateDeviceKeyPath
681 * Creates a registry key
685 * Name of the key to be created.
687 * Handle to the newly created key
690 * This method can create nested trees, so parent of RegistryPath can
691 * be not existant, and will be created if needed.
695 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
698 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
699 HANDLE hParent
= NULL
, hKey
;
700 OBJECT_ATTRIBUTES ObjectAttributes
;
701 UNICODE_STRING KeyName
;
702 LPCWSTR Current
, Last
;
709 /* Open root key for device instances */
710 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
711 if (!NT_SUCCESS(Status
))
713 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
717 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
718 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
720 /* Go up to the end of the string */
721 while (Current
<= Last
)
723 if (Current
!= Last
&& *Current
!= '\\')
725 /* Not the end of the string and not a separator */
730 /* Prepare relative key name */
731 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
732 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
733 DPRINT("Create '%wZ'\n", &KeyName
);
736 InitializeObjectAttributes(&ObjectAttributes
,
738 OBJ_CASE_INSENSITIVE
,
741 Status
= ZwCreateKey(&hKey
,
742 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
749 /* Close parent key handle, we don't need it anymore */
753 /* Key opening/creating failed? */
754 if (!NT_SUCCESS(Status
))
756 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
760 /* Check if it is the end of the string */
763 /* Yes, return success */
765 return STATUS_SUCCESS
;
768 /* Start with this new parent key */
771 KeyName
.Buffer
= (LPWSTR
)Current
;
774 return STATUS_UNSUCCESSFUL
;
778 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode
, PWCHAR Level1Key
, PWCHAR Level2Key
)
782 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
783 UNICODE_STRING KeyName
;
784 OBJECT_ATTRIBUTES ObjectAttributes
;
786 RtlInitUnicodeString(&KeyName
,
787 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
788 InitializeObjectAttributes(&ObjectAttributes
,
790 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
793 Status
= ZwCreateKey(&ResourceMapKey
,
800 if (!NT_SUCCESS(Status
))
803 RtlInitUnicodeString(&KeyName
, Level1Key
);
804 InitializeObjectAttributes(&ObjectAttributes
,
806 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
809 Status
= ZwCreateKey(&PnpMgrLevel1
,
816 ZwClose(ResourceMapKey
);
817 if (!NT_SUCCESS(Status
))
820 RtlInitUnicodeString(&KeyName
, Level2Key
);
821 InitializeObjectAttributes(&ObjectAttributes
,
823 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
826 Status
= ZwCreateKey(&PnpMgrLevel2
,
833 ZwClose(PnpMgrLevel1
);
834 if (!NT_SUCCESS(Status
))
837 if (DeviceNode
->ResourceList
)
840 UNICODE_STRING NameU
;
841 UNICODE_STRING Suffix
;
844 ASSERT(DeviceNode
->ResourceListTranslated
);
846 NameU
.Buffer
= NameBuff
;
848 NameU
.MaximumLength
= 256 * sizeof(WCHAR
);
850 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
851 DevicePropertyPhysicalDeviceObjectName
,
855 ASSERT(Status
== STATUS_SUCCESS
);
857 NameU
.Length
= (USHORT
)OldLength
;
859 RtlInitUnicodeString(&Suffix
, L
".Raw");
860 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
862 Status
= ZwSetValueKey(PnpMgrLevel2
,
866 DeviceNode
->ResourceList
,
867 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceList
));
868 if (!NT_SUCCESS(Status
))
870 ZwClose(PnpMgrLevel2
);
874 /* "Remove" the suffix by setting the length back to what it used to be */
875 NameU
.Length
= (USHORT
)OldLength
;
877 RtlInitUnicodeString(&Suffix
, L
".Translated");
878 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
880 Status
= ZwSetValueKey(PnpMgrLevel2
,
884 DeviceNode
->ResourceListTranslated
,
885 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceListTranslated
));
886 ZwClose(PnpMgrLevel2
);
887 if (!NT_SUCCESS(Status
))
892 ZwClose(PnpMgrLevel2
);
895 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
897 return STATUS_SUCCESS
;
901 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode
)
903 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
907 IopSetDeviceInstanceData(HANDLE InstanceKey
,
908 PDEVICE_NODE DeviceNode
)
910 OBJECT_ATTRIBUTES ObjectAttributes
;
911 UNICODE_STRING KeyName
;
914 ULONG ListSize
, ResultLength
;
916 HANDLE ControlHandle
;
918 DPRINT("IopSetDeviceInstanceData() called\n");
920 /* Create the 'LogConf' key */
921 RtlInitUnicodeString(&KeyName
, L
"LogConf");
922 InitializeObjectAttributes(&ObjectAttributes
,
924 OBJ_CASE_INSENSITIVE
,
927 Status
= ZwCreateKey(&LogConfKey
,
934 if (NT_SUCCESS(Status
))
936 /* Set 'BootConfig' value */
937 if (DeviceNode
->BootResources
!= NULL
)
939 ResCount
= DeviceNode
->BootResources
->Count
;
942 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
944 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
945 Status
= ZwSetValueKey(LogConfKey
,
949 DeviceNode
->BootResources
,
954 /* Set 'BasicConfigVector' value */
955 if (DeviceNode
->ResourceRequirements
!= NULL
&&
956 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
958 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
959 Status
= ZwSetValueKey(LogConfKey
,
962 REG_RESOURCE_REQUIREMENTS_LIST
,
963 DeviceNode
->ResourceRequirements
,
964 DeviceNode
->ResourceRequirements
->ListSize
);
970 /* Set the 'ConfigFlags' value */
971 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
972 Status
= ZwQueryValueKey(InstanceKey
,
974 KeyValueBasicInformation
,
978 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
980 /* Write the default value */
981 ULONG DefaultConfigFlags
= 0;
982 Status
= ZwSetValueKey(InstanceKey
,
987 sizeof(DefaultConfigFlags
));
990 /* Create the 'Control' key */
991 RtlInitUnicodeString(&KeyName
, L
"Control");
992 InitializeObjectAttributes(&ObjectAttributes
,
994 OBJ_CASE_INSENSITIVE
,
997 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
999 if (NT_SUCCESS(Status
))
1000 ZwClose(ControlHandle
);
1002 DPRINT("IopSetDeviceInstanceData() done\n");
1008 IopCheckForResourceConflict(
1009 IN PCM_RESOURCE_LIST ResourceList1
,
1010 IN PCM_RESOURCE_LIST ResourceList2
)
1012 ULONG i1
, i2
, ii1
, ii2
;
1013 BOOLEAN Result
= FALSE
;
1015 for (i1
= 0; i1
< ResourceList1
->Count
; i1
++)
1017 PCM_PARTIAL_RESOURCE_LIST ResList1
= &ResourceList1
->List
[i1
].PartialResourceList
;
1018 for (i2
= 0; i2
< ResourceList2
->Count
; i2
++)
1020 PCM_PARTIAL_RESOURCE_LIST ResList2
= &ResourceList2
->List
[i2
].PartialResourceList
;
1021 for (ii1
= 0; ii1
< ResList1
->Count
; ii1
++)
1023 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc1
= &ResList1
->PartialDescriptors
[ii1
];
1025 if (ResDesc1
->ShareDisposition
== CmResourceShareShared
)
1028 for (ii2
= 0; ii2
< ResList2
->Count
; ii2
++)
1030 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList2
->PartialDescriptors
[ii2
];
1032 /* We don't care about shared resources */
1033 if (ResDesc2
->ShareDisposition
== CmResourceShareShared
)
1036 /* Make sure we're comparing the same types */
1037 if (ResDesc1
->Type
!= ResDesc2
->Type
)
1040 switch (ResDesc1
->Type
)
1042 case CmResourceTypeMemory
:
1043 if ((ResDesc1
->u
.Memory
.Start
.QuadPart
< ResDesc2
->u
.Memory
.Start
.QuadPart
&&
1044 ResDesc1
->u
.Memory
.Start
.QuadPart
+ ResDesc1
->u
.Memory
.Length
>
1045 ResDesc2
->u
.Memory
.Start
.QuadPart
) || (ResDesc2
->u
.Memory
.Start
.QuadPart
<
1046 ResDesc1
->u
.Memory
.Start
.QuadPart
&& ResDesc2
->u
.Memory
.Start
.QuadPart
+
1047 ResDesc2
->u
.Memory
.Length
> ResDesc1
->u
.Memory
.Start
.QuadPart
))
1049 DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1050 ResDesc1
->u
.Memory
.Start
.QuadPart
, ResDesc1
->u
.Memory
.Start
.QuadPart
+
1051 ResDesc1
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
1052 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
1060 case CmResourceTypePort
:
1061 if ((ResDesc1
->u
.Port
.Start
.QuadPart
< ResDesc2
->u
.Port
.Start
.QuadPart
&&
1062 ResDesc1
->u
.Port
.Start
.QuadPart
+ ResDesc1
->u
.Port
.Length
>
1063 ResDesc2
->u
.Port
.Start
.QuadPart
) || (ResDesc2
->u
.Port
.Start
.QuadPart
<
1064 ResDesc1
->u
.Port
.Start
.QuadPart
&& ResDesc2
->u
.Port
.Start
.QuadPart
+
1065 ResDesc2
->u
.Port
.Length
> ResDesc1
->u
.Port
.Start
.QuadPart
))
1067 DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1068 ResDesc1
->u
.Port
.Start
.QuadPart
, ResDesc1
->u
.Port
.Start
.QuadPart
+
1069 ResDesc1
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
1070 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
1078 case CmResourceTypeInterrupt
:
1079 if (ResDesc1
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
1081 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
1082 ResDesc1
->u
.Interrupt
.Vector
, ResDesc1
->u
.Interrupt
.Level
,
1083 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
1091 case CmResourceTypeBusNumber
:
1092 if ((ResDesc1
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
1093 ResDesc1
->u
.BusNumber
.Start
+ ResDesc1
->u
.BusNumber
.Length
>
1094 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
1095 ResDesc1
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
1096 ResDesc2
->u
.BusNumber
.Length
> ResDesc1
->u
.BusNumber
.Start
))
1098 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1099 ResDesc1
->u
.BusNumber
.Start
, ResDesc1
->u
.BusNumber
.Start
+
1100 ResDesc1
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
1101 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
1109 case CmResourceTypeDma
:
1110 if (ResDesc1
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
1112 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
1113 ResDesc1
->u
.Dma
.Channel
, ResDesc1
->u
.Dma
.Port
,
1114 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
1129 #ifdef ENABLE_RESOURCE_CONFLICT_DETECTION
1137 IopDetectResourceConflict(
1138 IN PCM_RESOURCE_LIST ResourceList
)
1140 OBJECT_ATTRIBUTES ObjectAttributes
;
1141 UNICODE_STRING KeyName
;
1142 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
1143 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
1144 PKEY_BASIC_INFORMATION KeyInformation
;
1145 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
1146 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
1147 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
1150 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1151 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
1152 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1153 if (!NT_SUCCESS(Status
))
1155 /* The key is missing which means we are the first device */
1156 return STATUS_SUCCESS
;
1161 Status
= ZwEnumerateKey(ResourceMapKey
,
1163 KeyBasicInformation
,
1167 if (Status
== STATUS_NO_MORE_ENTRIES
)
1169 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1171 KeyInformationLength
= RequiredLength
;
1172 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1173 if (!KeyInformation
)
1175 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1179 Status
= ZwEnumerateKey(ResourceMapKey
,
1181 KeyBasicInformation
,
1183 KeyInformationLength
,
1189 if (!NT_SUCCESS(Status
))
1192 KeyName
.Buffer
= KeyInformation
->Name
;
1193 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1194 InitializeObjectAttributes(&ObjectAttributes
,
1196 OBJ_CASE_INSENSITIVE
,
1199 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1200 ExFreePool(KeyInformation
);
1201 if (!NT_SUCCESS(Status
))
1206 Status
= ZwEnumerateKey(ChildKey2
,
1208 KeyBasicInformation
,
1212 if (Status
== STATUS_NO_MORE_ENTRIES
)
1214 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1216 KeyInformationLength
= RequiredLength
;
1217 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1218 if (!KeyInformation
)
1220 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1224 Status
= ZwEnumerateKey(ChildKey2
,
1226 KeyBasicInformation
,
1228 KeyInformationLength
,
1234 if (!NT_SUCCESS(Status
))
1237 KeyName
.Buffer
= KeyInformation
->Name
;
1238 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1239 InitializeObjectAttributes(&ObjectAttributes
,
1241 OBJ_CASE_INSENSITIVE
,
1244 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1245 ExFreePool(KeyInformation
);
1246 if (!NT_SUCCESS(Status
))
1251 Status
= ZwEnumerateValueKey(ChildKey3
,
1253 KeyValuePartialInformation
,
1257 if (Status
== STATUS_NO_MORE_ENTRIES
)
1259 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1261 KeyValueInformationLength
= RequiredLength
;
1262 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1263 if (!KeyValueInformation
)
1265 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1269 Status
= ZwEnumerateValueKey(ChildKey3
,
1271 KeyValuePartialInformation
,
1272 KeyValueInformation
,
1273 KeyValueInformationLength
,
1278 if (!NT_SUCCESS(Status
))
1281 Status
= ZwEnumerateValueKey(ChildKey3
,
1283 KeyValueBasicInformation
,
1287 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1289 KeyNameInformationLength
= RequiredLength
;
1290 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1291 if (!KeyNameInformation
)
1293 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1297 Status
= ZwEnumerateValueKey(ChildKey3
,
1299 KeyValueBasicInformation
,
1301 KeyNameInformationLength
,
1309 if (!NT_SUCCESS(Status
))
1312 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1314 /* Skip translated entries */
1315 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1317 ExFreePool(KeyNameInformation
);
1321 ExFreePool(KeyNameInformation
);
1323 if (IopCheckForResourceConflict(ResourceList
,
1324 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
))
1326 ExFreePool(KeyValueInformation
);
1327 Status
= STATUS_CONFLICTING_ADDRESSES
;
1331 ExFreePool(KeyValueInformation
);
1337 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1338 ZwClose(ResourceMapKey
);
1339 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1341 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1344 if (Status
== STATUS_NO_MORE_ENTRIES
)
1345 Status
= STATUS_SUCCESS
;
1351 IopAssignDeviceResources(
1352 IN PDEVICE_NODE DeviceNode
,
1353 OUT ULONG
*pRequiredSize
)
1355 PIO_RESOURCE_LIST ResourceList
;
1356 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1357 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
1358 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1359 ULONG NumberOfResources
= 0;
1364 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1366 /* No resource needed for this device */
1367 DeviceNode
->ResourceList
= NULL
;
1369 return STATUS_SUCCESS
;
1372 /* Fill DeviceNode->ResourceList
1373 * FIXME: the PnP arbiter should go there!
1374 * Actually, use the BootResources if provided, else the resource list #0
1377 if (DeviceNode
->BootResources
)
1379 /* Browse the boot resources to know if we have some custom structures */
1380 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1381 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1383 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1384 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1385 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1386 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1388 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1389 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1393 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1394 if (!DeviceNode
->ResourceList
)
1396 Status
= STATUS_NO_MEMORY
;
1399 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1401 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
);
1402 if (!NT_SUCCESS(Status
))
1405 *pRequiredSize
= Size
;
1406 return STATUS_SUCCESS
;
1409 /* Ok, here, we have to use the device requirement list */
1410 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1411 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1413 Status
= STATUS_REVISION_MISMATCH
;
1417 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1418 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1419 if (!DeviceNode
->ResourceList
)
1421 Status
= STATUS_NO_MEMORY
;
1425 DeviceNode
->ResourceList
->Count
= 1;
1426 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1427 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1428 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1429 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1431 for (i
= 0; i
< ResourceList
->Count
; i
++)
1433 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1435 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1437 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1438 NumberOfResources
++;
1440 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1441 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
1442 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1443 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
1444 switch (ResourceDescriptor
->Type
)
1446 case CmResourceTypePort
:
1448 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1449 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
1452 case CmResourceTypeInterrupt
:
1454 INTERFACE_TYPE BusType
;
1459 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1460 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1461 /* FIXME: HACK: if we have a PCI device, we try
1462 * to keep the IRQ assigned by the BIOS */
1463 if (NT_SUCCESS(IoGetDeviceProperty(
1464 DeviceNode
->PhysicalDeviceObject
,
1465 DevicePropertyLegacyBusType
,
1466 sizeof(INTERFACE_TYPE
),
1468 &ret
)) && BusType
== PCIBus
)
1470 /* We have a PCI bus */
1471 if (NT_SUCCESS(IoGetDeviceProperty(
1472 DeviceNode
->PhysicalDeviceObject
,
1473 DevicePropertyAddress
,
1476 &ret
)) && SlotNumber
> 0)
1478 /* We have a good slot number */
1479 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1480 DeviceNode
->ResourceRequirements
->BusNumber
,
1483 0x3c /* PCI_INTERRUPT_LINE */,
1485 if (ret
!= 0 && ret
!= 2
1486 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1487 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1489 /* The device already has an assigned IRQ */
1490 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1494 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1495 DescriptorRaw
->u
.Interrupt
.Vector
,
1496 &DeviceNode
->InstancePath
);
1497 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1498 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1499 DeviceNode
->ResourceRequirements
->BusNumber
,
1502 0x3c /* PCI_INTERRUPT_LINE */,
1504 if (ret
== 0 || ret
== 2)
1511 case CmResourceTypeMemory
:
1513 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1514 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
1517 case CmResourceTypeDma
:
1519 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1520 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
1521 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
1524 case CmResourceTypeBusNumber
:
1526 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1527 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
1528 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
1531 /*CmResourceTypeDevicePrivate:
1532 case CmResourceTypePcCardConfig:
1533 case CmResourceTypeMfCardConfig:
1536 &DescriptorRaw->u.DevicePrivate,
1537 &ResourceDescriptor->u.DevicePrivate,
1538 sizeof(ResourceDescriptor->u.DevicePrivate));
1540 &DescriptorTranslated->u.DevicePrivate,
1541 &ResourceDescriptor->u.DevicePrivate,
1542 sizeof(ResourceDescriptor->u.DevicePrivate));
1546 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1547 NumberOfResources
--;
1553 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1555 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
);
1556 if (!NT_SUCCESS(Status
))
1559 *pRequiredSize
= Size
;
1560 return STATUS_SUCCESS
;
1563 if (DeviceNode
->ResourceList
)
1565 ExFreePool(DeviceNode
->ResourceList
);
1566 DeviceNode
->ResourceList
= NULL
;
1574 IopTranslateDeviceResources(
1575 IN PDEVICE_NODE DeviceNode
,
1576 IN ULONG RequiredSize
)
1578 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1579 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1583 if (!DeviceNode
->ResourceList
)
1585 DeviceNode
->ResourceListTranslated
= NULL
;
1586 return STATUS_SUCCESS
;
1589 /* That's easy to translate a resource list. Just copy the
1590 * untranslated one and change few fields in the copy
1592 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1593 if (!DeviceNode
->ResourceListTranslated
)
1595 Status
=STATUS_NO_MEMORY
;
1598 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1600 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1602 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1603 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1605 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1606 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1607 switch (DescriptorRaw
->Type
)
1609 case CmResourceTypePort
:
1611 ULONG AddressSpace
= 1; /* IO space */
1612 if (!HalTranslateBusAddress(
1613 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1614 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1615 DescriptorRaw
->u
.Port
.Start
,
1617 &DescriptorTranslated
->u
.Port
.Start
))
1619 Status
= STATUS_UNSUCCESSFUL
;
1624 case CmResourceTypeInterrupt
:
1626 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1627 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1628 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1629 DescriptorRaw
->u
.Interrupt
.Level
,
1630 DescriptorRaw
->u
.Interrupt
.Vector
,
1631 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1632 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1635 case CmResourceTypeMemory
:
1637 ULONG AddressSpace
= 0; /* Memory space */
1638 if (!HalTranslateBusAddress(
1639 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1640 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1641 DescriptorRaw
->u
.Memory
.Start
,
1643 &DescriptorTranslated
->u
.Memory
.Start
))
1645 Status
= STATUS_UNSUCCESSFUL
;
1650 case CmResourceTypeDma
:
1651 case CmResourceTypeBusNumber
:
1652 case CmResourceTypeDeviceSpecific
:
1656 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1657 Status
= STATUS_NOT_IMPLEMENTED
;
1662 return STATUS_SUCCESS
;
1665 /* Yes! Also delete ResourceList because ResourceList and
1666 * ResourceListTranslated should be a pair! */
1667 ExFreePool(DeviceNode
->ResourceList
);
1668 DeviceNode
->ResourceList
= NULL
;
1669 if (DeviceNode
->ResourceListTranslated
)
1671 ExFreePool(DeviceNode
->ResourceListTranslated
);
1672 DeviceNode
->ResourceList
= NULL
;
1679 * IopGetParentIdPrefix
1681 * Retrieve (or create) a string which identifies a device.
1685 * Pointer to device node.
1687 * Pointer to the string where is returned the parent node identifier
1690 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1691 * valid and its Buffer field is NULL-terminated. The caller needs to
1692 * to free the string with RtlFreeUnicodeString when it is no longer
1697 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1698 PUNICODE_STRING ParentIdPrefix
)
1700 ULONG KeyNameBufferLength
;
1701 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1702 UNICODE_STRING KeyName
;
1703 UNICODE_STRING KeyValue
;
1704 UNICODE_STRING ValueName
;
1709 /* HACK: As long as some devices have a NULL device
1710 * instance path, the following test is required :(
1712 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1714 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1715 &DeviceNode
->InstancePath
);
1716 return STATUS_UNSUCCESSFUL
;
1719 /* 1. Try to retrieve ParentIdPrefix from registry */
1720 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1721 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1722 if (!ParentIdPrefixInformation
)
1724 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1729 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1730 if (!KeyName
.Buffer
)
1732 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1736 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1738 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1739 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1741 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1742 if (!NT_SUCCESS(Status
))
1744 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1745 Status
= ZwQueryValueKey(
1747 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1748 KeyNameBufferLength
, &KeyNameBufferLength
);
1749 if (NT_SUCCESS(Status
))
1751 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1752 Status
= STATUS_UNSUCCESSFUL
;
1755 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1756 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1760 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1762 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1763 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1767 /* 2. Create the ParentIdPrefix value */
1768 crc32
= RtlComputeCrc32(0,
1769 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1770 DeviceNode
->Parent
->InstancePath
.Length
);
1772 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1773 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1775 /* 3. Try to write the ParentIdPrefix to registry */
1776 Status
= ZwSetValueKey(hKey
,
1780 (PVOID
)KeyValue
.Buffer
,
1781 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1784 if (NT_SUCCESS(Status
))
1786 /* Duplicate the string to return it */
1787 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1789 ExFreePool(ParentIdPrefixInformation
);
1790 RtlFreeUnicodeString(&KeyName
);
1798 * IopActionInterrogateDeviceStack
1800 * Retrieve information for all (direct) child nodes of a parent node.
1804 * Pointer to device node.
1806 * Pointer to parent node to retrieve child node information for.
1809 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1810 * when we reach a device node which is not a direct child of the device
1811 * node for which we retrieve information of child nodes for. Any errors
1812 * that occur is logged instead so that all child services have a chance
1813 * of being interrogated.
1817 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1820 IO_STATUS_BLOCK IoStatusBlock
;
1821 PDEVICE_NODE ParentDeviceNode
;
1822 WCHAR InstancePath
[MAX_PATH
];
1823 IO_STACK_LOCATION Stack
;
1828 ULONG RequiredLength
;
1830 HANDLE InstanceKey
= NULL
;
1831 UNICODE_STRING ValueName
;
1832 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1833 DEVICE_CAPABILITIES DeviceCapabilities
;
1835 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1836 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1838 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1841 * We are called for the parent too, but we don't need to do special
1842 * handling for this node
1845 if (DeviceNode
== ParentDeviceNode
)
1847 DPRINT("Success\n");
1848 return STATUS_SUCCESS
;
1852 * Make sure this device node is a direct child of the parent device node
1853 * that is given as an argument
1856 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1858 /* Stop the traversal immediately and indicate successful operation */
1860 return STATUS_UNSUCCESSFUL
;
1864 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1865 if (!NT_SUCCESS(Status
))
1867 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1872 * FIXME: For critical errors, cleanup and disable device, but always
1873 * return STATUS_SUCCESS.
1876 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1878 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1879 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1883 if (NT_SUCCESS(Status
))
1885 /* Copy the device id string */
1886 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1889 * FIXME: Check for valid characters, if there is invalid characters
1895 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1898 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1900 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1901 if (!NT_SUCCESS(Status
))
1903 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1906 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1908 if (!DeviceCapabilities
.UniqueID
)
1910 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1911 DPRINT("Instance ID is not unique\n");
1912 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1913 if (!NT_SUCCESS(Status
))
1915 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1919 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1921 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1922 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1926 if (NT_SUCCESS(Status
))
1928 /* Append the instance id string */
1929 wcscat(InstancePath
, L
"\\");
1930 if (ParentIdPrefix
.Length
> 0)
1932 /* Add information from parent bus device to InstancePath */
1933 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1934 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1935 wcscat(InstancePath
, L
"&");
1937 if (IoStatusBlock
.Information
)
1938 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1941 * FIXME: Check for valid characters, if there is invalid characters
1947 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1949 RtlFreeUnicodeString(&ParentIdPrefix
);
1951 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1953 DPRINT("No resources\n");
1954 /* FIXME: Cleanup and disable device */
1957 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1960 * Create registry key for the instance id, if it doesn't exist yet
1962 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceKey
);
1963 if (!NT_SUCCESS(Status
))
1965 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1969 /* Set 'Capabilities' value */
1970 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1971 Status
= ZwSetValueKey(InstanceKey
,
1975 (PVOID
)&DeviceNode
->CapabilityFlags
,
1978 /* Set 'UINumber' value */
1979 if (DeviceCapabilities
.UINumber
!= MAXULONG
)
1981 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1982 Status
= ZwSetValueKey(InstanceKey
,
1986 &DeviceCapabilities
.UINumber
,
1991 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1993 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1994 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1998 if (NT_SUCCESS(Status
))
2001 * FIXME: Check for valid characters, if there is invalid characters
2005 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
2006 DPRINT("Hardware IDs:\n");
2009 DPRINT(" %S\n", Ptr
);
2010 Length
= wcslen(Ptr
) + 1;
2013 TotalLength
+= Length
;
2015 DPRINT("TotalLength: %hu\n", TotalLength
);
2018 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
2019 Status
= ZwSetValueKey(InstanceKey
,
2023 (PVOID
)IoStatusBlock
.Information
,
2024 (TotalLength
+ 1) * sizeof(WCHAR
));
2025 if (!NT_SUCCESS(Status
))
2027 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2032 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2035 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
2037 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
2038 Status
= IopInitiatePnpIrp(
2039 DeviceNode
->PhysicalDeviceObject
,
2043 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2046 * FIXME: Check for valid characters, if there is invalid characters
2050 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
2051 DPRINT("Compatible IDs:\n");
2054 DPRINT(" %S\n", Ptr
);
2055 Length
= wcslen(Ptr
) + 1;
2058 TotalLength
+= Length
;
2060 DPRINT("TotalLength: %hu\n", TotalLength
);
2063 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
2064 Status
= ZwSetValueKey(InstanceKey
,
2068 (PVOID
)IoStatusBlock
.Information
,
2069 (TotalLength
+ 1) * sizeof(WCHAR
));
2070 if (!NT_SUCCESS(Status
))
2072 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
2077 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2080 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2082 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2083 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2084 Status
= IopInitiatePnpIrp(
2085 DeviceNode
->PhysicalDeviceObject
,
2087 IRP_MN_QUERY_DEVICE_TEXT
,
2089 /* This key is mandatory, so even if the Irp fails, we still write it */
2090 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2091 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2093 if (NT_SUCCESS(Status
) &&
2094 IoStatusBlock
.Information
&&
2095 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2097 /* This key is overriden when a driver is installed. Don't write the
2098 * new description if another one already exists */
2099 Status
= ZwSetValueKey(InstanceKey
,
2103 (PVOID
)IoStatusBlock
.Information
,
2104 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2108 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2109 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2111 Status
= ZwSetValueKey(InstanceKey
,
2116 DeviceDesc
.MaximumLength
);
2118 if (!NT_SUCCESS(Status
))
2120 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2126 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2128 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2129 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2130 Status
= IopInitiatePnpIrp(
2131 DeviceNode
->PhysicalDeviceObject
,
2133 IRP_MN_QUERY_DEVICE_TEXT
,
2135 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2137 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2138 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2139 Status
= ZwSetValueKey(InstanceKey
,
2143 (PVOID
)IoStatusBlock
.Information
,
2144 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2145 if (!NT_SUCCESS(Status
))
2147 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2152 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2155 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2157 Status
= IopInitiatePnpIrp(
2158 DeviceNode
->PhysicalDeviceObject
,
2160 IRP_MN_QUERY_BUS_INFORMATION
,
2162 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2164 PPNP_BUS_INFORMATION BusInformation
=
2165 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2167 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2168 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2169 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2170 ExFreePool(BusInformation
);
2174 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2176 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2177 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2178 DeviceNode
->ChildBusTypeIndex
= -1;
2181 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2183 Status
= IopInitiatePnpIrp(
2184 DeviceNode
->PhysicalDeviceObject
,
2186 IRP_MN_QUERY_RESOURCES
,
2188 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2190 DeviceNode
->BootResources
=
2191 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2192 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2196 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2197 DeviceNode
->BootResources
= NULL
;
2200 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2202 Status
= IopInitiatePnpIrp(
2203 DeviceNode
->PhysicalDeviceObject
,
2205 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2207 if (NT_SUCCESS(Status
))
2209 DeviceNode
->ResourceRequirements
=
2210 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2211 if (IoStatusBlock
.Information
)
2212 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2214 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2218 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2219 DeviceNode
->ResourceRequirements
= NULL
;
2223 if (InstanceKey
!= NULL
)
2225 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2228 ZwClose(InstanceKey
);
2230 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
2232 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
2234 /* Report the device to the user-mode pnp manager */
2235 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
2236 &DeviceNode
->InstancePath
);
2239 return STATUS_SUCCESS
;
2245 IN PDEVICE_OBJECT DeviceObject
)
2247 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2248 DEVICETREE_TRAVERSE_CONTEXT Context
;
2249 PDEVICE_RELATIONS DeviceRelations
;
2250 PDEVICE_OBJECT ChildDeviceObject
;
2251 IO_STATUS_BLOCK IoStatusBlock
;
2252 PDEVICE_NODE ChildDeviceNode
;
2253 IO_STACK_LOCATION Stack
;
2257 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2259 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
2261 /* Report the device to the user-mode pnp manager */
2262 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2263 &DeviceNode
->InstancePath
);
2265 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2267 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
2269 Status
= IopInitiatePnpIrp(
2272 IRP_MN_QUERY_DEVICE_RELATIONS
,
2274 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
2276 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2280 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2282 if (!DeviceRelations
)
2284 DPRINT("No PDOs\n");
2285 return STATUS_UNSUCCESSFUL
;
2288 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
2291 * Create device nodes for all discovered devices
2293 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2295 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
2296 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
2298 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
2299 if (!ChildDeviceNode
)
2301 /* One doesn't exist, create it */
2302 Status
= IopCreateDeviceNode(
2307 if (NT_SUCCESS(Status
))
2309 /* Mark the node as enumerated */
2310 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2312 /* Mark the DO as bus enumerated */
2313 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2317 /* Ignore this DO */
2318 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
2319 ObDereferenceObject(ChildDeviceNode
);
2324 /* Mark it as enumerated */
2325 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2326 ObDereferenceObject(ChildDeviceObject
);
2329 ExFreePool(DeviceRelations
);
2332 * Retrieve information about all discovered children from the bus driver
2334 IopInitDeviceTreeTraverseContext(
2337 IopActionInterrogateDeviceStack
,
2340 Status
= IopTraverseDeviceTree(&Context
);
2341 if (!NT_SUCCESS(Status
))
2343 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2348 * Retrieve configuration from the registry for discovered children
2350 IopInitDeviceTreeTraverseContext(
2353 IopActionConfigureChildServices
,
2356 Status
= IopTraverseDeviceTree(&Context
);
2357 if (!NT_SUCCESS(Status
))
2359 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2364 * Initialize services for discovered children.
2366 Status
= IopInitializePnpServices(DeviceNode
);
2367 if (!NT_SUCCESS(Status
))
2369 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2373 DPRINT("IopEnumerateDevice() finished\n");
2374 return STATUS_SUCCESS
;
2379 * IopActionConfigureChildServices
2381 * Retrieve configuration for all (direct) child nodes of a parent node.
2385 * Pointer to device node.
2387 * Pointer to parent node to retrieve child node configuration for.
2390 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2391 * when we reach a device node which is not a direct child of the device
2392 * node for which we configure child services for. Any errors that occur is
2393 * logged instead so that all child services have a chance of beeing
2398 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2401 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2402 PDEVICE_NODE ParentDeviceNode
;
2403 PUNICODE_STRING Service
;
2404 UNICODE_STRING ClassGUID
;
2406 DEVICE_CAPABILITIES DeviceCaps
;
2408 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2410 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2413 * We are called for the parent too, but we don't need to do special
2414 * handling for this node
2416 if (DeviceNode
== ParentDeviceNode
)
2418 DPRINT("Success\n");
2419 return STATUS_SUCCESS
;
2423 * Make sure this device node is a direct child of the parent device node
2424 * that is given as an argument
2426 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2428 /* Stop the traversal immediately and indicate successful operation */
2430 return STATUS_UNSUCCESSFUL
;
2433 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2435 WCHAR RegKeyBuffer
[MAX_PATH
];
2436 UNICODE_STRING RegKey
;
2439 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2440 RegKey
.Buffer
= RegKeyBuffer
;
2443 * Retrieve configuration from Enum key
2446 Service
= &DeviceNode
->ServiceName
;
2448 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2449 RtlInitUnicodeString(Service
, NULL
);
2450 RtlInitUnicodeString(&ClassGUID
, NULL
);
2452 QueryTable
[0].Name
= L
"Service";
2453 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2454 QueryTable
[0].EntryContext
= Service
;
2456 QueryTable
[1].Name
= L
"ClassGUID";
2457 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2458 QueryTable
[1].EntryContext
= &ClassGUID
;
2459 QueryTable
[1].DefaultType
= REG_SZ
;
2460 QueryTable
[1].DefaultData
= L
"";
2461 QueryTable
[1].DefaultLength
= 0;
2463 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2464 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2466 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2467 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2469 if (!NT_SUCCESS(Status
))
2471 /* FIXME: Log the error */
2472 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2473 &DeviceNode
->InstancePath
, Status
);
2474 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2475 return STATUS_SUCCESS
;
2478 if (Service
->Buffer
== NULL
)
2480 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
2481 DeviceCaps
.RawDeviceOK
)
2483 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
2485 DeviceNode
->ServiceName
.Length
= 0;
2486 DeviceNode
->ServiceName
.MaximumLength
= ParentDeviceNode
->ServiceName
.MaximumLength
;
2487 DeviceNode
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, DeviceNode
->ServiceName
.MaximumLength
);
2488 if (!DeviceNode
->ServiceName
.Buffer
)
2489 return STATUS_SUCCESS
;
2491 RtlCopyUnicodeString(&DeviceNode
->ServiceName
, &ParentDeviceNode
->ServiceName
);
2493 IopDeviceNodeSetFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
2495 else if (ClassGUID
.Length
!= 0)
2497 /* Device has a ClassGUID value, but no Service value.
2498 * Suppose it is using the NULL driver, so state the
2499 * device is started */
2500 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2501 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2505 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2507 return STATUS_SUCCESS
;
2510 DPRINT("Got Service %S\n", Service
->Buffer
);
2513 return STATUS_SUCCESS
;
2517 * IopActionInitChildServices
2519 * Initialize the service for all (direct) child nodes of a parent node
2523 * Pointer to device node.
2525 * Pointer to parent node to initialize child node services for.
2528 * If the driver image for a service is not loaded and initialized
2529 * it is done here too. We only return a status code indicating an
2530 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2531 * not a direct child of the device node for which we initialize
2532 * child services for. Any errors that occur is logged instead so
2533 * that all child services have a chance of being initialized.
2537 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2540 PDEVICE_NODE ParentDeviceNode
;
2542 BOOLEAN BootDrivers
= !PnpSystemInit
;
2544 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2546 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2549 * We are called for the parent too, but we don't need to do special
2550 * handling for this node
2552 if (DeviceNode
== ParentDeviceNode
)
2554 DPRINT("Success\n");
2555 return STATUS_SUCCESS
;
2559 * Make sure this device node is a direct child of the parent device node
2560 * that is given as an argument
2563 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2566 * Stop the traversal immediately and indicate unsuccessful operation
2569 return STATUS_UNSUCCESSFUL
;
2573 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2574 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2575 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2577 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2578 PDRIVER_OBJECT DriverObject
;
2580 /* Get existing DriverObject pointer (in case the driver has
2581 already been loaded and initialized) */
2582 Status
= IopGetDriverObject(
2584 &DeviceNode
->ServiceName
,
2587 if (!NT_SUCCESS(Status
))
2589 /* Driver is not initialized, try to load it */
2590 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2592 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2594 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2595 was loaded by the bootloader */
2596 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2597 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2599 /* Initialize the driver */
2600 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2601 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2605 Status
= STATUS_SUCCESS
;
2610 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2611 &DeviceNode
->ServiceName
, Status
);
2615 /* Driver is loaded and initialized at this point */
2616 if (NT_SUCCESS(Status
))
2618 /* Attach lower level filter drivers. */
2619 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2620 /* Initialize the function driver for the device node */
2621 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2623 if (NT_SUCCESS(Status
))
2625 /* Attach upper level filter drivers. */
2626 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2627 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2629 Status
= IopStartDevice(DeviceNode
);
2633 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2634 &DeviceNode
->InstancePath
, Status
);
2640 * Don't disable when trying to load only boot drivers
2644 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2645 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2646 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2647 DPRINT1("Initialization of service %S failed (Status %x)\n",
2648 DeviceNode
->ServiceName
.Buffer
, Status
);
2654 DPRINT("Device %wZ is disabled or already initialized\n",
2655 &DeviceNode
->InstancePath
);
2658 return STATUS_SUCCESS
;
2662 * IopInitializePnpServices
2664 * Initialize services for discovered children
2668 * Top device node to start initializing services.
2674 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2676 DEVICETREE_TRAVERSE_CONTEXT Context
;
2678 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2680 IopInitDeviceTreeTraverseContext(
2683 IopActionInitChildServices
,
2686 return IopTraverseDeviceTree(&Context
);
2689 static NTSTATUS INIT_FUNCTION
2690 IopEnumerateDetectedDevices(
2692 IN PUNICODE_STRING RelativePath OPTIONAL
,
2694 IN BOOLEAN EnumerateSubKeys
,
2695 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2696 IN ULONG ParentBootResourcesLength
)
2698 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2699 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2700 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2701 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2702 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2703 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2704 OBJECT_ATTRIBUTES ObjectAttributes
;
2705 HANDLE hDevicesKey
= NULL
;
2706 HANDLE hDeviceKey
= NULL
;
2707 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2708 UNICODE_STRING Level2NameU
;
2709 WCHAR Level2Name
[5];
2710 ULONG IndexDevice
= 0;
2712 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2713 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2714 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2715 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2716 UNICODE_STRING DeviceName
, ValueName
;
2718 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2719 ULONG BootResourcesLength
;
2722 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2723 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2724 static ULONG DeviceIndexPci
= 0;
2725 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2726 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2727 static ULONG DeviceIndexSerial
= 0;
2728 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2729 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2730 static ULONG DeviceIndexKeyboard
= 0;
2731 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2732 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2733 static ULONG DeviceIndexMouse
= 0;
2734 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2735 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2736 static ULONG DeviceIndexParallel
= 0;
2737 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2738 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2739 static ULONG DeviceIndexFloppy
= 0;
2740 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2741 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2742 static ULONG DeviceIndexIsa
= 0;
2743 UNICODE_STRING HardwareIdKey
;
2744 PUNICODE_STRING pHardwareId
;
2745 ULONG DeviceIndex
= 0;
2746 BOOLEAN IsDeviceDesc
;
2750 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2751 if (!NT_SUCCESS(Status
))
2753 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2758 hDevicesKey
= hBaseKey
;
2760 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2761 if (!pDeviceInformation
)
2763 DPRINT("ExAllocatePool() failed\n");
2764 Status
= STATUS_NO_MEMORY
;
2768 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2769 if (!pValueInformation
)
2771 DPRINT("ExAllocatePool() failed\n");
2772 Status
= STATUS_NO_MEMORY
;
2778 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2779 if (Status
== STATUS_NO_MORE_ENTRIES
)
2781 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2783 ExFreePool(pDeviceInformation
);
2784 DeviceInfoLength
= RequiredSize
;
2785 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2786 if (!pDeviceInformation
)
2788 DPRINT("ExAllocatePool() failed\n");
2789 Status
= STATUS_NO_MEMORY
;
2792 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2794 if (!NT_SUCCESS(Status
))
2796 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2801 /* Open device key */
2802 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2803 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2805 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2806 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2807 if (!NT_SUCCESS(Status
))
2809 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2813 /* Read boot resources, and add then to parent ones */
2814 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2815 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2817 ExFreePool(pValueInformation
);
2818 ValueInfoLength
= RequiredSize
;
2819 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2820 if (!pValueInformation
)
2822 DPRINT("ExAllocatePool() failed\n");
2823 ZwDeleteKey(hLevel2Key
);
2824 Status
= STATUS_NO_MEMORY
;
2827 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2829 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2831 BootResources
= ParentBootResources
;
2832 BootResourcesLength
= ParentBootResourcesLength
;
2834 else if (!NT_SUCCESS(Status
))
2836 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2839 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2841 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2846 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2848 /* Concatenate current resources and parent ones */
2849 if (ParentBootResourcesLength
== 0)
2850 BootResourcesLength
= pValueInformation
->DataLength
;
2852 BootResourcesLength
= ParentBootResourcesLength
2853 + pValueInformation
->DataLength
2855 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2858 DPRINT("ExAllocatePool() failed\n");
2861 if (ParentBootResourcesLength
== 0)
2863 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2865 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2867 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2869 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2870 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2871 ParentBootResourcesLength
- Header
);
2872 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2876 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2878 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2879 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2880 ParentBootResourcesLength
- Header
);
2882 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2883 pValueInformation
->Data
+ Header
,
2884 pValueInformation
->DataLength
- Header
);
2885 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2889 if (EnumerateSubKeys
)
2894 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2895 if (Status
== STATUS_NO_MORE_ENTRIES
)
2897 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2899 ExFreePool(pDeviceInformation
);
2900 DeviceInfoLength
= RequiredSize
;
2901 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2902 if (!pDeviceInformation
)
2904 DPRINT("ExAllocatePool() failed\n");
2905 Status
= STATUS_NO_MEMORY
;
2908 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2910 if (!NT_SUCCESS(Status
))
2912 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2916 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2917 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2919 Status
= IopEnumerateDetectedDevices(
2925 BootResourcesLength
);
2926 if (!NT_SUCCESS(Status
))
2931 /* Read identifier */
2932 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2933 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2935 ExFreePool(pValueInformation
);
2936 ValueInfoLength
= RequiredSize
;
2937 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2938 if (!pValueInformation
)
2940 DPRINT("ExAllocatePool() failed\n");
2941 Status
= STATUS_NO_MEMORY
;
2944 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2946 if (!NT_SUCCESS(Status
))
2948 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2950 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2953 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2955 else if (pValueInformation
->Type
!= REG_SZ
)
2957 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2962 /* Assign hardware id to this device */
2963 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2964 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2965 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2966 ValueName
.Length
-= sizeof(WCHAR
);
2969 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2971 pHardwareId
= &HardwareIdSerial
;
2972 DeviceIndex
= DeviceIndexSerial
++;
2973 IsDeviceDesc
= TRUE
;
2975 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2977 pHardwareId
= &HardwareIdKeyboard
;
2978 DeviceIndex
= DeviceIndexKeyboard
++;
2979 IsDeviceDesc
= FALSE
;
2981 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2983 pHardwareId
= &HardwareIdMouse
;
2984 DeviceIndex
= DeviceIndexMouse
++;
2985 IsDeviceDesc
= FALSE
;
2987 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
2989 pHardwareId
= &HardwareIdParallel
;
2990 DeviceIndex
= DeviceIndexParallel
++;
2991 IsDeviceDesc
= FALSE
;
2993 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
2995 pHardwareId
= &HardwareIdFloppy
;
2996 DeviceIndex
= DeviceIndexFloppy
++;
2997 IsDeviceDesc
= FALSE
;
2999 else if (NT_SUCCESS(Status
))
3001 /* Try to also match the device identifier */
3002 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
3004 pHardwareId
= &HardwareIdPci
;
3005 DeviceIndex
= DeviceIndexPci
++;
3006 IsDeviceDesc
= FALSE
;
3008 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
3010 pHardwareId
= &HardwareIdIsa
;
3011 DeviceIndex
= DeviceIndexIsa
++;
3012 IsDeviceDesc
= FALSE
;
3016 DPRINT("Unknown device '%wZ'\n", &ValueName
);
3022 /* Unknown key path */
3023 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
3027 /* Prepare hardware id key (hardware id value without final \0) */
3028 HardwareIdKey
= *pHardwareId
;
3029 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
3031 /* Add the detected device to Root key */
3032 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
3033 Status
= ZwCreateKey(
3039 REG_OPTION_NON_VOLATILE
,
3041 if (!NT_SUCCESS(Status
))
3043 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3046 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
3047 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
3048 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
3049 Status
= ZwCreateKey(
3051 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3055 REG_OPTION_NON_VOLATILE
,
3057 ZwClose(hLevel1Key
);
3058 if (!NT_SUCCESS(Status
))
3060 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3063 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
3066 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
3067 if (!NT_SUCCESS(Status
))
3069 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3070 ZwDeleteKey(hLevel2Key
);
3074 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3075 if (!NT_SUCCESS(Status
))
3077 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3078 ZwDeleteKey(hLevel2Key
);
3081 /* Create 'LogConf' subkey */
3082 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3083 Status
= ZwCreateKey(
3089 REG_OPTION_VOLATILE
,
3091 if (!NT_SUCCESS(Status
))
3093 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3094 ZwDeleteKey(hLevel2Key
);
3097 if (BootResourcesLength
> 0)
3099 /* Save boot resources to 'LogConf\BootConfig' */
3100 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
3101 if (!NT_SUCCESS(Status
))
3103 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3105 ZwDeleteKey(hLevel2Key
);
3112 if (BootResources
&& BootResources
!= ParentBootResources
)
3113 ExFreePool(BootResources
);
3116 ZwClose(hLevel2Key
);
3121 ZwClose(hDeviceKey
);
3126 Status
= STATUS_SUCCESS
;
3129 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
3130 ZwClose(hDevicesKey
);
3132 ZwClose(hDeviceKey
);
3133 if (pDeviceInformation
)
3134 ExFreePool(pDeviceInformation
);
3135 if (pValueInformation
)
3136 ExFreePool(pValueInformation
);
3140 static BOOLEAN INIT_FUNCTION
3141 IopIsAcpiComputer(VOID
)
3146 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3147 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3148 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3149 OBJECT_ATTRIBUTES ObjectAttributes
;
3150 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3151 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3152 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3153 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3155 ULONG IndexDevice
= 0;
3156 UNICODE_STRING DeviceName
, ValueName
;
3157 HANDLE hDevicesKey
= NULL
;
3158 HANDLE hDeviceKey
= NULL
;
3160 BOOLEAN ret
= FALSE
;
3162 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3163 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3164 if (!NT_SUCCESS(Status
))
3166 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3170 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3171 if (!pDeviceInformation
)
3173 DPRINT("ExAllocatePool() failed\n");
3174 Status
= STATUS_NO_MEMORY
;
3178 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3179 if (!pDeviceInformation
)
3181 DPRINT("ExAllocatePool() failed\n");
3182 Status
= STATUS_NO_MEMORY
;
3188 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3189 if (Status
== STATUS_NO_MORE_ENTRIES
)
3191 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3193 ExFreePool(pDeviceInformation
);
3194 DeviceInfoLength
= RequiredSize
;
3195 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3196 if (!pDeviceInformation
)
3198 DPRINT("ExAllocatePool() failed\n");
3199 Status
= STATUS_NO_MEMORY
;
3202 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3204 if (!NT_SUCCESS(Status
))
3206 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3211 /* Open device key */
3212 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3213 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3214 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3219 if (!NT_SUCCESS(Status
))
3221 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3225 /* Read identifier */
3226 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3227 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3229 ExFreePool(pValueInformation
);
3230 ValueInfoLength
= RequiredSize
;
3231 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3232 if (!pValueInformation
)
3234 DPRINT("ExAllocatePool() failed\n");
3235 Status
= STATUS_NO_MEMORY
;
3238 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3240 if (!NT_SUCCESS(Status
))
3242 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3245 else if (pValueInformation
->Type
!= REG_SZ
)
3247 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3251 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3252 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3253 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3254 ValueName
.Length
-= sizeof(WCHAR
);
3255 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3257 DPRINT("Found ACPI BIOS\n");
3263 ZwClose(hDeviceKey
);
3268 if (pDeviceInformation
)
3269 ExFreePool(pDeviceInformation
);
3270 if (pValueInformation
)
3271 ExFreePool(pValueInformation
);
3273 ZwClose(hDevicesKey
);
3275 ZwClose(hDeviceKey
);
3280 static NTSTATUS INIT_FUNCTION
3281 IopUpdateRootKey(VOID
)
3283 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
3284 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
3285 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3286 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3287 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3288 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
3289 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3290 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3291 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3292 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3293 OBJECT_ATTRIBUTES ObjectAttributes
;
3294 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
3297 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3298 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3299 if (!NT_SUCCESS(Status
))
3301 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3305 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
3306 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3308 if (!NT_SUCCESS(Status
))
3310 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3314 if (IopIsAcpiComputer())
3316 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
3317 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3319 if (!NT_SUCCESS(Status
))
3321 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
3322 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3323 ZwClose(hHalAcpiDevice
);
3324 if (!NT_SUCCESS(Status
))
3326 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3327 if (NT_SUCCESS(Status
))
3328 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3329 if (NT_SUCCESS(Status
))
3331 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
3332 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3333 if (NT_SUCCESS(Status
))
3336 ZwClose(hHalAcpiId
);
3341 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
3342 if (!NT_SUCCESS(Status
))
3344 /* Nothing to do, don't return with an error status */
3345 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3347 return STATUS_SUCCESS
;
3349 Status
= IopEnumerateDetectedDevices(
3364 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
3366 PUNICODE_STRING Name
,
3367 ACCESS_MASK DesiredAccess
)
3369 OBJECT_ATTRIBUTES ObjectAttributes
;
3376 InitializeObjectAttributes(&ObjectAttributes
,
3378 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3382 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
3389 IopGetRegistryValue(IN HANDLE Handle
,
3391 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
3393 UNICODE_STRING ValueString
;
3395 PKEY_VALUE_FULL_INFORMATION FullInformation
;
3399 RtlInitUnicodeString(&ValueString
, ValueName
);
3401 Status
= ZwQueryValueKey(Handle
,
3403 KeyValueFullInformation
,
3407 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
3408 (Status
!= STATUS_BUFFER_TOO_SMALL
))
3413 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
3414 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
3416 Status
= ZwQueryValueKey(Handle
,
3418 KeyValueFullInformation
,
3422 if (!NT_SUCCESS(Status
))
3424 ExFreePool(FullInformation
);
3428 *Information
= FullInformation
;
3429 return STATUS_SUCCESS
;
3432 static NTSTATUS INIT_FUNCTION
3434 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
3436 return STATUS_SUCCESS
;
3445 DPRINT("PnpInit()\n");
3447 KeInitializeSpinLock(&IopDeviceTreeLock
);
3448 ExInitializeFastMutex(&IopBusTypeGuidListLock
);
3450 /* Initialize the Bus Type GUID List */
3451 IopBusTypeGuidList
= ExAllocatePool(NonPagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3452 if (!IopBusTypeGuidList
) {
3453 DPRINT1("ExAllocatePool() failed\n");
3454 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3457 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3458 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3460 /* Initialize PnP-Event notification support */
3461 Status
= IopInitPlugPlayEvents();
3462 if (!NT_SUCCESS(Status
))
3464 DPRINT1("IopInitPlugPlayEvents() failed\n");
3465 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3469 * Create root device node
3472 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
3473 if (!NT_SUCCESS(Status
))
3475 DPRINT1("IoCreateDriverObject() failed\n");
3476 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3479 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3481 if (!NT_SUCCESS(Status
))
3483 DPRINT1("IoCreateDevice() failed\n");
3484 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3487 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
3488 if (!NT_SUCCESS(Status
))
3490 DPRINT1("Insufficient resources\n");
3491 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3494 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3497 DPRINT1("Failed to create the instance path!\n");
3498 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3501 /* Report the device to the user-mode pnp manager */
3502 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3503 &IopRootDeviceNode
->InstancePath
);
3505 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3506 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3507 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3508 IopRootDriverObject
->DriverExtension
->AddDevice(
3509 IopRootDriverObject
,
3510 IopRootDeviceNode
->PhysicalDeviceObject
);
3512 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3513 Status
= IopUpdateRootKey();
3514 if (!NT_SUCCESS(Status
))
3516 DPRINT1("IopUpdateRootKey() failed\n");
3517 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3521 RTL_GENERIC_COMPARE_RESULTS
3523 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3524 IN PVOID FirstStruct
,
3525 IN PVOID SecondStruct
)
3533 // The allocation function is called by the generic table package whenever
3534 // it needs to allocate memory for the table.
3539 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3549 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3558 PpInitializeDeviceReferenceTable(VOID
)
3560 /* Setup the guarded mutex and AVL table */
3561 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3562 RtlInitializeGenericTableAvl(
3563 &PpDeviceReferenceTable
,
3564 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3565 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3566 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3574 /* Initialize the resource when accessing device registry data */
3575 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3577 /* Setup the device reference AVL table */
3578 PpInitializeDeviceReferenceTable();
3586 /* Check the initialization phase */
3587 switch (ExpInitializationPhase
)
3592 return PiInitPhase0();
3598 //return PiInitPhase1();
3602 /* Don't know any other phase! Bugcheck! */
3603 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3608 /* PUBLIC FUNCTIONS **********************************************************/
3615 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3616 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3617 IN ULONG BufferLength
,
3618 OUT PVOID PropertyBuffer
,
3619 OUT PULONG ResultLength
)
3621 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3622 DEVICE_CAPABILITIES DeviceCaps
;
3627 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
3628 ULONG RequiredLength
, ObjectNameInfoLength
;
3630 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3634 if (DeviceNode
== NULL
)
3635 return STATUS_INVALID_DEVICE_REQUEST
;
3637 switch (DeviceProperty
)
3639 case DevicePropertyBusNumber
:
3640 Length
= sizeof(ULONG
);
3641 Data
= &DeviceNode
->ChildBusNumber
;
3644 /* Complete, untested */
3645 case DevicePropertyBusTypeGuid
:
3647 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
3648 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
3650 /* Return the GUID */
3651 *ResultLength
= sizeof(GUID
);
3653 /* Check if the buffer given was large enough */
3654 if (BufferLength
< *ResultLength
)
3656 return STATUS_BUFFER_TOO_SMALL
;
3660 RtlCopyMemory(PropertyBuffer
,
3661 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
3663 return STATUS_SUCCESS
;
3667 return STATUS_OBJECT_NAME_NOT_FOUND
;
3671 case DevicePropertyLegacyBusType
:
3672 Length
= sizeof(INTERFACE_TYPE
);
3673 Data
= &DeviceNode
->ChildInterfaceType
;
3676 case DevicePropertyAddress
:
3677 /* Query the device caps */
3678 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3679 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= MAXULONG
))
3682 *ResultLength
= sizeof(ULONG
);
3684 /* Check if the buffer given was large enough */
3685 if (BufferLength
< *ResultLength
)
3687 return STATUS_BUFFER_TOO_SMALL
;
3690 /* Return address */
3691 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
3692 return STATUS_SUCCESS
;
3696 return STATUS_OBJECT_NAME_NOT_FOUND
;
3700 // case DevicePropertyUINumber:
3701 // if (DeviceNode->CapabilityFlags == NULL)
3702 // return STATUS_INVALID_DEVICE_REQUEST;
3703 // Length = sizeof(ULONG);
3704 // Data = &DeviceNode->CapabilityFlags->UINumber;
3707 case DevicePropertyClassName
:
3708 case DevicePropertyClassGuid
:
3709 case DevicePropertyDriverKeyName
:
3710 case DevicePropertyManufacturer
:
3711 case DevicePropertyFriendlyName
:
3712 case DevicePropertyHardwareID
:
3713 case DevicePropertyCompatibleIDs
:
3714 case DevicePropertyDeviceDescription
:
3715 case DevicePropertyLocationInformation
:
3716 case DevicePropertyUINumber
:
3718 LPCWSTR RegistryPropertyName
;
3719 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
3720 UNICODE_STRING ValueName
;
3721 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
3722 ULONG ValueInformationLength
;
3723 HANDLE KeyHandle
, EnumRootHandle
;
3726 switch (DeviceProperty
)
3728 case DevicePropertyClassName
:
3729 RegistryPropertyName
= L
"Class"; break;
3730 case DevicePropertyClassGuid
:
3731 RegistryPropertyName
= L
"ClassGuid"; break;
3732 case DevicePropertyDriverKeyName
:
3733 RegistryPropertyName
= L
"Driver"; break;
3734 case DevicePropertyManufacturer
:
3735 RegistryPropertyName
= L
"Mfg"; break;
3736 case DevicePropertyFriendlyName
:
3737 RegistryPropertyName
= L
"FriendlyName"; break;
3738 case DevicePropertyHardwareID
:
3739 RegistryPropertyName
= L
"HardwareID"; break;
3740 case DevicePropertyCompatibleIDs
:
3741 RegistryPropertyName
= L
"CompatibleIDs"; break;
3742 case DevicePropertyDeviceDescription
:
3743 RegistryPropertyName
= L
"DeviceDesc"; break;
3744 case DevicePropertyLocationInformation
:
3745 RegistryPropertyName
= L
"LocationInformation"; break;
3746 case DevicePropertyUINumber
:
3747 RegistryPropertyName
= L
"UINumber"; break;
3749 /* Should not happen */
3751 return STATUS_UNSUCCESSFUL
;
3754 DPRINT("Registry property %S\n", RegistryPropertyName
);
3757 Status
= IopOpenRegistryKeyEx(&EnumRootHandle
, NULL
,
3758 &EnumRoot
, KEY_READ
);
3759 if (!NT_SUCCESS(Status
))
3761 DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status
);
3765 /* Open instance key */
3766 Status
= IopOpenRegistryKeyEx(&KeyHandle
, EnumRootHandle
,
3767 &DeviceNode
->InstancePath
, KEY_READ
);
3768 if (!NT_SUCCESS(Status
))
3770 DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status
);
3771 ZwClose(EnumRootHandle
);
3775 /* Allocate buffer to read as much data as required by the caller */
3776 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
3777 Data
[0]) + BufferLength
;
3778 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
3779 if (!ValueInformation
)
3782 return STATUS_INSUFFICIENT_RESOURCES
;
3785 /* Read the value */
3786 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
3787 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
3788 KeyValuePartialInformation
, ValueInformation
,
3789 ValueInformationLength
,
3790 &ValueInformationLength
);
3794 *ResultLength
= ValueInformation
->DataLength
;
3796 if (!NT_SUCCESS(Status
))
3798 ExFreePool(ValueInformation
);
3799 if (Status
== STATUS_BUFFER_OVERFLOW
)
3800 return STATUS_BUFFER_TOO_SMALL
;
3801 DPRINT1("Problem: Status=0x%08x, ResultLength = %d\n", Status
, *ResultLength
);
3805 /* FIXME: Verify the value (NULL-terminated, correct format). */
3806 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
3807 ValueInformation
->DataLength
);
3808 ExFreePool(ValueInformation
);
3810 return STATUS_SUCCESS
;
3813 case DevicePropertyBootConfiguration
:
3815 if (DeviceNode
->BootResources
->Count
!= 0)
3817 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
3819 Data
= DeviceNode
->BootResources
;
3822 /* FIXME: use a translated boot configuration instead */
3823 case DevicePropertyBootConfigurationTranslated
:
3825 if (DeviceNode
->BootResources
->Count
!= 0)
3827 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
3829 Data
= DeviceNode
->BootResources
;
3832 case DevicePropertyEnumeratorName
:
3833 /* A buffer overflow can't happen here, since InstancePath
3834 * always contains the enumerator name followed by \\ */
3835 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
3837 Length
= (Ptr
- DeviceNode
->InstancePath
.Buffer
) * sizeof(WCHAR
);
3838 Data
= DeviceNode
->InstancePath
.Buffer
;
3841 case DevicePropertyPhysicalDeviceObjectName
:
3842 Status
= ObQueryNameString(DeviceNode
->PhysicalDeviceObject
,
3846 if (Status
== STATUS_SUCCESS
)
3851 else if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
3853 ObjectNameInfoLength
= RequiredLength
;
3854 ObjectNameInfo
= ExAllocatePool(PagedPool
, ObjectNameInfoLength
);
3855 if (!ObjectNameInfo
)
3856 return STATUS_INSUFFICIENT_RESOURCES
;
3858 Status
= ObQueryNameString(DeviceNode
->PhysicalDeviceObject
,
3860 ObjectNameInfoLength
,
3862 if (NT_SUCCESS(Status
))
3864 Length
= ObjectNameInfo
->Name
.Length
;
3865 Data
= ObjectNameInfo
->Name
.Buffer
;
3875 return STATUS_INVALID_PARAMETER_2
;
3878 /* Prepare returned values */
3879 *ResultLength
= Length
;
3880 if (BufferLength
< Length
)
3882 if (ObjectNameInfo
!= NULL
)
3883 ExFreePool(ObjectNameInfo
);
3885 return STATUS_BUFFER_TOO_SMALL
;
3887 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
3889 /* NULL terminate the string (if required) */
3890 if (DeviceProperty
== DevicePropertyEnumeratorName
||
3891 DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
3892 ((LPWSTR
)PropertyBuffer
)[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3894 if (ObjectNameInfo
!= NULL
)
3895 ExFreePool(ObjectNameInfo
);
3897 return STATUS_SUCCESS
;
3905 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3911 * @name IoOpenDeviceRegistryKey
3913 * Open a registry key unique for a specified driver or device instance.
3915 * @param DeviceObject Device to get the registry key for.
3916 * @param DevInstKeyType Type of the key to return.
3917 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
3918 * @param DevInstRegKey Handle to the opened registry key on
3919 * successful return.
3927 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
3928 IN ULONG DevInstKeyType
,
3929 IN ACCESS_MASK DesiredAccess
,
3930 OUT PHANDLE DevInstRegKey
)
3932 static WCHAR RootKeyName
[] =
3933 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
3934 static WCHAR ProfileKeyName
[] =
3935 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
3936 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
3937 static WCHAR EnumKeyName
[] = L
"Enum\\";
3938 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
3939 ULONG KeyNameLength
;
3940 LPWSTR KeyNameBuffer
;
3941 UNICODE_STRING KeyName
;
3942 ULONG DriverKeyLength
;
3943 OBJECT_ATTRIBUTES ObjectAttributes
;
3944 PDEVICE_NODE DeviceNode
= NULL
;
3947 DPRINT("IoOpenDeviceRegistryKey() called\n");
3949 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
3951 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
3952 return STATUS_INVALID_PARAMETER
;
3956 * Calculate the length of the base key name. This is the full
3957 * name for driver key or the name excluding "Device Parameters"
3958 * subkey for device key.
3961 KeyNameLength
= sizeof(RootKeyName
);
3962 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3963 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
3964 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3966 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
3967 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3968 0, NULL
, &DriverKeyLength
);
3969 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
3971 KeyNameLength
+= DriverKeyLength
;
3975 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3976 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
3977 DeviceNode
->InstancePath
.Length
;
3981 * Now allocate the buffer for the key name...
3984 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
3985 if (KeyNameBuffer
== NULL
)
3986 return STATUS_INSUFFICIENT_RESOURCES
;
3989 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
3990 KeyName
.Buffer
= KeyNameBuffer
;
3993 * ...and build the key name.
3996 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
3997 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
3999 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4000 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
4002 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4004 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
4005 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4006 DriverKeyLength
, KeyNameBuffer
+
4007 (KeyName
.Length
/ sizeof(WCHAR
)),
4009 if (!NT_SUCCESS(Status
))
4011 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
4012 ExFreePool(KeyNameBuffer
);
4015 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
4019 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
4020 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
4021 if (DeviceNode
->InstancePath
.Length
== 0)
4023 ExFreePool(KeyNameBuffer
);
4029 * Open the base key.
4031 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
4032 if (!NT_SUCCESS(Status
))
4034 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
4035 ExFreePool(KeyNameBuffer
);
4038 ExFreePool(KeyNameBuffer
);
4041 * For driver key we're done now.
4044 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4048 * Let's go further. For device key we must open "Device Parameters"
4049 * subkey and create it if it doesn't exist yet.
4052 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
4053 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
4054 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
4055 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
4056 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
4057 ZwClose(ObjectAttributes
.RootDirectory
);
4067 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4077 IoInvalidateDeviceRelations(
4078 IN PDEVICE_OBJECT DeviceObject
,
4079 IN DEVICE_RELATION_TYPE Type
)
4081 PIO_WORKITEM WorkItem
;
4082 PINVALIDATE_DEVICE_RELATION_DATA Data
;
4084 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
4087 WorkItem
= IoAllocateWorkItem(DeviceObject
);
4094 ObReferenceObject(DeviceObject
);
4095 Data
->DeviceObject
= DeviceObject
;
4097 Data
->WorkItem
= WorkItem
;
4101 IopAsynchronousInvalidateDeviceRelations
,
4111 IoSynchronousInvalidateDeviceRelations(
4112 IN PDEVICE_OBJECT DeviceObject
,
4113 IN DEVICE_RELATION_TYPE Type
)
4120 /* Enumerate the device */
4121 return IopEnumerateDevice(DeviceObject
);
4122 case PowerRelations
:
4123 /* Not handled yet */
4124 return STATUS_NOT_IMPLEMENTED
;
4125 case TargetDeviceRelation
:
4127 return STATUS_SUCCESS
;
4129 /* Ejection relations are not supported */
4130 return STATUS_NOT_SUPPORTED
;
4139 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
4141 IN PHYSICAL_ADDRESS BusAddress
,
4142 IN OUT PULONG AddressSpace
,
4143 OUT PPHYSICAL_ADDRESS TranslatedAddress
)