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 else if (NT_SUCCESS(Status
))
168 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
171 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
172 if (NT_SUCCESS(Status
))
174 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
175 if (NT_SUCCESS(Status
))
177 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
178 if (!NT_SUCCESS(Status
))
180 DPRINT("IopUpdateResourceMap() failed (Status 0x%08lx)\n", Status
);
185 DPRINT("IopTranslateDeviceResources() failed (Status 0x%08lx)\n", Status
);
190 DPRINT("IopAssignDeviceResources() failed (Status 0x%08lx)\n", Status
);
192 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
194 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
195 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
196 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
199 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and
200 * actually _depend_ on this!. This is because NT will lock the Device Node
201 * with an ERESOURCE, which of course requires APCs to be disabled.
203 KeEnterCriticalRegion();
205 Status
= IopInitiatePnpIrp(
206 DeviceNode
->PhysicalDeviceObject
,
211 KeLeaveCriticalRegion();
213 if (!NT_SUCCESS(Status
))
215 DPRINT("IopInitiatePnpIrp() failed\n");
219 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
221 DPRINT("Device needs enumeration, invalidating bus relations\n");
222 /* Invalidate device relations synchronously
223 (otherwise there will be dirty read of DeviceNode) */
224 IopEnumerateDevice(DeviceNode
->PhysicalDeviceObject
);
225 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
229 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceHandle
);
230 if (!NT_SUCCESS(Status
))
233 RtlInitUnicodeString(&KeyName
, L
"Control");
234 InitializeObjectAttributes(&ObjectAttributes
,
236 OBJ_CASE_INSENSITIVE
,
239 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
240 if (!NT_SUCCESS(Status
))
242 ZwClose(InstanceHandle
);
246 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
247 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
249 if (NT_SUCCESS(Status
))
250 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
252 ZwClose(ControlHandle
);
253 ZwClose(InstanceHandle
);
260 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
261 PDEVICE_CAPABILITIES DeviceCaps
)
263 IO_STATUS_BLOCK StatusBlock
;
264 IO_STACK_LOCATION Stack
;
266 /* Set up the Header */
267 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
268 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
269 DeviceCaps
->Version
= 1;
270 DeviceCaps
->Address
= -1;
271 DeviceCaps
->UINumber
= -1;
273 /* Set up the Stack */
274 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
275 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
278 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
280 IRP_MN_QUERY_CAPABILITIES
,
285 IopAsynchronousInvalidateDeviceRelations(
286 IN PDEVICE_OBJECT DeviceObject
,
287 IN PVOID InvalidateContext
)
289 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
291 IoSynchronousInvalidateDeviceRelations(
295 ObDereferenceObject(Data
->DeviceObject
);
296 IoFreeWorkItem(Data
->WorkItem
);
301 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
305 if (PopSystemPowerDeviceNode
)
307 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
308 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
309 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
311 return STATUS_SUCCESS
;
314 return STATUS_UNSUCCESSFUL
;
319 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
321 USHORT i
= 0, FoundIndex
= 0xFFFF;
325 /* Acquire the lock */
326 ExAcquireFastMutex(&IopBusTypeGuidListLock
);
328 /* Loop all entries */
329 while (i
< IopBusTypeGuidList
->GuidCount
)
331 /* Try to find a match */
332 if (RtlCompareMemory(BusTypeGuid
,
333 &IopBusTypeGuidList
->Guids
[i
],
334 sizeof(GUID
)) == sizeof(GUID
))
343 /* Check if we have to grow the list */
344 if (IopBusTypeGuidList
->GuidCount
)
346 /* Calculate the new size */
347 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
348 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
350 /* Allocate the new copy */
351 NewList
= ExAllocatePool(PagedPool
, NewSize
);
355 ExFreePool(IopBusTypeGuidList
);
359 /* Now copy them, decrease the size too */
360 NewSize
-= sizeof(GUID
);
361 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
363 /* Free the old list */
364 ExFreePool(IopBusTypeGuidList
);
366 /* Use the new buffer */
367 IopBusTypeGuidList
= NewList
;
370 /* Copy the new GUID */
371 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
375 /* The new entry is the index */
376 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
377 IopBusTypeGuidList
->GuidCount
++;
380 ExReleaseFastMutex(&IopBusTypeGuidListLock
);
386 * Creates a device node
389 * ParentNode = Pointer to parent device node
390 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
391 * to have the root device node create one
392 * (eg. for legacy drivers)
393 * DeviceNode = Pointer to storage for created device node
399 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
400 PDEVICE_OBJECT PhysicalDeviceObject
,
401 PUNICODE_STRING ServiceName
,
402 PDEVICE_NODE
*DeviceNode
)
407 UNICODE_STRING FullServiceName
;
408 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
409 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
412 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
413 ParentNode
, PhysicalDeviceObject
, ServiceName
);
415 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
418 return STATUS_INSUFFICIENT_RESOURCES
;
421 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
424 ServiceName
= &UnknownDeviceName
;
426 if (!PhysicalDeviceObject
)
428 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName
->Length
;
429 FullServiceName
.Length
= 0;
430 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
431 if (!FullServiceName
.Buffer
)
434 return STATUS_INSUFFICIENT_RESOURCES
;
437 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
438 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName
);
440 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
441 if (!NT_SUCCESS(Status
))
443 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
448 /* Create the device key for legacy drivers */
449 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, &TempHandle
);
450 if (NT_SUCCESS(Status
))
453 ExFreePool(FullServiceName
.Buffer
);
455 /* This is for drivers passed on the command line to ntoskrnl.exe */
456 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
457 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
460 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
462 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
466 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
467 Node
->Parent
= ParentNode
;
468 Node
->Sibling
= ParentNode
->Child
;
469 ParentNode
->Child
= Node
;
470 if (ParentNode
->LastChild
== NULL
)
471 ParentNode
->LastChild
= Node
;
472 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
473 Node
->Level
= ParentNode
->Level
+ 1;
476 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
480 return STATUS_SUCCESS
;
484 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
487 PDEVICE_NODE PrevSibling
= NULL
;
489 /* All children must be deleted before a parent is deleted */
490 ASSERT(!DeviceNode
->Child
);
492 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
494 ASSERT(DeviceNode
->PhysicalDeviceObject
);
496 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
498 /* Get previous sibling */
499 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
501 PrevSibling
= DeviceNode
->Parent
->Child
;
502 while (PrevSibling
->Sibling
!= DeviceNode
)
503 PrevSibling
= PrevSibling
->Sibling
;
506 /* Unlink from parent if it exists */
507 if (DeviceNode
->Parent
)
509 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
511 DeviceNode
->Parent
->LastChild
= PrevSibling
;
513 PrevSibling
->Sibling
= NULL
;
515 if (DeviceNode
->Parent
->Child
== DeviceNode
)
516 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
519 /* Unlink from sibling list */
521 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
523 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
525 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
527 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
529 if (DeviceNode
->ResourceList
)
531 ExFreePool(DeviceNode
->ResourceList
);
534 if (DeviceNode
->ResourceListTranslated
)
536 ExFreePool(DeviceNode
->ResourceListTranslated
);
539 if (DeviceNode
->ResourceRequirements
)
541 ExFreePool(DeviceNode
->ResourceRequirements
);
544 if (DeviceNode
->BootResources
)
546 ExFreePool(DeviceNode
->BootResources
);
549 ExFreePool(DeviceNode
);
551 return STATUS_SUCCESS
;
555 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
556 PIO_STATUS_BLOCK IoStatusBlock
,
558 PIO_STACK_LOCATION Stack OPTIONAL
)
560 PDEVICE_OBJECT TopDeviceObject
;
561 PIO_STACK_LOCATION IrpSp
;
566 /* Always call the top of the device stack */
567 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
574 Irp
= IoBuildSynchronousFsdRequest(
583 /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */
584 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
585 Irp
->IoStatus
.Information
= 0;
587 if (MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
589 Irp
->IoStatus
.Information
= (ULONG_PTR
)Stack
->Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
592 IrpSp
= IoGetNextIrpStackLocation(Irp
);
593 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
597 RtlCopyMemory(&IrpSp
->Parameters
,
599 sizeof(Stack
->Parameters
));
602 Status
= IoCallDriver(TopDeviceObject
, Irp
);
603 if (Status
== STATUS_PENDING
)
605 KeWaitForSingleObject(&Event
,
610 Status
= IoStatusBlock
->Status
;
613 ObDereferenceObject(TopDeviceObject
);
620 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
622 PDEVICE_NODE ParentDeviceNode
;
623 PDEVICE_NODE ChildDeviceNode
;
626 /* Copy context data so we don't overwrite it in subsequent calls to this function */
627 ParentDeviceNode
= Context
->DeviceNode
;
629 /* Call the action routine */
630 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
631 if (!NT_SUCCESS(Status
))
636 /* Traversal of all children nodes */
637 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
638 ChildDeviceNode
!= NULL
;
639 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
641 /* Pass the current device node to the action routine */
642 Context
->DeviceNode
= ChildDeviceNode
;
644 Status
= IopTraverseDeviceTreeNode(Context
);
645 if (!NT_SUCCESS(Status
))
656 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
660 DPRINT("Context 0x%p\n", Context
);
662 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
663 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
665 /* Start from the specified device node */
666 Context
->DeviceNode
= Context
->FirstDeviceNode
;
668 /* Recursively traverse the device tree */
669 Status
= IopTraverseDeviceTreeNode(Context
);
670 if (Status
== STATUS_UNSUCCESSFUL
)
672 /* The action routine just wanted to terminate the traversal with status
673 code STATUS_SUCCESS */
674 Status
= STATUS_SUCCESS
;
682 * IopCreateDeviceKeyPath
684 * Creates a registry key
688 * Name of the key to be created.
690 * Handle to the newly created key
693 * This method can create nested trees, so parent of RegistryPath can
694 * be not existant, and will be created if needed.
698 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
701 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
702 HANDLE hParent
= NULL
, hKey
;
703 OBJECT_ATTRIBUTES ObjectAttributes
;
704 UNICODE_STRING KeyName
;
705 LPCWSTR Current
, Last
;
712 /* Open root key for device instances */
713 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
714 if (!NT_SUCCESS(Status
))
716 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
720 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
721 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
723 /* Go up to the end of the string */
724 while (Current
<= Last
)
726 if (Current
!= Last
&& *Current
!= '\\')
728 /* Not the end of the string and not a separator */
733 /* Prepare relative key name */
734 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
735 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
736 DPRINT("Create '%wZ'\n", &KeyName
);
739 InitializeObjectAttributes(&ObjectAttributes
,
741 OBJ_CASE_INSENSITIVE
,
744 Status
= ZwCreateKey(&hKey
,
745 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
752 /* Close parent key handle, we don't need it anymore */
756 /* Key opening/creating failed? */
757 if (!NT_SUCCESS(Status
))
759 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
763 /* Check if it is the end of the string */
766 /* Yes, return success */
768 return STATUS_SUCCESS
;
771 /* Start with this new parent key */
774 KeyName
.Buffer
= (LPWSTR
)Current
;
777 return STATUS_UNSUCCESSFUL
;
781 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode
, PWCHAR Level1Key
, PWCHAR Level2Key
)
785 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
786 UNICODE_STRING KeyName
;
787 OBJECT_ATTRIBUTES ObjectAttributes
;
789 RtlInitUnicodeString(&KeyName
,
790 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
791 InitializeObjectAttributes(&ObjectAttributes
,
793 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
796 Status
= ZwCreateKey(&ResourceMapKey
,
803 if (!NT_SUCCESS(Status
))
806 RtlInitUnicodeString(&KeyName
, Level1Key
);
807 InitializeObjectAttributes(&ObjectAttributes
,
809 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
812 Status
= ZwCreateKey(&PnpMgrLevel1
,
819 ZwClose(ResourceMapKey
);
820 if (!NT_SUCCESS(Status
))
823 RtlInitUnicodeString(&KeyName
, Level2Key
);
824 InitializeObjectAttributes(&ObjectAttributes
,
826 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
829 Status
= ZwCreateKey(&PnpMgrLevel2
,
836 ZwClose(PnpMgrLevel1
);
837 if (!NT_SUCCESS(Status
))
840 if (DeviceNode
->ResourceList
)
843 UNICODE_STRING NameU
;
844 UNICODE_STRING Suffix
;
847 ASSERT(DeviceNode
->ResourceListTranslated
);
849 NameU
.Buffer
= NameBuff
;
851 NameU
.MaximumLength
= 256 * sizeof(WCHAR
);
853 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
854 DevicePropertyPhysicalDeviceObjectName
,
858 ASSERT(Status
== STATUS_SUCCESS
);
860 NameU
.Length
= (USHORT
)OldLength
;
862 RtlInitUnicodeString(&Suffix
, L
".Raw");
863 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
865 Status
= ZwSetValueKey(PnpMgrLevel2
,
869 DeviceNode
->ResourceList
,
870 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceList
));
871 if (!NT_SUCCESS(Status
))
873 ZwClose(PnpMgrLevel2
);
877 /* "Remove" the suffix by setting the length back to what it used to be */
878 NameU
.Length
= (USHORT
)OldLength
;
880 RtlInitUnicodeString(&Suffix
, L
".Translated");
881 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
883 Status
= ZwSetValueKey(PnpMgrLevel2
,
887 DeviceNode
->ResourceListTranslated
,
888 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceListTranslated
));
889 ZwClose(PnpMgrLevel2
);
890 if (!NT_SUCCESS(Status
))
895 ZwClose(PnpMgrLevel2
);
898 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
900 return STATUS_SUCCESS
;
904 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode
)
906 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
910 IopSetDeviceInstanceData(HANDLE InstanceKey
,
911 PDEVICE_NODE DeviceNode
)
913 OBJECT_ATTRIBUTES ObjectAttributes
;
914 UNICODE_STRING KeyName
;
917 ULONG ListSize
, ResultLength
;
919 HANDLE ControlHandle
;
921 DPRINT("IopSetDeviceInstanceData() called\n");
923 /* Create the 'LogConf' key */
924 RtlInitUnicodeString(&KeyName
, L
"LogConf");
925 InitializeObjectAttributes(&ObjectAttributes
,
927 OBJ_CASE_INSENSITIVE
,
930 Status
= ZwCreateKey(&LogConfKey
,
937 if (NT_SUCCESS(Status
))
939 /* Set 'BootConfig' value */
940 if (DeviceNode
->BootResources
!= NULL
)
942 ResCount
= DeviceNode
->BootResources
->Count
;
945 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
947 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
948 Status
= ZwSetValueKey(LogConfKey
,
952 DeviceNode
->BootResources
,
957 /* Set 'BasicConfigVector' value */
958 if (DeviceNode
->ResourceRequirements
!= NULL
&&
959 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
961 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
962 Status
= ZwSetValueKey(LogConfKey
,
965 REG_RESOURCE_REQUIREMENTS_LIST
,
966 DeviceNode
->ResourceRequirements
,
967 DeviceNode
->ResourceRequirements
->ListSize
);
973 /* Set the 'ConfigFlags' value */
974 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
975 Status
= ZwQueryValueKey(InstanceKey
,
977 KeyValueBasicInformation
,
981 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
983 /* Write the default value */
984 ULONG DefaultConfigFlags
= 0;
985 Status
= ZwSetValueKey(InstanceKey
,
990 sizeof(DefaultConfigFlags
));
993 /* Create the 'Control' key */
994 RtlInitUnicodeString(&KeyName
, L
"Control");
995 InitializeObjectAttributes(&ObjectAttributes
,
997 OBJ_CASE_INSENSITIVE
,
1000 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1002 if (NT_SUCCESS(Status
))
1003 ZwClose(ControlHandle
);
1005 DPRINT("IopSetDeviceInstanceData() done\n");
1011 IopCheckResourceDescriptor(
1012 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
1013 IN PCM_RESOURCE_LIST ResourceList
,
1015 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1018 BOOLEAN Result
= FALSE
;
1020 if (ResDesc
->ShareDisposition
== CmResourceShareShared
)
1023 for (i
= 0; i
< ResourceList
->Count
; i
++)
1025 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList
->List
[i
].PartialResourceList
;
1026 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1028 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
1030 /* We don't care about shared resources */
1031 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
1032 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
1035 /* Make sure we're comparing the same types */
1036 if (ResDesc
->Type
!= ResDesc2
->Type
)
1039 switch (ResDesc
->Type
)
1041 case CmResourceTypeMemory
:
1042 if ((ResDesc
->u
.Memory
.Start
.QuadPart
< ResDesc2
->u
.Memory
.Start
.QuadPart
&&
1043 ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
1044 ResDesc2
->u
.Memory
.Start
.QuadPart
) || (ResDesc2
->u
.Memory
.Start
.QuadPart
<
1045 ResDesc
->u
.Memory
.Start
.QuadPart
&& ResDesc2
->u
.Memory
.Start
.QuadPart
+
1046 ResDesc2
->u
.Memory
.Length
> ResDesc
->u
.Memory
.Start
.QuadPart
))
1050 DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1051 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
1052 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
1053 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
1062 case CmResourceTypePort
:
1063 if ((ResDesc
->u
.Port
.Start
.QuadPart
< ResDesc2
->u
.Port
.Start
.QuadPart
&&
1064 ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
1065 ResDesc2
->u
.Port
.Start
.QuadPart
) || (ResDesc2
->u
.Port
.Start
.QuadPart
<
1066 ResDesc
->u
.Port
.Start
.QuadPart
&& ResDesc2
->u
.Port
.Start
.QuadPart
+
1067 ResDesc2
->u
.Port
.Length
> ResDesc
->u
.Port
.Start
.QuadPart
))
1071 DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1072 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
1073 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
1074 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
1083 case CmResourceTypeInterrupt
:
1084 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
1088 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
1089 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
1090 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
1099 case CmResourceTypeBusNumber
:
1100 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
1101 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
1102 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
1103 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
1104 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
1108 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1109 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
1110 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
1111 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
1120 case CmResourceTypeDma
:
1121 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
1125 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
1126 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
1127 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
1141 if (Result
&& ConflictingDescriptor
)
1143 RtlCopyMemory(ConflictingDescriptor
,
1145 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1153 IopCheckForResourceConflict(
1154 IN PCM_RESOURCE_LIST ResourceList1
,
1155 IN PCM_RESOURCE_LIST ResourceList2
,
1157 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1160 BOOLEAN Result
= FALSE
;
1162 for (i
= 0; i
< ResourceList1
->Count
; i
++)
1164 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
1165 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1167 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
1169 Result
= IopCheckResourceDescriptor(ResDesc
,
1172 ConflictingDescriptor
);
1173 if (Result
) goto ByeBye
;
1184 IopDetectResourceConflict(
1185 IN PCM_RESOURCE_LIST ResourceList
,
1187 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1189 OBJECT_ATTRIBUTES ObjectAttributes
;
1190 UNICODE_STRING KeyName
;
1191 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
1192 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
1193 PKEY_BASIC_INFORMATION KeyInformation
;
1194 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
1195 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
1196 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
1199 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1200 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
1201 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1202 if (!NT_SUCCESS(Status
))
1204 /* The key is missing which means we are the first device */
1205 return STATUS_SUCCESS
;
1210 Status
= ZwEnumerateKey(ResourceMapKey
,
1212 KeyBasicInformation
,
1216 if (Status
== STATUS_NO_MORE_ENTRIES
)
1218 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1220 KeyInformationLength
= RequiredLength
;
1221 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1222 if (!KeyInformation
)
1224 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1228 Status
= ZwEnumerateKey(ResourceMapKey
,
1230 KeyBasicInformation
,
1232 KeyInformationLength
,
1238 if (!NT_SUCCESS(Status
))
1241 KeyName
.Buffer
= KeyInformation
->Name
;
1242 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1243 InitializeObjectAttributes(&ObjectAttributes
,
1245 OBJ_CASE_INSENSITIVE
,
1248 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1249 ExFreePool(KeyInformation
);
1250 if (!NT_SUCCESS(Status
))
1255 Status
= ZwEnumerateKey(ChildKey2
,
1257 KeyBasicInformation
,
1261 if (Status
== STATUS_NO_MORE_ENTRIES
)
1263 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1265 KeyInformationLength
= RequiredLength
;
1266 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1267 if (!KeyInformation
)
1269 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1273 Status
= ZwEnumerateKey(ChildKey2
,
1275 KeyBasicInformation
,
1277 KeyInformationLength
,
1283 if (!NT_SUCCESS(Status
))
1286 KeyName
.Buffer
= KeyInformation
->Name
;
1287 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1288 InitializeObjectAttributes(&ObjectAttributes
,
1290 OBJ_CASE_INSENSITIVE
,
1293 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1294 ExFreePool(KeyInformation
);
1295 if (!NT_SUCCESS(Status
))
1300 Status
= ZwEnumerateValueKey(ChildKey3
,
1302 KeyValuePartialInformation
,
1306 if (Status
== STATUS_NO_MORE_ENTRIES
)
1308 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1310 KeyValueInformationLength
= RequiredLength
;
1311 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1312 if (!KeyValueInformation
)
1314 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1318 Status
= ZwEnumerateValueKey(ChildKey3
,
1320 KeyValuePartialInformation
,
1321 KeyValueInformation
,
1322 KeyValueInformationLength
,
1327 if (!NT_SUCCESS(Status
))
1330 Status
= ZwEnumerateValueKey(ChildKey3
,
1332 KeyValueBasicInformation
,
1336 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1338 KeyNameInformationLength
= RequiredLength
;
1339 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1340 if (!KeyNameInformation
)
1342 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1346 Status
= ZwEnumerateValueKey(ChildKey3
,
1348 KeyValueBasicInformation
,
1350 KeyNameInformationLength
,
1358 if (!NT_SUCCESS(Status
))
1361 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1363 /* Skip translated entries */
1364 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1366 ExFreePool(KeyNameInformation
);
1370 ExFreePool(KeyNameInformation
);
1372 if (IopCheckForResourceConflict(ResourceList
,
1373 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1375 ConflictingDescriptor
))
1377 ExFreePool(KeyValueInformation
);
1378 Status
= STATUS_CONFLICTING_ADDRESSES
;
1382 ExFreePool(KeyValueInformation
);
1388 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1389 ZwClose(ResourceMapKey
);
1390 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1392 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1395 if (Status
== STATUS_NO_MORE_ENTRIES
)
1396 Status
= STATUS_SUCCESS
;
1402 IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1404 CM_RESOURCE_LIST CmList
;
1408 CmList
.List
[0].InterfaceType
= InterfaceTypeUndefined
;
1409 CmList
.List
[0].BusNumber
= 0;
1410 CmList
.List
[0].PartialResourceList
.Version
= 1;
1411 CmList
.List
[0].PartialResourceList
.Revision
= 1;
1412 CmList
.List
[0].PartialResourceList
.Count
= 1;
1413 CmList
.List
[0].PartialResourceList
.PartialDescriptors
[0] = *CmDesc
;
1415 Status
= IopDetectResourceConflict(&CmList
, TRUE
, ConflictingDescriptor
);
1416 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
1423 IopFindBusNumberResource(
1424 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1425 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1428 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1430 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1431 ASSERT(IoDesc
->Type
== CmResourceTypeBusNumber
);
1433 for (Start
= IoDesc
->u
.BusNumber
.MinBusNumber
;
1434 Start
< IoDesc
->u
.BusNumber
.MaxBusNumber
;
1437 CmDesc
->u
.BusNumber
.Length
= IoDesc
->u
.BusNumber
.Length
;
1438 CmDesc
->u
.BusNumber
.Start
= Start
;
1440 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1442 Start
+= ConflictingDesc
.u
.BusNumber
.Start
+ ConflictingDesc
.u
.BusNumber
.Length
;
1454 IopFindMemoryResource(
1455 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1456 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1459 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1461 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1462 ASSERT(IoDesc
->Type
== CmResourceTypeMemory
);
1464 for (Start
= IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
;
1465 Start
< IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
;
1468 CmDesc
->u
.Memory
.Length
= IoDesc
->u
.Memory
.Length
;
1469 CmDesc
->u
.Memory
.Start
.QuadPart
= Start
;
1471 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1473 Start
+= ConflictingDesc
.u
.Memory
.Start
.QuadPart
+ ConflictingDesc
.u
.Memory
.Length
;
1485 IopFindPortResource(
1486 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1487 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1490 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1492 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1493 ASSERT(IoDesc
->Type
== CmResourceTypePort
);
1495 for (Start
= IoDesc
->u
.Port
.MinimumAddress
.QuadPart
;
1496 Start
< IoDesc
->u
.Port
.MaximumAddress
.QuadPart
;
1499 CmDesc
->u
.Port
.Length
= IoDesc
->u
.Port
.Length
;
1500 CmDesc
->u
.Port
.Start
.QuadPart
= Start
;
1502 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1504 Start
+= ConflictingDesc
.u
.Port
.Start
.QuadPart
+ ConflictingDesc
.u
.Port
.Length
;
1517 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1518 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1522 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1523 ASSERT(IoDesc
->Type
== CmResourceTypeDma
);
1525 for (Channel
= IoDesc
->u
.Dma
.MinimumChannel
;
1526 Channel
< IoDesc
->u
.Dma
.MaximumChannel
;
1529 CmDesc
->u
.Dma
.Channel
= Channel
;
1530 CmDesc
->u
.Dma
.Port
= 0;
1532 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
1540 IopFindInterruptResource(
1541 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1542 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1546 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1547 ASSERT(IoDesc
->Type
== CmResourceTypeInterrupt
);
1549 for (Vector
= IoDesc
->u
.Interrupt
.MinimumVector
;
1550 Vector
< IoDesc
->u
.Interrupt
.MaximumVector
;
1553 CmDesc
->u
.Interrupt
.Vector
= Vector
;
1554 CmDesc
->u
.Interrupt
.Level
= Vector
;
1555 CmDesc
->u
.Interrupt
.Affinity
= (KAFFINITY
)-1;
1557 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
1565 IopCreateResourceListFromRequirements(
1566 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
,
1567 OUT PCM_RESOURCE_LIST
*ResourceList
)
1570 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
;
1572 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1573 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
1575 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
1576 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1577 + ResList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1580 *ResourceList
= ExAllocatePool(PagedPool
, Size
);
1582 return STATUS_INSUFFICIENT_RESOURCES
;
1584 (*ResourceList
)->Count
= 1;
1585 (*ResourceList
)->List
[0].BusNumber
= RequirementsList
->BusNumber
;
1586 (*ResourceList
)->List
[0].InterfaceType
= RequirementsList
->InterfaceType
;
1587 (*ResourceList
)->List
[0].PartialResourceList
.Version
= 1;
1588 (*ResourceList
)->List
[0].PartialResourceList
.Revision
= 1;
1589 (*ResourceList
)->List
[0].PartialResourceList
.Count
= 0;
1591 ResDesc
= &(*ResourceList
)->List
[0].PartialResourceList
.PartialDescriptors
[0];
1593 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
1595 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
1596 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1598 PIO_RESOURCE_DESCRIPTOR ReqDesc
= &ResList
->Descriptors
[ii
];
1600 /* FIXME: Handle alternate ranges */
1601 if (ReqDesc
->Option
== IO_RESOURCE_ALTERNATIVE
)
1604 ResDesc
->Type
= ReqDesc
->Type
;
1605 ResDesc
->Flags
= ReqDesc
->Flags
;
1606 ResDesc
->ShareDisposition
= ReqDesc
->ShareDisposition
;
1608 switch (ReqDesc
->Type
)
1610 case CmResourceTypeInterrupt
:
1611 if (!IopFindInterruptResource(ReqDesc
, ResDesc
))
1613 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
1614 ReqDesc
->u
.Interrupt
.MinimumVector
, ReqDesc
->u
.Interrupt
.MaximumVector
);
1616 if (ReqDesc
->Option
== 0)
1618 ExFreePool(*ResourceList
);
1619 return STATUS_CONFLICTING_ADDRESSES
;
1624 case CmResourceTypePort
:
1625 if (!IopFindPortResource(ReqDesc
, ResDesc
))
1627 DPRINT1("Failed to find an available port resource (0x%x to 0x%x length: 0x%x)\n",
1628 ReqDesc
->u
.Port
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Port
.MaximumAddress
.QuadPart
,
1629 ReqDesc
->u
.Port
.Length
);
1631 if (ReqDesc
->Option
== 0)
1633 ExFreePool(*ResourceList
);
1634 return STATUS_CONFLICTING_ADDRESSES
;
1639 case CmResourceTypeMemory
:
1640 if (!IopFindMemoryResource(ReqDesc
, ResDesc
))
1642 DPRINT1("Failed to find an available memory resource (0x%x to 0x%x length: 0x%x)\n",
1643 ReqDesc
->u
.Memory
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
1644 ReqDesc
->u
.Memory
.Length
);
1646 if (ReqDesc
->Option
== 0)
1648 ExFreePool(*ResourceList
);
1649 return STATUS_CONFLICTING_ADDRESSES
;
1654 case CmResourceTypeBusNumber
:
1655 if (!IopFindBusNumberResource(ReqDesc
, ResDesc
))
1657 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
1658 ReqDesc
->u
.BusNumber
.MinBusNumber
, ReqDesc
->u
.BusNumber
.MaxBusNumber
,
1659 ReqDesc
->u
.BusNumber
.Length
);
1661 if (ReqDesc
->Option
== 0)
1663 ExFreePool(*ResourceList
);
1664 return STATUS_CONFLICTING_ADDRESSES
;
1669 case CmResourceTypeDma
:
1670 if (!IopFindDmaResource(ReqDesc
, ResDesc
))
1672 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
1673 ReqDesc
->u
.Dma
.MinimumChannel
, ReqDesc
->u
.Dma
.MaximumChannel
);
1675 if (ReqDesc
->Option
== 0)
1677 ExFreePool(*ResourceList
);
1678 return STATUS_CONFLICTING_ADDRESSES
;
1684 DPRINT1("Unsupported resource type: %x\n", ReqDesc
->Type
);
1688 (*ResourceList
)->List
[0].PartialResourceList
.Count
++;
1693 return STATUS_SUCCESS
;
1697 IopAssignDeviceResources(
1698 IN PDEVICE_NODE DeviceNode
,
1699 OUT ULONG
*pRequiredSize
)
1701 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1707 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1709 /* No resource needed for this device */
1710 DeviceNode
->ResourceList
= NULL
;
1712 return STATUS_SUCCESS
;
1715 /* Fill DeviceNode->ResourceList
1716 * FIXME: the PnP arbiter should go there!
1717 * Actually, use the BootResources if provided, else the resource requirements
1720 if (DeviceNode
->BootResources
)
1722 /* Browse the boot resources to know if we have some custom structures */
1723 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1724 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1726 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1727 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1728 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1729 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1731 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1732 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1736 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1737 if (!DeviceNode
->ResourceList
)
1739 Status
= STATUS_NO_MEMORY
;
1742 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1744 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
1745 if (NT_SUCCESS(Status
) || !DeviceNode
->ResourceRequirements
)
1747 if (!NT_SUCCESS(Status
) && !DeviceNode
->ResourceRequirements
)
1749 DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
1752 *pRequiredSize
= Size
;
1753 return STATUS_SUCCESS
;
1757 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
1758 ExFreePool(DeviceNode
->ResourceList
);
1762 Status
= IopCreateResourceListFromRequirements(DeviceNode
->ResourceRequirements
,
1763 &DeviceNode
->ResourceList
);
1764 if (!NT_SUCCESS(Status
))
1767 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1768 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1770 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1771 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1772 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1775 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
1776 if (!NT_SUCCESS(Status
))
1779 *pRequiredSize
= Size
;
1780 return STATUS_SUCCESS
;
1783 if (DeviceNode
->ResourceList
)
1785 ExFreePool(DeviceNode
->ResourceList
);
1786 DeviceNode
->ResourceList
= NULL
;
1794 IopTranslateDeviceResources(
1795 IN PDEVICE_NODE DeviceNode
,
1796 IN ULONG RequiredSize
)
1798 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1799 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1803 if (!DeviceNode
->ResourceList
)
1805 DeviceNode
->ResourceListTranslated
= NULL
;
1806 return STATUS_SUCCESS
;
1809 /* That's easy to translate a resource list. Just copy the
1810 * untranslated one and change few fields in the copy
1812 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1813 if (!DeviceNode
->ResourceListTranslated
)
1815 Status
=STATUS_NO_MEMORY
;
1818 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1820 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1822 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1823 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1825 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1826 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1827 switch (DescriptorRaw
->Type
)
1829 case CmResourceTypePort
:
1831 ULONG AddressSpace
= 1; /* IO space */
1832 if (!HalTranslateBusAddress(
1833 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1834 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1835 DescriptorRaw
->u
.Port
.Start
,
1837 &DescriptorTranslated
->u
.Port
.Start
))
1839 Status
= STATUS_UNSUCCESSFUL
;
1844 case CmResourceTypeInterrupt
:
1846 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1847 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1848 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1849 DescriptorRaw
->u
.Interrupt
.Level
,
1850 DescriptorRaw
->u
.Interrupt
.Vector
,
1851 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1852 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1855 case CmResourceTypeMemory
:
1857 ULONG AddressSpace
= 0; /* Memory space */
1858 if (!HalTranslateBusAddress(
1859 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1860 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1861 DescriptorRaw
->u
.Memory
.Start
,
1863 &DescriptorTranslated
->u
.Memory
.Start
))
1865 Status
= STATUS_UNSUCCESSFUL
;
1870 case CmResourceTypeDma
:
1871 case CmResourceTypeBusNumber
:
1872 case CmResourceTypeDeviceSpecific
:
1876 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1877 Status
= STATUS_NOT_IMPLEMENTED
;
1882 return STATUS_SUCCESS
;
1885 /* Yes! Also delete ResourceList because ResourceList and
1886 * ResourceListTranslated should be a pair! */
1887 ExFreePool(DeviceNode
->ResourceList
);
1888 DeviceNode
->ResourceList
= NULL
;
1889 if (DeviceNode
->ResourceListTranslated
)
1891 ExFreePool(DeviceNode
->ResourceListTranslated
);
1892 DeviceNode
->ResourceList
= NULL
;
1899 * IopGetParentIdPrefix
1901 * Retrieve (or create) a string which identifies a device.
1905 * Pointer to device node.
1907 * Pointer to the string where is returned the parent node identifier
1910 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1911 * valid and its Buffer field is NULL-terminated. The caller needs to
1912 * to free the string with RtlFreeUnicodeString when it is no longer
1917 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1918 PUNICODE_STRING ParentIdPrefix
)
1920 ULONG KeyNameBufferLength
;
1921 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1922 UNICODE_STRING KeyName
;
1923 UNICODE_STRING KeyValue
;
1924 UNICODE_STRING ValueName
;
1929 /* HACK: As long as some devices have a NULL device
1930 * instance path, the following test is required :(
1932 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1934 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1935 &DeviceNode
->InstancePath
);
1936 return STATUS_UNSUCCESSFUL
;
1939 /* 1. Try to retrieve ParentIdPrefix from registry */
1940 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1941 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1942 if (!ParentIdPrefixInformation
)
1944 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1949 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1950 if (!KeyName
.Buffer
)
1952 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1956 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1958 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1959 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1961 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1962 if (!NT_SUCCESS(Status
))
1964 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1965 Status
= ZwQueryValueKey(
1967 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1968 KeyNameBufferLength
, &KeyNameBufferLength
);
1969 if (NT_SUCCESS(Status
))
1971 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1972 Status
= STATUS_UNSUCCESSFUL
;
1975 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1976 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1980 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1982 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1983 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1987 /* 2. Create the ParentIdPrefix value */
1988 crc32
= RtlComputeCrc32(0,
1989 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1990 DeviceNode
->Parent
->InstancePath
.Length
);
1992 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1993 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1995 /* 3. Try to write the ParentIdPrefix to registry */
1996 Status
= ZwSetValueKey(hKey
,
2000 (PVOID
)KeyValue
.Buffer
,
2001 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
2004 if (NT_SUCCESS(Status
))
2006 /* Duplicate the string to return it */
2007 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
2009 ExFreePool(ParentIdPrefixInformation
);
2010 RtlFreeUnicodeString(&KeyName
);
2018 * IopActionInterrogateDeviceStack
2020 * Retrieve information for all (direct) child nodes of a parent node.
2024 * Pointer to device node.
2026 * Pointer to parent node to retrieve child node information for.
2029 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2030 * when we reach a device node which is not a direct child of the device
2031 * node for which we retrieve information of child nodes for. Any errors
2032 * that occur is logged instead so that all child services have a chance
2033 * of being interrogated.
2037 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
2040 IO_STATUS_BLOCK IoStatusBlock
;
2041 PDEVICE_NODE ParentDeviceNode
;
2042 WCHAR InstancePath
[MAX_PATH
];
2043 IO_STACK_LOCATION Stack
;
2048 ULONG RequiredLength
;
2050 HANDLE InstanceKey
= NULL
;
2051 UNICODE_STRING ValueName
;
2052 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
2053 DEVICE_CAPABILITIES DeviceCapabilities
;
2055 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
2056 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
2058 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2061 * We are called for the parent too, but we don't need to do special
2062 * handling for this node
2065 if (DeviceNode
== ParentDeviceNode
)
2067 DPRINT("Success\n");
2068 return STATUS_SUCCESS
;
2072 * Make sure this device node is a direct child of the parent device node
2073 * that is given as an argument
2076 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2078 /* Stop the traversal immediately and indicate successful operation */
2080 return STATUS_UNSUCCESSFUL
;
2084 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
2085 if (!NT_SUCCESS(Status
))
2087 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
2092 * FIXME: For critical errors, cleanup and disable device, but always
2093 * return STATUS_SUCCESS.
2096 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
2098 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
2099 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2103 if (NT_SUCCESS(Status
))
2105 /* Copy the device id string */
2106 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
2109 * FIXME: Check for valid characters, if there is invalid characters
2115 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2118 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
2120 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
2121 if (!NT_SUCCESS(Status
))
2123 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
2126 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
2128 if (!DeviceCapabilities
.UniqueID
)
2130 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
2131 DPRINT("Instance ID is not unique\n");
2132 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
2133 if (!NT_SUCCESS(Status
))
2135 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
2139 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
2141 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
2142 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2146 if (NT_SUCCESS(Status
))
2148 /* Append the instance id string */
2149 wcscat(InstancePath
, L
"\\");
2150 if (ParentIdPrefix
.Length
> 0)
2152 /* Add information from parent bus device to InstancePath */
2153 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
2154 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
2155 wcscat(InstancePath
, L
"&");
2157 if (IoStatusBlock
.Information
)
2158 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
2161 * FIXME: Check for valid characters, if there is invalid characters
2167 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2169 RtlFreeUnicodeString(&ParentIdPrefix
);
2171 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
2173 DPRINT("No resources\n");
2174 /* FIXME: Cleanup and disable device */
2177 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
2180 * Create registry key for the instance id, if it doesn't exist yet
2182 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceKey
);
2183 if (!NT_SUCCESS(Status
))
2185 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2189 /* Set 'Capabilities' value */
2190 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
2191 Status
= ZwSetValueKey(InstanceKey
,
2195 (PVOID
)&DeviceNode
->CapabilityFlags
,
2198 /* Set 'UINumber' value */
2199 if (DeviceCapabilities
.UINumber
!= MAXULONG
)
2201 RtlInitUnicodeString(&ValueName
, L
"UINumber");
2202 Status
= ZwSetValueKey(InstanceKey
,
2206 &DeviceCapabilities
.UINumber
,
2211 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
2213 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
2214 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2218 if (NT_SUCCESS(Status
))
2221 * FIXME: Check for valid characters, if there is invalid characters
2225 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
2226 DPRINT("Hardware IDs:\n");
2229 DPRINT(" %S\n", Ptr
);
2230 Length
= wcslen(Ptr
) + 1;
2233 TotalLength
+= Length
;
2235 DPRINT("TotalLength: %hu\n", TotalLength
);
2238 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
2239 Status
= ZwSetValueKey(InstanceKey
,
2243 (PVOID
)IoStatusBlock
.Information
,
2244 (TotalLength
+ 1) * sizeof(WCHAR
));
2245 if (!NT_SUCCESS(Status
))
2247 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2252 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2255 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
2257 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
2258 Status
= IopInitiatePnpIrp(
2259 DeviceNode
->PhysicalDeviceObject
,
2263 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2266 * FIXME: Check for valid characters, if there is invalid characters
2270 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
2271 DPRINT("Compatible IDs:\n");
2274 DPRINT(" %S\n", Ptr
);
2275 Length
= wcslen(Ptr
) + 1;
2278 TotalLength
+= Length
;
2280 DPRINT("TotalLength: %hu\n", TotalLength
);
2283 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
2284 Status
= ZwSetValueKey(InstanceKey
,
2288 (PVOID
)IoStatusBlock
.Information
,
2289 (TotalLength
+ 1) * sizeof(WCHAR
));
2290 if (!NT_SUCCESS(Status
))
2292 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
2297 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2300 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2302 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2303 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2304 Status
= IopInitiatePnpIrp(
2305 DeviceNode
->PhysicalDeviceObject
,
2307 IRP_MN_QUERY_DEVICE_TEXT
,
2309 /* This key is mandatory, so even if the Irp fails, we still write it */
2310 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2311 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2313 if (NT_SUCCESS(Status
) &&
2314 IoStatusBlock
.Information
&&
2315 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2317 /* This key is overriden when a driver is installed. Don't write the
2318 * new description if another one already exists */
2319 Status
= ZwSetValueKey(InstanceKey
,
2323 (PVOID
)IoStatusBlock
.Information
,
2324 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2328 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2329 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2331 Status
= ZwSetValueKey(InstanceKey
,
2336 DeviceDesc
.MaximumLength
);
2338 if (!NT_SUCCESS(Status
))
2340 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2346 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2348 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2349 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2350 Status
= IopInitiatePnpIrp(
2351 DeviceNode
->PhysicalDeviceObject
,
2353 IRP_MN_QUERY_DEVICE_TEXT
,
2355 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2357 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2358 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2359 Status
= ZwSetValueKey(InstanceKey
,
2363 (PVOID
)IoStatusBlock
.Information
,
2364 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2365 if (!NT_SUCCESS(Status
))
2367 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2372 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2375 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2377 Status
= IopInitiatePnpIrp(
2378 DeviceNode
->PhysicalDeviceObject
,
2380 IRP_MN_QUERY_BUS_INFORMATION
,
2382 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2384 PPNP_BUS_INFORMATION BusInformation
=
2385 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2387 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2388 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2389 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2390 ExFreePool(BusInformation
);
2394 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2396 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2397 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2398 DeviceNode
->ChildBusTypeIndex
= -1;
2401 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2403 Status
= IopInitiatePnpIrp(
2404 DeviceNode
->PhysicalDeviceObject
,
2406 IRP_MN_QUERY_RESOURCES
,
2408 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2410 DeviceNode
->BootResources
=
2411 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2412 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2416 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2417 DeviceNode
->BootResources
= NULL
;
2420 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2422 Status
= IopInitiatePnpIrp(
2423 DeviceNode
->PhysicalDeviceObject
,
2425 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2427 if (NT_SUCCESS(Status
))
2429 DeviceNode
->ResourceRequirements
=
2430 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2431 if (IoStatusBlock
.Information
)
2432 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2434 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2438 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2439 DeviceNode
->ResourceRequirements
= NULL
;
2443 if (InstanceKey
!= NULL
)
2445 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2448 ZwClose(InstanceKey
);
2450 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
2452 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
2454 /* Report the device to the user-mode pnp manager */
2455 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
2456 &DeviceNode
->InstancePath
);
2459 return STATUS_SUCCESS
;
2465 IN PDEVICE_OBJECT DeviceObject
)
2467 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2468 DEVICETREE_TRAVERSE_CONTEXT Context
;
2469 PDEVICE_RELATIONS DeviceRelations
;
2470 PDEVICE_OBJECT ChildDeviceObject
;
2471 IO_STATUS_BLOCK IoStatusBlock
;
2472 PDEVICE_NODE ChildDeviceNode
;
2473 IO_STACK_LOCATION Stack
;
2477 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2479 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
2481 /* Report the device to the user-mode pnp manager */
2482 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2483 &DeviceNode
->InstancePath
);
2485 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2487 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
2489 Status
= IopInitiatePnpIrp(
2492 IRP_MN_QUERY_DEVICE_RELATIONS
,
2494 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
2496 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2500 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2502 if (!DeviceRelations
)
2504 DPRINT("No PDOs\n");
2505 return STATUS_UNSUCCESSFUL
;
2508 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
2511 * Create device nodes for all discovered devices
2513 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2515 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
2516 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
2518 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
2519 if (!ChildDeviceNode
)
2521 /* One doesn't exist, create it */
2522 Status
= IopCreateDeviceNode(
2527 if (NT_SUCCESS(Status
))
2529 /* Mark the node as enumerated */
2530 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2532 /* Mark the DO as bus enumerated */
2533 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2537 /* Ignore this DO */
2538 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
2539 ObDereferenceObject(ChildDeviceNode
);
2544 /* Mark it as enumerated */
2545 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2546 ObDereferenceObject(ChildDeviceObject
);
2549 ExFreePool(DeviceRelations
);
2552 * Retrieve information about all discovered children from the bus driver
2554 IopInitDeviceTreeTraverseContext(
2557 IopActionInterrogateDeviceStack
,
2560 Status
= IopTraverseDeviceTree(&Context
);
2561 if (!NT_SUCCESS(Status
))
2563 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2568 * Retrieve configuration from the registry for discovered children
2570 IopInitDeviceTreeTraverseContext(
2573 IopActionConfigureChildServices
,
2576 Status
= IopTraverseDeviceTree(&Context
);
2577 if (!NT_SUCCESS(Status
))
2579 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2584 * Initialize services for discovered children.
2586 Status
= IopInitializePnpServices(DeviceNode
);
2587 if (!NT_SUCCESS(Status
))
2589 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2593 DPRINT("IopEnumerateDevice() finished\n");
2594 return STATUS_SUCCESS
;
2599 * IopActionConfigureChildServices
2601 * Retrieve configuration for all (direct) child nodes of a parent node.
2605 * Pointer to device node.
2607 * Pointer to parent node to retrieve child node configuration for.
2610 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2611 * when we reach a device node which is not a direct child of the device
2612 * node for which we configure child services for. Any errors that occur is
2613 * logged instead so that all child services have a chance of beeing
2618 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2621 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2622 PDEVICE_NODE ParentDeviceNode
;
2623 PUNICODE_STRING Service
;
2624 UNICODE_STRING ClassGUID
;
2626 DEVICE_CAPABILITIES DeviceCaps
;
2628 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2630 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2633 * We are called for the parent too, but we don't need to do special
2634 * handling for this node
2636 if (DeviceNode
== ParentDeviceNode
)
2638 DPRINT("Success\n");
2639 return STATUS_SUCCESS
;
2643 * Make sure this device node is a direct child of the parent device node
2644 * that is given as an argument
2646 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2648 /* Stop the traversal immediately and indicate successful operation */
2650 return STATUS_UNSUCCESSFUL
;
2653 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2655 WCHAR RegKeyBuffer
[MAX_PATH
];
2656 UNICODE_STRING RegKey
;
2659 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2660 RegKey
.Buffer
= RegKeyBuffer
;
2663 * Retrieve configuration from Enum key
2666 Service
= &DeviceNode
->ServiceName
;
2668 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2669 RtlInitUnicodeString(Service
, NULL
);
2670 RtlInitUnicodeString(&ClassGUID
, NULL
);
2672 QueryTable
[0].Name
= L
"Service";
2673 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2674 QueryTable
[0].EntryContext
= Service
;
2676 QueryTable
[1].Name
= L
"ClassGUID";
2677 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2678 QueryTable
[1].EntryContext
= &ClassGUID
;
2679 QueryTable
[1].DefaultType
= REG_SZ
;
2680 QueryTable
[1].DefaultData
= L
"";
2681 QueryTable
[1].DefaultLength
= 0;
2683 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2684 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2686 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2687 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2689 if (!NT_SUCCESS(Status
))
2691 /* FIXME: Log the error */
2692 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2693 &DeviceNode
->InstancePath
, Status
);
2694 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2695 return STATUS_SUCCESS
;
2698 if (Service
->Buffer
== NULL
)
2700 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
2701 DeviceCaps
.RawDeviceOK
)
2703 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
2705 DeviceNode
->ServiceName
.Length
= 0;
2706 DeviceNode
->ServiceName
.MaximumLength
= ParentDeviceNode
->ServiceName
.MaximumLength
;
2707 DeviceNode
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, DeviceNode
->ServiceName
.MaximumLength
);
2708 if (!DeviceNode
->ServiceName
.Buffer
)
2709 return STATUS_SUCCESS
;
2711 RtlCopyUnicodeString(&DeviceNode
->ServiceName
, &ParentDeviceNode
->ServiceName
);
2713 IopDeviceNodeSetFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
2715 else if (ClassGUID
.Length
!= 0)
2717 /* Device has a ClassGUID value, but no Service value.
2718 * Suppose it is using the NULL driver, so state the
2719 * device is started */
2720 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2721 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2725 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2727 return STATUS_SUCCESS
;
2730 DPRINT("Got Service %S\n", Service
->Buffer
);
2733 return STATUS_SUCCESS
;
2737 * IopActionInitChildServices
2739 * Initialize the service for all (direct) child nodes of a parent node
2743 * Pointer to device node.
2745 * Pointer to parent node to initialize child node services for.
2748 * If the driver image for a service is not loaded and initialized
2749 * it is done here too. We only return a status code indicating an
2750 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2751 * not a direct child of the device node for which we initialize
2752 * child services for. Any errors that occur is logged instead so
2753 * that all child services have a chance of being initialized.
2757 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2760 PDEVICE_NODE ParentDeviceNode
;
2762 BOOLEAN BootDrivers
= !PnpSystemInit
;
2764 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2766 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2769 * We are called for the parent too, but we don't need to do special
2770 * handling for this node
2772 if (DeviceNode
== ParentDeviceNode
)
2774 DPRINT("Success\n");
2775 return STATUS_SUCCESS
;
2779 * Make sure this device node is a direct child of the parent device node
2780 * that is given as an argument
2783 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2786 * Stop the traversal immediately and indicate unsuccessful operation
2789 return STATUS_UNSUCCESSFUL
;
2793 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2794 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2795 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2797 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2798 PDRIVER_OBJECT DriverObject
;
2800 /* Get existing DriverObject pointer (in case the driver has
2801 already been loaded and initialized) */
2802 Status
= IopGetDriverObject(
2804 &DeviceNode
->ServiceName
,
2807 if (!NT_SUCCESS(Status
))
2809 /* Driver is not initialized, try to load it */
2810 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2812 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2814 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2815 was loaded by the bootloader */
2816 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2817 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2819 /* Initialize the driver */
2820 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2821 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2825 Status
= STATUS_SUCCESS
;
2830 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2831 &DeviceNode
->ServiceName
, Status
);
2835 /* Driver is loaded and initialized at this point */
2836 if (NT_SUCCESS(Status
))
2838 /* Attach lower level filter drivers. */
2839 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2840 /* Initialize the function driver for the device node */
2841 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2843 if (NT_SUCCESS(Status
))
2845 /* Attach upper level filter drivers. */
2846 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2847 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2849 Status
= IopStartDevice(DeviceNode
);
2853 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2854 &DeviceNode
->InstancePath
, Status
);
2860 * Don't disable when trying to load only boot drivers
2864 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2865 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2866 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2867 DPRINT1("Initialization of service %S failed (Status %x)\n",
2868 DeviceNode
->ServiceName
.Buffer
, Status
);
2874 DPRINT("Device %wZ is disabled or already initialized\n",
2875 &DeviceNode
->InstancePath
);
2878 return STATUS_SUCCESS
;
2882 * IopInitializePnpServices
2884 * Initialize services for discovered children
2888 * Top device node to start initializing services.
2894 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2896 DEVICETREE_TRAVERSE_CONTEXT Context
;
2898 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2900 IopInitDeviceTreeTraverseContext(
2903 IopActionInitChildServices
,
2906 return IopTraverseDeviceTree(&Context
);
2909 static NTSTATUS INIT_FUNCTION
2910 IopEnumerateDetectedDevices(
2912 IN PUNICODE_STRING RelativePath OPTIONAL
,
2914 IN BOOLEAN EnumerateSubKeys
,
2915 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2916 IN ULONG ParentBootResourcesLength
)
2918 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2919 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2920 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2921 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2922 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2923 OBJECT_ATTRIBUTES ObjectAttributes
;
2924 HANDLE hDevicesKey
= NULL
;
2925 HANDLE hDeviceKey
= NULL
;
2926 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2927 UNICODE_STRING Level2NameU
;
2928 WCHAR Level2Name
[5];
2929 ULONG IndexDevice
= 0;
2931 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2932 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2933 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2934 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2935 UNICODE_STRING DeviceName
, ValueName
;
2937 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2938 ULONG BootResourcesLength
;
2941 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2942 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2943 static ULONG DeviceIndexPci
= 0;
2944 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2945 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2946 static ULONG DeviceIndexSerial
= 0;
2947 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2948 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2949 static ULONG DeviceIndexKeyboard
= 0;
2950 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2951 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2952 static ULONG DeviceIndexMouse
= 0;
2953 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2954 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2955 static ULONG DeviceIndexParallel
= 0;
2956 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2957 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2958 static ULONG DeviceIndexFloppy
= 0;
2959 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2960 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2961 static ULONG DeviceIndexIsa
= 0;
2962 UNICODE_STRING HardwareIdKey
;
2963 PUNICODE_STRING pHardwareId
;
2964 ULONG DeviceIndex
= 0;
2965 PUCHAR CmResourceList
;
2970 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2971 if (!NT_SUCCESS(Status
))
2973 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2978 hDevicesKey
= hBaseKey
;
2980 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2981 if (!pDeviceInformation
)
2983 DPRINT("ExAllocatePool() failed\n");
2984 Status
= STATUS_NO_MEMORY
;
2988 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2989 if (!pValueInformation
)
2991 DPRINT("ExAllocatePool() failed\n");
2992 Status
= STATUS_NO_MEMORY
;
2998 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2999 if (Status
== STATUS_NO_MORE_ENTRIES
)
3001 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3003 ExFreePool(pDeviceInformation
);
3004 DeviceInfoLength
= RequiredSize
;
3005 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3006 if (!pDeviceInformation
)
3008 DPRINT("ExAllocatePool() failed\n");
3009 Status
= STATUS_NO_MEMORY
;
3012 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3014 if (!NT_SUCCESS(Status
))
3016 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3021 /* Open device key */
3022 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
3023 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3025 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
3026 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
3027 if (!NT_SUCCESS(Status
))
3029 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3033 /* Read boot resources, and add then to parent ones */
3034 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3035 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3037 ExFreePool(pValueInformation
);
3038 ValueInfoLength
= RequiredSize
;
3039 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3040 if (!pValueInformation
)
3042 DPRINT("ExAllocatePool() failed\n");
3043 ZwDeleteKey(hLevel2Key
);
3044 Status
= STATUS_NO_MEMORY
;
3047 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3049 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3051 BootResources
= ParentBootResources
;
3052 BootResourcesLength
= ParentBootResourcesLength
;
3054 else if (!NT_SUCCESS(Status
))
3056 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3059 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
3061 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
3066 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
3068 /* Concatenate current resources and parent ones */
3069 if (ParentBootResourcesLength
== 0)
3070 BootResourcesLength
= pValueInformation
->DataLength
;
3072 BootResourcesLength
= ParentBootResourcesLength
3073 + pValueInformation
->DataLength
3075 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
3078 DPRINT("ExAllocatePool() failed\n");
3081 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
3083 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
3085 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
3087 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
3089 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
3090 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
3091 ParentBootResourcesLength
- Header
);
3092 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
3096 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
3098 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
3099 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
3100 ParentBootResourcesLength
- Header
);
3102 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
3103 pValueInformation
->Data
+ Header
,
3104 pValueInformation
->DataLength
- Header
);
3105 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
3109 if (EnumerateSubKeys
)
3114 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3115 if (Status
== STATUS_NO_MORE_ENTRIES
)
3117 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3119 ExFreePool(pDeviceInformation
);
3120 DeviceInfoLength
= RequiredSize
;
3121 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3122 if (!pDeviceInformation
)
3124 DPRINT("ExAllocatePool() failed\n");
3125 Status
= STATUS_NO_MEMORY
;
3128 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3130 if (!NT_SUCCESS(Status
))
3132 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3136 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
3137 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3139 Status
= IopEnumerateDetectedDevices(
3145 BootResourcesLength
);
3146 if (!NT_SUCCESS(Status
))
3151 /* Read identifier */
3152 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3153 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3155 ExFreePool(pValueInformation
);
3156 ValueInfoLength
= RequiredSize
;
3157 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3158 if (!pValueInformation
)
3160 DPRINT("ExAllocatePool() failed\n");
3161 Status
= STATUS_NO_MEMORY
;
3164 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3166 if (!NT_SUCCESS(Status
))
3168 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
3170 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3173 ValueName
.Length
= ValueName
.MaximumLength
= 0;
3175 else if (pValueInformation
->Type
!= REG_SZ
)
3177 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3182 /* Assign hardware id to this device */
3183 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
3184 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3185 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3186 ValueName
.Length
-= sizeof(WCHAR
);
3189 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
3191 pHardwareId
= &HardwareIdSerial
;
3192 DeviceIndex
= DeviceIndexSerial
++;
3194 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
3196 pHardwareId
= &HardwareIdKeyboard
;
3197 DeviceIndex
= DeviceIndexKeyboard
++;
3199 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
3201 pHardwareId
= &HardwareIdMouse
;
3202 DeviceIndex
= DeviceIndexMouse
++;
3204 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
3206 pHardwareId
= &HardwareIdParallel
;
3207 DeviceIndex
= DeviceIndexParallel
++;
3209 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
3211 pHardwareId
= &HardwareIdFloppy
;
3212 DeviceIndex
= DeviceIndexFloppy
++;
3214 else if (NT_SUCCESS(Status
))
3216 /* Try to also match the device identifier */
3217 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
3219 pHardwareId
= &HardwareIdPci
;
3220 DeviceIndex
= DeviceIndexPci
++;
3222 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
3224 pHardwareId
= &HardwareIdIsa
;
3225 DeviceIndex
= DeviceIndexIsa
++;
3229 DPRINT("Unknown device '%wZ'\n", &ValueName
);
3235 /* Unknown key path */
3236 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
3240 /* Prepare hardware id key (hardware id value without final \0) */
3241 HardwareIdKey
= *pHardwareId
;
3242 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
3244 /* Add the detected device to Root key */
3245 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
3246 Status
= ZwCreateKey(
3252 REG_OPTION_NON_VOLATILE
,
3254 if (!NT_SUCCESS(Status
))
3256 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3259 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
3260 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
3261 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
3262 Status
= ZwCreateKey(
3264 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3268 REG_OPTION_NON_VOLATILE
,
3270 ZwClose(hLevel1Key
);
3271 if (!NT_SUCCESS(Status
))
3273 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3276 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
3277 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3278 if (!NT_SUCCESS(Status
))
3280 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3281 ZwDeleteKey(hLevel2Key
);
3284 /* Create 'LogConf' subkey */
3285 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3286 Status
= ZwCreateKey(
3292 REG_OPTION_VOLATILE
,
3294 if (!NT_SUCCESS(Status
))
3296 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3297 ZwDeleteKey(hLevel2Key
);
3300 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
3302 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
3303 if (!CmResourceList
)
3306 ZwDeleteKey(hLevel2Key
);
3310 /* Add the list count (1st member of CM_RESOURCE_LIST) */
3312 RtlCopyMemory(CmResourceList
,
3316 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
3317 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
3319 BootResourcesLength
);
3321 /* Save boot resources to 'LogConf\BootConfig' */
3322 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
3323 if (!NT_SUCCESS(Status
))
3325 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3327 ZwDeleteKey(hLevel2Key
);
3334 if (BootResources
&& BootResources
!= ParentBootResources
)
3336 ExFreePool(BootResources
);
3337 BootResources
= NULL
;
3341 ZwClose(hLevel2Key
);
3346 ZwClose(hDeviceKey
);
3351 Status
= STATUS_SUCCESS
;
3354 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
3355 ZwClose(hDevicesKey
);
3357 ZwClose(hDeviceKey
);
3358 if (pDeviceInformation
)
3359 ExFreePool(pDeviceInformation
);
3360 if (pValueInformation
)
3361 ExFreePool(pValueInformation
);
3365 static BOOLEAN INIT_FUNCTION
3366 IopIsAcpiComputer(VOID
)
3371 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3372 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3373 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3374 OBJECT_ATTRIBUTES ObjectAttributes
;
3375 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3376 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3377 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3378 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3380 ULONG IndexDevice
= 0;
3381 UNICODE_STRING DeviceName
, ValueName
;
3382 HANDLE hDevicesKey
= NULL
;
3383 HANDLE hDeviceKey
= NULL
;
3385 BOOLEAN ret
= FALSE
;
3387 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3388 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3389 if (!NT_SUCCESS(Status
))
3391 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3395 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3396 if (!pDeviceInformation
)
3398 DPRINT("ExAllocatePool() failed\n");
3399 Status
= STATUS_NO_MEMORY
;
3403 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3404 if (!pDeviceInformation
)
3406 DPRINT("ExAllocatePool() failed\n");
3407 Status
= STATUS_NO_MEMORY
;
3413 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3414 if (Status
== STATUS_NO_MORE_ENTRIES
)
3416 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3418 ExFreePool(pDeviceInformation
);
3419 DeviceInfoLength
= RequiredSize
;
3420 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3421 if (!pDeviceInformation
)
3423 DPRINT("ExAllocatePool() failed\n");
3424 Status
= STATUS_NO_MEMORY
;
3427 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3429 if (!NT_SUCCESS(Status
))
3431 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3436 /* Open device key */
3437 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3438 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3439 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3444 if (!NT_SUCCESS(Status
))
3446 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3450 /* Read identifier */
3451 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3452 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3454 ExFreePool(pValueInformation
);
3455 ValueInfoLength
= RequiredSize
;
3456 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3457 if (!pValueInformation
)
3459 DPRINT("ExAllocatePool() failed\n");
3460 Status
= STATUS_NO_MEMORY
;
3463 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3465 if (!NT_SUCCESS(Status
))
3467 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3470 else if (pValueInformation
->Type
!= REG_SZ
)
3472 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3476 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3477 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3478 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3479 ValueName
.Length
-= sizeof(WCHAR
);
3480 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3482 DPRINT("Found ACPI BIOS\n");
3488 ZwClose(hDeviceKey
);
3493 if (pDeviceInformation
)
3494 ExFreePool(pDeviceInformation
);
3495 if (pValueInformation
)
3496 ExFreePool(pValueInformation
);
3498 ZwClose(hDevicesKey
);
3500 ZwClose(hDeviceKey
);
3505 static NTSTATUS INIT_FUNCTION
3506 IopUpdateRootKey(VOID
)
3508 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
3509 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
3510 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3511 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3512 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3513 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
3514 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3515 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3516 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3517 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3518 OBJECT_ATTRIBUTES ObjectAttributes
;
3519 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
3522 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3523 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3524 if (!NT_SUCCESS(Status
))
3526 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3530 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
3531 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3533 if (!NT_SUCCESS(Status
))
3535 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3539 if (IopIsAcpiComputer())
3541 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
3542 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3544 if (!NT_SUCCESS(Status
))
3546 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
3547 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3548 ZwClose(hHalAcpiDevice
);
3549 if (!NT_SUCCESS(Status
))
3551 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3552 if (NT_SUCCESS(Status
))
3553 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3554 if (NT_SUCCESS(Status
))
3556 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
3557 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3558 if (NT_SUCCESS(Status
))
3561 ZwClose(hHalAcpiId
);
3566 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
3567 if (!NT_SUCCESS(Status
))
3569 /* Nothing to do, don't return with an error status */
3570 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3572 return STATUS_SUCCESS
;
3574 Status
= IopEnumerateDetectedDevices(
3589 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
3591 PUNICODE_STRING Name
,
3592 ACCESS_MASK DesiredAccess
)
3594 OBJECT_ATTRIBUTES ObjectAttributes
;
3601 InitializeObjectAttributes(&ObjectAttributes
,
3603 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3607 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
3614 IopGetRegistryValue(IN HANDLE Handle
,
3616 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
3618 UNICODE_STRING ValueString
;
3620 PKEY_VALUE_FULL_INFORMATION FullInformation
;
3624 RtlInitUnicodeString(&ValueString
, ValueName
);
3626 Status
= ZwQueryValueKey(Handle
,
3628 KeyValueFullInformation
,
3632 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
3633 (Status
!= STATUS_BUFFER_TOO_SMALL
))
3638 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
3639 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
3641 Status
= ZwQueryValueKey(Handle
,
3643 KeyValueFullInformation
,
3647 if (!NT_SUCCESS(Status
))
3649 ExFreePool(FullInformation
);
3653 *Information
= FullInformation
;
3654 return STATUS_SUCCESS
;
3657 static NTSTATUS INIT_FUNCTION
3659 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
3661 return STATUS_SUCCESS
;
3670 DPRINT("PnpInit()\n");
3672 KeInitializeSpinLock(&IopDeviceTreeLock
);
3673 ExInitializeFastMutex(&IopBusTypeGuidListLock
);
3675 /* Initialize the Bus Type GUID List */
3676 IopBusTypeGuidList
= ExAllocatePool(NonPagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3677 if (!IopBusTypeGuidList
) {
3678 DPRINT1("ExAllocatePool() failed\n");
3679 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3682 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3683 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3685 /* Initialize PnP-Event notification support */
3686 Status
= IopInitPlugPlayEvents();
3687 if (!NT_SUCCESS(Status
))
3689 DPRINT1("IopInitPlugPlayEvents() failed\n");
3690 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3694 * Create root device node
3697 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
3698 if (!NT_SUCCESS(Status
))
3700 DPRINT1("IoCreateDriverObject() failed\n");
3701 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3704 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3706 if (!NT_SUCCESS(Status
))
3708 DPRINT1("IoCreateDevice() failed\n");
3709 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3712 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
3713 if (!NT_SUCCESS(Status
))
3715 DPRINT1("Insufficient resources\n");
3716 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3719 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3722 DPRINT1("Failed to create the instance path!\n");
3723 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3726 /* Report the device to the user-mode pnp manager */
3727 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3728 &IopRootDeviceNode
->InstancePath
);
3730 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3731 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3732 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3733 IopRootDriverObject
->DriverExtension
->AddDevice(
3734 IopRootDriverObject
,
3735 IopRootDeviceNode
->PhysicalDeviceObject
);
3737 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3738 Status
= IopUpdateRootKey();
3739 if (!NT_SUCCESS(Status
))
3741 DPRINT1("IopUpdateRootKey() failed\n");
3742 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3746 RTL_GENERIC_COMPARE_RESULTS
3748 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3749 IN PVOID FirstStruct
,
3750 IN PVOID SecondStruct
)
3758 // The allocation function is called by the generic table package whenever
3759 // it needs to allocate memory for the table.
3764 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3774 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3783 PpInitializeDeviceReferenceTable(VOID
)
3785 /* Setup the guarded mutex and AVL table */
3786 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3787 RtlInitializeGenericTableAvl(
3788 &PpDeviceReferenceTable
,
3789 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3790 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3791 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3799 /* Initialize the resource when accessing device registry data */
3800 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3802 /* Setup the device reference AVL table */
3803 PpInitializeDeviceReferenceTable();
3811 /* Check the initialization phase */
3812 switch (ExpInitializationPhase
)
3817 return PiInitPhase0();
3823 //return PiInitPhase1();
3827 /* Don't know any other phase! Bugcheck! */
3828 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3833 /* PUBLIC FUNCTIONS **********************************************************/
3840 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3841 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3842 IN ULONG BufferLength
,
3843 OUT PVOID PropertyBuffer
,
3844 OUT PULONG ResultLength
)
3846 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3847 DEVICE_CAPABILITIES DeviceCaps
;
3852 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
3853 ULONG RequiredLength
, ObjectNameInfoLength
;
3855 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3859 if (DeviceNode
== NULL
)
3860 return STATUS_INVALID_DEVICE_REQUEST
;
3862 switch (DeviceProperty
)
3864 case DevicePropertyBusNumber
:
3865 Length
= sizeof(ULONG
);
3866 Data
= &DeviceNode
->ChildBusNumber
;
3869 /* Complete, untested */
3870 case DevicePropertyBusTypeGuid
:
3872 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
3873 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
3875 /* Return the GUID */
3876 *ResultLength
= sizeof(GUID
);
3878 /* Check if the buffer given was large enough */
3879 if (BufferLength
< *ResultLength
)
3881 return STATUS_BUFFER_TOO_SMALL
;
3885 RtlCopyMemory(PropertyBuffer
,
3886 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
3888 return STATUS_SUCCESS
;
3892 return STATUS_OBJECT_NAME_NOT_FOUND
;
3896 case DevicePropertyLegacyBusType
:
3897 Length
= sizeof(INTERFACE_TYPE
);
3898 Data
= &DeviceNode
->ChildInterfaceType
;
3901 case DevicePropertyAddress
:
3902 /* Query the device caps */
3903 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3904 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= MAXULONG
))
3907 *ResultLength
= sizeof(ULONG
);
3909 /* Check if the buffer given was large enough */
3910 if (BufferLength
< *ResultLength
)
3912 return STATUS_BUFFER_TOO_SMALL
;
3915 /* Return address */
3916 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
3917 return STATUS_SUCCESS
;
3921 return STATUS_OBJECT_NAME_NOT_FOUND
;
3925 // case DevicePropertyUINumber:
3926 // if (DeviceNode->CapabilityFlags == NULL)
3927 // return STATUS_INVALID_DEVICE_REQUEST;
3928 // Length = sizeof(ULONG);
3929 // Data = &DeviceNode->CapabilityFlags->UINumber;
3932 case DevicePropertyClassName
:
3933 case DevicePropertyClassGuid
:
3934 case DevicePropertyDriverKeyName
:
3935 case DevicePropertyManufacturer
:
3936 case DevicePropertyFriendlyName
:
3937 case DevicePropertyHardwareID
:
3938 case DevicePropertyCompatibleIDs
:
3939 case DevicePropertyDeviceDescription
:
3940 case DevicePropertyLocationInformation
:
3941 case DevicePropertyUINumber
:
3943 LPCWSTR RegistryPropertyName
;
3944 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
3945 UNICODE_STRING ValueName
;
3946 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
3947 ULONG ValueInformationLength
;
3948 HANDLE KeyHandle
, EnumRootHandle
;
3951 switch (DeviceProperty
)
3953 case DevicePropertyClassName
:
3954 RegistryPropertyName
= L
"Class"; break;
3955 case DevicePropertyClassGuid
:
3956 RegistryPropertyName
= L
"ClassGuid"; break;
3957 case DevicePropertyDriverKeyName
:
3958 RegistryPropertyName
= L
"Driver"; break;
3959 case DevicePropertyManufacturer
:
3960 RegistryPropertyName
= L
"Mfg"; break;
3961 case DevicePropertyFriendlyName
:
3962 RegistryPropertyName
= L
"FriendlyName"; break;
3963 case DevicePropertyHardwareID
:
3964 RegistryPropertyName
= L
"HardwareID"; break;
3965 case DevicePropertyCompatibleIDs
:
3966 RegistryPropertyName
= L
"CompatibleIDs"; break;
3967 case DevicePropertyDeviceDescription
:
3968 RegistryPropertyName
= L
"DeviceDesc"; break;
3969 case DevicePropertyLocationInformation
:
3970 RegistryPropertyName
= L
"LocationInformation"; break;
3971 case DevicePropertyUINumber
:
3972 RegistryPropertyName
= L
"UINumber"; break;
3974 /* Should not happen */
3976 return STATUS_UNSUCCESSFUL
;
3979 DPRINT("Registry property %S\n", RegistryPropertyName
);
3982 Status
= IopOpenRegistryKeyEx(&EnumRootHandle
, NULL
,
3983 &EnumRoot
, KEY_READ
);
3984 if (!NT_SUCCESS(Status
))
3986 DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status
);
3990 /* Open instance key */
3991 Status
= IopOpenRegistryKeyEx(&KeyHandle
, EnumRootHandle
,
3992 &DeviceNode
->InstancePath
, KEY_READ
);
3993 if (!NT_SUCCESS(Status
))
3995 DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status
);
3996 ZwClose(EnumRootHandle
);
4000 /* Allocate buffer to read as much data as required by the caller */
4001 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
4002 Data
[0]) + BufferLength
;
4003 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
4004 if (!ValueInformation
)
4007 return STATUS_INSUFFICIENT_RESOURCES
;
4010 /* Read the value */
4011 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
4012 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
4013 KeyValuePartialInformation
, ValueInformation
,
4014 ValueInformationLength
,
4015 &ValueInformationLength
);
4019 *ResultLength
= ValueInformation
->DataLength
;
4021 if (!NT_SUCCESS(Status
))
4023 ExFreePool(ValueInformation
);
4024 if (Status
== STATUS_BUFFER_OVERFLOW
)
4025 return STATUS_BUFFER_TOO_SMALL
;
4026 DPRINT1("Problem: Status=0x%08x, ResultLength = %d\n", Status
, *ResultLength
);
4030 /* FIXME: Verify the value (NULL-terminated, correct format). */
4031 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
4032 ValueInformation
->DataLength
);
4033 ExFreePool(ValueInformation
);
4035 return STATUS_SUCCESS
;
4038 case DevicePropertyBootConfiguration
:
4040 if (DeviceNode
->BootResources
->Count
!= 0)
4042 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
4044 Data
= DeviceNode
->BootResources
;
4047 /* FIXME: use a translated boot configuration instead */
4048 case DevicePropertyBootConfigurationTranslated
:
4050 if (DeviceNode
->BootResources
->Count
!= 0)
4052 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
4054 Data
= DeviceNode
->BootResources
;
4057 case DevicePropertyEnumeratorName
:
4058 /* A buffer overflow can't happen here, since InstancePath
4059 * always contains the enumerator name followed by \\ */
4060 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
4062 Length
= (Ptr
- DeviceNode
->InstancePath
.Buffer
) * sizeof(WCHAR
);
4063 Data
= DeviceNode
->InstancePath
.Buffer
;
4066 case DevicePropertyPhysicalDeviceObjectName
:
4067 Status
= ObQueryNameString(DeviceNode
->PhysicalDeviceObject
,
4071 if (Status
== STATUS_SUCCESS
)
4076 else if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
4078 ObjectNameInfoLength
= RequiredLength
;
4079 ObjectNameInfo
= ExAllocatePool(PagedPool
, ObjectNameInfoLength
);
4080 if (!ObjectNameInfo
)
4081 return STATUS_INSUFFICIENT_RESOURCES
;
4083 Status
= ObQueryNameString(DeviceNode
->PhysicalDeviceObject
,
4085 ObjectNameInfoLength
,
4087 if (NT_SUCCESS(Status
))
4089 Length
= ObjectNameInfo
->Name
.Length
;
4090 Data
= ObjectNameInfo
->Name
.Buffer
;
4100 return STATUS_INVALID_PARAMETER_2
;
4103 /* Prepare returned values */
4104 *ResultLength
= Length
;
4105 if (BufferLength
< Length
)
4107 if (ObjectNameInfo
!= NULL
)
4108 ExFreePool(ObjectNameInfo
);
4110 return STATUS_BUFFER_TOO_SMALL
;
4112 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
4114 /* NULL terminate the string (if required) */
4115 if (DeviceProperty
== DevicePropertyEnumeratorName
||
4116 DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
4117 ((LPWSTR
)PropertyBuffer
)[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
4119 if (ObjectNameInfo
!= NULL
)
4120 ExFreePool(ObjectNameInfo
);
4122 return STATUS_SUCCESS
;
4130 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4136 * @name IoOpenDeviceRegistryKey
4138 * Open a registry key unique for a specified driver or device instance.
4140 * @param DeviceObject Device to get the registry key for.
4141 * @param DevInstKeyType Type of the key to return.
4142 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
4143 * @param DevInstRegKey Handle to the opened registry key on
4144 * successful return.
4152 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
4153 IN ULONG DevInstKeyType
,
4154 IN ACCESS_MASK DesiredAccess
,
4155 OUT PHANDLE DevInstRegKey
)
4157 static WCHAR RootKeyName
[] =
4158 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
4159 static WCHAR ProfileKeyName
[] =
4160 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
4161 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
4162 static WCHAR EnumKeyName
[] = L
"Enum\\";
4163 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
4164 ULONG KeyNameLength
;
4165 LPWSTR KeyNameBuffer
;
4166 UNICODE_STRING KeyName
;
4167 ULONG DriverKeyLength
;
4168 OBJECT_ATTRIBUTES ObjectAttributes
;
4169 PDEVICE_NODE DeviceNode
= NULL
;
4172 DPRINT("IoOpenDeviceRegistryKey() called\n");
4174 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
4176 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
4177 return STATUS_INVALID_PARAMETER
;
4181 * Calculate the length of the base key name. This is the full
4182 * name for driver key or the name excluding "Device Parameters"
4183 * subkey for device key.
4186 KeyNameLength
= sizeof(RootKeyName
);
4187 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4188 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
4189 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4191 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
4192 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4193 0, NULL
, &DriverKeyLength
);
4194 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
4196 KeyNameLength
+= DriverKeyLength
;
4200 DeviceNode
= IopGetDeviceNode(DeviceObject
);
4201 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
4202 DeviceNode
->InstancePath
.Length
;
4206 * Now allocate the buffer for the key name...
4209 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
4210 if (KeyNameBuffer
== NULL
)
4211 return STATUS_INSUFFICIENT_RESOURCES
;
4214 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
4215 KeyName
.Buffer
= KeyNameBuffer
;
4218 * ...and build the key name.
4221 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
4222 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
4224 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4225 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
4227 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4229 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
4230 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4231 DriverKeyLength
, KeyNameBuffer
+
4232 (KeyName
.Length
/ sizeof(WCHAR
)),
4234 if (!NT_SUCCESS(Status
))
4236 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
4237 ExFreePool(KeyNameBuffer
);
4240 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
4244 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
4245 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
4246 if (DeviceNode
->InstancePath
.Length
== 0)
4248 ExFreePool(KeyNameBuffer
);
4254 * Open the base key.
4256 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
4257 if (!NT_SUCCESS(Status
))
4259 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
4260 ExFreePool(KeyNameBuffer
);
4263 ExFreePool(KeyNameBuffer
);
4266 * For driver key we're done now.
4269 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4273 * Let's go further. For device key we must open "Device Parameters"
4274 * subkey and create it if it doesn't exist yet.
4277 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
4278 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
4279 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
4280 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
4281 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
4282 ZwClose(ObjectAttributes
.RootDirectory
);
4292 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4302 IoInvalidateDeviceRelations(
4303 IN PDEVICE_OBJECT DeviceObject
,
4304 IN DEVICE_RELATION_TYPE Type
)
4306 PIO_WORKITEM WorkItem
;
4307 PINVALIDATE_DEVICE_RELATION_DATA Data
;
4309 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
4312 WorkItem
= IoAllocateWorkItem(DeviceObject
);
4319 ObReferenceObject(DeviceObject
);
4320 Data
->DeviceObject
= DeviceObject
;
4322 Data
->WorkItem
= WorkItem
;
4326 IopAsynchronousInvalidateDeviceRelations
,
4336 IoSynchronousInvalidateDeviceRelations(
4337 IN PDEVICE_OBJECT DeviceObject
,
4338 IN DEVICE_RELATION_TYPE Type
)
4345 /* Enumerate the device */
4346 return IopEnumerateDevice(DeviceObject
);
4347 case PowerRelations
:
4348 /* Not handled yet */
4349 return STATUS_NOT_IMPLEMENTED
;
4350 case TargetDeviceRelation
:
4352 return STATUS_SUCCESS
;
4354 /* Ejection relations are not supported */
4355 return STATUS_NOT_SUPPORTED
;
4364 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
4366 IN PHYSICAL_ADDRESS BusAddress
,
4367 IN OUT PULONG AddressSpace
,
4368 OUT PPHYSICAL_ADDRESS TranslatedAddress
)