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
);
54 IopTranslateDeviceResources(
55 IN PDEVICE_NODE DeviceNode
,
56 IN ULONG RequiredSize
);
60 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
62 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
67 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
68 PDRIVER_OBJECT DriverObject
)
73 if (!DriverObject
->DriverExtension
->AddDevice
)
74 return STATUS_SUCCESS
;
76 /* This is a Plug and Play driver */
77 DPRINT("Plug and Play driver found\n");
78 ASSERT(DeviceNode
->PhysicalDeviceObject
);
80 /* Check if this plug-and-play driver is used as a legacy one for this device node */
81 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
83 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
84 return STATUS_SUCCESS
;
87 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
88 &DriverObject
->DriverName
,
89 &DeviceNode
->InstancePath
);
90 Status
= DriverObject
->DriverExtension
->AddDevice(
91 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
92 if (!NT_SUCCESS(Status
))
94 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
98 /* Check if driver added a FDO above the PDO */
99 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
100 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
102 /* FIXME: What do we do? Unload the driver or just disable the device? */
103 DPRINT1("An FDO was not attached\n");
104 ObDereferenceObject(Fdo
);
105 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
106 return STATUS_UNSUCCESSFUL
;
109 /* Check if we have a ACPI device (needed for power management) */
110 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
112 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
114 /* There can be only one system power device */
115 if (!SystemPowerDeviceNodeCreated
)
117 PopSystemPowerDeviceNode
= DeviceNode
;
118 ObReferenceObject(PopSystemPowerDeviceNode
);
119 SystemPowerDeviceNodeCreated
= TRUE
;
123 ObDereferenceObject(Fdo
);
125 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
126 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
128 return STATUS_SUCCESS
;
133 PDEVICE_NODE DeviceNode
)
135 IO_STATUS_BLOCK IoStatusBlock
;
136 IO_STACK_LOCATION Stack
;
137 ULONG RequiredLength
;
140 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
141 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
142 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
143 Status
= IopInitiatePnpIrp(
144 DeviceNode
->PhysicalDeviceObject
,
146 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
148 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
150 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
153 DeviceNode
->ResourceRequirements
= Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
155 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
156 if (NT_SUCCESS(Status
))
158 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
159 if (NT_SUCCESS(Status
))
161 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
165 DPRINT("IopTranslateDeviceResources() failed (Status 0x%08lx)\n", Status
);
170 DPRINT("IopAssignDeviceResources() failed (Status 0x%08lx)\n", Status
);
172 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
174 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
175 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
176 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
179 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and
180 * actually _depend_ on this!. This is because NT will lock the Device Node
181 * with an ERESOURCE, which of course requires APCs to be disabled.
183 KeEnterCriticalRegion();
185 Status
= IopInitiatePnpIrp(
186 DeviceNode
->PhysicalDeviceObject
,
191 KeLeaveCriticalRegion();
193 if (!NT_SUCCESS(Status
))
195 DPRINT("IopInitiatePnpIrp() failed\n");
199 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
201 DPRINT("Device needs enumeration, invalidating bus relations\n");
202 /* Invalidate device relations synchronously
203 (otherwise there will be dirty read of DeviceNode) */
204 IopEnumerateDevice(DeviceNode
->PhysicalDeviceObject
);
205 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
209 if (NT_SUCCESS(Status
))
210 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
217 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
218 PDEVICE_CAPABILITIES DeviceCaps
)
220 IO_STATUS_BLOCK StatusBlock
;
221 IO_STACK_LOCATION Stack
;
223 /* Set up the Header */
224 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
225 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
226 DeviceCaps
->Version
= 1;
227 DeviceCaps
->Address
= -1;
228 DeviceCaps
->UINumber
= -1;
230 /* Set up the Stack */
231 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
232 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
235 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
237 IRP_MN_QUERY_CAPABILITIES
,
242 IopAsynchronousInvalidateDeviceRelations(
243 IN PDEVICE_OBJECT DeviceObject
,
244 IN PVOID InvalidateContext
)
246 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
248 IoSynchronousInvalidateDeviceRelations(
252 ObDereferenceObject(Data
->DeviceObject
);
253 IoFreeWorkItem(Data
->WorkItem
);
258 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
262 if (PopSystemPowerDeviceNode
)
264 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
265 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
266 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
268 return STATUS_SUCCESS
;
271 return STATUS_UNSUCCESSFUL
;
276 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
278 USHORT i
= 0, FoundIndex
= 0xFFFF;
282 /* Acquire the lock */
283 ExAcquireFastMutex(&IopBusTypeGuidListLock
);
285 /* Loop all entries */
286 while (i
< IopBusTypeGuidList
->GuidCount
)
288 /* Try to find a match */
289 if (RtlCompareMemory(BusTypeGuid
,
290 &IopBusTypeGuidList
->Guids
[i
],
291 sizeof(GUID
)) == sizeof(GUID
))
300 /* Check if we have to grow the list */
301 if (IopBusTypeGuidList
->GuidCount
)
303 /* Calculate the new size */
304 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
305 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
307 /* Allocate the new copy */
308 NewList
= ExAllocatePool(PagedPool
, NewSize
);
312 ExFreePool(IopBusTypeGuidList
);
316 /* Now copy them, decrease the size too */
317 NewSize
-= sizeof(GUID
);
318 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
320 /* Free the old list */
321 ExFreePool(IopBusTypeGuidList
);
323 /* Use the new buffer */
324 IopBusTypeGuidList
= NewList
;
327 /* Copy the new GUID */
328 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
332 /* The new entry is the index */
333 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
334 IopBusTypeGuidList
->GuidCount
++;
337 ExReleaseFastMutex(&IopBusTypeGuidListLock
);
343 * Creates a device node
346 * ParentNode = Pointer to parent device node
347 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
348 * to have the root device node create one
349 * (eg. for legacy drivers)
350 * DeviceNode = Pointer to storage for created device node
356 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
357 PDEVICE_OBJECT PhysicalDeviceObject
,
358 PUNICODE_STRING ServiceName
,
359 PDEVICE_NODE
*DeviceNode
)
365 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
366 ParentNode
, PhysicalDeviceObject
, ServiceName
);
368 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
371 return STATUS_INSUFFICIENT_RESOURCES
;
374 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
376 if (!PhysicalDeviceObject
)
378 Status
= PnpRootCreateDevice(ServiceName
, &PhysicalDeviceObject
);
379 if (!NT_SUCCESS(Status
))
381 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
386 /* This is for drivers passed on the command line to ntoskrnl.exe */
387 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
388 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
391 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
393 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
397 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
398 Node
->Parent
= ParentNode
;
399 Node
->Sibling
= ParentNode
->Child
;
400 ParentNode
->Child
= Node
;
401 if (ParentNode
->LastChild
== NULL
)
402 ParentNode
->LastChild
= Node
;
403 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
404 Node
->Level
= ParentNode
->Level
+ 1;
407 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
411 return STATUS_SUCCESS
;
415 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
418 PDEVICE_NODE PrevSibling
= NULL
;
420 /* All children must be deleted before a parent is deleted */
421 ASSERT(!DeviceNode
->Child
);
423 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
425 ASSERT(DeviceNode
->PhysicalDeviceObject
);
427 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
429 /* Get previous sibling */
430 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
432 PrevSibling
= DeviceNode
->Parent
->Child
;
433 while (PrevSibling
->Sibling
!= DeviceNode
)
434 PrevSibling
= PrevSibling
->Sibling
;
437 /* Unlink from parent if it exists */
438 if (DeviceNode
->Parent
)
440 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
442 DeviceNode
->Parent
->LastChild
= PrevSibling
;
444 PrevSibling
->Sibling
= NULL
;
446 if (DeviceNode
->Parent
->Child
== DeviceNode
)
447 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
450 /* Unlink from sibling list */
452 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
454 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
456 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
458 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
460 if (DeviceNode
->ResourceList
)
462 ExFreePool(DeviceNode
->ResourceList
);
465 if (DeviceNode
->ResourceListTranslated
)
467 ExFreePool(DeviceNode
->ResourceListTranslated
);
470 if (DeviceNode
->ResourceRequirements
)
472 ExFreePool(DeviceNode
->ResourceRequirements
);
475 if (DeviceNode
->BootResources
)
477 ExFreePool(DeviceNode
->BootResources
);
480 ExFreePool(DeviceNode
);
482 return STATUS_SUCCESS
;
486 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
487 PIO_STATUS_BLOCK IoStatusBlock
,
489 PIO_STACK_LOCATION Stack OPTIONAL
)
491 PDEVICE_OBJECT TopDeviceObject
;
492 PIO_STACK_LOCATION IrpSp
;
497 /* Always call the top of the device stack */
498 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
505 Irp
= IoBuildSynchronousFsdRequest(
514 /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */
515 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
516 Irp
->IoStatus
.Information
= 0;
518 if (MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
520 Irp
->IoStatus
.Information
= (ULONG_PTR
)Stack
->Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
523 IrpSp
= IoGetNextIrpStackLocation(Irp
);
524 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
528 RtlCopyMemory(&IrpSp
->Parameters
,
530 sizeof(Stack
->Parameters
));
533 Status
= IoCallDriver(TopDeviceObject
, Irp
);
534 if (Status
== STATUS_PENDING
)
536 KeWaitForSingleObject(&Event
,
541 Status
= IoStatusBlock
->Status
;
544 ObDereferenceObject(TopDeviceObject
);
551 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
553 PDEVICE_NODE ParentDeviceNode
;
554 PDEVICE_NODE ChildDeviceNode
;
557 /* Copy context data so we don't overwrite it in subsequent calls to this function */
558 ParentDeviceNode
= Context
->DeviceNode
;
560 /* Call the action routine */
561 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
562 if (!NT_SUCCESS(Status
))
567 /* Traversal of all children nodes */
568 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
569 ChildDeviceNode
!= NULL
;
570 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
572 /* Pass the current device node to the action routine */
573 Context
->DeviceNode
= ChildDeviceNode
;
575 Status
= IopTraverseDeviceTreeNode(Context
);
576 if (!NT_SUCCESS(Status
))
587 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
591 DPRINT("Context 0x%p\n", Context
);
593 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
594 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
596 /* Start from the specified device node */
597 Context
->DeviceNode
= Context
->FirstDeviceNode
;
599 /* Recursively traverse the device tree */
600 Status
= IopTraverseDeviceTreeNode(Context
);
601 if (Status
== STATUS_UNSUCCESSFUL
)
603 /* The action routine just wanted to terminate the traversal with status
604 code STATUS_SUCCESS */
605 Status
= STATUS_SUCCESS
;
613 * IopCreateDeviceKeyPath
615 * Creates a registry key
619 * Name of the key to be created.
621 * Handle to the newly created key
624 * This method can create nested trees, so parent of RegistryPath can
625 * be not existant, and will be created if needed.
629 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
632 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
633 HANDLE hParent
= NULL
, hKey
;
634 OBJECT_ATTRIBUTES ObjectAttributes
;
635 UNICODE_STRING KeyName
;
636 LPCWSTR Current
, Last
;
643 /* Open root key for device instances */
644 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
645 if (!NT_SUCCESS(Status
))
647 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
651 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
652 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
654 /* Go up to the end of the string */
655 while (Current
<= Last
)
657 if (Current
!= Last
&& *Current
!= '\\')
659 /* Not the end of the string and not a separator */
664 /* Prepare relative key name */
665 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
666 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
667 DPRINT("Create '%wZ'\n", &KeyName
);
670 InitializeObjectAttributes(&ObjectAttributes
,
672 OBJ_CASE_INSENSITIVE
,
675 Status
= ZwCreateKey(&hKey
,
676 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
683 /* Close parent key handle, we don't need it anymore */
687 /* Key opening/creating failed? */
688 if (!NT_SUCCESS(Status
))
690 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
694 /* Check if it is the end of the string */
697 /* Yes, return success */
699 return STATUS_SUCCESS
;
702 /* Start with this new parent key */
705 KeyName
.Buffer
= (LPWSTR
)Current
;
708 return STATUS_UNSUCCESSFUL
;
714 IopSetDeviceInstanceData(HANDLE InstanceKey
,
715 PDEVICE_NODE DeviceNode
)
717 OBJECT_ATTRIBUTES ObjectAttributes
;
718 UNICODE_STRING KeyName
;
721 ULONG ListSize
, ResultLength
;
724 DPRINT("IopSetDeviceInstanceData() called\n");
726 /* Create the 'LogConf' key */
727 RtlInitUnicodeString(&KeyName
, L
"LogConf");
728 InitializeObjectAttributes(&ObjectAttributes
,
730 OBJ_CASE_INSENSITIVE
,
733 Status
= ZwCreateKey(&LogConfKey
,
740 if (NT_SUCCESS(Status
))
742 /* Set 'BootConfig' value */
743 if (DeviceNode
->BootResources
!= NULL
)
745 ResCount
= DeviceNode
->BootResources
->Count
;
748 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
750 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
751 Status
= ZwSetValueKey(LogConfKey
,
755 DeviceNode
->BootResources
,
760 /* Set 'BasicConfigVector' value */
761 if (DeviceNode
->ResourceRequirements
!= NULL
&&
762 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
764 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
765 Status
= ZwSetValueKey(LogConfKey
,
768 REG_RESOURCE_REQUIREMENTS_LIST
,
769 DeviceNode
->ResourceRequirements
,
770 DeviceNode
->ResourceRequirements
->ListSize
);
776 /* Set the 'ConfigFlags' value */
777 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
778 Status
= ZwQueryValueKey(InstanceKey
,
780 KeyValueBasicInformation
,
784 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
786 /* Write the default value */
787 ULONG DefaultConfigFlags
= 0;
788 Status
= ZwSetValueKey(InstanceKey
,
793 sizeof(DefaultConfigFlags
));
796 DPRINT("IopSetDeviceInstanceData() done\n");
798 return STATUS_SUCCESS
;
803 IopAssignDeviceResources(
804 IN PDEVICE_NODE DeviceNode
,
805 OUT ULONG
*pRequiredSize
)
807 PIO_RESOURCE_LIST ResourceList
;
808 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
809 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
810 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
811 ULONG NumberOfResources
= 0;
816 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
818 /* No resource needed for this device */
819 DeviceNode
->ResourceList
= NULL
;
821 return STATUS_SUCCESS
;
824 /* Fill DeviceNode->ResourceList
825 * FIXME: the PnP arbiter should go there!
826 * Actually, use the BootResources if provided, else the resource list #0
829 if (DeviceNode
->BootResources
)
831 /* Browse the boot resources to know if we have some custom structures */
832 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
833 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
835 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
836 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
837 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
838 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
840 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
841 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
845 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
846 if (!DeviceNode
->ResourceList
)
848 Status
= STATUS_NO_MEMORY
;
851 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
853 *pRequiredSize
= Size
;
854 return STATUS_SUCCESS
;
857 /* Ok, here, we have to use the device requirement list */
858 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
859 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
861 Status
= STATUS_REVISION_MISMATCH
;
865 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
866 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
867 if (!DeviceNode
->ResourceList
)
869 Status
= STATUS_NO_MEMORY
;
873 DeviceNode
->ResourceList
->Count
= 1;
874 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
875 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
876 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
877 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
879 for (i
= 0; i
< ResourceList
->Count
; i
++)
881 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
883 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
885 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
888 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
889 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
890 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
891 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
892 switch (ResourceDescriptor
->Type
)
894 case CmResourceTypePort
:
896 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
897 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
900 case CmResourceTypeInterrupt
:
902 INTERFACE_TYPE BusType
;
907 DescriptorRaw
->u
.Interrupt
.Level
= 0;
908 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
909 /* FIXME: HACK: if we have a PCI device, we try
910 * to keep the IRQ assigned by the BIOS */
911 if (NT_SUCCESS(IoGetDeviceProperty(
912 DeviceNode
->PhysicalDeviceObject
,
913 DevicePropertyLegacyBusType
,
914 sizeof(INTERFACE_TYPE
),
916 &ret
)) && BusType
== PCIBus
)
918 /* We have a PCI bus */
919 if (NT_SUCCESS(IoGetDeviceProperty(
920 DeviceNode
->PhysicalDeviceObject
,
921 DevicePropertyAddress
,
924 &ret
)) && SlotNumber
> 0)
926 /* We have a good slot number */
927 ret
= HalGetBusDataByOffset(PCIConfiguration
,
928 DeviceNode
->ResourceRequirements
->BusNumber
,
931 0x3c /* PCI_INTERRUPT_LINE */,
933 if (ret
!= 0 && ret
!= 2
934 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
935 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
937 /* The device already has an assigned IRQ */
938 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
942 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
943 DescriptorRaw
->u
.Interrupt
.Vector
,
944 &DeviceNode
->InstancePath
);
945 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
946 ret
= HalSetBusDataByOffset(PCIConfiguration
,
947 DeviceNode
->ResourceRequirements
->BusNumber
,
950 0x3c /* PCI_INTERRUPT_LINE */,
952 if (ret
== 0 || ret
== 2)
959 case CmResourceTypeMemory
:
961 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
962 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
965 case CmResourceTypeDma
:
967 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
968 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
969 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
972 case CmResourceTypeBusNumber
:
974 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
975 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
976 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
979 /*CmResourceTypeDevicePrivate:
980 case CmResourceTypePcCardConfig:
981 case CmResourceTypeMfCardConfig:
984 &DescriptorRaw->u.DevicePrivate,
985 &ResourceDescriptor->u.DevicePrivate,
986 sizeof(ResourceDescriptor->u.DevicePrivate));
988 &DescriptorTranslated->u.DevicePrivate,
989 &ResourceDescriptor->u.DevicePrivate,
990 sizeof(ResourceDescriptor->u.DevicePrivate));
994 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1001 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1003 *pRequiredSize
= Size
;
1004 return STATUS_SUCCESS
;
1007 if (DeviceNode
->ResourceList
)
1009 ExFreePool(DeviceNode
->ResourceList
);
1010 DeviceNode
->ResourceList
= NULL
;
1018 IopTranslateDeviceResources(
1019 IN PDEVICE_NODE DeviceNode
,
1020 IN ULONG RequiredSize
)
1022 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1023 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1027 if (!DeviceNode
->ResourceList
)
1029 DeviceNode
->ResourceListTranslated
= NULL
;
1030 return STATUS_SUCCESS
;
1033 /* That's easy to translate a resource list. Just copy the
1034 * untranslated one and change few fields in the copy
1036 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1037 if (!DeviceNode
->ResourceListTranslated
)
1039 Status
=STATUS_NO_MEMORY
;
1042 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1044 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1046 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1047 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1049 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1050 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1051 switch (DescriptorRaw
->Type
)
1053 case CmResourceTypePort
:
1055 ULONG AddressSpace
= 1; /* IO space */
1056 if (!HalTranslateBusAddress(
1057 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1058 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1059 DescriptorRaw
->u
.Port
.Start
,
1061 &DescriptorTranslated
->u
.Port
.Start
))
1063 Status
= STATUS_UNSUCCESSFUL
;
1068 case CmResourceTypeInterrupt
:
1070 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1071 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1072 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1073 DescriptorRaw
->u
.Interrupt
.Level
,
1074 DescriptorRaw
->u
.Interrupt
.Vector
,
1075 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1076 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1079 case CmResourceTypeMemory
:
1081 ULONG AddressSpace
= 0; /* Memory space */
1082 if (!HalTranslateBusAddress(
1083 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1084 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1085 DescriptorRaw
->u
.Memory
.Start
,
1087 &DescriptorTranslated
->u
.Memory
.Start
))
1089 Status
= STATUS_UNSUCCESSFUL
;
1094 case CmResourceTypeDma
:
1095 case CmResourceTypeBusNumber
:
1096 case CmResourceTypeDeviceSpecific
:
1100 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1101 Status
= STATUS_NOT_IMPLEMENTED
;
1106 return STATUS_SUCCESS
;
1109 /* Yes! Also delete ResourceList because ResourceList and
1110 * ResourceListTranslated should be a pair! */
1111 ExFreePool(DeviceNode
->ResourceList
);
1112 DeviceNode
->ResourceList
= NULL
;
1113 if (DeviceNode
->ResourceListTranslated
)
1115 ExFreePool(DeviceNode
->ResourceListTranslated
);
1116 DeviceNode
->ResourceList
= NULL
;
1123 * IopGetParentIdPrefix
1125 * Retrieve (or create) a string which identifies a device.
1129 * Pointer to device node.
1131 * Pointer to the string where is returned the parent node identifier
1134 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1135 * valid and its Buffer field is NULL-terminated. The caller needs to
1136 * to free the string with RtlFreeUnicodeString when it is no longer
1141 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1142 PUNICODE_STRING ParentIdPrefix
)
1144 ULONG KeyNameBufferLength
;
1145 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1146 UNICODE_STRING KeyName
;
1147 UNICODE_STRING KeyValue
;
1148 UNICODE_STRING ValueName
;
1153 /* HACK: As long as some devices have a NULL device
1154 * instance path, the following test is required :(
1156 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1158 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1159 &DeviceNode
->InstancePath
);
1160 return STATUS_UNSUCCESSFUL
;
1163 /* 1. Try to retrieve ParentIdPrefix from registry */
1164 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1165 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1166 if (!ParentIdPrefixInformation
)
1168 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1173 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1174 if (!KeyName
.Buffer
)
1176 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1180 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1182 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1183 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1185 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1186 if (!NT_SUCCESS(Status
))
1188 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1189 Status
= ZwQueryValueKey(
1191 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1192 KeyNameBufferLength
, &KeyNameBufferLength
);
1193 if (NT_SUCCESS(Status
))
1195 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1196 Status
= STATUS_UNSUCCESSFUL
;
1199 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1200 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1204 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1206 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1207 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1211 /* 2. Create the ParentIdPrefix value */
1212 crc32
= RtlComputeCrc32(0,
1213 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1214 DeviceNode
->Parent
->InstancePath
.Length
);
1216 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1217 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1219 /* 3. Try to write the ParentIdPrefix to registry */
1220 Status
= ZwSetValueKey(hKey
,
1224 (PVOID
)KeyValue
.Buffer
,
1225 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1228 if (NT_SUCCESS(Status
))
1230 /* Duplicate the string to return it */
1231 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1233 ExFreePool(ParentIdPrefixInformation
);
1234 RtlFreeUnicodeString(&KeyName
);
1242 * IopActionInterrogateDeviceStack
1244 * Retrieve information for all (direct) child nodes of a parent node.
1248 * Pointer to device node.
1250 * Pointer to parent node to retrieve child node information for.
1253 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1254 * when we reach a device node which is not a direct child of the device
1255 * node for which we retrieve information of child nodes for. Any errors
1256 * that occur is logged instead so that all child services have a chance
1257 * of being interrogated.
1261 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1264 IO_STATUS_BLOCK IoStatusBlock
;
1265 PDEVICE_NODE ParentDeviceNode
;
1266 WCHAR InstancePath
[MAX_PATH
];
1267 IO_STACK_LOCATION Stack
;
1272 ULONG RequiredLength
;
1274 HANDLE InstanceKey
= NULL
;
1275 UNICODE_STRING ValueName
;
1276 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1277 DEVICE_CAPABILITIES DeviceCapabilities
;
1279 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1280 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1282 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1285 * We are called for the parent too, but we don't need to do special
1286 * handling for this node
1289 if (DeviceNode
== ParentDeviceNode
)
1291 DPRINT("Success\n");
1292 return STATUS_SUCCESS
;
1296 * Make sure this device node is a direct child of the parent device node
1297 * that is given as an argument
1300 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1302 /* Stop the traversal immediately and indicate successful operation */
1304 return STATUS_UNSUCCESSFUL
;
1308 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1309 if (!NT_SUCCESS(Status
))
1311 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1316 * FIXME: For critical errors, cleanup and disable device, but always
1317 * return STATUS_SUCCESS.
1320 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1322 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1323 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1327 if (NT_SUCCESS(Status
))
1329 /* Copy the device id string */
1330 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1333 * FIXME: Check for valid characters, if there is invalid characters
1339 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1342 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1344 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1345 if (!NT_SUCCESS(Status
))
1347 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1350 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1352 if (!DeviceCapabilities
.UniqueID
)
1354 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1355 DPRINT("Instance ID is not unique\n");
1356 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1357 if (!NT_SUCCESS(Status
))
1359 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1363 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1365 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1366 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1370 if (NT_SUCCESS(Status
))
1372 /* Append the instance id string */
1373 wcscat(InstancePath
, L
"\\");
1374 if (ParentIdPrefix
.Length
> 0)
1376 /* Add information from parent bus device to InstancePath */
1377 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1378 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1379 wcscat(InstancePath
, L
"&");
1381 if (IoStatusBlock
.Information
)
1382 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1385 * FIXME: Check for valid characters, if there is invalid characters
1391 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1393 RtlFreeUnicodeString(&ParentIdPrefix
);
1395 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1397 DPRINT("No resources\n");
1398 /* FIXME: Cleanup and disable device */
1401 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1404 * Create registry key for the instance id, if it doesn't exist yet
1406 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceKey
);
1407 if (!NT_SUCCESS(Status
))
1409 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1413 /* Set 'Capabilities' value */
1414 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1415 Status
= ZwSetValueKey(InstanceKey
,
1419 (PVOID
)&DeviceNode
->CapabilityFlags
,
1422 /* Set 'UINumber' value */
1423 if (DeviceCapabilities
.UINumber
!= MAXULONG
)
1425 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1426 Status
= ZwSetValueKey(InstanceKey
,
1430 &DeviceCapabilities
.UINumber
,
1435 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1437 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1438 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1442 if (NT_SUCCESS(Status
))
1445 * FIXME: Check for valid characters, if there is invalid characters
1449 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1450 DPRINT("Hardware IDs:\n");
1453 DPRINT(" %S\n", Ptr
);
1454 Length
= wcslen(Ptr
) + 1;
1457 TotalLength
+= Length
;
1459 DPRINT("TotalLength: %hu\n", TotalLength
);
1462 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1463 Status
= ZwSetValueKey(InstanceKey
,
1467 (PVOID
)IoStatusBlock
.Information
,
1468 (TotalLength
+ 1) * sizeof(WCHAR
));
1469 if (!NT_SUCCESS(Status
))
1471 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1476 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1479 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1481 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1482 Status
= IopInitiatePnpIrp(
1483 DeviceNode
->PhysicalDeviceObject
,
1487 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1490 * FIXME: Check for valid characters, if there is invalid characters
1494 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1495 DPRINT("Compatible IDs:\n");
1498 DPRINT(" %S\n", Ptr
);
1499 Length
= wcslen(Ptr
) + 1;
1502 TotalLength
+= Length
;
1504 DPRINT("TotalLength: %hu\n", TotalLength
);
1507 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1508 Status
= ZwSetValueKey(InstanceKey
,
1512 (PVOID
)IoStatusBlock
.Information
,
1513 (TotalLength
+ 1) * sizeof(WCHAR
));
1514 if (!NT_SUCCESS(Status
))
1516 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1521 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1524 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1526 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1527 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1528 Status
= IopInitiatePnpIrp(
1529 DeviceNode
->PhysicalDeviceObject
,
1531 IRP_MN_QUERY_DEVICE_TEXT
,
1533 /* This key is mandatory, so even if the Irp fails, we still write it */
1534 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1535 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1537 if (NT_SUCCESS(Status
) &&
1538 IoStatusBlock
.Information
&&
1539 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1541 /* This key is overriden when a driver is installed. Don't write the
1542 * new description if another one already exists */
1543 Status
= ZwSetValueKey(InstanceKey
,
1547 (PVOID
)IoStatusBlock
.Information
,
1548 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1552 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1553 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1555 Status
= ZwSetValueKey(InstanceKey
,
1560 DeviceDesc
.MaximumLength
);
1562 if (!NT_SUCCESS(Status
))
1564 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1570 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1572 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1573 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1574 Status
= IopInitiatePnpIrp(
1575 DeviceNode
->PhysicalDeviceObject
,
1577 IRP_MN_QUERY_DEVICE_TEXT
,
1579 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1581 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1582 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1583 Status
= ZwSetValueKey(InstanceKey
,
1587 (PVOID
)IoStatusBlock
.Information
,
1588 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1589 if (!NT_SUCCESS(Status
))
1591 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1596 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1599 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1601 Status
= IopInitiatePnpIrp(
1602 DeviceNode
->PhysicalDeviceObject
,
1604 IRP_MN_QUERY_BUS_INFORMATION
,
1606 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1608 PPNP_BUS_INFORMATION BusInformation
=
1609 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1611 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1612 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1613 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1614 ExFreePool(BusInformation
);
1618 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1620 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1621 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1622 DeviceNode
->ChildBusTypeIndex
= -1;
1625 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1627 Status
= IopInitiatePnpIrp(
1628 DeviceNode
->PhysicalDeviceObject
,
1630 IRP_MN_QUERY_RESOURCES
,
1632 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1634 DeviceNode
->BootResources
=
1635 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1636 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1640 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1641 DeviceNode
->BootResources
= NULL
;
1644 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1646 Status
= IopInitiatePnpIrp(
1647 DeviceNode
->PhysicalDeviceObject
,
1649 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1651 if (NT_SUCCESS(Status
))
1653 DeviceNode
->ResourceRequirements
=
1654 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1655 if (IoStatusBlock
.Information
)
1656 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
1658 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
1662 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1663 DeviceNode
->ResourceRequirements
= NULL
;
1667 if (InstanceKey
!= NULL
)
1669 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1672 ZwClose(InstanceKey
);
1674 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1676 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1678 /* Report the device to the user-mode pnp manager */
1679 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1680 &DeviceNode
->InstancePath
);
1683 return STATUS_SUCCESS
;
1689 IN PDEVICE_OBJECT DeviceObject
)
1691 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1692 DEVICETREE_TRAVERSE_CONTEXT Context
;
1693 PDEVICE_RELATIONS DeviceRelations
;
1694 PDEVICE_OBJECT ChildDeviceObject
;
1695 IO_STATUS_BLOCK IoStatusBlock
;
1696 PDEVICE_NODE ChildDeviceNode
;
1697 IO_STACK_LOCATION Stack
;
1701 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1703 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1705 /* Report the device to the user-mode pnp manager */
1706 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1707 &DeviceNode
->InstancePath
);
1709 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1711 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1713 Status
= IopInitiatePnpIrp(
1716 IRP_MN_QUERY_DEVICE_RELATIONS
,
1718 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1720 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1724 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1726 if (!DeviceRelations
)
1728 DPRINT("No PDOs\n");
1729 return STATUS_UNSUCCESSFUL
;
1732 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1735 * Create device nodes for all discovered devices
1737 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1739 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1740 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1742 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1743 if (!ChildDeviceNode
)
1745 /* One doesn't exist, create it */
1746 Status
= IopCreateDeviceNode(
1751 if (NT_SUCCESS(Status
))
1753 /* Mark the node as enumerated */
1754 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1756 /* Mark the DO as bus enumerated */
1757 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1761 /* Ignore this DO */
1762 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1763 ObDereferenceObject(ChildDeviceNode
);
1768 /* Mark it as enumerated */
1769 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1770 ObDereferenceObject(ChildDeviceObject
);
1773 ExFreePool(DeviceRelations
);
1776 * Retrieve information about all discovered children from the bus driver
1778 IopInitDeviceTreeTraverseContext(
1781 IopActionInterrogateDeviceStack
,
1784 Status
= IopTraverseDeviceTree(&Context
);
1785 if (!NT_SUCCESS(Status
))
1787 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1792 * Retrieve configuration from the registry for discovered children
1794 IopInitDeviceTreeTraverseContext(
1797 IopActionConfigureChildServices
,
1800 Status
= IopTraverseDeviceTree(&Context
);
1801 if (!NT_SUCCESS(Status
))
1803 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1808 * Initialize services for discovered children.
1810 Status
= IopInitializePnpServices(DeviceNode
);
1811 if (!NT_SUCCESS(Status
))
1813 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1817 DPRINT("IopEnumerateDevice() finished\n");
1818 return STATUS_SUCCESS
;
1823 * IopActionConfigureChildServices
1825 * Retrieve configuration for all (direct) child nodes of a parent node.
1829 * Pointer to device node.
1831 * Pointer to parent node to retrieve child node configuration for.
1834 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1835 * when we reach a device node which is not a direct child of the device
1836 * node for which we configure child services for. Any errors that occur is
1837 * logged instead so that all child services have a chance of beeing
1842 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1845 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1846 PDEVICE_NODE ParentDeviceNode
;
1847 PUNICODE_STRING Service
;
1848 UNICODE_STRING ClassGUID
;
1850 DEVICE_CAPABILITIES DeviceCaps
;
1852 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1854 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1857 * We are called for the parent too, but we don't need to do special
1858 * handling for this node
1860 if (DeviceNode
== ParentDeviceNode
)
1862 DPRINT("Success\n");
1863 return STATUS_SUCCESS
;
1867 * Make sure this device node is a direct child of the parent device node
1868 * that is given as an argument
1870 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1872 /* Stop the traversal immediately and indicate successful operation */
1874 return STATUS_UNSUCCESSFUL
;
1877 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1879 WCHAR RegKeyBuffer
[MAX_PATH
];
1880 UNICODE_STRING RegKey
;
1883 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1884 RegKey
.Buffer
= RegKeyBuffer
;
1887 * Retrieve configuration from Enum key
1890 Service
= &DeviceNode
->ServiceName
;
1892 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1893 RtlInitUnicodeString(Service
, NULL
);
1894 RtlInitUnicodeString(&ClassGUID
, NULL
);
1896 QueryTable
[0].Name
= L
"Service";
1897 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1898 QueryTable
[0].EntryContext
= Service
;
1900 QueryTable
[1].Name
= L
"ClassGUID";
1901 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1902 QueryTable
[1].EntryContext
= &ClassGUID
;
1903 QueryTable
[1].DefaultType
= REG_SZ
;
1904 QueryTable
[1].DefaultData
= L
"";
1905 QueryTable
[1].DefaultLength
= 0;
1907 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1908 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1910 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1911 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1913 if (!NT_SUCCESS(Status
))
1915 /* FIXME: Log the error */
1916 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
1917 &DeviceNode
->InstancePath
, Status
);
1918 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1919 return STATUS_SUCCESS
;
1922 if (Service
->Buffer
== NULL
)
1924 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
1925 DeviceCaps
.RawDeviceOK
)
1927 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
1929 DeviceNode
->ServiceName
.Length
= 0;
1930 DeviceNode
->ServiceName
.MaximumLength
= ParentDeviceNode
->ServiceName
.MaximumLength
;
1931 DeviceNode
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, DeviceNode
->ServiceName
.MaximumLength
);
1932 if (!DeviceNode
->ServiceName
.Buffer
)
1933 return STATUS_SUCCESS
;
1935 RtlCopyUnicodeString(&DeviceNode
->ServiceName
, &ParentDeviceNode
->ServiceName
);
1937 IopDeviceNodeSetFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
1939 else if (ClassGUID
.Length
!= 0)
1941 /* Device has a ClassGUID value, but no Service value.
1942 * Suppose it is using the NULL driver, so state the
1943 * device is started */
1944 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
1945 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1949 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1951 return STATUS_SUCCESS
;
1954 DPRINT("Got Service %S\n", Service
->Buffer
);
1957 return STATUS_SUCCESS
;
1961 * IopActionInitChildServices
1963 * Initialize the service for all (direct) child nodes of a parent node
1967 * Pointer to device node.
1969 * Pointer to parent node to initialize child node services for.
1972 * If the driver image for a service is not loaded and initialized
1973 * it is done here too. We only return a status code indicating an
1974 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1975 * not a direct child of the device node for which we initialize
1976 * child services for. Any errors that occur is logged instead so
1977 * that all child services have a chance of being initialized.
1981 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
1984 PDEVICE_NODE ParentDeviceNode
;
1986 BOOLEAN BootDrivers
= !PnpSystemInit
;
1988 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
1990 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1993 * We are called for the parent too, but we don't need to do special
1994 * handling for this node
1996 if (DeviceNode
== ParentDeviceNode
)
1998 DPRINT("Success\n");
1999 return STATUS_SUCCESS
;
2003 * Make sure this device node is a direct child of the parent device node
2004 * that is given as an argument
2007 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2010 * Stop the traversal immediately and indicate unsuccessful operation
2013 return STATUS_UNSUCCESSFUL
;
2017 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2018 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2019 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2021 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2022 PDRIVER_OBJECT DriverObject
;
2024 /* Get existing DriverObject pointer (in case the driver has
2025 already been loaded and initialized) */
2026 Status
= IopGetDriverObject(
2028 &DeviceNode
->ServiceName
,
2031 if (!NT_SUCCESS(Status
))
2033 /* Driver is not initialized, try to load it */
2034 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2036 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2038 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2039 was loaded by the bootloader */
2040 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2041 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2043 /* Initialize the driver */
2044 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2045 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2049 Status
= STATUS_SUCCESS
;
2054 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2055 &DeviceNode
->ServiceName
, Status
);
2059 /* Driver is loaded and initialized at this point */
2060 if (NT_SUCCESS(Status
))
2062 /* Attach lower level filter drivers. */
2063 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2064 /* Initialize the function driver for the device node */
2065 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2067 if (NT_SUCCESS(Status
))
2069 /* Attach upper level filter drivers. */
2070 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2071 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2073 Status
= IopStartDevice(DeviceNode
);
2077 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2078 &DeviceNode
->InstancePath
, Status
);
2084 * Don't disable when trying to load only boot drivers
2088 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2089 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2090 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2091 DPRINT1("Initialization of service %S failed (Status %x)\n",
2092 DeviceNode
->ServiceName
.Buffer
, Status
);
2098 DPRINT("Device %wZ is disabled or already initialized\n",
2099 &DeviceNode
->InstancePath
);
2102 return STATUS_SUCCESS
;
2106 * IopInitializePnpServices
2108 * Initialize services for discovered children
2112 * Top device node to start initializing services.
2118 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2120 DEVICETREE_TRAVERSE_CONTEXT Context
;
2122 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2124 IopInitDeviceTreeTraverseContext(
2127 IopActionInitChildServices
,
2130 return IopTraverseDeviceTree(&Context
);
2133 static NTSTATUS INIT_FUNCTION
2134 IopEnumerateDetectedDevices(
2136 IN PUNICODE_STRING RelativePath OPTIONAL
,
2138 IN BOOLEAN EnumerateSubKeys
,
2139 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2140 IN ULONG ParentBootResourcesLength
)
2142 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2143 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2144 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2145 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2146 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2147 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2148 OBJECT_ATTRIBUTES ObjectAttributes
;
2149 HANDLE hDevicesKey
= NULL
;
2150 HANDLE hDeviceKey
= NULL
;
2151 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2152 UNICODE_STRING Level2NameU
;
2153 WCHAR Level2Name
[5];
2154 ULONG IndexDevice
= 0;
2156 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2157 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2158 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2159 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2160 UNICODE_STRING DeviceName
, ValueName
;
2162 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2163 ULONG BootResourcesLength
;
2166 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2167 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2168 static ULONG DeviceIndexPci
= 0;
2170 const UNICODE_STRING IdentifierAcpi
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2171 UNICODE_STRING HardwareIdAcpi
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2172 static ULONG DeviceIndexAcpi
= 0;
2174 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2175 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2176 static ULONG DeviceIndexSerial
= 0;
2177 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2178 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2179 static ULONG DeviceIndexKeyboard
= 0;
2180 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2181 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2182 static ULONG DeviceIndexMouse
= 0;
2183 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"PARALLEL");
2184 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2185 static ULONG DeviceIndexParallel
= 0;
2186 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FLOPPY");
2187 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2188 static ULONG DeviceIndexFloppy
= 0;
2189 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2190 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2191 static ULONG DeviceIndexIsa
= 0;
2192 UNICODE_STRING HardwareIdKey
;
2193 PUNICODE_STRING pHardwareId
;
2194 ULONG DeviceIndex
= 0;
2198 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2199 if (!NT_SUCCESS(Status
))
2201 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2206 hDevicesKey
= hBaseKey
;
2208 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2209 if (!pDeviceInformation
)
2211 DPRINT("ExAllocatePool() failed\n");
2212 Status
= STATUS_NO_MEMORY
;
2216 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2217 if (!pValueInformation
)
2219 DPRINT("ExAllocatePool() failed\n");
2220 Status
= STATUS_NO_MEMORY
;
2226 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2227 if (Status
== STATUS_NO_MORE_ENTRIES
)
2229 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2231 ExFreePool(pDeviceInformation
);
2232 DeviceInfoLength
= RequiredSize
;
2233 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2234 if (!pDeviceInformation
)
2236 DPRINT("ExAllocatePool() failed\n");
2237 Status
= STATUS_NO_MEMORY
;
2240 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2242 if (!NT_SUCCESS(Status
))
2244 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2249 /* Open device key */
2250 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2251 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2253 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2254 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2255 if (!NT_SUCCESS(Status
))
2257 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2261 /* Read boot resources, and add then to parent ones */
2262 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2263 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2265 ExFreePool(pValueInformation
);
2266 ValueInfoLength
= RequiredSize
;
2267 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2268 if (!pValueInformation
)
2270 DPRINT("ExAllocatePool() failed\n");
2271 ZwDeleteKey(hLevel2Key
);
2272 Status
= STATUS_NO_MEMORY
;
2275 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2277 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2279 BootResources
= ParentBootResources
;
2280 BootResourcesLength
= ParentBootResourcesLength
;
2282 else if (!NT_SUCCESS(Status
))
2284 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2287 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2289 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2294 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2296 /* Concatenate current resources and parent ones */
2297 if (ParentBootResourcesLength
== 0)
2298 BootResourcesLength
= pValueInformation
->DataLength
;
2300 BootResourcesLength
= ParentBootResourcesLength
2301 + pValueInformation
->DataLength
2303 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2306 DPRINT("ExAllocatePool() failed\n");
2309 if (ParentBootResourcesLength
== 0)
2311 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2313 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2315 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2317 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2318 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2319 ParentBootResourcesLength
- Header
);
2320 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2324 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2326 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2327 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2328 ParentBootResourcesLength
- Header
);
2330 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2331 pValueInformation
->Data
+ Header
,
2332 pValueInformation
->DataLength
- Header
);
2333 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2337 if (EnumerateSubKeys
)
2342 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2343 if (Status
== STATUS_NO_MORE_ENTRIES
)
2345 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2347 ExFreePool(pDeviceInformation
);
2348 DeviceInfoLength
= RequiredSize
;
2349 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2350 if (!pDeviceInformation
)
2352 DPRINT("ExAllocatePool() failed\n");
2353 Status
= STATUS_NO_MEMORY
;
2356 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2358 if (!NT_SUCCESS(Status
))
2360 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2364 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2365 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2367 Status
= IopEnumerateDetectedDevices(
2373 BootResourcesLength
);
2374 if (!NT_SUCCESS(Status
))
2379 /* Read identifier */
2380 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2381 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2383 ExFreePool(pValueInformation
);
2384 ValueInfoLength
= RequiredSize
;
2385 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2386 if (!pValueInformation
)
2388 DPRINT("ExAllocatePool() failed\n");
2389 Status
= STATUS_NO_MEMORY
;
2392 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2394 if (!NT_SUCCESS(Status
))
2396 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2398 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2401 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2403 else if (pValueInformation
->Type
!= REG_SZ
)
2405 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2410 /* Assign hardware id to this device */
2411 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2412 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2413 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2414 ValueName
.Length
-= sizeof(WCHAR
);
2417 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2419 pHardwareId
= &HardwareIdSerial
;
2420 DeviceIndex
= DeviceIndexSerial
++;
2422 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2424 pHardwareId
= &HardwareIdKeyboard
;
2425 DeviceIndex
= DeviceIndexKeyboard
++;
2427 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2429 pHardwareId
= &HardwareIdMouse
;
2430 DeviceIndex
= DeviceIndexMouse
++;
2432 else if (NT_SUCCESS(Status
))
2434 /* Try to also match the device identifier */
2435 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2437 pHardwareId
= &HardwareIdPci
;
2438 DeviceIndex
= DeviceIndexPci
++;
2440 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
2442 pHardwareId
= &HardwareIdIsa
;
2443 DeviceIndex
= DeviceIndexIsa
++;
2446 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierAcpi
, FALSE
) == 0)
2448 pHardwareId
= &HardwareIdAcpi
;
2449 DeviceIndex
= DeviceIndexAcpi
++;
2452 else /* Now let's detect devices with a device number at the end */
2454 /* First, we remove the number */
2455 ValueName
.Length
-= sizeof(WCHAR
);
2457 /* Let's see if it is a floppy device */
2458 if (RtlCompareUnicodeString(&ValueName
, &IdentifierFloppy
, FALSE
) == 0)
2460 pHardwareId
= &HardwareIdFloppy
;
2461 DeviceIndex
= DeviceIndexFloppy
++;
2463 /* Nope, is it a parallel port? */
2464 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierParallel
, FALSE
) == 0)
2466 pHardwareId
= &HardwareIdParallel
;
2467 DeviceIndex
= DeviceIndexParallel
++;
2469 /* Nope, out of ideas so let's skip this one */
2472 ValueName
.Length
+= sizeof(WCHAR
);
2473 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2477 /* Add the number back */
2478 ValueName
.Length
+= sizeof(WCHAR
);
2483 /* Unknown key path */
2484 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2488 /* Prepare hardware id key (hardware id value without final \0) */
2489 HardwareIdKey
= *pHardwareId
;
2490 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2492 /* Add the detected device to Root key */
2493 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2494 Status
= ZwCreateKey(
2500 REG_OPTION_NON_VOLATILE
,
2502 if (!NT_SUCCESS(Status
))
2504 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2507 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2508 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2509 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2510 Status
= ZwCreateKey(
2512 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2516 REG_OPTION_NON_VOLATILE
,
2518 ZwClose(hLevel1Key
);
2519 if (!NT_SUCCESS(Status
))
2521 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2524 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
2525 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
2526 if (!NT_SUCCESS(Status
))
2528 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2529 ZwDeleteKey(hLevel2Key
);
2532 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2533 if (!NT_SUCCESS(Status
))
2535 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2536 ZwDeleteKey(hLevel2Key
);
2539 /* Create 'LogConf' subkey */
2540 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2541 Status
= ZwCreateKey(
2547 REG_OPTION_VOLATILE
,
2549 if (!NT_SUCCESS(Status
))
2551 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2552 ZwDeleteKey(hLevel2Key
);
2555 if (BootResourcesLength
> 0)
2557 /* Save boot resources to 'LogConf\BootConfig' */
2558 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
2559 if (!NT_SUCCESS(Status
))
2561 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2563 ZwDeleteKey(hLevel2Key
);
2570 if (BootResources
&& BootResources
!= ParentBootResources
)
2571 ExFreePool(BootResources
);
2574 ZwClose(hLevel2Key
);
2579 ZwClose(hDeviceKey
);
2584 Status
= STATUS_SUCCESS
;
2587 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2588 ZwClose(hDevicesKey
);
2590 ZwClose(hDeviceKey
);
2591 if (pDeviceInformation
)
2592 ExFreePool(pDeviceInformation
);
2593 if (pValueInformation
)
2594 ExFreePool(pValueInformation
);
2598 static BOOLEAN INIT_FUNCTION
2599 IopIsAcpiComputer(VOID
)
2604 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2605 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2606 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2607 OBJECT_ATTRIBUTES ObjectAttributes
;
2608 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2609 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2610 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2611 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2613 ULONG IndexDevice
= 0;
2614 UNICODE_STRING DeviceName
, ValueName
;
2615 HANDLE hDevicesKey
= NULL
;
2616 HANDLE hDeviceKey
= NULL
;
2618 BOOLEAN ret
= FALSE
;
2620 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
2621 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2622 if (!NT_SUCCESS(Status
))
2624 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2628 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2629 if (!pDeviceInformation
)
2631 DPRINT("ExAllocatePool() failed\n");
2632 Status
= STATUS_NO_MEMORY
;
2636 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2637 if (!pDeviceInformation
)
2639 DPRINT("ExAllocatePool() failed\n");
2640 Status
= STATUS_NO_MEMORY
;
2646 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2647 if (Status
== STATUS_NO_MORE_ENTRIES
)
2649 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2651 ExFreePool(pDeviceInformation
);
2652 DeviceInfoLength
= RequiredSize
;
2653 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2654 if (!pDeviceInformation
)
2656 DPRINT("ExAllocatePool() failed\n");
2657 Status
= STATUS_NO_MEMORY
;
2660 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2662 if (!NT_SUCCESS(Status
))
2664 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2669 /* Open device key */
2670 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2671 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2672 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2677 if (!NT_SUCCESS(Status
))
2679 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2683 /* Read identifier */
2684 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2685 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2687 ExFreePool(pValueInformation
);
2688 ValueInfoLength
= RequiredSize
;
2689 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2690 if (!pValueInformation
)
2692 DPRINT("ExAllocatePool() failed\n");
2693 Status
= STATUS_NO_MEMORY
;
2696 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2698 if (!NT_SUCCESS(Status
))
2700 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2703 else if (pValueInformation
->Type
!= REG_SZ
)
2705 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2709 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2710 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2711 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2712 ValueName
.Length
-= sizeof(WCHAR
);
2713 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
2715 DPRINT("Found ACPI BIOS\n");
2721 ZwClose(hDeviceKey
);
2726 if (pDeviceInformation
)
2727 ExFreePool(pDeviceInformation
);
2728 if (pValueInformation
)
2729 ExFreePool(pValueInformation
);
2731 ZwClose(hDevicesKey
);
2733 ZwClose(hDeviceKey
);
2738 static NTSTATUS INIT_FUNCTION
2739 IopUpdateRootKey(VOID
)
2741 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2742 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2743 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2744 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2745 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2746 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2747 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
2748 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
2749 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
2750 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2751 OBJECT_ATTRIBUTES ObjectAttributes
;
2752 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
2755 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2756 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2757 if (!NT_SUCCESS(Status
))
2759 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2763 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2764 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2766 if (!NT_SUCCESS(Status
))
2768 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2772 if (IopIsAcpiComputer())
2774 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
2775 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2777 if (!NT_SUCCESS(Status
))
2779 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
2780 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2781 ZwClose(hHalAcpiDevice
);
2782 if (!NT_SUCCESS(Status
))
2784 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
2785 if (NT_SUCCESS(Status
))
2786 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
2787 if (NT_SUCCESS(Status
))
2789 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
2790 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2791 if (NT_SUCCESS(Status
))
2794 ZwClose(hHalAcpiId
);
2799 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2800 if (!NT_SUCCESS(Status
))
2802 /* Nothing to do, don't return with an error status */
2803 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2805 return STATUS_SUCCESS
;
2807 Status
= IopEnumerateDetectedDevices(
2822 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2824 PUNICODE_STRING Name
,
2825 ACCESS_MASK DesiredAccess
)
2827 OBJECT_ATTRIBUTES ObjectAttributes
;
2834 InitializeObjectAttributes(&ObjectAttributes
,
2836 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2840 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2847 IopGetRegistryValue(IN HANDLE Handle
,
2849 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
2851 UNICODE_STRING ValueString
;
2853 PKEY_VALUE_FULL_INFORMATION FullInformation
;
2857 RtlInitUnicodeString(&ValueString
, ValueName
);
2859 Status
= ZwQueryValueKey(Handle
,
2861 KeyValueFullInformation
,
2865 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
2866 (Status
!= STATUS_BUFFER_TOO_SMALL
))
2871 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
2872 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
2874 Status
= ZwQueryValueKey(Handle
,
2876 KeyValueFullInformation
,
2880 if (!NT_SUCCESS(Status
))
2882 ExFreePool(FullInformation
);
2886 *Information
= FullInformation
;
2887 return STATUS_SUCCESS
;
2890 static NTSTATUS INIT_FUNCTION
2892 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
2894 return STATUS_SUCCESS
;
2903 DPRINT("PnpInit()\n");
2905 KeInitializeSpinLock(&IopDeviceTreeLock
);
2906 ExInitializeFastMutex(&IopBusTypeGuidListLock
);
2908 /* Initialize the Bus Type GUID List */
2909 IopBusTypeGuidList
= ExAllocatePool(NonPagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2910 if (!IopBusTypeGuidList
) {
2911 DPRINT1("ExAllocatePool() failed\n");
2912 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
2915 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2916 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2918 /* Initialize PnP-Event notification support */
2919 Status
= IopInitPlugPlayEvents();
2920 if (!NT_SUCCESS(Status
))
2922 DPRINT1("IopInitPlugPlayEvents() failed\n");
2923 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2927 * Create root device node
2930 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
2931 if (!NT_SUCCESS(Status
))
2933 DPRINT1("IoCreateDriverObject() failed\n");
2934 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2937 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2939 if (!NT_SUCCESS(Status
))
2941 DPRINT1("IoCreateDevice() failed\n");
2942 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2945 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
2946 if (!NT_SUCCESS(Status
))
2948 DPRINT1("Insufficient resources\n");
2949 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2952 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2955 DPRINT1("Failed to create the instance path!\n");
2956 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
2959 /* Report the device to the user-mode pnp manager */
2960 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2961 &IopRootDeviceNode
->InstancePath
);
2963 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2964 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2965 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2966 IopRootDriverObject
->DriverExtension
->AddDevice(
2967 IopRootDriverObject
,
2968 IopRootDeviceNode
->PhysicalDeviceObject
);
2970 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
2971 Status
= IopUpdateRootKey();
2972 if (!NT_SUCCESS(Status
))
2974 DPRINT1("IopUpdateRootKey() failed\n");
2975 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2979 RTL_GENERIC_COMPARE_RESULTS
2981 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
2982 IN PVOID FirstStruct
,
2983 IN PVOID SecondStruct
)
2991 // The allocation function is called by the generic table package whenever
2992 // it needs to allocate memory for the table.
2997 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3007 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3016 PpInitializeDeviceReferenceTable(VOID
)
3018 /* Setup the guarded mutex and AVL table */
3019 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3020 RtlInitializeGenericTableAvl(
3021 &PpDeviceReferenceTable
,
3022 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3023 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3024 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3032 /* Initialize the resource when accessing device registry data */
3033 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3035 /* Setup the device reference AVL table */
3036 PpInitializeDeviceReferenceTable();
3044 /* Check the initialization phase */
3045 switch (ExpInitializationPhase
)
3050 return PiInitPhase0();
3056 //return PiInitPhase1();
3060 /* Don't know any other phase! Bugcheck! */
3061 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3066 /* PUBLIC FUNCTIONS **********************************************************/
3073 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3074 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3075 IN ULONG BufferLength
,
3076 OUT PVOID PropertyBuffer
,
3077 OUT PULONG ResultLength
)
3079 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3080 DEVICE_CAPABILITIES DeviceCaps
;
3086 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3090 if (DeviceNode
== NULL
)
3091 return STATUS_INVALID_DEVICE_REQUEST
;
3093 switch (DeviceProperty
)
3095 case DevicePropertyBusNumber
:
3096 Length
= sizeof(ULONG
);
3097 Data
= &DeviceNode
->ChildBusNumber
;
3100 /* Complete, untested */
3101 case DevicePropertyBusTypeGuid
:
3103 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
3104 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
3106 /* Return the GUID */
3107 *ResultLength
= sizeof(GUID
);
3109 /* Check if the buffer given was large enough */
3110 if (BufferLength
< *ResultLength
)
3112 return STATUS_BUFFER_TOO_SMALL
;
3116 RtlCopyMemory(PropertyBuffer
,
3117 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
3119 return STATUS_SUCCESS
;
3123 return STATUS_OBJECT_NAME_NOT_FOUND
;
3127 case DevicePropertyLegacyBusType
:
3128 Length
= sizeof(INTERFACE_TYPE
);
3129 Data
= &DeviceNode
->ChildInterfaceType
;
3132 case DevicePropertyAddress
:
3133 /* Query the device caps */
3134 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3135 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= MAXULONG
))
3138 *ResultLength
= sizeof(ULONG
);
3140 /* Check if the buffer given was large enough */
3141 if (BufferLength
< *ResultLength
)
3143 return STATUS_BUFFER_TOO_SMALL
;
3146 /* Return address */
3147 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
3148 return STATUS_SUCCESS
;
3152 return STATUS_OBJECT_NAME_NOT_FOUND
;
3156 // case DevicePropertyUINumber:
3157 // if (DeviceNode->CapabilityFlags == NULL)
3158 // return STATUS_INVALID_DEVICE_REQUEST;
3159 // Length = sizeof(ULONG);
3160 // Data = &DeviceNode->CapabilityFlags->UINumber;
3163 case DevicePropertyClassName
:
3164 case DevicePropertyClassGuid
:
3165 case DevicePropertyDriverKeyName
:
3166 case DevicePropertyManufacturer
:
3167 case DevicePropertyFriendlyName
:
3168 case DevicePropertyHardwareID
:
3169 case DevicePropertyCompatibleIDs
:
3170 case DevicePropertyDeviceDescription
:
3171 case DevicePropertyLocationInformation
:
3172 case DevicePropertyUINumber
:
3174 LPCWSTR RegistryPropertyName
;
3175 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
3176 UNICODE_STRING ValueName
;
3177 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
3178 ULONG ValueInformationLength
;
3179 HANDLE KeyHandle
, EnumRootHandle
;
3182 switch (DeviceProperty
)
3184 case DevicePropertyClassName
:
3185 RegistryPropertyName
= L
"Class"; break;
3186 case DevicePropertyClassGuid
:
3187 RegistryPropertyName
= L
"ClassGuid"; break;
3188 case DevicePropertyDriverKeyName
:
3189 RegistryPropertyName
= L
"Driver"; break;
3190 case DevicePropertyManufacturer
:
3191 RegistryPropertyName
= L
"Mfg"; break;
3192 case DevicePropertyFriendlyName
:
3193 RegistryPropertyName
= L
"FriendlyName"; break;
3194 case DevicePropertyHardwareID
:
3195 RegistryPropertyName
= L
"HardwareID"; break;
3196 case DevicePropertyCompatibleIDs
:
3197 RegistryPropertyName
= L
"CompatibleIDs"; break;
3198 case DevicePropertyDeviceDescription
:
3199 RegistryPropertyName
= L
"DeviceDesc"; break;
3200 case DevicePropertyLocationInformation
:
3201 RegistryPropertyName
= L
"LocationInformation"; break;
3202 case DevicePropertyUINumber
:
3203 RegistryPropertyName
= L
"UINumber"; break;
3205 /* Should not happen */
3207 return STATUS_UNSUCCESSFUL
;
3210 DPRINT("Registry property %S\n", RegistryPropertyName
);
3213 Status
= IopOpenRegistryKeyEx(&EnumRootHandle
, NULL
,
3214 &EnumRoot
, KEY_READ
);
3215 if (!NT_SUCCESS(Status
))
3217 DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status
);
3221 /* Open instance key */
3222 Status
= IopOpenRegistryKeyEx(&KeyHandle
, EnumRootHandle
,
3223 &DeviceNode
->InstancePath
, KEY_READ
);
3224 if (!NT_SUCCESS(Status
))
3226 DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status
);
3227 ZwClose(EnumRootHandle
);
3231 /* Allocate buffer to read as much data as required by the caller */
3232 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
3233 Data
[0]) + BufferLength
;
3234 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
3235 if (!ValueInformation
)