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
) && DeviceNode
->ResourceList
)
251 RtlInitUnicodeString(&KeyName
, L
"AllocConfig");
252 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_RESOURCE_LIST
,
253 DeviceNode
->ResourceList
, CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceList
));
256 if (NT_SUCCESS(Status
))
257 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
259 ZwClose(ControlHandle
);
260 ZwClose(InstanceHandle
);
267 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
268 PDEVICE_CAPABILITIES DeviceCaps
)
270 IO_STATUS_BLOCK StatusBlock
;
271 IO_STACK_LOCATION Stack
;
273 /* Set up the Header */
274 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
275 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
276 DeviceCaps
->Version
= 1;
277 DeviceCaps
->Address
= -1;
278 DeviceCaps
->UINumber
= -1;
280 /* Set up the Stack */
281 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
282 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
285 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
287 IRP_MN_QUERY_CAPABILITIES
,
292 IopAsynchronousInvalidateDeviceRelations(
293 IN PDEVICE_OBJECT DeviceObject
,
294 IN PVOID InvalidateContext
)
296 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
298 IoSynchronousInvalidateDeviceRelations(
302 ObDereferenceObject(Data
->DeviceObject
);
303 IoFreeWorkItem(Data
->WorkItem
);
308 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
312 if (PopSystemPowerDeviceNode
)
314 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
315 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
316 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
318 return STATUS_SUCCESS
;
321 return STATUS_UNSUCCESSFUL
;
326 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
328 USHORT i
= 0, FoundIndex
= 0xFFFF;
332 /* Acquire the lock */
333 ExAcquireFastMutex(&IopBusTypeGuidListLock
);
335 /* Loop all entries */
336 while (i
< IopBusTypeGuidList
->GuidCount
)
338 /* Try to find a match */
339 if (RtlCompareMemory(BusTypeGuid
,
340 &IopBusTypeGuidList
->Guids
[i
],
341 sizeof(GUID
)) == sizeof(GUID
))
350 /* Check if we have to grow the list */
351 if (IopBusTypeGuidList
->GuidCount
)
353 /* Calculate the new size */
354 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
355 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
357 /* Allocate the new copy */
358 NewList
= ExAllocatePool(PagedPool
, NewSize
);
362 ExFreePool(IopBusTypeGuidList
);
366 /* Now copy them, decrease the size too */
367 NewSize
-= sizeof(GUID
);
368 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
370 /* Free the old list */
371 ExFreePool(IopBusTypeGuidList
);
373 /* Use the new buffer */
374 IopBusTypeGuidList
= NewList
;
377 /* Copy the new GUID */
378 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
382 /* The new entry is the index */
383 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
384 IopBusTypeGuidList
->GuidCount
++;
387 ExReleaseFastMutex(&IopBusTypeGuidListLock
);
393 * Creates a device node
396 * ParentNode = Pointer to parent device node
397 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
398 * to have the root device node create one
399 * (eg. for legacy drivers)
400 * DeviceNode = Pointer to storage for created device node
406 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
407 PDEVICE_OBJECT PhysicalDeviceObject
,
408 PUNICODE_STRING ServiceName
,
409 PDEVICE_NODE
*DeviceNode
)
414 UNICODE_STRING FullServiceName
;
415 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
416 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
417 UNICODE_STRING KeyName
, ClassName
, ClassGUID
;
418 PUNICODE_STRING ServiceName1
;
420 HANDLE InstanceHandle
;
422 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
423 ParentNode
, PhysicalDeviceObject
, ServiceName
);
425 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
428 return STATUS_INSUFFICIENT_RESOURCES
;
431 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
434 ServiceName1
= &UnknownDeviceName
;
436 ServiceName1
= ServiceName
;
438 if (!PhysicalDeviceObject
)
440 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
441 FullServiceName
.Length
= 0;
442 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
443 if (!FullServiceName
.Buffer
)
446 return STATUS_INSUFFICIENT_RESOURCES
;
449 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
450 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
452 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
453 if (!NT_SUCCESS(Status
))
455 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
460 /* Create the device key for legacy drivers */
461 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, &InstanceHandle
);
462 if (!NT_SUCCESS(Status
))
464 ZwClose(InstanceHandle
);
466 ExFreePool(FullServiceName
.Buffer
);
470 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
471 if (!Node
->ServiceName
.Buffer
)
473 ZwClose(InstanceHandle
);
475 ExFreePool(FullServiceName
.Buffer
);
479 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
480 Node
->ServiceName
.Length
= 0;
482 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
486 RtlInitUnicodeString(&KeyName
, L
"Service");
487 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
490 if (NT_SUCCESS(Status
))
492 RtlInitUnicodeString(&KeyName
, L
"Legacy");
495 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
496 if (NT_SUCCESS(Status
))
498 RtlInitUnicodeString(&KeyName
, L
"Class");
500 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
501 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
);
502 if (NT_SUCCESS(Status
))
504 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
506 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
507 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
);
512 ZwClose(InstanceHandle
);
513 ExFreePool(FullServiceName
.Buffer
);
515 if (!NT_SUCCESS(Status
))
521 /* This is for drivers passed on the command line to ntoskrnl.exe */
522 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
525 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
527 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
531 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
532 Node
->Parent
= ParentNode
;
533 Node
->Sibling
= ParentNode
->Child
;
534 ParentNode
->Child
= Node
;
535 if (ParentNode
->LastChild
== NULL
)
536 ParentNode
->LastChild
= Node
;
537 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
538 Node
->Level
= ParentNode
->Level
+ 1;
541 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
545 return STATUS_SUCCESS
;
549 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
552 PDEVICE_NODE PrevSibling
= NULL
;
554 /* All children must be deleted before a parent is deleted */
555 ASSERT(!DeviceNode
->Child
);
557 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
559 ASSERT(DeviceNode
->PhysicalDeviceObject
);
561 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
563 /* Get previous sibling */
564 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
566 PrevSibling
= DeviceNode
->Parent
->Child
;
567 while (PrevSibling
->Sibling
!= DeviceNode
)
568 PrevSibling
= PrevSibling
->Sibling
;
571 /* Unlink from parent if it exists */
572 if (DeviceNode
->Parent
)
574 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
576 DeviceNode
->Parent
->LastChild
= PrevSibling
;
578 PrevSibling
->Sibling
= NULL
;
580 if (DeviceNode
->Parent
->Child
== DeviceNode
)
581 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
584 /* Unlink from sibling list */
586 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
588 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
590 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
592 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
594 if (DeviceNode
->ResourceList
)
596 ExFreePool(DeviceNode
->ResourceList
);
599 if (DeviceNode
->ResourceListTranslated
)
601 ExFreePool(DeviceNode
->ResourceListTranslated
);
604 if (DeviceNode
->ResourceRequirements
)
606 ExFreePool(DeviceNode
->ResourceRequirements
);
609 if (DeviceNode
->BootResources
)
611 ExFreePool(DeviceNode
->BootResources
);
614 ExFreePool(DeviceNode
);
616 return STATUS_SUCCESS
;
620 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
621 PIO_STATUS_BLOCK IoStatusBlock
,
623 PIO_STACK_LOCATION Stack OPTIONAL
)
625 PDEVICE_OBJECT TopDeviceObject
;
626 PIO_STACK_LOCATION IrpSp
;
631 /* Always call the top of the device stack */
632 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
639 Irp
= IoBuildSynchronousFsdRequest(
648 /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */
649 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
650 Irp
->IoStatus
.Information
= 0;
652 if (MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
654 Irp
->IoStatus
.Information
= (ULONG_PTR
)Stack
->Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
657 IrpSp
= IoGetNextIrpStackLocation(Irp
);
658 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
662 RtlCopyMemory(&IrpSp
->Parameters
,
664 sizeof(Stack
->Parameters
));
667 Status
= IoCallDriver(TopDeviceObject
, Irp
);
668 if (Status
== STATUS_PENDING
)
670 KeWaitForSingleObject(&Event
,
675 Status
= IoStatusBlock
->Status
;
678 ObDereferenceObject(TopDeviceObject
);
685 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
687 PDEVICE_NODE ParentDeviceNode
;
688 PDEVICE_NODE ChildDeviceNode
;
691 /* Copy context data so we don't overwrite it in subsequent calls to this function */
692 ParentDeviceNode
= Context
->DeviceNode
;
694 /* Call the action routine */
695 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
696 if (!NT_SUCCESS(Status
))
701 /* Traversal of all children nodes */
702 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
703 ChildDeviceNode
!= NULL
;
704 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
706 /* Pass the current device node to the action routine */
707 Context
->DeviceNode
= ChildDeviceNode
;
709 Status
= IopTraverseDeviceTreeNode(Context
);
710 if (!NT_SUCCESS(Status
))
721 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
725 DPRINT("Context 0x%p\n", Context
);
727 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
728 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
730 /* Start from the specified device node */
731 Context
->DeviceNode
= Context
->FirstDeviceNode
;
733 /* Recursively traverse the device tree */
734 Status
= IopTraverseDeviceTreeNode(Context
);
735 if (Status
== STATUS_UNSUCCESSFUL
)
737 /* The action routine just wanted to terminate the traversal with status
738 code STATUS_SUCCESS */
739 Status
= STATUS_SUCCESS
;
747 * IopCreateDeviceKeyPath
749 * Creates a registry key
753 * Name of the key to be created.
755 * Handle to the newly created key
758 * This method can create nested trees, so parent of RegistryPath can
759 * be not existant, and will be created if needed.
763 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
766 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
767 HANDLE hParent
= NULL
, hKey
;
768 OBJECT_ATTRIBUTES ObjectAttributes
;
769 UNICODE_STRING KeyName
;
770 LPCWSTR Current
, Last
;
777 /* Open root key for device instances */
778 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
779 if (!NT_SUCCESS(Status
))
781 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
785 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
786 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
788 /* Go up to the end of the string */
789 while (Current
<= Last
)
791 if (Current
!= Last
&& *Current
!= '\\')
793 /* Not the end of the string and not a separator */
798 /* Prepare relative key name */
799 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
800 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
801 DPRINT("Create '%wZ'\n", &KeyName
);
804 InitializeObjectAttributes(&ObjectAttributes
,
806 OBJ_CASE_INSENSITIVE
,
809 Status
= ZwCreateKey(&hKey
,
810 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
817 /* Close parent key handle, we don't need it anymore */
821 /* Key opening/creating failed? */
822 if (!NT_SUCCESS(Status
))
824 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
828 /* Check if it is the end of the string */
831 /* Yes, return success */
833 return STATUS_SUCCESS
;
836 /* Start with this new parent key */
839 KeyName
.Buffer
= (LPWSTR
)Current
;
842 return STATUS_UNSUCCESSFUL
;
846 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode
, PWCHAR Level1Key
, PWCHAR Level2Key
)
850 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
851 UNICODE_STRING KeyName
;
852 OBJECT_ATTRIBUTES ObjectAttributes
;
854 RtlInitUnicodeString(&KeyName
,
855 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
856 InitializeObjectAttributes(&ObjectAttributes
,
858 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
861 Status
= ZwCreateKey(&ResourceMapKey
,
868 if (!NT_SUCCESS(Status
))
871 RtlInitUnicodeString(&KeyName
, Level1Key
);
872 InitializeObjectAttributes(&ObjectAttributes
,
874 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
877 Status
= ZwCreateKey(&PnpMgrLevel1
,
884 ZwClose(ResourceMapKey
);
885 if (!NT_SUCCESS(Status
))
888 RtlInitUnicodeString(&KeyName
, Level2Key
);
889 InitializeObjectAttributes(&ObjectAttributes
,
891 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
894 Status
= ZwCreateKey(&PnpMgrLevel2
,
901 ZwClose(PnpMgrLevel1
);
902 if (!NT_SUCCESS(Status
))
905 if (DeviceNode
->ResourceList
)
908 UNICODE_STRING NameU
;
909 UNICODE_STRING Suffix
;
912 ASSERT(DeviceNode
->ResourceListTranslated
);
914 NameU
.Buffer
= NameBuff
;
916 NameU
.MaximumLength
= 256 * sizeof(WCHAR
);
918 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
919 DevicePropertyPhysicalDeviceObjectName
,
923 ASSERT(Status
== STATUS_SUCCESS
);
925 NameU
.Length
= (USHORT
)OldLength
;
927 RtlInitUnicodeString(&Suffix
, L
".Raw");
928 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
930 Status
= ZwSetValueKey(PnpMgrLevel2
,
934 DeviceNode
->ResourceList
,
935 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceList
));
936 if (!NT_SUCCESS(Status
))
938 ZwClose(PnpMgrLevel2
);
942 /* "Remove" the suffix by setting the length back to what it used to be */
943 NameU
.Length
= (USHORT
)OldLength
;
945 RtlInitUnicodeString(&Suffix
, L
".Translated");
946 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
948 Status
= ZwSetValueKey(PnpMgrLevel2
,
952 DeviceNode
->ResourceListTranslated
,
953 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceListTranslated
));
954 ZwClose(PnpMgrLevel2
);
955 if (!NT_SUCCESS(Status
))
960 ZwClose(PnpMgrLevel2
);
963 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
965 return STATUS_SUCCESS
;
969 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode
)
971 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
975 IopSetDeviceInstanceData(HANDLE InstanceKey
,
976 PDEVICE_NODE DeviceNode
)
978 OBJECT_ATTRIBUTES ObjectAttributes
;
979 UNICODE_STRING KeyName
;
982 ULONG ListSize
, ResultLength
;
984 HANDLE ControlHandle
;
986 DPRINT("IopSetDeviceInstanceData() called\n");
988 /* Create the 'LogConf' key */
989 RtlInitUnicodeString(&KeyName
, L
"LogConf");
990 InitializeObjectAttributes(&ObjectAttributes
,
992 OBJ_CASE_INSENSITIVE
,
995 Status
= ZwCreateKey(&LogConfKey
,
1002 if (NT_SUCCESS(Status
))
1004 /* Set 'BootConfig' value */
1005 if (DeviceNode
->BootResources
!= NULL
)
1007 ResCount
= DeviceNode
->BootResources
->Count
;
1010 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1012 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1013 Status
= ZwSetValueKey(LogConfKey
,
1017 DeviceNode
->BootResources
,
1022 /* Set 'BasicConfigVector' value */
1023 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1024 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1026 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1027 Status
= ZwSetValueKey(LogConfKey
,
1030 REG_RESOURCE_REQUIREMENTS_LIST
,
1031 DeviceNode
->ResourceRequirements
,
1032 DeviceNode
->ResourceRequirements
->ListSize
);
1035 ZwClose(LogConfKey
);
1038 /* Set the 'ConfigFlags' value */
1039 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1040 Status
= ZwQueryValueKey(InstanceKey
,
1042 KeyValueBasicInformation
,
1046 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1048 /* Write the default value */
1049 ULONG DefaultConfigFlags
= 0;
1050 Status
= ZwSetValueKey(InstanceKey
,
1054 &DefaultConfigFlags
,
1055 sizeof(DefaultConfigFlags
));
1058 /* Create the 'Control' key */
1059 RtlInitUnicodeString(&KeyName
, L
"Control");
1060 InitializeObjectAttributes(&ObjectAttributes
,
1062 OBJ_CASE_INSENSITIVE
,
1065 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1067 if (NT_SUCCESS(Status
))
1068 ZwClose(ControlHandle
);
1070 DPRINT("IopSetDeviceInstanceData() done\n");
1076 IopCheckResourceDescriptor(
1077 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
1078 IN PCM_RESOURCE_LIST ResourceList
,
1080 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1083 BOOLEAN Result
= FALSE
;
1085 if (ResDesc
->ShareDisposition
== CmResourceShareShared
)
1088 for (i
= 0; i
< ResourceList
->Count
; i
++)
1090 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList
->List
[i
].PartialResourceList
;
1091 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1093 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
1095 /* We don't care about shared resources */
1096 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
1097 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
1100 /* Make sure we're comparing the same types */
1101 if (ResDesc
->Type
!= ResDesc2
->Type
)
1104 switch (ResDesc
->Type
)
1106 case CmResourceTypeMemory
:
1107 if ((ResDesc
->u
.Memory
.Start
.QuadPart
< ResDesc2
->u
.Memory
.Start
.QuadPart
&&
1108 ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
1109 ResDesc2
->u
.Memory
.Start
.QuadPart
) || (ResDesc2
->u
.Memory
.Start
.QuadPart
<
1110 ResDesc
->u
.Memory
.Start
.QuadPart
&& ResDesc2
->u
.Memory
.Start
.QuadPart
+
1111 ResDesc2
->u
.Memory
.Length
> ResDesc
->u
.Memory
.Start
.QuadPart
))
1115 DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1116 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
1117 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
1118 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
1127 case CmResourceTypePort
:
1128 if ((ResDesc
->u
.Port
.Start
.QuadPart
< ResDesc2
->u
.Port
.Start
.QuadPart
&&
1129 ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
1130 ResDesc2
->u
.Port
.Start
.QuadPart
) || (ResDesc2
->u
.Port
.Start
.QuadPart
<
1131 ResDesc
->u
.Port
.Start
.QuadPart
&& ResDesc2
->u
.Port
.Start
.QuadPart
+
1132 ResDesc2
->u
.Port
.Length
> ResDesc
->u
.Port
.Start
.QuadPart
))
1136 DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1137 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
1138 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
1139 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
1148 case CmResourceTypeInterrupt
:
1149 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
1153 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
1154 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
1155 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
1164 case CmResourceTypeBusNumber
:
1165 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
1166 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
1167 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
1168 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
1169 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
1173 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1174 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
1175 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
1176 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
1185 case CmResourceTypeDma
:
1186 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
1190 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
1191 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
1192 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
1206 if (Result
&& ConflictingDescriptor
)
1208 RtlCopyMemory(ConflictingDescriptor
,
1210 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1218 IopCheckForResourceConflict(
1219 IN PCM_RESOURCE_LIST ResourceList1
,
1220 IN PCM_RESOURCE_LIST ResourceList2
,
1222 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1225 BOOLEAN Result
= FALSE
;
1227 for (i
= 0; i
< ResourceList1
->Count
; i
++)
1229 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
1230 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1232 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
1234 Result
= IopCheckResourceDescriptor(ResDesc
,
1237 ConflictingDescriptor
);
1238 if (Result
) goto ByeBye
;
1249 IopDetectResourceConflict(
1250 IN PCM_RESOURCE_LIST ResourceList
,
1252 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1254 OBJECT_ATTRIBUTES ObjectAttributes
;
1255 UNICODE_STRING KeyName
;
1256 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
1257 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
1258 PKEY_BASIC_INFORMATION KeyInformation
;
1259 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
1260 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
1261 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
1264 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1265 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
1266 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1267 if (!NT_SUCCESS(Status
))
1269 /* The key is missing which means we are the first device */
1270 return STATUS_SUCCESS
;
1275 Status
= ZwEnumerateKey(ResourceMapKey
,
1277 KeyBasicInformation
,
1281 if (Status
== STATUS_NO_MORE_ENTRIES
)
1283 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1285 KeyInformationLength
= RequiredLength
;
1286 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1287 if (!KeyInformation
)
1289 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1293 Status
= ZwEnumerateKey(ResourceMapKey
,
1295 KeyBasicInformation
,
1297 KeyInformationLength
,
1303 if (!NT_SUCCESS(Status
))
1306 KeyName
.Buffer
= KeyInformation
->Name
;
1307 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1308 InitializeObjectAttributes(&ObjectAttributes
,
1310 OBJ_CASE_INSENSITIVE
,
1313 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1314 ExFreePool(KeyInformation
);
1315 if (!NT_SUCCESS(Status
))
1320 Status
= ZwEnumerateKey(ChildKey2
,
1322 KeyBasicInformation
,
1326 if (Status
== STATUS_NO_MORE_ENTRIES
)
1328 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1330 KeyInformationLength
= RequiredLength
;
1331 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1332 if (!KeyInformation
)
1334 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1338 Status
= ZwEnumerateKey(ChildKey2
,
1340 KeyBasicInformation
,
1342 KeyInformationLength
,
1348 if (!NT_SUCCESS(Status
))
1351 KeyName
.Buffer
= KeyInformation
->Name
;
1352 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1353 InitializeObjectAttributes(&ObjectAttributes
,
1355 OBJ_CASE_INSENSITIVE
,
1358 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1359 ExFreePool(KeyInformation
);
1360 if (!NT_SUCCESS(Status
))
1365 Status
= ZwEnumerateValueKey(ChildKey3
,
1367 KeyValuePartialInformation
,
1371 if (Status
== STATUS_NO_MORE_ENTRIES
)
1373 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1375 KeyValueInformationLength
= RequiredLength
;
1376 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1377 if (!KeyValueInformation
)
1379 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1383 Status
= ZwEnumerateValueKey(ChildKey3
,
1385 KeyValuePartialInformation
,
1386 KeyValueInformation
,
1387 KeyValueInformationLength
,
1392 if (!NT_SUCCESS(Status
))
1395 Status
= ZwEnumerateValueKey(ChildKey3
,
1397 KeyValueBasicInformation
,
1401 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1403 KeyNameInformationLength
= RequiredLength
;
1404 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1405 if (!KeyNameInformation
)
1407 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1411 Status
= ZwEnumerateValueKey(ChildKey3
,
1413 KeyValueBasicInformation
,
1415 KeyNameInformationLength
,
1423 if (!NT_SUCCESS(Status
))
1426 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1428 /* Skip translated entries */
1429 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1431 ExFreePool(KeyNameInformation
);
1435 ExFreePool(KeyNameInformation
);
1437 if (IopCheckForResourceConflict(ResourceList
,
1438 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1440 ConflictingDescriptor
))
1442 ExFreePool(KeyValueInformation
);
1443 Status
= STATUS_CONFLICTING_ADDRESSES
;
1447 ExFreePool(KeyValueInformation
);
1453 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1454 ZwClose(ResourceMapKey
);
1455 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1457 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1460 if (Status
== STATUS_NO_MORE_ENTRIES
)
1461 Status
= STATUS_SUCCESS
;
1467 IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1469 CM_RESOURCE_LIST CmList
;
1473 CmList
.List
[0].InterfaceType
= InterfaceTypeUndefined
;
1474 CmList
.List
[0].BusNumber
= 0;
1475 CmList
.List
[0].PartialResourceList
.Version
= 1;
1476 CmList
.List
[0].PartialResourceList
.Revision
= 1;
1477 CmList
.List
[0].PartialResourceList
.Count
= 1;
1478 CmList
.List
[0].PartialResourceList
.PartialDescriptors
[0] = *CmDesc
;
1480 Status
= IopDetectResourceConflict(&CmList
, TRUE
, ConflictingDescriptor
);
1481 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
1488 IopFindBusNumberResource(
1489 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1490 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1493 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1495 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1496 ASSERT(IoDesc
->Type
== CmResourceTypeBusNumber
);
1498 for (Start
= IoDesc
->u
.BusNumber
.MinBusNumber
;
1499 Start
< IoDesc
->u
.BusNumber
.MaxBusNumber
;
1502 CmDesc
->u
.BusNumber
.Length
= IoDesc
->u
.BusNumber
.Length
;
1503 CmDesc
->u
.BusNumber
.Start
= Start
;
1505 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1507 Start
+= ConflictingDesc
.u
.BusNumber
.Start
+ ConflictingDesc
.u
.BusNumber
.Length
;
1519 IopFindMemoryResource(
1520 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1521 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1524 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1526 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1527 ASSERT(IoDesc
->Type
== CmResourceTypeMemory
);
1529 for (Start
= IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
;
1530 Start
< IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
;
1533 CmDesc
->u
.Memory
.Length
= IoDesc
->u
.Memory
.Length
;
1534 CmDesc
->u
.Memory
.Start
.QuadPart
= Start
;
1536 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1538 Start
+= ConflictingDesc
.u
.Memory
.Start
.QuadPart
+ ConflictingDesc
.u
.Memory
.Length
;
1550 IopFindPortResource(
1551 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1552 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1555 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1557 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1558 ASSERT(IoDesc
->Type
== CmResourceTypePort
);
1560 for (Start
= IoDesc
->u
.Port
.MinimumAddress
.QuadPart
;
1561 Start
< IoDesc
->u
.Port
.MaximumAddress
.QuadPart
;
1564 CmDesc
->u
.Port
.Length
= IoDesc
->u
.Port
.Length
;
1565 CmDesc
->u
.Port
.Start
.QuadPart
= Start
;
1567 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1569 Start
+= ConflictingDesc
.u
.Port
.Start
.QuadPart
+ ConflictingDesc
.u
.Port
.Length
;
1582 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1583 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1587 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1588 ASSERT(IoDesc
->Type
== CmResourceTypeDma
);
1590 for (Channel
= IoDesc
->u
.Dma
.MinimumChannel
;
1591 Channel
< IoDesc
->u
.Dma
.MaximumChannel
;
1594 CmDesc
->u
.Dma
.Channel
= Channel
;
1595 CmDesc
->u
.Dma
.Port
= 0;
1597 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
1605 IopFindInterruptResource(
1606 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1607 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1611 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1612 ASSERT(IoDesc
->Type
== CmResourceTypeInterrupt
);
1614 for (Vector
= IoDesc
->u
.Interrupt
.MinimumVector
;
1615 Vector
< IoDesc
->u
.Interrupt
.MaximumVector
;
1618 CmDesc
->u
.Interrupt
.Vector
= Vector
;
1619 CmDesc
->u
.Interrupt
.Level
= Vector
;
1620 CmDesc
->u
.Interrupt
.Affinity
= (KAFFINITY
)-1;
1622 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
1630 IopCreateResourceListFromRequirements(
1631 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
,
1632 OUT PCM_RESOURCE_LIST
*ResourceList
)
1635 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
;
1637 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1638 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
1640 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
1641 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1642 + ResList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1645 *ResourceList
= ExAllocatePool(PagedPool
, Size
);
1647 return STATUS_INSUFFICIENT_RESOURCES
;
1649 (*ResourceList
)->Count
= 1;
1650 (*ResourceList
)->List
[0].BusNumber
= RequirementsList
->BusNumber
;
1651 (*ResourceList
)->List
[0].InterfaceType
= RequirementsList
->InterfaceType
;
1652 (*ResourceList
)->List
[0].PartialResourceList
.Version
= 1;
1653 (*ResourceList
)->List
[0].PartialResourceList
.Revision
= 1;
1654 (*ResourceList
)->List
[0].PartialResourceList
.Count
= 0;
1656 ResDesc
= &(*ResourceList
)->List
[0].PartialResourceList
.PartialDescriptors
[0];
1658 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
1660 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
1661 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1663 PIO_RESOURCE_DESCRIPTOR ReqDesc
= &ResList
->Descriptors
[ii
];
1665 /* FIXME: Handle alternate ranges */
1666 if (ReqDesc
->Option
== IO_RESOURCE_ALTERNATIVE
)
1669 ResDesc
->Type
= ReqDesc
->Type
;
1670 ResDesc
->Flags
= ReqDesc
->Flags
;
1671 ResDesc
->ShareDisposition
= ReqDesc
->ShareDisposition
;
1673 switch (ReqDesc
->Type
)
1675 case CmResourceTypeInterrupt
:
1676 if (!IopFindInterruptResource(ReqDesc
, ResDesc
))
1678 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
1679 ReqDesc
->u
.Interrupt
.MinimumVector
, ReqDesc
->u
.Interrupt
.MaximumVector
);
1681 if (ReqDesc
->Option
== 0)
1683 ExFreePool(*ResourceList
);
1684 return STATUS_CONFLICTING_ADDRESSES
;
1689 case CmResourceTypePort
:
1690 if (!IopFindPortResource(ReqDesc
, ResDesc
))
1692 DPRINT1("Failed to find an available port resource (0x%x to 0x%x length: 0x%x)\n",
1693 ReqDesc
->u
.Port
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Port
.MaximumAddress
.QuadPart
,
1694 ReqDesc
->u
.Port
.Length
);
1696 if (ReqDesc
->Option
== 0)
1698 ExFreePool(*ResourceList
);
1699 return STATUS_CONFLICTING_ADDRESSES
;
1704 case CmResourceTypeMemory
:
1705 if (!IopFindMemoryResource(ReqDesc
, ResDesc
))
1707 DPRINT1("Failed to find an available memory resource (0x%x to 0x%x length: 0x%x)\n",
1708 ReqDesc
->u
.Memory
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
1709 ReqDesc
->u
.Memory
.Length
);
1711 if (ReqDesc
->Option
== 0)
1713 ExFreePool(*ResourceList
);
1714 return STATUS_CONFLICTING_ADDRESSES
;
1719 case CmResourceTypeBusNumber
:
1720 if (!IopFindBusNumberResource(ReqDesc
, ResDesc
))
1722 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
1723 ReqDesc
->u
.BusNumber
.MinBusNumber
, ReqDesc
->u
.BusNumber
.MaxBusNumber
,
1724 ReqDesc
->u
.BusNumber
.Length
);
1726 if (ReqDesc
->Option
== 0)
1728 ExFreePool(*ResourceList
);
1729 return STATUS_CONFLICTING_ADDRESSES
;
1734 case CmResourceTypeDma
:
1735 if (!IopFindDmaResource(ReqDesc
, ResDesc
))
1737 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
1738 ReqDesc
->u
.Dma
.MinimumChannel
, ReqDesc
->u
.Dma
.MaximumChannel
);
1740 if (ReqDesc
->Option
== 0)
1742 ExFreePool(*ResourceList
);
1743 return STATUS_CONFLICTING_ADDRESSES
;
1749 DPRINT1("Unsupported resource type: %x\n", ReqDesc
->Type
);
1753 (*ResourceList
)->List
[0].PartialResourceList
.Count
++;
1758 return STATUS_SUCCESS
;
1762 IopAssignDeviceResources(
1763 IN PDEVICE_NODE DeviceNode
,
1764 OUT ULONG
*pRequiredSize
)
1766 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1772 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1774 /* No resource needed for this device */
1775 DeviceNode
->ResourceList
= NULL
;
1777 return STATUS_SUCCESS
;
1780 /* Fill DeviceNode->ResourceList
1781 * FIXME: the PnP arbiter should go there!
1782 * Actually, use the BootResources if provided, else the resource requirements
1785 if (DeviceNode
->BootResources
)
1787 /* Browse the boot resources to know if we have some custom structures */
1788 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1789 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1791 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1792 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1793 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1794 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1796 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1797 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1801 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1802 if (!DeviceNode
->ResourceList
)
1804 Status
= STATUS_NO_MEMORY
;
1807 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1809 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
1810 if (NT_SUCCESS(Status
) || !DeviceNode
->ResourceRequirements
)
1812 if (!NT_SUCCESS(Status
) && !DeviceNode
->ResourceRequirements
)
1814 DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
1817 *pRequiredSize
= Size
;
1818 return STATUS_SUCCESS
;
1822 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
1823 ExFreePool(DeviceNode
->ResourceList
);
1827 Status
= IopCreateResourceListFromRequirements(DeviceNode
->ResourceRequirements
,
1828 &DeviceNode
->ResourceList
);
1829 if (!NT_SUCCESS(Status
))
1832 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1833 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1835 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1836 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1837 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1840 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
1841 if (!NT_SUCCESS(Status
))
1844 *pRequiredSize
= Size
;
1845 return STATUS_SUCCESS
;
1848 if (DeviceNode
->ResourceList
)
1850 ExFreePool(DeviceNode
->ResourceList
);
1851 DeviceNode
->ResourceList
= NULL
;
1859 IopTranslateDeviceResources(
1860 IN PDEVICE_NODE DeviceNode
,
1861 IN ULONG RequiredSize
)
1863 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1864 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1868 if (!DeviceNode
->ResourceList
)
1870 DeviceNode
->ResourceListTranslated
= NULL
;
1871 return STATUS_SUCCESS
;
1874 /* That's easy to translate a resource list. Just copy the
1875 * untranslated one and change few fields in the copy
1877 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1878 if (!DeviceNode
->ResourceListTranslated
)
1880 Status
=STATUS_NO_MEMORY
;
1883 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1885 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1887 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1888 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1890 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1891 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1892 switch (DescriptorRaw
->Type
)
1894 case CmResourceTypePort
:
1896 ULONG AddressSpace
= 1; /* IO space */
1897 if (!HalTranslateBusAddress(
1898 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1899 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1900 DescriptorRaw
->u
.Port
.Start
,
1902 &DescriptorTranslated
->u
.Port
.Start
))
1904 Status
= STATUS_UNSUCCESSFUL
;
1909 case CmResourceTypeInterrupt
:
1911 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1912 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1913 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1914 DescriptorRaw
->u
.Interrupt
.Level
,
1915 DescriptorRaw
->u
.Interrupt
.Vector
,
1916 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1917 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1920 case CmResourceTypeMemory
:
1922 ULONG AddressSpace
= 0; /* Memory space */
1923 if (!HalTranslateBusAddress(
1924 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1925 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1926 DescriptorRaw
->u
.Memory
.Start
,
1928 &DescriptorTranslated
->u
.Memory
.Start
))
1930 Status
= STATUS_UNSUCCESSFUL
;
1935 case CmResourceTypeDma
:
1936 case CmResourceTypeBusNumber
:
1937 case CmResourceTypeDeviceSpecific
:
1941 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1942 Status
= STATUS_NOT_IMPLEMENTED
;
1947 return STATUS_SUCCESS
;
1950 /* Yes! Also delete ResourceList because ResourceList and
1951 * ResourceListTranslated should be a pair! */
1952 ExFreePool(DeviceNode
->ResourceList
);
1953 DeviceNode
->ResourceList
= NULL
;
1954 if (DeviceNode
->ResourceListTranslated
)
1956 ExFreePool(DeviceNode
->ResourceListTranslated
);
1957 DeviceNode
->ResourceList
= NULL
;
1964 * IopGetParentIdPrefix
1966 * Retrieve (or create) a string which identifies a device.
1970 * Pointer to device node.
1972 * Pointer to the string where is returned the parent node identifier
1975 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1976 * valid and its Buffer field is NULL-terminated. The caller needs to
1977 * to free the string with RtlFreeUnicodeString when it is no longer
1982 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1983 PUNICODE_STRING ParentIdPrefix
)
1985 ULONG KeyNameBufferLength
;
1986 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1987 UNICODE_STRING KeyName
;
1988 UNICODE_STRING KeyValue
;
1989 UNICODE_STRING ValueName
;
1994 /* HACK: As long as some devices have a NULL device
1995 * instance path, the following test is required :(
1997 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1999 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
2000 &DeviceNode
->InstancePath
);
2001 return STATUS_UNSUCCESSFUL
;
2004 /* 1. Try to retrieve ParentIdPrefix from registry */
2005 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
2006 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
2007 if (!ParentIdPrefixInformation
)
2009 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2014 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
2015 if (!KeyName
.Buffer
)
2017 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2021 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
2023 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2024 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
2026 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
2027 if (!NT_SUCCESS(Status
))
2029 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
2030 Status
= ZwQueryValueKey(
2032 KeyValuePartialInformation
, ParentIdPrefixInformation
,
2033 KeyNameBufferLength
, &KeyNameBufferLength
);
2034 if (NT_SUCCESS(Status
))
2036 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
2037 Status
= STATUS_UNSUCCESSFUL
;
2040 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
2041 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
2045 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2047 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
2048 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
2052 /* 2. Create the ParentIdPrefix value */
2053 crc32
= RtlComputeCrc32(0,
2054 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
2055 DeviceNode
->Parent
->InstancePath
.Length
);
2057 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
2058 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
2060 /* 3. Try to write the ParentIdPrefix to registry */
2061 Status
= ZwSetValueKey(hKey
,
2065 (PVOID
)KeyValue
.Buffer
,
2066 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
2069 if (NT_SUCCESS(Status
))
2071 /* Duplicate the string to return it */
2072 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
2074 ExFreePool(ParentIdPrefixInformation
);
2075 RtlFreeUnicodeString(&KeyName
);
2083 * IopActionInterrogateDeviceStack
2085 * Retrieve information for all (direct) child nodes of a parent node.
2089 * Pointer to device node.
2091 * Pointer to parent node to retrieve child node information for.
2094 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2095 * when we reach a device node which is not a direct child of the device
2096 * node for which we retrieve information of child nodes for. Any errors
2097 * that occur is logged instead so that all child services have a chance
2098 * of being interrogated.
2102 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
2105 IO_STATUS_BLOCK IoStatusBlock
;
2106 PDEVICE_NODE ParentDeviceNode
;
2107 WCHAR InstancePath
[MAX_PATH
];
2108 IO_STACK_LOCATION Stack
;
2113 ULONG RequiredLength
;
2115 HANDLE InstanceKey
= NULL
;
2116 UNICODE_STRING ValueName
;
2117 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
2118 DEVICE_CAPABILITIES DeviceCapabilities
;
2120 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
2121 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
2123 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2126 * We are called for the parent too, but we don't need to do special
2127 * handling for this node
2130 if (DeviceNode
== ParentDeviceNode
)
2132 DPRINT("Success\n");
2133 return STATUS_SUCCESS
;
2137 * Make sure this device node is a direct child of the parent device node
2138 * that is given as an argument
2141 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2143 /* Stop the traversal immediately and indicate successful operation */
2145 return STATUS_UNSUCCESSFUL
;
2149 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
2150 if (!NT_SUCCESS(Status
))
2152 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
2157 * FIXME: For critical errors, cleanup and disable device, but always
2158 * return STATUS_SUCCESS.
2161 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
2163 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
2164 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2168 if (NT_SUCCESS(Status
))
2170 /* Copy the device id string */
2171 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
2174 * FIXME: Check for valid characters, if there is invalid characters
2180 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2183 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
2185 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
2186 if (!NT_SUCCESS(Status
))
2188 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
2191 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
2193 if (!DeviceCapabilities
.UniqueID
)
2195 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
2196 DPRINT("Instance ID is not unique\n");
2197 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
2198 if (!NT_SUCCESS(Status
))
2200 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
2204 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
2206 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
2207 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2211 if (NT_SUCCESS(Status
))
2213 /* Append the instance id string */
2214 wcscat(InstancePath
, L
"\\");
2215 if (ParentIdPrefix
.Length
> 0)
2217 /* Add information from parent bus device to InstancePath */
2218 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
2219 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
2220 wcscat(InstancePath
, L
"&");
2222 if (IoStatusBlock
.Information
)
2223 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
2226 * FIXME: Check for valid characters, if there is invalid characters
2232 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2234 RtlFreeUnicodeString(&ParentIdPrefix
);
2236 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
2238 DPRINT("No resources\n");
2239 /* FIXME: Cleanup and disable device */
2242 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
2245 * Create registry key for the instance id, if it doesn't exist yet
2247 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceKey
);
2248 if (!NT_SUCCESS(Status
))
2250 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2254 /* Set 'Capabilities' value */
2255 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
2256 Status
= ZwSetValueKey(InstanceKey
,
2260 (PVOID
)&DeviceNode
->CapabilityFlags
,
2263 /* Set 'UINumber' value */
2264 if (DeviceCapabilities
.UINumber
!= MAXULONG
)
2266 RtlInitUnicodeString(&ValueName
, L
"UINumber");
2267 Status
= ZwSetValueKey(InstanceKey
,
2271 &DeviceCapabilities
.UINumber
,
2276 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
2278 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
2279 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2283 if (NT_SUCCESS(Status
))
2286 * FIXME: Check for valid characters, if there is invalid characters
2290 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
2291 DPRINT("Hardware IDs:\n");
2294 DPRINT(" %S\n", Ptr
);
2295 Length
= wcslen(Ptr
) + 1;
2298 TotalLength
+= Length
;
2300 DPRINT("TotalLength: %hu\n", TotalLength
);
2303 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
2304 Status
= ZwSetValueKey(InstanceKey
,
2308 (PVOID
)IoStatusBlock
.Information
,
2309 (TotalLength
+ 1) * sizeof(WCHAR
));
2310 if (!NT_SUCCESS(Status
))
2312 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2317 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2320 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
2322 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
2323 Status
= IopInitiatePnpIrp(
2324 DeviceNode
->PhysicalDeviceObject
,
2328 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2331 * FIXME: Check for valid characters, if there is invalid characters
2335 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
2336 DPRINT("Compatible IDs:\n");
2339 DPRINT(" %S\n", Ptr
);
2340 Length
= wcslen(Ptr
) + 1;
2343 TotalLength
+= Length
;
2345 DPRINT("TotalLength: %hu\n", TotalLength
);
2348 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
2349 Status
= ZwSetValueKey(InstanceKey
,
2353 (PVOID
)IoStatusBlock
.Information
,
2354 (TotalLength
+ 1) * sizeof(WCHAR
));
2355 if (!NT_SUCCESS(Status
))
2357 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
2362 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2365 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2367 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2368 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2369 Status
= IopInitiatePnpIrp(
2370 DeviceNode
->PhysicalDeviceObject
,
2372 IRP_MN_QUERY_DEVICE_TEXT
,
2374 /* This key is mandatory, so even if the Irp fails, we still write it */
2375 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2376 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2378 if (NT_SUCCESS(Status
) &&
2379 IoStatusBlock
.Information
&&
2380 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2382 /* This key is overriden when a driver is installed. Don't write the
2383 * new description if another one already exists */
2384 Status
= ZwSetValueKey(InstanceKey
,
2388 (PVOID
)IoStatusBlock
.Information
,
2389 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2393 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2394 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2396 Status
= ZwSetValueKey(InstanceKey
,
2401 DeviceDesc
.MaximumLength
);
2403 if (!NT_SUCCESS(Status
))
2405 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2411 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2413 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2414 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2415 Status
= IopInitiatePnpIrp(
2416 DeviceNode
->PhysicalDeviceObject
,
2418 IRP_MN_QUERY_DEVICE_TEXT
,
2420 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2422 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2423 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2424 Status
= ZwSetValueKey(InstanceKey
,
2428 (PVOID
)IoStatusBlock
.Information
,
2429 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2430 if (!NT_SUCCESS(Status
))
2432 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2437 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2440 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2442 Status
= IopInitiatePnpIrp(
2443 DeviceNode
->PhysicalDeviceObject
,
2445 IRP_MN_QUERY_BUS_INFORMATION
,
2447 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2449 PPNP_BUS_INFORMATION BusInformation
=
2450 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2452 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2453 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2454 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2455 ExFreePool(BusInformation
);
2459 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2461 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2462 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2463 DeviceNode
->ChildBusTypeIndex
= -1;
2466 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2468 Status
= IopInitiatePnpIrp(
2469 DeviceNode
->PhysicalDeviceObject
,
2471 IRP_MN_QUERY_RESOURCES
,
2473 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2475 DeviceNode
->BootResources
=
2476 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2477 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2481 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2482 DeviceNode
->BootResources
= NULL
;
2485 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2487 Status
= IopInitiatePnpIrp(
2488 DeviceNode
->PhysicalDeviceObject
,
2490 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2492 if (NT_SUCCESS(Status
))
2494 DeviceNode
->ResourceRequirements
=
2495 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2496 if (IoStatusBlock
.Information
)
2497 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2499 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2503 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2504 DeviceNode
->ResourceRequirements
= NULL
;
2508 if (InstanceKey
!= NULL
)
2510 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2513 ZwClose(InstanceKey
);
2515 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
2517 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
2519 /* Report the device to the user-mode pnp manager */
2520 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
2521 &DeviceNode
->InstancePath
);
2524 return STATUS_SUCCESS
;
2530 IN PDEVICE_OBJECT DeviceObject
)
2532 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2533 DEVICETREE_TRAVERSE_CONTEXT Context
;
2534 PDEVICE_RELATIONS DeviceRelations
;
2535 PDEVICE_OBJECT ChildDeviceObject
;
2536 IO_STATUS_BLOCK IoStatusBlock
;
2537 PDEVICE_NODE ChildDeviceNode
;
2538 IO_STACK_LOCATION Stack
;
2542 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2544 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
2546 /* Report the device to the user-mode pnp manager */
2547 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2548 &DeviceNode
->InstancePath
);
2550 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2552 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
2554 Status
= IopInitiatePnpIrp(
2557 IRP_MN_QUERY_DEVICE_RELATIONS
,
2559 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
2561 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2565 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2567 if (!DeviceRelations
)
2569 DPRINT("No PDOs\n");
2570 return STATUS_UNSUCCESSFUL
;
2573 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
2576 * Create device nodes for all discovered devices
2578 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2580 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
2581 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
2583 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
2584 if (!ChildDeviceNode
)
2586 /* One doesn't exist, create it */
2587 Status
= IopCreateDeviceNode(
2592 if (NT_SUCCESS(Status
))
2594 /* Mark the node as enumerated */
2595 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2597 /* Mark the DO as bus enumerated */
2598 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2602 /* Ignore this DO */
2603 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
2604 ObDereferenceObject(ChildDeviceNode
);
2609 /* Mark it as enumerated */
2610 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2611 ObDereferenceObject(ChildDeviceObject
);
2614 ExFreePool(DeviceRelations
);
2617 * Retrieve information about all discovered children from the bus driver
2619 IopInitDeviceTreeTraverseContext(
2622 IopActionInterrogateDeviceStack
,
2625 Status
= IopTraverseDeviceTree(&Context
);
2626 if (!NT_SUCCESS(Status
))
2628 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2633 * Retrieve configuration from the registry for discovered children
2635 IopInitDeviceTreeTraverseContext(
2638 IopActionConfigureChildServices
,
2641 Status
= IopTraverseDeviceTree(&Context
);
2642 if (!NT_SUCCESS(Status
))
2644 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2649 * Initialize services for discovered children.
2651 Status
= IopInitializePnpServices(DeviceNode
);
2652 if (!NT_SUCCESS(Status
))
2654 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2658 DPRINT("IopEnumerateDevice() finished\n");
2659 return STATUS_SUCCESS
;
2664 * IopActionConfigureChildServices
2666 * Retrieve configuration for all (direct) child nodes of a parent node.
2670 * Pointer to device node.
2672 * Pointer to parent node to retrieve child node configuration for.
2675 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2676 * when we reach a device node which is not a direct child of the device
2677 * node for which we configure child services for. Any errors that occur is
2678 * logged instead so that all child services have a chance of beeing
2683 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2686 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2687 PDEVICE_NODE ParentDeviceNode
;
2688 PUNICODE_STRING Service
;
2689 UNICODE_STRING ClassGUID
;
2691 DEVICE_CAPABILITIES DeviceCaps
;
2693 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2695 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2698 * We are called for the parent too, but we don't need to do special
2699 * handling for this node
2701 if (DeviceNode
== ParentDeviceNode
)
2703 DPRINT("Success\n");
2704 return STATUS_SUCCESS
;
2708 * Make sure this device node is a direct child of the parent device node
2709 * that is given as an argument
2711 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2713 /* Stop the traversal immediately and indicate successful operation */
2715 return STATUS_UNSUCCESSFUL
;
2718 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2720 WCHAR RegKeyBuffer
[MAX_PATH
];
2721 UNICODE_STRING RegKey
;
2724 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2725 RegKey
.Buffer
= RegKeyBuffer
;
2728 * Retrieve configuration from Enum key
2731 Service
= &DeviceNode
->ServiceName
;
2733 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2734 RtlInitUnicodeString(Service
, NULL
);
2735 RtlInitUnicodeString(&ClassGUID
, NULL
);
2737 QueryTable
[0].Name
= L
"Service";
2738 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2739 QueryTable
[0].EntryContext
= Service
;
2741 QueryTable
[1].Name
= L
"ClassGUID";
2742 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2743 QueryTable
[1].EntryContext
= &ClassGUID
;
2744 QueryTable
[1].DefaultType
= REG_SZ
;
2745 QueryTable
[1].DefaultData
= L
"";
2746 QueryTable
[1].DefaultLength
= 0;
2748 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2749 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2751 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2752 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2754 if (!NT_SUCCESS(Status
))
2756 /* FIXME: Log the error */
2757 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2758 &DeviceNode
->InstancePath
, Status
);
2759 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2760 return STATUS_SUCCESS
;
2763 if (Service
->Buffer
== NULL
)
2765 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
2766 DeviceCaps
.RawDeviceOK
)
2768 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
2770 DeviceNode
->ServiceName
.Length
= 0;
2771 DeviceNode
->ServiceName
.MaximumLength
= 0;
2772 DeviceNode
->ServiceName
.Buffer
= NULL
;
2774 else if (ClassGUID
.Length
!= 0)
2776 /* Device has a ClassGUID value, but no Service value.
2777 * Suppose it is using the NULL driver, so state the
2778 * device is started */
2779 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2780 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2784 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2786 return STATUS_SUCCESS
;
2789 DPRINT("Got Service %S\n", Service
->Buffer
);
2792 return STATUS_SUCCESS
;
2796 * IopActionInitChildServices
2798 * Initialize the service for all (direct) child nodes of a parent node
2802 * Pointer to device node.
2804 * Pointer to parent node to initialize child node services for.
2807 * If the driver image for a service is not loaded and initialized
2808 * it is done here too. We only return a status code indicating an
2809 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2810 * not a direct child of the device node for which we initialize
2811 * child services for. Any errors that occur is logged instead so
2812 * that all child services have a chance of being initialized.
2816 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2819 PDEVICE_NODE ParentDeviceNode
;
2821 BOOLEAN BootDrivers
= !PnpSystemInit
;
2823 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2825 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2828 * We are called for the parent too, but we don't need to do special
2829 * handling for this node
2831 if (DeviceNode
== ParentDeviceNode
)
2833 DPRINT("Success\n");
2834 return STATUS_SUCCESS
;
2838 * Make sure this device node is a direct child of the parent device node
2839 * that is given as an argument
2842 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2845 * Stop the traversal immediately and indicate unsuccessful operation
2848 return STATUS_UNSUCCESSFUL
;
2851 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
2852 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
2853 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2854 return STATUS_SUCCESS
;
2856 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
2858 /* We don't need to worry about loading the driver because we're
2859 * being driven in raw mode so our parent must be loaded to get here */
2860 Status
= IopStartDevice(DeviceNode
);
2861 if (!NT_SUCCESS(Status
))
2863 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
2864 &DeviceNode
->InstancePath
, Status
);
2869 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2870 PDRIVER_OBJECT DriverObject
;
2872 /* Get existing DriverObject pointer (in case the driver has
2873 already been loaded and initialized) */
2874 Status
= IopGetDriverObject(
2876 &DeviceNode
->ServiceName
,
2879 if (!NT_SUCCESS(Status
))
2881 /* Driver is not initialized, try to load it */
2882 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2884 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2886 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2887 was loaded by the bootloader */
2888 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2889 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2891 /* Initialize the driver */
2892 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2893 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2897 Status
= STATUS_SUCCESS
;
2902 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2903 &DeviceNode
->ServiceName
, Status
);
2907 /* Driver is loaded and initialized at this point */
2908 if (NT_SUCCESS(Status
))
2910 /* Attach lower level filter drivers. */
2911 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2913 /* Initialize the function driver for the device node */
2914 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2916 if (NT_SUCCESS(Status
))
2918 /* Attach upper level filter drivers. */
2919 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2921 Status
= IopStartDevice(DeviceNode
);
2922 if (!NT_SUCCESS(Status
))
2924 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
2925 &DeviceNode
->InstancePath
, Status
);
2930 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2931 &DeviceNode
->InstancePath
, Status
);
2937 * Don't disable when trying to load only boot drivers
2941 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2942 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2943 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2944 DPRINT1("Initialization of service %S failed (Status %x)\n",
2945 DeviceNode
->ServiceName
.Buffer
, Status
);
2950 return STATUS_SUCCESS
;
2954 * IopInitializePnpServices
2956 * Initialize services for discovered children
2960 * Top device node to start initializing services.
2966 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2968 DEVICETREE_TRAVERSE_CONTEXT Context
;
2970 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2972 IopInitDeviceTreeTraverseContext(
2975 IopActionInitChildServices
,
2978 return IopTraverseDeviceTree(&Context
);
2981 static NTSTATUS INIT_FUNCTION
2982 IopEnumerateDetectedDevices(
2984 IN PUNICODE_STRING RelativePath OPTIONAL
,
2986 IN BOOLEAN EnumerateSubKeys
,
2987 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2988 IN ULONG ParentBootResourcesLength
)
2990 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2991 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2992 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2993 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2994 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2995 OBJECT_ATTRIBUTES ObjectAttributes
;
2996 HANDLE hDevicesKey
= NULL
;
2997 HANDLE hDeviceKey
= NULL
;
2998 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2999 UNICODE_STRING Level2NameU
;
3000 WCHAR Level2Name
[5];
3001 ULONG IndexDevice
= 0;
3003 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3004 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3005 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3006 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3007 UNICODE_STRING DeviceName
, ValueName
;
3009 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
3010 ULONG BootResourcesLength
;
3013 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
3014 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
3015 static ULONG DeviceIndexPci
= 0;
3016 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
3017 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
3018 static ULONG DeviceIndexSerial
= 0;
3019 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
3020 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
3021 static ULONG DeviceIndexKeyboard
= 0;
3022 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
3023 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
3024 static ULONG DeviceIndexMouse
= 0;
3025 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
3026 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
3027 static ULONG DeviceIndexParallel
= 0;
3028 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
3029 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
3030 static ULONG DeviceIndexFloppy
= 0;
3031 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
3032 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
3033 static ULONG DeviceIndexIsa
= 0;
3034 UNICODE_STRING HardwareIdKey
;
3035 PUNICODE_STRING pHardwareId
;
3036 ULONG DeviceIndex
= 0;
3037 PUCHAR CmResourceList
;
3042 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
3043 if (!NT_SUCCESS(Status
))
3045 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3050 hDevicesKey
= hBaseKey
;
3052 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3053 if (!pDeviceInformation
)
3055 DPRINT("ExAllocatePool() failed\n");
3056 Status
= STATUS_NO_MEMORY
;
3060 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3061 if (!pValueInformation
)
3063 DPRINT("ExAllocatePool() failed\n");
3064 Status
= STATUS_NO_MEMORY
;
3070 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3071 if (Status
== STATUS_NO_MORE_ENTRIES
)
3073 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3075 ExFreePool(pDeviceInformation
);
3076 DeviceInfoLength
= RequiredSize
;
3077 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3078 if (!pDeviceInformation
)
3080 DPRINT("ExAllocatePool() failed\n");
3081 Status
= STATUS_NO_MEMORY
;
3084 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3086 if (!NT_SUCCESS(Status
))
3088 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3093 /* Open device key */
3094 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
3095 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3097 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
3098 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
3099 if (!NT_SUCCESS(Status
))
3101 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3105 /* Read boot resources, and add then to parent ones */
3106 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3107 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3109 ExFreePool(pValueInformation
);
3110 ValueInfoLength
= RequiredSize
;
3111 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3112 if (!pValueInformation
)
3114 DPRINT("ExAllocatePool() failed\n");
3115 ZwDeleteKey(hLevel2Key
);
3116 Status
= STATUS_NO_MEMORY
;
3119 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3121 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3123 BootResources
= ParentBootResources
;
3124 BootResourcesLength
= ParentBootResourcesLength
;
3126 else if (!NT_SUCCESS(Status
))
3128 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3131 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
3133 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
3138 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
3140 /* Concatenate current resources and parent ones */
3141 if (ParentBootResourcesLength
== 0)
3142 BootResourcesLength
= pValueInformation
->DataLength
;
3144 BootResourcesLength
= ParentBootResourcesLength
3145 + pValueInformation
->DataLength
3147 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
3150 DPRINT("ExAllocatePool() failed\n");
3153 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
3155 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
3157 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
3159 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
3161 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
3162 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
3163 ParentBootResourcesLength
- Header
);
3164 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
3168 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
3170 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
3171 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
3172 ParentBootResourcesLength
- Header
);
3174 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
3175 pValueInformation
->Data
+ Header
,
3176 pValueInformation
->DataLength
- Header
);
3177 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
3181 if (EnumerateSubKeys
)
3186 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3187 if (Status
== STATUS_NO_MORE_ENTRIES
)
3189 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3191 ExFreePool(pDeviceInformation
);
3192 DeviceInfoLength
= RequiredSize
;
3193 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3194 if (!pDeviceInformation
)
3196 DPRINT("ExAllocatePool() failed\n");
3197 Status
= STATUS_NO_MEMORY
;
3200 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3202 if (!NT_SUCCESS(Status
))
3204 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3208 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
3209 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3211 Status
= IopEnumerateDetectedDevices(
3217 BootResourcesLength
);
3218 if (!NT_SUCCESS(Status
))
3223 /* Read identifier */
3224 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3225 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3227 ExFreePool(pValueInformation
);
3228 ValueInfoLength
= RequiredSize
;
3229 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3230 if (!pValueInformation
)
3232 DPRINT("ExAllocatePool() failed\n");
3233 Status
= STATUS_NO_MEMORY
;
3236 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3238 if (!NT_SUCCESS(Status
))
3240 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
3242 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);