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
);
61 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
63 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
68 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
69 PDRIVER_OBJECT DriverObject
)
74 if (!DriverObject
->DriverExtension
->AddDevice
)
75 return STATUS_SUCCESS
;
77 /* This is a Plug and Play driver */
78 DPRINT("Plug and Play driver found\n");
79 ASSERT(DeviceNode
->PhysicalDeviceObject
);
81 /* Check if this plug-and-play driver is used as a legacy one for this device node */
82 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
84 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
85 return STATUS_SUCCESS
;
88 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
89 &DriverObject
->DriverName
,
90 &DeviceNode
->InstancePath
);
91 Status
= DriverObject
->DriverExtension
->AddDevice(
92 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
93 if (!NT_SUCCESS(Status
))
95 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
99 /* Check if driver added a FDO above the PDO */
100 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
101 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
103 /* FIXME: What do we do? Unload the driver or just disable the device? */
104 DPRINT1("An FDO was not attached\n");
105 ObDereferenceObject(Fdo
);
106 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
107 return STATUS_UNSUCCESSFUL
;
110 /* Check if we have a ACPI device (needed for power management) */
111 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
113 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
115 /* There can be only one system power device */
116 if (!SystemPowerDeviceNodeCreated
)
118 PopSystemPowerDeviceNode
= DeviceNode
;
119 ObReferenceObject(PopSystemPowerDeviceNode
);
120 SystemPowerDeviceNodeCreated
= TRUE
;
124 ObDereferenceObject(Fdo
);
126 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
127 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
129 return STATUS_SUCCESS
;
134 PDEVICE_NODE DeviceNode
)
136 IO_STATUS_BLOCK IoStatusBlock
;
137 IO_STACK_LOCATION Stack
;
138 ULONG RequiredLength
;
141 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
142 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
143 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
144 Status
= IopInitiatePnpIrp(
145 DeviceNode
->PhysicalDeviceObject
,
147 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
149 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
151 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
154 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
156 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
157 if (NT_SUCCESS(Status
))
159 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
160 if (NT_SUCCESS(Status
))
162 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
166 DPRINT("IopTranslateDeviceResources() failed (Status 0x%08lx)\n", Status
);
171 DPRINT("IopAssignDeviceResources() failed (Status 0x%08lx)\n", Status
);
173 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
175 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
176 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
177 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
180 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and
181 * actually _depend_ on this!. This is because NT will lock the Device Node
182 * with an ERESOURCE, which of course requires APCs to be disabled.
184 KeEnterCriticalRegion();
186 Status
= IopInitiatePnpIrp(
187 DeviceNode
->PhysicalDeviceObject
,
192 KeLeaveCriticalRegion();
194 if (!NT_SUCCESS(Status
))
196 DPRINT("IopInitiatePnpIrp() failed\n");
200 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
202 DPRINT("Device needs enumeration, invalidating bus relations\n");
203 /* Invalidate device relations synchronously
204 (otherwise there will be dirty read of DeviceNode) */
205 IopEnumerateDevice(DeviceNode
->PhysicalDeviceObject
);
206 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
210 if (NT_SUCCESS(Status
))
211 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
218 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
219 PDEVICE_CAPABILITIES DeviceCaps
)
221 IO_STATUS_BLOCK StatusBlock
;
222 IO_STACK_LOCATION Stack
;
224 /* Set up the Header */
225 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
226 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
227 DeviceCaps
->Version
= 1;
228 DeviceCaps
->Address
= -1;
229 DeviceCaps
->UINumber
= -1;
231 /* Set up the Stack */
232 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
233 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
236 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
238 IRP_MN_QUERY_CAPABILITIES
,
243 IopAsynchronousInvalidateDeviceRelations(
244 IN PDEVICE_OBJECT DeviceObject
,
245 IN PVOID InvalidateContext
)
247 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
249 IoSynchronousInvalidateDeviceRelations(
253 ObDereferenceObject(Data
->DeviceObject
);
254 IoFreeWorkItem(Data
->WorkItem
);
259 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
263 if (PopSystemPowerDeviceNode
)
265 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
266 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
267 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
269 return STATUS_SUCCESS
;
272 return STATUS_UNSUCCESSFUL
;
277 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
279 USHORT i
= 0, FoundIndex
= 0xFFFF;
283 /* Acquire the lock */
284 ExAcquireFastMutex(&IopBusTypeGuidListLock
);
286 /* Loop all entries */
287 while (i
< IopBusTypeGuidList
->GuidCount
)
289 /* Try to find a match */
290 if (RtlCompareMemory(BusTypeGuid
,
291 &IopBusTypeGuidList
->Guids
[i
],
292 sizeof(GUID
)) == sizeof(GUID
))
301 /* Check if we have to grow the list */
302 if (IopBusTypeGuidList
->GuidCount
)
304 /* Calculate the new size */
305 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
306 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
308 /* Allocate the new copy */
309 NewList
= ExAllocatePool(PagedPool
, NewSize
);
313 ExFreePool(IopBusTypeGuidList
);
317 /* Now copy them, decrease the size too */
318 NewSize
-= sizeof(GUID
);
319 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
321 /* Free the old list */
322 ExFreePool(IopBusTypeGuidList
);
324 /* Use the new buffer */
325 IopBusTypeGuidList
= NewList
;
328 /* Copy the new GUID */
329 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
333 /* The new entry is the index */
334 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
335 IopBusTypeGuidList
->GuidCount
++;
338 ExReleaseFastMutex(&IopBusTypeGuidListLock
);
344 * Creates a device node
347 * ParentNode = Pointer to parent device node
348 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
349 * to have the root device node create one
350 * (eg. for legacy drivers)
351 * DeviceNode = Pointer to storage for created device node
357 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
358 PDEVICE_OBJECT PhysicalDeviceObject
,
359 PUNICODE_STRING ServiceName
,
360 PDEVICE_NODE
*DeviceNode
)
365 UNICODE_STRING FullServiceName
;
366 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
368 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
369 ParentNode
, PhysicalDeviceObject
, ServiceName
);
371 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
374 return STATUS_INSUFFICIENT_RESOURCES
;
377 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
379 if (!PhysicalDeviceObject
)
383 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName
->Length
;
384 FullServiceName
.Length
= 0;
385 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
386 if (!FullServiceName
.Buffer
)
389 return STATUS_INSUFFICIENT_RESOURCES
;
392 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
393 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName
);
396 Status
= PnpRootCreateDevice(ServiceName
? &FullServiceName
: NULL
, &PhysicalDeviceObject
);
397 if (!NT_SUCCESS(Status
))
399 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
404 /* This is for drivers passed on the command line to ntoskrnl.exe */
405 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
406 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
409 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
411 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
415 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
416 Node
->Parent
= ParentNode
;
417 Node
->Sibling
= ParentNode
->Child
;
418 ParentNode
->Child
= Node
;
419 if (ParentNode
->LastChild
== NULL
)
420 ParentNode
->LastChild
= Node
;
421 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
422 Node
->Level
= ParentNode
->Level
+ 1;
425 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
429 return STATUS_SUCCESS
;
433 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
436 PDEVICE_NODE PrevSibling
= NULL
;
438 /* All children must be deleted before a parent is deleted */
439 ASSERT(!DeviceNode
->Child
);
441 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
443 ASSERT(DeviceNode
->PhysicalDeviceObject
);
445 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
447 /* Get previous sibling */
448 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
450 PrevSibling
= DeviceNode
->Parent
->Child
;
451 while (PrevSibling
->Sibling
!= DeviceNode
)
452 PrevSibling
= PrevSibling
->Sibling
;
455 /* Unlink from parent if it exists */
456 if (DeviceNode
->Parent
)
458 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
460 DeviceNode
->Parent
->LastChild
= PrevSibling
;
462 PrevSibling
->Sibling
= NULL
;
464 if (DeviceNode
->Parent
->Child
== DeviceNode
)
465 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
468 /* Unlink from sibling list */
470 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
472 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
474 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
476 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
478 if (DeviceNode
->ResourceList
)
480 ExFreePool(DeviceNode
->ResourceList
);
483 if (DeviceNode
->ResourceListTranslated
)
485 ExFreePool(DeviceNode
->ResourceListTranslated
);
488 if (DeviceNode
->ResourceRequirements
)
490 ExFreePool(DeviceNode
->ResourceRequirements
);
493 if (DeviceNode
->BootResources
)
495 ExFreePool(DeviceNode
->BootResources
);
498 ExFreePool(DeviceNode
);
500 return STATUS_SUCCESS
;
504 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
505 PIO_STATUS_BLOCK IoStatusBlock
,
507 PIO_STACK_LOCATION Stack OPTIONAL
)
509 PDEVICE_OBJECT TopDeviceObject
;
510 PIO_STACK_LOCATION IrpSp
;
515 /* Always call the top of the device stack */
516 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
523 Irp
= IoBuildSynchronousFsdRequest(
532 /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */
533 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
534 Irp
->IoStatus
.Information
= 0;
536 if (MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
538 Irp
->IoStatus
.Information
= (ULONG_PTR
)Stack
->Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
541 IrpSp
= IoGetNextIrpStackLocation(Irp
);
542 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
546 RtlCopyMemory(&IrpSp
->Parameters
,
548 sizeof(Stack
->Parameters
));
551 Status
= IoCallDriver(TopDeviceObject
, Irp
);
552 if (Status
== STATUS_PENDING
)
554 KeWaitForSingleObject(&Event
,
559 Status
= IoStatusBlock
->Status
;
562 ObDereferenceObject(TopDeviceObject
);
569 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
571 PDEVICE_NODE ParentDeviceNode
;
572 PDEVICE_NODE ChildDeviceNode
;
575 /* Copy context data so we don't overwrite it in subsequent calls to this function */
576 ParentDeviceNode
= Context
->DeviceNode
;
578 /* Call the action routine */
579 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
580 if (!NT_SUCCESS(Status
))
585 /* Traversal of all children nodes */
586 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
587 ChildDeviceNode
!= NULL
;
588 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
590 /* Pass the current device node to the action routine */
591 Context
->DeviceNode
= ChildDeviceNode
;
593 Status
= IopTraverseDeviceTreeNode(Context
);
594 if (!NT_SUCCESS(Status
))
605 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
609 DPRINT("Context 0x%p\n", Context
);
611 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
612 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
614 /* Start from the specified device node */
615 Context
->DeviceNode
= Context
->FirstDeviceNode
;
617 /* Recursively traverse the device tree */
618 Status
= IopTraverseDeviceTreeNode(Context
);
619 if (Status
== STATUS_UNSUCCESSFUL
)
621 /* The action routine just wanted to terminate the traversal with status
622 code STATUS_SUCCESS */
623 Status
= STATUS_SUCCESS
;
631 * IopCreateDeviceKeyPath
633 * Creates a registry key
637 * Name of the key to be created.
639 * Handle to the newly created key
642 * This method can create nested trees, so parent of RegistryPath can
643 * be not existant, and will be created if needed.
647 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
650 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
651 HANDLE hParent
= NULL
, hKey
;
652 OBJECT_ATTRIBUTES ObjectAttributes
;
653 UNICODE_STRING KeyName
;
654 LPCWSTR Current
, Last
;
661 /* Open root key for device instances */
662 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
663 if (!NT_SUCCESS(Status
))
665 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
669 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
670 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
672 /* Go up to the end of the string */
673 while (Current
<= Last
)
675 if (Current
!= Last
&& *Current
!= '\\')
677 /* Not the end of the string and not a separator */
682 /* Prepare relative key name */
683 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
684 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
685 DPRINT("Create '%wZ'\n", &KeyName
);
688 InitializeObjectAttributes(&ObjectAttributes
,
690 OBJ_CASE_INSENSITIVE
,
693 Status
= ZwCreateKey(&hKey
,
694 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
701 /* Close parent key handle, we don't need it anymore */
705 /* Key opening/creating failed? */
706 if (!NT_SUCCESS(Status
))
708 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
712 /* Check if it is the end of the string */
715 /* Yes, return success */
717 return STATUS_SUCCESS
;
720 /* Start with this new parent key */
723 KeyName
.Buffer
= (LPWSTR
)Current
;
726 return STATUS_UNSUCCESSFUL
;
731 IopSetDeviceInstanceData(HANDLE InstanceKey
,
732 PDEVICE_NODE DeviceNode
)
734 OBJECT_ATTRIBUTES ObjectAttributes
;
735 UNICODE_STRING KeyName
;
738 ULONG ListSize
, ResultLength
;
741 DPRINT("IopSetDeviceInstanceData() called\n");
743 /* Create the 'LogConf' key */
744 RtlInitUnicodeString(&KeyName
, L
"LogConf");
745 InitializeObjectAttributes(&ObjectAttributes
,
747 OBJ_CASE_INSENSITIVE
,
750 Status
= ZwCreateKey(&LogConfKey
,
757 if (NT_SUCCESS(Status
))
759 /* Set 'BootConfig' value */
760 if (DeviceNode
->BootResources
!= NULL
)
762 ResCount
= DeviceNode
->BootResources
->Count
;
765 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
767 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
768 Status
= ZwSetValueKey(LogConfKey
,
772 DeviceNode
->BootResources
,
777 /* Set 'BasicConfigVector' value */
778 if (DeviceNode
->ResourceRequirements
!= NULL
&&
779 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
781 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
782 Status
= ZwSetValueKey(LogConfKey
,
785 REG_RESOURCE_REQUIREMENTS_LIST
,
786 DeviceNode
->ResourceRequirements
,
787 DeviceNode
->ResourceRequirements
->ListSize
);
793 /* Set the 'ConfigFlags' value */
794 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
795 Status
= ZwQueryValueKey(InstanceKey
,
797 KeyValueBasicInformation
,
801 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
803 /* Write the default value */
804 ULONG DefaultConfigFlags
= 0;
805 Status
= ZwSetValueKey(InstanceKey
,
810 sizeof(DefaultConfigFlags
));
813 DPRINT("IopSetDeviceInstanceData() done\n");
815 return STATUS_SUCCESS
;
820 IopAssignDeviceResources(
821 IN PDEVICE_NODE DeviceNode
,
822 OUT ULONG
*pRequiredSize
)
824 PIO_RESOURCE_LIST ResourceList
;
825 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
826 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
827 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
828 ULONG NumberOfResources
= 0;
833 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
835 /* No resource needed for this device */
836 DeviceNode
->ResourceList
= NULL
;
838 return STATUS_SUCCESS
;
841 /* Fill DeviceNode->ResourceList
842 * FIXME: the PnP arbiter should go there!
843 * Actually, use the BootResources if provided, else the resource list #0
846 if (DeviceNode
->BootResources
)
848 /* Browse the boot resources to know if we have some custom structures */
849 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
850 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
852 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
853 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
854 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
855 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
857 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
858 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
862 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
863 if (!DeviceNode
->ResourceList
)
865 Status
= STATUS_NO_MEMORY
;
868 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
870 *pRequiredSize
= Size
;
871 return STATUS_SUCCESS
;
874 /* Ok, here, we have to use the device requirement list */
875 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
876 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
878 Status
= STATUS_REVISION_MISMATCH
;
882 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
883 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
884 if (!DeviceNode
->ResourceList
)
886 Status
= STATUS_NO_MEMORY
;
890 DeviceNode
->ResourceList
->Count
= 1;
891 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
892 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
893 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
894 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
896 for (i
= 0; i
< ResourceList
->Count
; i
++)
898 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
900 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
902 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
905 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
906 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
907 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
908 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
909 switch (ResourceDescriptor
->Type
)
911 case CmResourceTypePort
:
913 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
914 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
917 case CmResourceTypeInterrupt
:
919 INTERFACE_TYPE BusType
;
924 DescriptorRaw
->u
.Interrupt
.Level
= 0;
925 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
926 /* FIXME: HACK: if we have a PCI device, we try
927 * to keep the IRQ assigned by the BIOS */
928 if (NT_SUCCESS(IoGetDeviceProperty(
929 DeviceNode
->PhysicalDeviceObject
,
930 DevicePropertyLegacyBusType
,
931 sizeof(INTERFACE_TYPE
),
933 &ret
)) && BusType
== PCIBus
)
935 /* We have a PCI bus */
936 if (NT_SUCCESS(IoGetDeviceProperty(
937 DeviceNode
->PhysicalDeviceObject
,
938 DevicePropertyAddress
,
941 &ret
)) && SlotNumber
> 0)
943 /* We have a good slot number */
944 ret
= HalGetBusDataByOffset(PCIConfiguration
,
945 DeviceNode
->ResourceRequirements
->BusNumber
,
948 0x3c /* PCI_INTERRUPT_LINE */,
950 if (ret
!= 0 && ret
!= 2
951 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
952 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
954 /* The device already has an assigned IRQ */
955 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
959 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
960 DescriptorRaw
->u
.Interrupt
.Vector
,
961 &DeviceNode
->InstancePath
);
962 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
963 ret
= HalSetBusDataByOffset(PCIConfiguration
,
964 DeviceNode
->ResourceRequirements
->BusNumber
,
967 0x3c /* PCI_INTERRUPT_LINE */,
969 if (ret
== 0 || ret
== 2)
976 case CmResourceTypeMemory
:
978 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
979 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
982 case CmResourceTypeDma
:
984 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
985 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
986 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
989 case CmResourceTypeBusNumber
:
991 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
992 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
993 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
996 /*CmResourceTypeDevicePrivate:
997 case CmResourceTypePcCardConfig:
998 case CmResourceTypeMfCardConfig:
1001 &DescriptorRaw->u.DevicePrivate,
1002 &ResourceDescriptor->u.DevicePrivate,
1003 sizeof(ResourceDescriptor->u.DevicePrivate));
1005 &DescriptorTranslated->u.DevicePrivate,
1006 &ResourceDescriptor->u.DevicePrivate,
1007 sizeof(ResourceDescriptor->u.DevicePrivate));
1011 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1012 NumberOfResources
--;
1018 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1020 *pRequiredSize
= Size
;
1021 return STATUS_SUCCESS
;
1024 if (DeviceNode
->ResourceList
)
1026 ExFreePool(DeviceNode
->ResourceList
);
1027 DeviceNode
->ResourceList
= NULL
;
1035 IopTranslateDeviceResources(
1036 IN PDEVICE_NODE DeviceNode
,
1037 IN ULONG RequiredSize
)
1039 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1040 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1044 if (!DeviceNode
->ResourceList
)
1046 DeviceNode
->ResourceListTranslated
= NULL
;
1047 return STATUS_SUCCESS
;
1050 /* That's easy to translate a resource list. Just copy the
1051 * untranslated one and change few fields in the copy
1053 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1054 if (!DeviceNode
->ResourceListTranslated
)
1056 Status
=STATUS_NO_MEMORY
;
1059 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1061 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1063 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1064 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1066 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1067 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1068 switch (DescriptorRaw
->Type
)
1070 case CmResourceTypePort
:
1072 ULONG AddressSpace
= 1; /* IO space */
1073 if (!HalTranslateBusAddress(
1074 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1075 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1076 DescriptorRaw
->u
.Port
.Start
,
1078 &DescriptorTranslated
->u
.Port
.Start
))
1080 Status
= STATUS_UNSUCCESSFUL
;
1085 case CmResourceTypeInterrupt
:
1087 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1088 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1089 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1090 DescriptorRaw
->u
.Interrupt
.Level
,
1091 DescriptorRaw
->u
.Interrupt
.Vector
,
1092 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1093 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1096 case CmResourceTypeMemory
:
1098 ULONG AddressSpace
= 0; /* Memory space */
1099 if (!HalTranslateBusAddress(
1100 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1101 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1102 DescriptorRaw
->u
.Memory
.Start
,
1104 &DescriptorTranslated
->u
.Memory
.Start
))
1106 Status
= STATUS_UNSUCCESSFUL
;
1111 case CmResourceTypeDma
:
1112 case CmResourceTypeBusNumber
:
1113 case CmResourceTypeDeviceSpecific
:
1117 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1118 Status
= STATUS_NOT_IMPLEMENTED
;
1123 return STATUS_SUCCESS
;
1126 /* Yes! Also delete ResourceList because ResourceList and
1127 * ResourceListTranslated should be a pair! */
1128 ExFreePool(DeviceNode
->ResourceList
);
1129 DeviceNode
->ResourceList
= NULL
;
1130 if (DeviceNode
->ResourceListTranslated
)
1132 ExFreePool(DeviceNode
->ResourceListTranslated
);
1133 DeviceNode
->ResourceList
= NULL
;
1140 * IopGetParentIdPrefix
1142 * Retrieve (or create) a string which identifies a device.
1146 * Pointer to device node.
1148 * Pointer to the string where is returned the parent node identifier
1151 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1152 * valid and its Buffer field is NULL-terminated. The caller needs to
1153 * to free the string with RtlFreeUnicodeString when it is no longer
1158 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1159 PUNICODE_STRING ParentIdPrefix
)
1161 ULONG KeyNameBufferLength
;
1162 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1163 UNICODE_STRING KeyName
;
1164 UNICODE_STRING KeyValue
;
1165 UNICODE_STRING ValueName
;
1170 /* HACK: As long as some devices have a NULL device
1171 * instance path, the following test is required :(
1173 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1175 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1176 &DeviceNode
->InstancePath
);
1177 return STATUS_UNSUCCESSFUL
;
1180 /* 1. Try to retrieve ParentIdPrefix from registry */
1181 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1182 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1183 if (!ParentIdPrefixInformation
)
1185 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1190 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1191 if (!KeyName
.Buffer
)
1193 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1197 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1199 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1200 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1202 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1203 if (!NT_SUCCESS(Status
))
1205 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1206 Status
= ZwQueryValueKey(
1208 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1209 KeyNameBufferLength
, &KeyNameBufferLength
);
1210 if (NT_SUCCESS(Status
))
1212 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1213 Status
= STATUS_UNSUCCESSFUL
;
1216 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1217 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1221 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1223 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1224 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1228 /* 2. Create the ParentIdPrefix value */
1229 crc32
= RtlComputeCrc32(0,
1230 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1231 DeviceNode
->Parent
->InstancePath
.Length
);
1233 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1234 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1236 /* 3. Try to write the ParentIdPrefix to registry */
1237 Status
= ZwSetValueKey(hKey
,
1241 (PVOID
)KeyValue
.Buffer
,
1242 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1245 if (NT_SUCCESS(Status
))
1247 /* Duplicate the string to return it */
1248 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1250 ExFreePool(ParentIdPrefixInformation
);
1251 RtlFreeUnicodeString(&KeyName
);
1259 * IopActionInterrogateDeviceStack
1261 * Retrieve information for all (direct) child nodes of a parent node.
1265 * Pointer to device node.
1267 * Pointer to parent node to retrieve child node information for.
1270 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1271 * when we reach a device node which is not a direct child of the device
1272 * node for which we retrieve information of child nodes for. Any errors
1273 * that occur is logged instead so that all child services have a chance
1274 * of being interrogated.
1278 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1281 IO_STATUS_BLOCK IoStatusBlock
;
1282 PDEVICE_NODE ParentDeviceNode
;
1283 WCHAR InstancePath
[MAX_PATH
];
1284 IO_STACK_LOCATION Stack
;
1289 ULONG RequiredLength
;
1291 HANDLE InstanceKey
= NULL
;
1292 UNICODE_STRING ValueName
;
1293 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1294 DEVICE_CAPABILITIES DeviceCapabilities
;
1296 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1297 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1299 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1302 * We are called for the parent too, but we don't need to do special
1303 * handling for this node
1306 if (DeviceNode
== ParentDeviceNode
)
1308 DPRINT("Success\n");
1309 return STATUS_SUCCESS
;
1313 * Make sure this device node is a direct child of the parent device node
1314 * that is given as an argument
1317 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1319 /* Stop the traversal immediately and indicate successful operation */
1321 return STATUS_UNSUCCESSFUL
;
1325 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1326 if (!NT_SUCCESS(Status
))
1328 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1333 * FIXME: For critical errors, cleanup and disable device, but always
1334 * return STATUS_SUCCESS.
1337 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1339 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1340 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1344 if (NT_SUCCESS(Status
))
1346 /* Copy the device id string */
1347 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1350 * FIXME: Check for valid characters, if there is invalid characters
1356 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1359 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1361 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1362 if (!NT_SUCCESS(Status
))
1364 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1367 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1369 if (!DeviceCapabilities
.UniqueID
)
1371 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1372 DPRINT("Instance ID is not unique\n");
1373 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1374 if (!NT_SUCCESS(Status
))
1376 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1380 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1382 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1383 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1387 if (NT_SUCCESS(Status
))
1389 /* Append the instance id string */
1390 wcscat(InstancePath
, L
"\\");
1391 if (ParentIdPrefix
.Length
> 0)
1393 /* Add information from parent bus device to InstancePath */
1394 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1395 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1396 wcscat(InstancePath
, L
"&");
1398 if (IoStatusBlock
.Information
)
1399 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1402 * FIXME: Check for valid characters, if there is invalid characters
1408 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1410 RtlFreeUnicodeString(&ParentIdPrefix
);
1412 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1414 DPRINT("No resources\n");
1415 /* FIXME: Cleanup and disable device */
1418 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1421 * Create registry key for the instance id, if it doesn't exist yet
1423 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceKey
);
1424 if (!NT_SUCCESS(Status
))
1426 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1430 /* Set 'Capabilities' value */
1431 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1432 Status
= ZwSetValueKey(InstanceKey
,
1436 (PVOID
)&DeviceNode
->CapabilityFlags
,
1439 /* Set 'UINumber' value */
1440 if (DeviceCapabilities
.UINumber
!= MAXULONG
)
1442 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1443 Status
= ZwSetValueKey(InstanceKey
,
1447 &DeviceCapabilities
.UINumber
,
1452 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1454 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1455 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1459 if (NT_SUCCESS(Status
))
1462 * FIXME: Check for valid characters, if there is invalid characters
1466 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1467 DPRINT("Hardware IDs:\n");
1470 DPRINT(" %S\n", Ptr
);
1471 Length
= wcslen(Ptr
) + 1;
1474 TotalLength
+= Length
;
1476 DPRINT("TotalLength: %hu\n", TotalLength
);
1479 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1480 Status
= ZwSetValueKey(InstanceKey
,
1484 (PVOID
)IoStatusBlock
.Information
,
1485 (TotalLength
+ 1) * sizeof(WCHAR
));
1486 if (!NT_SUCCESS(Status
))
1488 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1493 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1496 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1498 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1499 Status
= IopInitiatePnpIrp(
1500 DeviceNode
->PhysicalDeviceObject
,
1504 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1507 * FIXME: Check for valid characters, if there is invalid characters
1511 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1512 DPRINT("Compatible IDs:\n");
1515 DPRINT(" %S\n", Ptr
);
1516 Length
= wcslen(Ptr
) + 1;
1519 TotalLength
+= Length
;
1521 DPRINT("TotalLength: %hu\n", TotalLength
);
1524 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1525 Status
= ZwSetValueKey(InstanceKey
,
1529 (PVOID
)IoStatusBlock
.Information
,
1530 (TotalLength
+ 1) * sizeof(WCHAR
));
1531 if (!NT_SUCCESS(Status
))
1533 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1538 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1541 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1543 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1544 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1545 Status
= IopInitiatePnpIrp(
1546 DeviceNode
->PhysicalDeviceObject
,
1548 IRP_MN_QUERY_DEVICE_TEXT
,
1550 /* This key is mandatory, so even if the Irp fails, we still write it */
1551 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1552 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1554 if (NT_SUCCESS(Status
) &&
1555 IoStatusBlock
.Information
&&
1556 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1558 /* This key is overriden when a driver is installed. Don't write the
1559 * new description if another one already exists */
1560 Status
= ZwSetValueKey(InstanceKey
,
1564 (PVOID
)IoStatusBlock
.Information
,
1565 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1569 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1570 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1572 Status
= ZwSetValueKey(InstanceKey
,
1577 DeviceDesc
.MaximumLength
);
1579 if (!NT_SUCCESS(Status
))
1581 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1587 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1589 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1590 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1591 Status
= IopInitiatePnpIrp(
1592 DeviceNode
->PhysicalDeviceObject
,
1594 IRP_MN_QUERY_DEVICE_TEXT
,
1596 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1598 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1599 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1600 Status
= ZwSetValueKey(InstanceKey
,
1604 (PVOID
)IoStatusBlock
.Information
,
1605 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1606 if (!NT_SUCCESS(Status
))
1608 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1613 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1616 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1618 Status
= IopInitiatePnpIrp(
1619 DeviceNode
->PhysicalDeviceObject
,
1621 IRP_MN_QUERY_BUS_INFORMATION
,
1623 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1625 PPNP_BUS_INFORMATION BusInformation
=
1626 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1628 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1629 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1630 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1631 ExFreePool(BusInformation
);
1635 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1637 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1638 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1639 DeviceNode
->ChildBusTypeIndex
= -1;
1642 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1644 Status
= IopInitiatePnpIrp(
1645 DeviceNode
->PhysicalDeviceObject
,
1647 IRP_MN_QUERY_RESOURCES
,
1649 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1651 DeviceNode
->BootResources
=
1652 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1653 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1657 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1658 DeviceNode
->BootResources
= NULL
;
1661 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1663 Status
= IopInitiatePnpIrp(
1664 DeviceNode
->PhysicalDeviceObject
,
1666 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1668 if (NT_SUCCESS(Status
))
1670 DeviceNode
->ResourceRequirements
=
1671 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1672 if (IoStatusBlock
.Information
)
1673 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
1675 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
1679 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1680 DeviceNode
->ResourceRequirements
= NULL
;
1684 if (InstanceKey
!= NULL
)
1686 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1689 ZwClose(InstanceKey
);
1691 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1693 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1695 /* Report the device to the user-mode pnp manager */
1696 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1697 &DeviceNode
->InstancePath
);
1700 return STATUS_SUCCESS
;
1706 IN PDEVICE_OBJECT DeviceObject
)
1708 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1709 DEVICETREE_TRAVERSE_CONTEXT Context
;
1710 PDEVICE_RELATIONS DeviceRelations
;
1711 PDEVICE_OBJECT ChildDeviceObject
;
1712 IO_STATUS_BLOCK IoStatusBlock
;
1713 PDEVICE_NODE ChildDeviceNode
;
1714 IO_STACK_LOCATION Stack
;
1718 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1720 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1722 /* Report the device to the user-mode pnp manager */
1723 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1724 &DeviceNode
->InstancePath
);
1726 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1728 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1730 Status
= IopInitiatePnpIrp(
1733 IRP_MN_QUERY_DEVICE_RELATIONS
,
1735 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1737 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1741 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1743 if (!DeviceRelations
)
1745 DPRINT("No PDOs\n");
1746 return STATUS_UNSUCCESSFUL
;
1749 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1752 * Create device nodes for all discovered devices
1754 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1756 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1757 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1759 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1760 if (!ChildDeviceNode
)
1762 /* One doesn't exist, create it */
1763 Status
= IopCreateDeviceNode(
1768 if (NT_SUCCESS(Status
))
1770 /* Mark the node as enumerated */
1771 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1773 /* Mark the DO as bus enumerated */
1774 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1778 /* Ignore this DO */
1779 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1780 ObDereferenceObject(ChildDeviceNode
);
1785 /* Mark it as enumerated */
1786 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1787 ObDereferenceObject(ChildDeviceObject
);
1790 ExFreePool(DeviceRelations
);
1793 * Retrieve information about all discovered children from the bus driver
1795 IopInitDeviceTreeTraverseContext(
1798 IopActionInterrogateDeviceStack
,
1801 Status
= IopTraverseDeviceTree(&Context
);
1802 if (!NT_SUCCESS(Status
))
1804 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1809 * Retrieve configuration from the registry for discovered children
1811 IopInitDeviceTreeTraverseContext(
1814 IopActionConfigureChildServices
,
1817 Status
= IopTraverseDeviceTree(&Context
);
1818 if (!NT_SUCCESS(Status
))
1820 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1825 * Initialize services for discovered children.
1827 Status
= IopInitializePnpServices(DeviceNode
);
1828 if (!NT_SUCCESS(Status
))
1830 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1834 DPRINT("IopEnumerateDevice() finished\n");
1835 return STATUS_SUCCESS
;
1840 * IopActionConfigureChildServices
1842 * Retrieve configuration for all (direct) child nodes of a parent node.
1846 * Pointer to device node.
1848 * Pointer to parent node to retrieve child node configuration for.
1851 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1852 * when we reach a device node which is not a direct child of the device
1853 * node for which we configure child services for. Any errors that occur is
1854 * logged instead so that all child services have a chance of beeing
1859 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1862 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1863 PDEVICE_NODE ParentDeviceNode
;
1864 PUNICODE_STRING Service
;
1865 UNICODE_STRING ClassGUID
;
1867 DEVICE_CAPABILITIES DeviceCaps
;
1869 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1871 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1874 * We are called for the parent too, but we don't need to do special
1875 * handling for this node
1877 if (DeviceNode
== ParentDeviceNode
)
1879 DPRINT("Success\n");
1880 return STATUS_SUCCESS
;
1884 * Make sure this device node is a direct child of the parent device node
1885 * that is given as an argument
1887 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1889 /* Stop the traversal immediately and indicate successful operation */
1891 return STATUS_UNSUCCESSFUL
;
1894 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1896 WCHAR RegKeyBuffer
[MAX_PATH
];
1897 UNICODE_STRING RegKey
;
1900 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1901 RegKey
.Buffer
= RegKeyBuffer
;
1904 * Retrieve configuration from Enum key
1907 Service
= &DeviceNode
->ServiceName
;
1909 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1910 RtlInitUnicodeString(Service
, NULL
);
1911 RtlInitUnicodeString(&ClassGUID
, NULL
);
1913 QueryTable
[0].Name
= L
"Service";
1914 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1915 QueryTable
[0].EntryContext
= Service
;
1917 QueryTable
[1].Name
= L
"ClassGUID";
1918 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1919 QueryTable
[1].EntryContext
= &ClassGUID
;
1920 QueryTable
[1].DefaultType
= REG_SZ
;
1921 QueryTable
[1].DefaultData
= L
"";
1922 QueryTable
[1].DefaultLength
= 0;
1924 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1925 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1927 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1928 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1930 if (!NT_SUCCESS(Status
))
1932 /* FIXME: Log the error */
1933 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
1934 &DeviceNode
->InstancePath
, Status
);
1935 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1936 return STATUS_SUCCESS
;
1939 if (Service
->Buffer
== NULL
)
1941 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
1942 DeviceCaps
.RawDeviceOK
)
1944 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
1946 DeviceNode
->ServiceName
.Length
= 0;
1947 DeviceNode
->ServiceName
.MaximumLength
= ParentDeviceNode
->ServiceName
.MaximumLength
;
1948 DeviceNode
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, DeviceNode
->ServiceName
.MaximumLength
);
1949 if (!DeviceNode
->ServiceName
.Buffer
)
1950 return STATUS_SUCCESS
;
1952 RtlCopyUnicodeString(&DeviceNode
->ServiceName
, &ParentDeviceNode
->ServiceName
);
1954 IopDeviceNodeSetFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
1956 else if (ClassGUID
.Length
!= 0)
1958 /* Device has a ClassGUID value, but no Service value.
1959 * Suppose it is using the NULL driver, so state the
1960 * device is started */
1961 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
1962 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1966 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1968 return STATUS_SUCCESS
;
1971 DPRINT("Got Service %S\n", Service
->Buffer
);
1974 return STATUS_SUCCESS
;
1978 * IopActionInitChildServices
1980 * Initialize the service for all (direct) child nodes of a parent node
1984 * Pointer to device node.
1986 * Pointer to parent node to initialize child node services for.
1989 * If the driver image for a service is not loaded and initialized
1990 * it is done here too. We only return a status code indicating an
1991 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1992 * not a direct child of the device node for which we initialize
1993 * child services for. Any errors that occur is logged instead so
1994 * that all child services have a chance of being initialized.
1998 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2001 PDEVICE_NODE ParentDeviceNode
;
2003 BOOLEAN BootDrivers
= !PnpSystemInit
;
2005 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2007 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2010 * We are called for the parent too, but we don't need to do special
2011 * handling for this node
2013 if (DeviceNode
== ParentDeviceNode
)
2015 DPRINT("Success\n");
2016 return STATUS_SUCCESS
;
2020 * Make sure this device node is a direct child of the parent device node
2021 * that is given as an argument
2024 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2027 * Stop the traversal immediately and indicate unsuccessful operation
2030 return STATUS_UNSUCCESSFUL
;
2034 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2035 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2036 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2038 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2039 PDRIVER_OBJECT DriverObject
;
2041 /* Get existing DriverObject pointer (in case the driver has
2042 already been loaded and initialized) */
2043 Status
= IopGetDriverObject(
2045 &DeviceNode
->ServiceName
,
2048 if (!NT_SUCCESS(Status
))
2050 /* Driver is not initialized, try to load it */
2051 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2053 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2055 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2056 was loaded by the bootloader */
2057 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2058 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2060 /* Initialize the driver */
2061 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2062 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2066 Status
= STATUS_SUCCESS
;
2071 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2072 &DeviceNode
->ServiceName
, Status
);
2076 /* Driver is loaded and initialized at this point */
2077 if (NT_SUCCESS(Status
))
2079 /* Attach lower level filter drivers. */
2080 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2081 /* Initialize the function driver for the device node */
2082 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2084 if (NT_SUCCESS(Status
))
2086 /* Attach upper level filter drivers. */
2087 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2088 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2090 Status
= IopStartDevice(DeviceNode
);
2094 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2095 &DeviceNode
->InstancePath
, Status
);
2101 * Don't disable when trying to load only boot drivers
2105 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2106 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2107 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2108 DPRINT1("Initialization of service %S failed (Status %x)\n",
2109 DeviceNode
->ServiceName
.Buffer
, Status
);
2115 DPRINT("Device %wZ is disabled or already initialized\n",
2116 &DeviceNode
->InstancePath
);
2119 return STATUS_SUCCESS
;
2123 * IopInitializePnpServices
2125 * Initialize services for discovered children
2129 * Top device node to start initializing services.
2135 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2137 DEVICETREE_TRAVERSE_CONTEXT Context
;
2139 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2141 IopInitDeviceTreeTraverseContext(
2144 IopActionInitChildServices
,
2147 return IopTraverseDeviceTree(&Context
);
2150 static NTSTATUS INIT_FUNCTION
2151 IopEnumerateDetectedDevices(
2153 IN PUNICODE_STRING RelativePath OPTIONAL
,
2155 IN BOOLEAN EnumerateSubKeys
,
2156 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2157 IN ULONG ParentBootResourcesLength
)
2159 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2160 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2161 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2162 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2163 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2164 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2165 OBJECT_ATTRIBUTES ObjectAttributes
;
2166 HANDLE hDevicesKey
= NULL
;
2167 HANDLE hDeviceKey
= NULL
;
2168 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2169 UNICODE_STRING Level2NameU
;
2170 WCHAR Level2Name
[5];
2171 ULONG IndexDevice
= 0;
2173 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2174 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2175 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2176 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2177 UNICODE_STRING DeviceName
, ValueName
;
2179 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2180 ULONG BootResourcesLength
;
2183 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2184 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2185 static ULONG DeviceIndexPci
= 0;
2186 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2187 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2188 static ULONG DeviceIndexSerial
= 0;
2189 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2190 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2191 static ULONG DeviceIndexKeyboard
= 0;
2192 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2193 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2194 static ULONG DeviceIndexMouse
= 0;
2195 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2196 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2197 static ULONG DeviceIndexParallel
= 0;
2198 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2199 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2200 static ULONG DeviceIndexFloppy
= 0;
2201 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2202 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2203 static ULONG DeviceIndexIsa
= 0;
2204 UNICODE_STRING HardwareIdKey
;
2205 PUNICODE_STRING pHardwareId
;
2206 ULONG DeviceIndex
= 0;
2207 BOOLEAN IsDeviceDesc
;
2211 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2212 if (!NT_SUCCESS(Status
))
2214 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2219 hDevicesKey
= hBaseKey
;
2221 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2222 if (!pDeviceInformation
)
2224 DPRINT("ExAllocatePool() failed\n");
2225 Status
= STATUS_NO_MEMORY
;
2229 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2230 if (!pValueInformation
)
2232 DPRINT("ExAllocatePool() failed\n");
2233 Status
= STATUS_NO_MEMORY
;
2239 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2240 if (Status
== STATUS_NO_MORE_ENTRIES
)
2242 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2244 ExFreePool(pDeviceInformation
);
2245 DeviceInfoLength
= RequiredSize
;
2246 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2247 if (!pDeviceInformation
)
2249 DPRINT("ExAllocatePool() failed\n");
2250 Status
= STATUS_NO_MEMORY
;
2253 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2255 if (!NT_SUCCESS(Status
))
2257 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2262 /* Open device key */
2263 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2264 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2266 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2267 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2268 if (!NT_SUCCESS(Status
))
2270 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2274 /* Read boot resources, and add then to parent ones */
2275 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2276 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2278 ExFreePool(pValueInformation
);
2279 ValueInfoLength
= RequiredSize
;
2280 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2281 if (!pValueInformation
)
2283 DPRINT("ExAllocatePool() failed\n");
2284 ZwDeleteKey(hLevel2Key
);
2285 Status
= STATUS_NO_MEMORY
;
2288 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2290 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2292 BootResources
= ParentBootResources
;
2293 BootResourcesLength
= ParentBootResourcesLength
;
2295 else if (!NT_SUCCESS(Status
))
2297 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2300 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2302 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2307 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2309 /* Concatenate current resources and parent ones */
2310 if (ParentBootResourcesLength
== 0)
2311 BootResourcesLength
= pValueInformation
->DataLength
;
2313 BootResourcesLength
= ParentBootResourcesLength
2314 + pValueInformation
->DataLength
2316 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2319 DPRINT("ExAllocatePool() failed\n");
2322 if (ParentBootResourcesLength
== 0)
2324 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2326 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2328 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2330 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2331 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2332 ParentBootResourcesLength
- Header
);
2333 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2337 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2339 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2340 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2341 ParentBootResourcesLength
- Header
);
2343 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2344 pValueInformation
->Data
+ Header
,
2345 pValueInformation
->DataLength
- Header
);
2346 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2350 if (EnumerateSubKeys
)
2355 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2356 if (Status
== STATUS_NO_MORE_ENTRIES
)
2358 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2360 ExFreePool(pDeviceInformation
);
2361 DeviceInfoLength
= RequiredSize
;
2362 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2363 if (!pDeviceInformation
)
2365 DPRINT("ExAllocatePool() failed\n");
2366 Status
= STATUS_NO_MEMORY
;
2369 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2371 if (!NT_SUCCESS(Status
))
2373 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2377 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2378 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2380 Status
= IopEnumerateDetectedDevices(
2386 BootResourcesLength
);
2387 if (!NT_SUCCESS(Status
))
2392 /* Read identifier */
2393 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2394 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2396 ExFreePool(pValueInformation
);
2397 ValueInfoLength
= RequiredSize
;
2398 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2399 if (!pValueInformation
)
2401 DPRINT("ExAllocatePool() failed\n");
2402 Status
= STATUS_NO_MEMORY
;
2405 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2407 if (!NT_SUCCESS(Status
))
2409 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2411 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2414 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2416 else if (pValueInformation
->Type
!= REG_SZ
)
2418 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2423 /* Assign hardware id to this device */
2424 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2425 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2426 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2427 ValueName
.Length
-= sizeof(WCHAR
);
2430 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2432 pHardwareId
= &HardwareIdSerial
;
2433 DeviceIndex
= DeviceIndexSerial
++;
2434 IsDeviceDesc
= TRUE
;
2436 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2438 pHardwareId
= &HardwareIdKeyboard
;
2439 DeviceIndex
= DeviceIndexKeyboard
++;
2440 IsDeviceDesc
= FALSE
;
2442 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2444 pHardwareId
= &HardwareIdMouse
;
2445 DeviceIndex
= DeviceIndexMouse
++;
2446 IsDeviceDesc
= FALSE
;
2448 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
2450 pHardwareId
= &HardwareIdParallel
;
2451 DeviceIndex
= DeviceIndexParallel
++;
2452 IsDeviceDesc
= FALSE
;
2454 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
2456 pHardwareId
= &HardwareIdFloppy
;
2457 DeviceIndex
= DeviceIndexFloppy
++;
2458 IsDeviceDesc
= FALSE
;
2460 else if (NT_SUCCESS(Status
))
2462 /* Try to also match the device identifier */
2463 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2465 pHardwareId
= &HardwareIdPci
;
2466 DeviceIndex
= DeviceIndexPci
++;
2467 IsDeviceDesc
= FALSE
;
2469 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
2471 pHardwareId
= &HardwareIdIsa
;
2472 DeviceIndex
= DeviceIndexIsa
++;
2473 IsDeviceDesc
= FALSE
;
2477 DPRINT("Unknown device '%wZ'\n", &ValueName
);
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
);
2527 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
2528 if (!NT_SUCCESS(Status
))
2530 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2531 ZwDeleteKey(hLevel2Key
);
2535 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2536 if (!NT_SUCCESS(Status
))
2538 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2539 ZwDeleteKey(hLevel2Key
);
2542 /* Create 'LogConf' subkey */
2543 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2544 Status
= ZwCreateKey(
2550 REG_OPTION_VOLATILE
,
2552 if (!NT_SUCCESS(Status
))
2554 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2555 ZwDeleteKey(hLevel2Key
);
2558 if (BootResourcesLength
> 0)
2560 /* Save boot resources to 'LogConf\BootConfig' */
2561 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
2562 if (!NT_SUCCESS(Status
))
2564 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2566 ZwDeleteKey(hLevel2Key
);
2573 if (BootResources
&& BootResources
!= ParentBootResources
)
2574 ExFreePool(BootResources
);
2577 ZwClose(hLevel2Key
);
2582 ZwClose(hDeviceKey
);
2587 Status
= STATUS_SUCCESS
;
2590 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2591 ZwClose(hDevicesKey
);
2593 ZwClose(hDeviceKey
);
2594 if (pDeviceInformation
)
2595 ExFreePool(pDeviceInformation
);
2596 if (pValueInformation
)
2597 ExFreePool(pValueInformation
);
2601 static BOOLEAN INIT_FUNCTION
2602 IopIsAcpiComputer(VOID
)
2607 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2608 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2609 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2610 OBJECT_ATTRIBUTES ObjectAttributes
;
2611 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2612 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2613 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2614 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2616 ULONG IndexDevice
= 0;
2617 UNICODE_STRING DeviceName
, ValueName
;
2618 HANDLE hDevicesKey
= NULL
;
2619 HANDLE hDeviceKey
= NULL
;
2621 BOOLEAN ret
= FALSE
;
2623 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2624 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2625 if (!NT_SUCCESS(Status
))
2627 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2631 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2632 if (!pDeviceInformation
)
2634 DPRINT("ExAllocatePool() failed\n");
2635 Status
= STATUS_NO_MEMORY
;
2639 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2640 if (!pDeviceInformation
)
2642 DPRINT("ExAllocatePool() failed\n");
2643 Status
= STATUS_NO_MEMORY
;
2649 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2650 if (Status
== STATUS_NO_MORE_ENTRIES
)
2652 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2654 ExFreePool(pDeviceInformation
);
2655 DeviceInfoLength
= RequiredSize
;
2656 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2657 if (!pDeviceInformation
)
2659 DPRINT("ExAllocatePool() failed\n");
2660 Status
= STATUS_NO_MEMORY
;
2663 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2665 if (!NT_SUCCESS(Status
))
2667 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2672 /* Open device key */
2673 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2674 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2675 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2680 if (!NT_SUCCESS(Status
))
2682 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2686 /* Read identifier */
2687 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2688 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2690 ExFreePool(pValueInformation
);
2691 ValueInfoLength
= RequiredSize
;
2692 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2693 if (!pValueInformation
)
2695 DPRINT("ExAllocatePool() failed\n");
2696 Status
= STATUS_NO_MEMORY
;
2699 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2701 if (!NT_SUCCESS(Status
))
2703 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2706 else if (pValueInformation
->Type
!= REG_SZ
)
2708 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2712 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2713 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2714 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2715 ValueName
.Length
-= sizeof(WCHAR
);
2716 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
2718 DPRINT("Found ACPI BIOS\n");
2724 ZwClose(hDeviceKey
);
2729 if (pDeviceInformation
)
2730 ExFreePool(pDeviceInformation
);
2731 if (pValueInformation
)
2732 ExFreePool(pValueInformation
);
2734 ZwClose(hDevicesKey
);
2736 ZwClose(hDeviceKey
);
2741 static NTSTATUS INIT_FUNCTION
2742 IopUpdateRootKey(VOID
)
2744 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2745 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2746 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2747 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2748 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2749 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2750 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
2751 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
2752 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
2753 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2754 OBJECT_ATTRIBUTES ObjectAttributes
;
2755 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
2758 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2759 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2760 if (!NT_SUCCESS(Status
))
2762 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2766 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2767 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2769 if (!NT_SUCCESS(Status
))
2771 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2775 if (IopIsAcpiComputer())
2777 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
2778 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2780 if (!NT_SUCCESS(Status
))
2782 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
2783 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2784 ZwClose(hHalAcpiDevice
);
2785 if (!NT_SUCCESS(Status
))
2787 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
2788 if (NT_SUCCESS(Status
))
2789 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
2790 if (NT_SUCCESS(Status
))
2792 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
2793 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2794 if (NT_SUCCESS(Status
))
2797 ZwClose(hHalAcpiId
);
2802 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2803 if (!NT_SUCCESS(Status
))
2805 /* Nothing to do, don't return with an error status */
2806 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2808 return STATUS_SUCCESS
;
2810 Status
= IopEnumerateDetectedDevices(
2825 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2827 PUNICODE_STRING Name
,
2828 ACCESS_MASK DesiredAccess
)
2830 OBJECT_ATTRIBUTES ObjectAttributes
;
2837 InitializeObjectAttributes(&ObjectAttributes
,
2839 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2843 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2850 IopGetRegistryValue(IN HANDLE Handle
,
2852 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
2854 UNICODE_STRING ValueString
;
2856 PKEY_VALUE_FULL_INFORMATION FullInformation
;
2860 RtlInitUnicodeString(&ValueString
, ValueName
);
2862 Status
= ZwQueryValueKey(Handle
,
2864 KeyValueFullInformation
,
2868 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
2869 (Status
!= STATUS_BUFFER_TOO_SMALL
))
2874 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
2875 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
2877 Status
= ZwQueryValueKey(Handle
,
2879 KeyValueFullInformation
,
2883 if (!NT_SUCCESS(Status
))
2885 ExFreePool(FullInformation
);
2889 *Information
= FullInformation
;
2890 return STATUS_SUCCESS
;
2893 static NTSTATUS INIT_FUNCTION
2895 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
2897 return STATUS_SUCCESS
;
2906 DPRINT("PnpInit()\n");
2908 KeInitializeSpinLock(&IopDeviceTreeLock
);
2909 ExInitializeFastMutex(&IopBusTypeGuidListLock
);
2911 /* Initialize the Bus Type GUID List */
2912 IopBusTypeGuidList
= ExAllocatePool(NonPagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2913 if (!IopBusTypeGuidList
) {
2914 DPRINT1("ExAllocatePool() failed\n");
2915 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
2918 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2919 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2921 /* Initialize PnP-Event notification support */
2922 Status
= IopInitPlugPlayEvents();
2923 if (!NT_SUCCESS(Status
))
2925 DPRINT1("IopInitPlugPlayEvents() failed\n");
2926 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2930 * Create root device node
2933 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
2934 if (!NT_SUCCESS(Status
))
2936 DPRINT1("IoCreateDriverObject() failed\n");
2937 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2940 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2942 if (!NT_SUCCESS(Status
))
2944 DPRINT1("IoCreateDevice() failed\n");
2945 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2948 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
2949 if (!NT_SUCCESS(Status
))
2951 DPRINT1("Insufficient resources\n");
2952 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2955 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2958 DPRINT1("Failed to create the instance path!\n");
2959 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
2962 /* Report the device to the user-mode pnp manager */
2963 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2964 &IopRootDeviceNode
->InstancePath
);
2966 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2967 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2968 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2969 IopRootDriverObject
->DriverExtension
->AddDevice(
2970 IopRootDriverObject
,
2971 IopRootDeviceNode
->PhysicalDeviceObject
);
2973 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
2974 Status
= IopUpdateRootKey();
2975 if (!NT_SUCCESS(Status
))
2977 DPRINT1("IopUpdateRootKey() failed\n");
2978 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2982 RTL_GENERIC_COMPARE_RESULTS
2984 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
2985 IN PVOID FirstStruct
,
2986 IN PVOID SecondStruct
)
2994 // The allocation function is called by the generic table package whenever
2995 // it needs to allocate memory for the table.
3000 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3010 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3019 PpInitializeDeviceReferenceTable(VOID
)
3021 /* Setup the guarded mutex and AVL table */
3022 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3023 RtlInitializeGenericTableAvl(
3024 &PpDeviceReferenceTable
,
3025 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3026 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3027 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3035 /* Initialize the resource when accessing device registry data */
3036 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3038 /* Setup the device reference AVL table */
3039 PpInitializeDeviceReferenceTable();
3047 /* Check the initialization phase */
3048 switch (ExpInitializationPhase
)
3053 return PiInitPhase0();
3059 //return PiInitPhase1();
3063 /* Don't know any other phase! Bugcheck! */
3064 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3069 /* PUBLIC FUNCTIONS **********************************************************/
3076 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3077 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3078 IN ULONG BufferLength
,
3079 OUT PVOID PropertyBuffer
,
3080 OUT PULONG ResultLength
)
3082 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3083 DEVICE_CAPABILITIES DeviceCaps
;
3089 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3093 if (DeviceNode
== NULL
)
3094 return STATUS_INVALID_DEVICE_REQUEST
;
3096 switch (DeviceProperty
)
3098 case DevicePropertyBusNumber
:
3099 Length
= sizeof(ULONG
);
3100 Data
= &DeviceNode
->ChildBusNumber
;
3103 /* Complete, untested */
3104 case DevicePropertyBusTypeGuid
:
3106 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
3107 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
3109 /* Return the GUID */
3110 *ResultLength
= sizeof(GUID
);
3112 /* Check if the buffer given was large enough */
3113 if (BufferLength
< *ResultLength
)
3115 return STATUS_BUFFER_TOO_SMALL
;
3119 RtlCopyMemory(PropertyBuffer
,
3120 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
3122 return STATUS_SUCCESS
;
3126 return STATUS_OBJECT_NAME_NOT_FOUND
;
3130 case DevicePropertyLegacyBusType
:
3131 Length
= sizeof(INTERFACE_TYPE
);
3132 Data
= &DeviceNode
->ChildInterfaceType
;
3135 case DevicePropertyAddress
:
3136 /* Query the device caps */
3137 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3138 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= MAXULONG
))
3141 *ResultLength
= sizeof(ULONG
);
3143 /* Check if the buffer given was large enough */
3144 if (BufferLength
< *ResultLength
)
3146 return STATUS_BUFFER_TOO_SMALL
;
3149 /* Return address */
3150 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
3151 return STATUS_SUCCESS
;
3155 return STATUS_OBJECT_NAME_NOT_FOUND
;
3159 // case DevicePropertyUINumber:
3160 // if (DeviceNode->CapabilityFlags == NULL)
3161 // return STATUS_INVALID_DEVICE_REQUEST;
3162 // Length = sizeof(ULONG);
3163 // Data = &DeviceNode->CapabilityFlags->UINumber;
3166 case DevicePropertyClassName
:
3167 case DevicePropertyClassGuid
:
3168 case DevicePropertyDriverKeyName
:
3169 case DevicePropertyManufacturer
:
3170 case DevicePropertyFriendlyName
:
3171 case DevicePropertyHardwareID
:
3172 case DevicePropertyCompatibleIDs
:
3173 case DevicePropertyDeviceDescription
:
3174 case DevicePropertyLocationInformation
:
3175 case DevicePropertyUINumber
:
3177 LPCWSTR RegistryPropertyName
;
3178 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
3179 UNICODE_STRING ValueName
;
3180 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
3181 ULONG ValueInformationLength
;
3182 HANDLE KeyHandle
, EnumRootHandle
;
3185 switch (DeviceProperty
)
3187 case DevicePropertyClassName
:
3188 RegistryPropertyName
= L
"Class"; break;
3189 case DevicePropertyClassGuid
:
3190 RegistryPropertyName
= L
"ClassGuid"; break;
3191 case DevicePropertyDriverKeyName
:
3192 RegistryPropertyName
= L
"Driver"; break;
3193 case DevicePropertyManufacturer
:
3194 RegistryPropertyName
= L
"Mfg"; break;
3195 case DevicePropertyFriendlyName
:
3196 RegistryPropertyName
= L
"FriendlyName"; break;
3197 case DevicePropertyHardwareID
:
3198 RegistryPropertyName
= L
"HardwareID"; break;
3199 case DevicePropertyCompatibleIDs
:
3200 RegistryPropertyName
= L
"CompatibleIDs"; break;
3201 case DevicePropertyDeviceDescription
:
3202 RegistryPropertyName
= L
"DeviceDesc"; break;
3203 case DevicePropertyLocationInformation
:
3204 RegistryPropertyName
= L
"LocationInformation"; break;
3205 case DevicePropertyUINumber
:
3206 RegistryPropertyName
= L
"UINumber"; break;
3208 /* Should not happen */
3210 return STATUS_UNSUCCESSFUL
;
3213 DPRINT("Registry property %S\n", RegistryPropertyName
);
3216 Status
= IopOpenRegistryKeyEx(&EnumRootHandle
, NULL
,
3217 &EnumRoot
, KEY_READ
);
3218 if (!NT_SUCCESS(Status
))
3220 DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status
);
3224 /* Open instance key */
3225 Status
= IopOpenRegistryKeyEx(&KeyHandle
, EnumRootHandle
,
3226 &DeviceNode
->InstancePath
, KEY_READ
);
3227 if (!NT_SUCCESS(Status
))
3229 DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status
);
3230 ZwClose(EnumRootHandle
);
3234 /* Allocate buffer to read as much data as required by the caller */
3235 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
3236 Data
[0]) + BufferLength
;
3237 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
3238 if (!ValueInformation
)