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 IrpSp
= IoGetNextIrpStackLocation(Irp
);
519 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
523 RtlCopyMemory(&IrpSp
->Parameters
,
525 sizeof(Stack
->Parameters
));
528 Status
= IoCallDriver(TopDeviceObject
, Irp
);
529 if (Status
== STATUS_PENDING
)
531 KeWaitForSingleObject(&Event
,
536 Status
= IoStatusBlock
->Status
;
539 ObDereferenceObject(TopDeviceObject
);
546 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
548 PDEVICE_NODE ParentDeviceNode
;
549 PDEVICE_NODE ChildDeviceNode
;
552 /* Copy context data so we don't overwrite it in subsequent calls to this function */
553 ParentDeviceNode
= Context
->DeviceNode
;
555 /* Call the action routine */
556 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
557 if (!NT_SUCCESS(Status
))
562 /* Traversal of all children nodes */
563 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
564 ChildDeviceNode
!= NULL
;
565 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
567 /* Pass the current device node to the action routine */
568 Context
->DeviceNode
= ChildDeviceNode
;
570 Status
= IopTraverseDeviceTreeNode(Context
);
571 if (!NT_SUCCESS(Status
))
582 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
586 DPRINT("Context 0x%p\n", Context
);
588 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
589 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
591 /* Start from the specified device node */
592 Context
->DeviceNode
= Context
->FirstDeviceNode
;
594 /* Recursively traverse the device tree */
595 Status
= IopTraverseDeviceTreeNode(Context
);
596 if (Status
== STATUS_UNSUCCESSFUL
)
598 /* The action routine just wanted to terminate the traversal with status
599 code STATUS_SUCCESS */
600 Status
= STATUS_SUCCESS
;
608 * IopCreateDeviceKeyPath
610 * Creates a registry key
614 * Name of the key to be created.
616 * Handle to the newly created key
619 * This method can create nested trees, so parent of RegistryPath can
620 * be not existant, and will be created if needed.
624 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
627 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
628 HANDLE hParent
= NULL
, hKey
;
629 OBJECT_ATTRIBUTES ObjectAttributes
;
630 UNICODE_STRING KeyName
;
631 LPCWSTR Current
, Last
;
638 /* Open root key for device instances */
639 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
640 if (!NT_SUCCESS(Status
))
642 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
646 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
647 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
649 /* Go up to the end of the string */
650 while (Current
<= Last
)
652 if (Current
!= Last
&& *Current
!= '\\')
654 /* Not the end of the string and not a separator */
659 /* Prepare relative key name */
660 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
661 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
662 DPRINT("Create '%wZ'\n", &KeyName
);
665 InitializeObjectAttributes(&ObjectAttributes
,
667 OBJ_CASE_INSENSITIVE
,
670 Status
= ZwCreateKey(&hKey
,
671 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
678 /* Close parent key handle, we don't need it anymore */
682 /* Key opening/creating failed? */
683 if (!NT_SUCCESS(Status
))
685 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
689 /* Check if it is the end of the string */
692 /* Yes, return success */
694 return STATUS_SUCCESS
;
697 /* Start with this new parent key */
700 KeyName
.Buffer
= (LPWSTR
)Current
;
703 return STATUS_UNSUCCESSFUL
;
709 IopSetDeviceInstanceData(HANDLE InstanceKey
,
710 PDEVICE_NODE DeviceNode
)
712 OBJECT_ATTRIBUTES ObjectAttributes
;
713 UNICODE_STRING KeyName
;
716 ULONG ListSize
, ResultLength
;
719 DPRINT("IopSetDeviceInstanceData() called\n");
721 /* Create the 'LogConf' key */
722 RtlInitUnicodeString(&KeyName
, L
"LogConf");
723 InitializeObjectAttributes(&ObjectAttributes
,
725 OBJ_CASE_INSENSITIVE
,
728 Status
= ZwCreateKey(&LogConfKey
,
735 if (NT_SUCCESS(Status
))
737 /* Set 'BootConfig' value */
738 if (DeviceNode
->BootResources
!= NULL
)
740 ResCount
= DeviceNode
->BootResources
->Count
;
743 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
745 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
746 Status
= ZwSetValueKey(LogConfKey
,
750 DeviceNode
->BootResources
,
755 /* Set 'BasicConfigVector' value */
756 if (DeviceNode
->ResourceRequirements
!= NULL
&&
757 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
759 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
760 Status
= ZwSetValueKey(LogConfKey
,
763 REG_RESOURCE_REQUIREMENTS_LIST
,
764 DeviceNode
->ResourceRequirements
,
765 DeviceNode
->ResourceRequirements
->ListSize
);
771 /* Set the 'ConfigFlags' value */
772 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
773 Status
= ZwQueryValueKey(InstanceKey
,
775 KeyValueBasicInformation
,
779 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
781 /* Write the default value */
782 ULONG DefaultConfigFlags
= 0;
783 Status
= ZwSetValueKey(InstanceKey
,
788 sizeof(DefaultConfigFlags
));
791 DPRINT("IopSetDeviceInstanceData() done\n");
793 return STATUS_SUCCESS
;
798 IopAssignDeviceResources(
799 IN PDEVICE_NODE DeviceNode
,
800 OUT ULONG
*pRequiredSize
)
802 PIO_RESOURCE_LIST ResourceList
;
803 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
804 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
805 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
806 ULONG NumberOfResources
= 0;
811 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
813 /* No resource needed for this device */
814 DeviceNode
->ResourceList
= NULL
;
816 return STATUS_SUCCESS
;
819 /* Fill DeviceNode->ResourceList
820 * FIXME: the PnP arbiter should go there!
821 * Actually, use the BootResources if provided, else the resource list #0
824 if (DeviceNode
->BootResources
)
826 /* Browse the boot resources to know if we have some custom structures */
827 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
828 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
830 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
831 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
832 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
833 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
835 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
836 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
840 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
841 if (!DeviceNode
->ResourceList
)
843 Status
= STATUS_NO_MEMORY
;
846 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
848 *pRequiredSize
= Size
;
849 return STATUS_SUCCESS
;
852 /* Ok, here, we have to use the device requirement list */
853 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
854 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
856 Status
= STATUS_REVISION_MISMATCH
;
860 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
861 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
862 if (!DeviceNode
->ResourceList
)
864 Status
= STATUS_NO_MEMORY
;
868 DeviceNode
->ResourceList
->Count
= 1;
869 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
870 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
871 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
872 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
874 for (i
= 0; i
< ResourceList
->Count
; i
++)
876 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
878 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
880 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
883 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
884 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
885 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
886 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
887 switch (ResourceDescriptor
->Type
)
889 case CmResourceTypePort
:
891 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
892 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
895 case CmResourceTypeInterrupt
:
897 INTERFACE_TYPE BusType
;
902 DescriptorRaw
->u
.Interrupt
.Level
= 0;
903 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
904 /* FIXME: HACK: if we have a PCI device, we try
905 * to keep the IRQ assigned by the BIOS */
906 if (NT_SUCCESS(IoGetDeviceProperty(
907 DeviceNode
->PhysicalDeviceObject
,
908 DevicePropertyLegacyBusType
,
909 sizeof(INTERFACE_TYPE
),
911 &ret
)) && BusType
== PCIBus
)
913 /* We have a PCI bus */
914 if (NT_SUCCESS(IoGetDeviceProperty(
915 DeviceNode
->PhysicalDeviceObject
,
916 DevicePropertyAddress
,
919 &ret
)) && SlotNumber
> 0)
921 /* We have a good slot number */
922 ret
= HalGetBusDataByOffset(PCIConfiguration
,
923 DeviceNode
->ResourceRequirements
->BusNumber
,
926 0x3c /* PCI_INTERRUPT_LINE */,
928 if (ret
!= 0 && ret
!= 2
929 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
930 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
932 /* The device already has an assigned IRQ */
933 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
937 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
938 DescriptorRaw
->u
.Interrupt
.Vector
,
939 &DeviceNode
->InstancePath
);
940 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
941 ret
= HalSetBusDataByOffset(PCIConfiguration
,
942 DeviceNode
->ResourceRequirements
->BusNumber
,
945 0x3c /* PCI_INTERRUPT_LINE */,
947 if (ret
== 0 || ret
== 2)
954 case CmResourceTypeMemory
:
956 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
957 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
960 case CmResourceTypeDma
:
962 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
963 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
964 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
967 case CmResourceTypeBusNumber
:
969 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
970 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
971 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
974 /*CmResourceTypeDevicePrivate:
975 case CmResourceTypePcCardConfig:
976 case CmResourceTypeMfCardConfig:
979 &DescriptorRaw->u.DevicePrivate,
980 &ResourceDescriptor->u.DevicePrivate,
981 sizeof(ResourceDescriptor->u.DevicePrivate));
983 &DescriptorTranslated->u.DevicePrivate,
984 &ResourceDescriptor->u.DevicePrivate,
985 sizeof(ResourceDescriptor->u.DevicePrivate));
989 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
996 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
998 *pRequiredSize
= Size
;
999 return STATUS_SUCCESS
;
1002 if (DeviceNode
->ResourceList
)
1004 ExFreePool(DeviceNode
->ResourceList
);
1005 DeviceNode
->ResourceList
= NULL
;
1013 IopTranslateDeviceResources(
1014 IN PDEVICE_NODE DeviceNode
,
1015 IN ULONG RequiredSize
)
1017 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1018 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1022 if (!DeviceNode
->ResourceList
)
1024 DeviceNode
->ResourceListTranslated
= NULL
;
1025 return STATUS_SUCCESS
;
1028 /* That's easy to translate a resource list. Just copy the
1029 * untranslated one and change few fields in the copy
1031 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1032 if (!DeviceNode
->ResourceListTranslated
)
1034 Status
=STATUS_NO_MEMORY
;
1037 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1039 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1041 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1042 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1044 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1045 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1046 switch (DescriptorRaw
->Type
)
1048 case CmResourceTypePort
:
1050 ULONG AddressSpace
= 1; /* IO space */
1051 if (!HalTranslateBusAddress(
1052 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1053 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1054 DescriptorRaw
->u
.Port
.Start
,
1056 &DescriptorTranslated
->u
.Port
.Start
))
1058 Status
= STATUS_UNSUCCESSFUL
;
1063 case CmResourceTypeInterrupt
:
1065 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1066 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1067 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1068 DescriptorRaw
->u
.Interrupt
.Level
,
1069 DescriptorRaw
->u
.Interrupt
.Vector
,
1070 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1071 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1074 case CmResourceTypeMemory
:
1076 ULONG AddressSpace
= 0; /* Memory space */
1077 if (!HalTranslateBusAddress(
1078 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1079 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1080 DescriptorRaw
->u
.Memory
.Start
,
1082 &DescriptorTranslated
->u
.Memory
.Start
))
1084 Status
= STATUS_UNSUCCESSFUL
;
1089 case CmResourceTypeDma
:
1090 case CmResourceTypeBusNumber
:
1091 case CmResourceTypeDeviceSpecific
:
1095 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1096 Status
= STATUS_NOT_IMPLEMENTED
;
1101 return STATUS_SUCCESS
;
1104 /* Yes! Also delete ResourceList because ResourceList and
1105 * ResourceListTranslated should be a pair! */
1106 ExFreePool(DeviceNode
->ResourceList
);
1107 DeviceNode
->ResourceList
= NULL
;
1108 if (DeviceNode
->ResourceListTranslated
)
1110 ExFreePool(DeviceNode
->ResourceListTranslated
);
1111 DeviceNode
->ResourceList
= NULL
;
1118 * IopGetParentIdPrefix
1120 * Retrieve (or create) a string which identifies a device.
1124 * Pointer to device node.
1126 * Pointer to the string where is returned the parent node identifier
1129 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1130 * valid and its Buffer field is NULL-terminated. The caller needs to
1131 * to free the string with RtlFreeUnicodeString when it is no longer
1136 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1137 PUNICODE_STRING ParentIdPrefix
)
1139 ULONG KeyNameBufferLength
;
1140 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1141 UNICODE_STRING KeyName
;
1142 UNICODE_STRING KeyValue
;
1143 UNICODE_STRING ValueName
;
1148 /* HACK: As long as some devices have a NULL device
1149 * instance path, the following test is required :(
1151 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1153 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1154 &DeviceNode
->InstancePath
);
1155 return STATUS_UNSUCCESSFUL
;
1158 /* 1. Try to retrieve ParentIdPrefix from registry */
1159 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1160 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1161 if (!ParentIdPrefixInformation
)
1163 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1168 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1169 if (!KeyName
.Buffer
)
1171 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1175 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1177 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1178 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1180 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1181 if (!NT_SUCCESS(Status
))
1183 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1184 Status
= ZwQueryValueKey(
1186 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1187 KeyNameBufferLength
, &KeyNameBufferLength
);
1188 if (NT_SUCCESS(Status
))
1190 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1191 Status
= STATUS_UNSUCCESSFUL
;
1194 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1195 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1199 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1201 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1202 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1206 /* 2. Create the ParentIdPrefix value */
1207 crc32
= RtlComputeCrc32(0,
1208 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1209 DeviceNode
->Parent
->InstancePath
.Length
);
1211 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1212 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1214 /* 3. Try to write the ParentIdPrefix to registry */
1215 Status
= ZwSetValueKey(hKey
,
1219 (PVOID
)KeyValue
.Buffer
,
1220 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1223 if (NT_SUCCESS(Status
))
1225 /* Duplicate the string to return it */
1226 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1228 ExFreePool(ParentIdPrefixInformation
);
1229 RtlFreeUnicodeString(&KeyName
);
1237 * IopActionInterrogateDeviceStack
1239 * Retrieve information for all (direct) child nodes of a parent node.
1243 * Pointer to device node.
1245 * Pointer to parent node to retrieve child node information for.
1248 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1249 * when we reach a device node which is not a direct child of the device
1250 * node for which we retrieve information of child nodes for. Any errors
1251 * that occur is logged instead so that all child services have a chance
1252 * of being interrogated.
1256 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1259 IO_STATUS_BLOCK IoStatusBlock
;
1260 PDEVICE_NODE ParentDeviceNode
;
1261 WCHAR InstancePath
[MAX_PATH
];
1262 IO_STACK_LOCATION Stack
;
1267 ULONG RequiredLength
;
1269 HANDLE InstanceKey
= NULL
;
1270 UNICODE_STRING ValueName
;
1271 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1272 DEVICE_CAPABILITIES DeviceCapabilities
;
1274 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1275 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1277 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1280 * We are called for the parent too, but we don't need to do special
1281 * handling for this node
1284 if (DeviceNode
== ParentDeviceNode
)
1286 DPRINT("Success\n");
1287 return STATUS_SUCCESS
;
1291 * Make sure this device node is a direct child of the parent device node
1292 * that is given as an argument
1295 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1297 /* Stop the traversal immediately and indicate successful operation */
1299 return STATUS_UNSUCCESSFUL
;
1303 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1304 if (!NT_SUCCESS(Status
))
1306 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1311 * FIXME: For critical errors, cleanup and disable device, but always
1312 * return STATUS_SUCCESS.
1315 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1317 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1318 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1322 if (NT_SUCCESS(Status
))
1324 /* Copy the device id string */
1325 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1328 * FIXME: Check for valid characters, if there is invalid characters
1334 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1337 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1339 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1340 if (!NT_SUCCESS(Status
))
1342 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1345 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1347 if (!DeviceCapabilities
.UniqueID
)
1349 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1350 DPRINT("Instance ID is not unique\n");
1351 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1352 if (!NT_SUCCESS(Status
))
1354 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1358 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1360 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1361 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1365 if (NT_SUCCESS(Status
))
1367 /* Append the instance id string */
1368 wcscat(InstancePath
, L
"\\");
1369 if (ParentIdPrefix
.Length
> 0)
1371 /* Add information from parent bus device to InstancePath */
1372 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1373 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1374 wcscat(InstancePath
, L
"&");
1376 if (IoStatusBlock
.Information
)
1377 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1380 * FIXME: Check for valid characters, if there is invalid characters
1386 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1388 RtlFreeUnicodeString(&ParentIdPrefix
);
1390 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1392 DPRINT("No resources\n");
1393 /* FIXME: Cleanup and disable device */
1396 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1399 * Create registry key for the instance id, if it doesn't exist yet
1401 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceKey
);
1402 if (!NT_SUCCESS(Status
))
1404 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1408 /* Set 'Capabilities' value */
1409 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1410 Status
= ZwSetValueKey(InstanceKey
,
1414 (PVOID
)&DeviceNode
->CapabilityFlags
,
1417 /* Set 'UINumber' value */
1418 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1420 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1421 Status
= ZwSetValueKey(InstanceKey
,
1425 &DeviceCapabilities
.UINumber
,
1430 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1432 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1433 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1437 if (NT_SUCCESS(Status
))
1440 * FIXME: Check for valid characters, if there is invalid characters
1444 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1445 DPRINT("Hardware IDs:\n");
1448 DPRINT(" %S\n", Ptr
);
1449 Length
= wcslen(Ptr
) + 1;
1452 TotalLength
+= Length
;
1454 DPRINT("TotalLength: %hu\n", TotalLength
);
1457 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1458 Status
= ZwSetValueKey(InstanceKey
,
1462 (PVOID
)IoStatusBlock
.Information
,
1463 (TotalLength
+ 1) * sizeof(WCHAR
));
1464 if (!NT_SUCCESS(Status
))
1466 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1471 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1474 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1476 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1477 Status
= IopInitiatePnpIrp(
1478 DeviceNode
->PhysicalDeviceObject
,
1482 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1485 * FIXME: Check for valid characters, if there is invalid characters
1489 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1490 DPRINT("Compatible IDs:\n");
1493 DPRINT(" %S\n", Ptr
);
1494 Length
= wcslen(Ptr
) + 1;
1497 TotalLength
+= Length
;
1499 DPRINT("TotalLength: %hu\n", TotalLength
);
1502 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1503 Status
= ZwSetValueKey(InstanceKey
,
1507 (PVOID
)IoStatusBlock
.Information
,
1508 (TotalLength
+ 1) * sizeof(WCHAR
));
1509 if (!NT_SUCCESS(Status
))
1511 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1516 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1519 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1521 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1522 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1523 Status
= IopInitiatePnpIrp(
1524 DeviceNode
->PhysicalDeviceObject
,
1526 IRP_MN_QUERY_DEVICE_TEXT
,
1528 /* This key is mandatory, so even if the Irp fails, we still write it */
1529 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1530 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1532 if (NT_SUCCESS(Status
) &&
1533 IoStatusBlock
.Information
&&
1534 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1536 /* This key is overriden when a driver is installed. Don't write the
1537 * new description if another one already exists */
1538 Status
= ZwSetValueKey(InstanceKey
,
1542 (PVOID
)IoStatusBlock
.Information
,
1543 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1547 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1548 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1550 Status
= ZwSetValueKey(InstanceKey
,
1555 DeviceDesc
.MaximumLength
);
1557 if (!NT_SUCCESS(Status
))
1559 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1565 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1567 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1568 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1569 Status
= IopInitiatePnpIrp(
1570 DeviceNode
->PhysicalDeviceObject
,
1572 IRP_MN_QUERY_DEVICE_TEXT
,
1574 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1576 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1577 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1578 Status
= ZwSetValueKey(InstanceKey
,
1582 (PVOID
)IoStatusBlock
.Information
,
1583 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1584 if (!NT_SUCCESS(Status
))
1586 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1591 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1594 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1596 Status
= IopInitiatePnpIrp(
1597 DeviceNode
->PhysicalDeviceObject
,
1599 IRP_MN_QUERY_BUS_INFORMATION
,
1601 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1603 PPNP_BUS_INFORMATION BusInformation
=
1604 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1606 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1607 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1608 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1609 ExFreePool(BusInformation
);
1613 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1615 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1616 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1617 DeviceNode
->ChildBusTypeIndex
= -1;
1620 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1622 Status
= IopInitiatePnpIrp(
1623 DeviceNode
->PhysicalDeviceObject
,
1625 IRP_MN_QUERY_RESOURCES
,
1627 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1629 DeviceNode
->BootResources
=
1630 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1631 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1635 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1636 DeviceNode
->BootResources
= NULL
;
1639 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1641 Status
= IopInitiatePnpIrp(
1642 DeviceNode
->PhysicalDeviceObject
,
1644 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1646 if (NT_SUCCESS(Status
))
1648 DeviceNode
->ResourceRequirements
=
1649 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1650 if (IoStatusBlock
.Information
)
1651 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
1653 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
1657 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1658 DeviceNode
->ResourceRequirements
= NULL
;
1662 if (InstanceKey
!= NULL
)
1664 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1667 ZwClose(InstanceKey
);
1669 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1671 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1673 /* Report the device to the user-mode pnp manager */
1674 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1675 &DeviceNode
->InstancePath
);
1678 return STATUS_SUCCESS
;
1684 IN PDEVICE_OBJECT DeviceObject
)
1686 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1687 DEVICETREE_TRAVERSE_CONTEXT Context
;
1688 PDEVICE_RELATIONS DeviceRelations
;
1689 PDEVICE_OBJECT ChildDeviceObject
;
1690 IO_STATUS_BLOCK IoStatusBlock
;
1691 PDEVICE_NODE ChildDeviceNode
;
1692 IO_STACK_LOCATION Stack
;
1696 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1698 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1700 /* Report the device to the user-mode pnp manager */
1701 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1702 &DeviceNode
->InstancePath
);
1704 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1706 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1708 Status
= IopInitiatePnpIrp(
1711 IRP_MN_QUERY_DEVICE_RELATIONS
,
1713 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1715 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1719 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1721 if (!DeviceRelations
)
1723 DPRINT("No PDOs\n");
1724 return STATUS_UNSUCCESSFUL
;
1727 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1730 * Create device nodes for all discovered devices
1732 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1734 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1735 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1737 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1738 if (!ChildDeviceNode
)
1740 /* One doesn't exist, create it */
1741 Status
= IopCreateDeviceNode(
1746 if (NT_SUCCESS(Status
))
1748 /* Mark the node as enumerated */
1749 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1751 /* Mark the DO as bus enumerated */
1752 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1756 /* Ignore this DO */
1757 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1758 ObDereferenceObject(ChildDeviceNode
);
1763 /* Mark it as enumerated */
1764 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1765 ObDereferenceObject(ChildDeviceObject
);
1768 ExFreePool(DeviceRelations
);
1771 * Retrieve information about all discovered children from the bus driver
1773 IopInitDeviceTreeTraverseContext(
1776 IopActionInterrogateDeviceStack
,
1779 Status
= IopTraverseDeviceTree(&Context
);
1780 if (!NT_SUCCESS(Status
))
1782 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1787 * Retrieve configuration from the registry for discovered children
1789 IopInitDeviceTreeTraverseContext(
1792 IopActionConfigureChildServices
,
1795 Status
= IopTraverseDeviceTree(&Context
);
1796 if (!NT_SUCCESS(Status
))
1798 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1803 * Initialize services for discovered children.
1805 Status
= IopInitializePnpServices(DeviceNode
);
1806 if (!NT_SUCCESS(Status
))
1808 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1812 DPRINT("IopEnumerateDevice() finished\n");
1813 return STATUS_SUCCESS
;
1818 * IopActionConfigureChildServices
1820 * Retrieve configuration for all (direct) child nodes of a parent node.
1824 * Pointer to device node.
1826 * Pointer to parent node to retrieve child node configuration for.
1829 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1830 * when we reach a device node which is not a direct child of the device
1831 * node for which we configure child services for. Any errors that occur is
1832 * logged instead so that all child services have a chance of beeing
1837 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1840 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1841 PDEVICE_NODE ParentDeviceNode
;
1842 PUNICODE_STRING Service
;
1843 UNICODE_STRING ClassGUID
;
1846 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1848 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1851 * We are called for the parent too, but we don't need to do special
1852 * handling for this node
1854 if (DeviceNode
== ParentDeviceNode
)
1856 DPRINT("Success\n");
1857 return STATUS_SUCCESS
;
1861 * Make sure this device node is a direct child of the parent device node
1862 * that is given as an argument
1864 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1866 /* Stop the traversal immediately and indicate successful operation */
1868 return STATUS_UNSUCCESSFUL
;
1871 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1873 WCHAR RegKeyBuffer
[MAX_PATH
];
1874 UNICODE_STRING RegKey
;
1877 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1878 RegKey
.Buffer
= RegKeyBuffer
;
1881 * Retrieve configuration from Enum key
1884 Service
= &DeviceNode
->ServiceName
;
1886 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1887 RtlInitUnicodeString(Service
, NULL
);
1888 RtlInitUnicodeString(&ClassGUID
, NULL
);
1890 QueryTable
[0].Name
= L
"Service";
1891 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1892 QueryTable
[0].EntryContext
= Service
;
1894 QueryTable
[1].Name
= L
"ClassGUID";
1895 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1896 QueryTable
[1].EntryContext
= &ClassGUID
;
1897 QueryTable
[1].DefaultType
= REG_SZ
;
1898 QueryTable
[1].DefaultData
= L
"";
1899 QueryTable
[1].DefaultLength
= 0;
1901 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1902 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1904 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1905 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1907 if (!NT_SUCCESS(Status
))
1909 /* FIXME: Log the error */
1910 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
1911 &DeviceNode
->InstancePath
, Status
);
1912 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1913 return STATUS_SUCCESS
;
1916 if (Service
->Buffer
== NULL
)
1918 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1920 if (ClassGUID
.Length
!= 0)
1922 /* Device has a ClassGUID value, but no Service value.
1923 * Suppose it is using the NULL driver, so state the
1924 * device is started */
1925 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
1926 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1928 return STATUS_SUCCESS
;
1931 DPRINT("Got Service %S\n", Service
->Buffer
);
1934 return STATUS_SUCCESS
;
1938 * IopActionInitChildServices
1940 * Initialize the service for all (direct) child nodes of a parent node
1944 * Pointer to device node.
1946 * Pointer to parent node to initialize child node services for.
1949 * If the driver image for a service is not loaded and initialized
1950 * it is done here too. We only return a status code indicating an
1951 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1952 * not a direct child of the device node for which we initialize
1953 * child services for. Any errors that occur is logged instead so
1954 * that all child services have a chance of being initialized.
1958 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
1961 PDEVICE_NODE ParentDeviceNode
;
1963 BOOLEAN BootDrivers
= !PnpSystemInit
;
1965 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
1967 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1970 * We are called for the parent too, but we don't need to do special
1971 * handling for this node
1973 if (DeviceNode
== ParentDeviceNode
)
1975 DPRINT("Success\n");
1976 return STATUS_SUCCESS
;
1980 * Make sure this device node is a direct child of the parent device node
1981 * that is given as an argument
1984 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1987 * Stop the traversal immediately and indicate unsuccessful operation
1990 return STATUS_UNSUCCESSFUL
;
1994 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1995 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1996 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1998 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1999 PDRIVER_OBJECT DriverObject
;
2001 /* Get existing DriverObject pointer (in case the driver has
2002 already been loaded and initialized) */
2003 Status
= IopGetDriverObject(
2005 &DeviceNode
->ServiceName
,
2008 if (!NT_SUCCESS(Status
))
2010 /* Driver is not initialized, try to load it */
2011 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2013 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2015 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2016 was loaded by the bootloader */
2017 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2018 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2020 /* Initialize the driver */
2021 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2022 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2026 Status
= STATUS_SUCCESS
;
2031 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2032 &DeviceNode
->ServiceName
, Status
);
2036 /* Driver is loaded and initialized at this point */
2037 if (NT_SUCCESS(Status
))
2039 /* Attach lower level filter drivers. */
2040 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2041 /* Initialize the function driver for the device node */
2042 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2044 if (NT_SUCCESS(Status
))
2046 /* Attach upper level filter drivers. */
2047 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2048 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2050 Status
= IopStartDevice(DeviceNode
);
2054 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2055 &DeviceNode
->InstancePath
, Status
);
2061 * Don't disable when trying to load only boot drivers
2065 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2066 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2067 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2068 DPRINT1("Initialization of service %S failed (Status %x)\n",
2069 DeviceNode
->ServiceName
.Buffer
, Status
);
2075 DPRINT("Device %wZ is disabled or already initialized\n",
2076 &DeviceNode
->InstancePath
);
2079 return STATUS_SUCCESS
;
2083 * IopInitializePnpServices
2085 * Initialize services for discovered children
2089 * Top device node to start initializing services.
2095 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2097 DEVICETREE_TRAVERSE_CONTEXT Context
;
2099 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2101 IopInitDeviceTreeTraverseContext(
2104 IopActionInitChildServices
,
2107 return IopTraverseDeviceTree(&Context
);
2110 static NTSTATUS INIT_FUNCTION
2111 IopEnumerateDetectedDevices(
2113 IN PUNICODE_STRING RelativePath OPTIONAL
,
2115 IN BOOLEAN EnumerateSubKeys
,
2116 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2117 IN ULONG ParentBootResourcesLength
)
2119 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2120 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2121 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2122 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2123 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2124 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2125 OBJECT_ATTRIBUTES ObjectAttributes
;
2126 HANDLE hDevicesKey
= NULL
;
2127 HANDLE hDeviceKey
= NULL
;
2128 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2129 UNICODE_STRING Level2NameU
;
2130 WCHAR Level2Name
[5];
2131 ULONG IndexDevice
= 0;
2133 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2134 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2135 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2136 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2137 UNICODE_STRING DeviceName
, ValueName
;
2139 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2140 ULONG BootResourcesLength
;
2143 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2144 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2145 static ULONG DeviceIndexPci
= 0;
2147 const UNICODE_STRING IdentifierAcpi
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2148 UNICODE_STRING HardwareIdAcpi
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2149 static ULONG DeviceIndexAcpi
= 0;
2151 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2152 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2153 static ULONG DeviceIndexSerial
= 0;
2154 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2155 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2156 static ULONG DeviceIndexKeyboard
= 0;
2157 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2158 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2159 static ULONG DeviceIndexMouse
= 0;
2160 UNICODE_STRING HardwareIdKey
;
2161 PUNICODE_STRING pHardwareId
;
2162 ULONG DeviceIndex
= 0;
2166 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2167 if (!NT_SUCCESS(Status
))
2169 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2174 hDevicesKey
= hBaseKey
;
2176 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2177 if (!pDeviceInformation
)
2179 DPRINT("ExAllocatePool() failed\n");
2180 Status
= STATUS_NO_MEMORY
;
2184 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2185 if (!pValueInformation
)
2187 DPRINT("ExAllocatePool() failed\n");
2188 Status
= STATUS_NO_MEMORY
;
2194 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2195 if (Status
== STATUS_NO_MORE_ENTRIES
)
2197 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2199 ExFreePool(pDeviceInformation
);
2200 DeviceInfoLength
= RequiredSize
;
2201 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2202 if (!pDeviceInformation
)
2204 DPRINT("ExAllocatePool() failed\n");
2205 Status
= STATUS_NO_MEMORY
;
2208 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2210 if (!NT_SUCCESS(Status
))
2212 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2217 /* Open device key */
2218 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2219 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2221 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2222 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2223 if (!NT_SUCCESS(Status
))
2225 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2229 /* Read boot resources, and add then to parent ones */
2230 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2231 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2233 ExFreePool(pValueInformation
);
2234 ValueInfoLength
= RequiredSize
;
2235 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2236 if (!pValueInformation
)
2238 DPRINT("ExAllocatePool() failed\n");
2239 ZwDeleteKey(hLevel2Key
);
2240 Status
= STATUS_NO_MEMORY
;
2243 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2245 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2247 BootResources
= ParentBootResources
;
2248 BootResourcesLength
= ParentBootResourcesLength
;
2250 else if (!NT_SUCCESS(Status
))
2252 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2255 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2257 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2262 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2264 /* Concatenate current resources and parent ones */
2265 if (ParentBootResourcesLength
== 0)
2266 BootResourcesLength
= pValueInformation
->DataLength
;
2268 BootResourcesLength
= ParentBootResourcesLength
2269 + pValueInformation
->DataLength
2271 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2274 DPRINT("ExAllocatePool() failed\n");
2277 if (ParentBootResourcesLength
== 0)
2279 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2281 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2283 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2285 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2286 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2287 ParentBootResourcesLength
- Header
);
2288 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2292 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2294 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2295 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2296 ParentBootResourcesLength
- Header
);
2298 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2299 pValueInformation
->Data
+ Header
,
2300 pValueInformation
->DataLength
- Header
);
2301 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2305 if (EnumerateSubKeys
)
2310 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2311 if (Status
== STATUS_NO_MORE_ENTRIES
)
2313 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2315 ExFreePool(pDeviceInformation
);
2316 DeviceInfoLength
= RequiredSize
;
2317 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2318 if (!pDeviceInformation
)
2320 DPRINT("ExAllocatePool() failed\n");
2321 Status
= STATUS_NO_MEMORY
;
2324 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2326 if (!NT_SUCCESS(Status
))
2328 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2332 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2333 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2335 Status
= IopEnumerateDetectedDevices(
2341 BootResourcesLength
);
2342 if (!NT_SUCCESS(Status
))
2347 /* Read identifier */
2348 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2349 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2351 ExFreePool(pValueInformation
);
2352 ValueInfoLength
= RequiredSize
;
2353 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2354 if (!pValueInformation
)
2356 DPRINT("ExAllocatePool() failed\n");
2357 Status
= STATUS_NO_MEMORY
;
2360 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2362 if (!NT_SUCCESS(Status
))
2364 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2366 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2369 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2371 else if (pValueInformation
->Type
!= REG_SZ
)
2373 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2378 /* Assign hardware id to this device */
2379 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2380 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2381 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2382 ValueName
.Length
-= sizeof(WCHAR
);
2385 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2387 pHardwareId
= &HardwareIdSerial
;
2388 DeviceIndex
= DeviceIndexSerial
++;
2390 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2392 pHardwareId
= &HardwareIdKeyboard
;
2393 DeviceIndex
= DeviceIndexKeyboard
++;
2395 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2397 pHardwareId
= &HardwareIdMouse
;
2398 DeviceIndex
= DeviceIndexMouse
++;
2400 else if (NT_SUCCESS(Status
))
2402 /* Try to also match the device identifier */
2403 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2405 pHardwareId
= &HardwareIdPci
;
2406 DeviceIndex
= DeviceIndexPci
++;
2409 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierAcpi
, FALSE
) == 0)
2411 pHardwareId
= &HardwareIdAcpi
;
2412 DeviceIndex
= DeviceIndexAcpi
++;
2417 /* Unknown device */
2418 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2424 /* Unknown key path */
2425 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2429 /* Prepare hardware id key (hardware id value without final \0) */
2430 HardwareIdKey
= *pHardwareId
;
2431 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2433 /* Add the detected device to Root key */
2434 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2435 Status
= ZwCreateKey(
2441 REG_OPTION_NON_VOLATILE
,
2443 if (!NT_SUCCESS(Status
))
2445 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2448 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2449 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2450 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2451 Status
= ZwCreateKey(
2453 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2457 REG_OPTION_NON_VOLATILE
,
2459 ZwClose(hLevel1Key
);
2460 if (!NT_SUCCESS(Status
))
2462 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2465 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
2466 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
2467 if (!NT_SUCCESS(Status
))
2469 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2470 ZwDeleteKey(hLevel2Key
);
2473 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2474 if (!NT_SUCCESS(Status
))
2476 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2477 ZwDeleteKey(hLevel2Key
);
2480 /* Create 'LogConf' subkey */
2481 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2482 Status
= ZwCreateKey(
2488 REG_OPTION_VOLATILE
,
2490 if (!NT_SUCCESS(Status
))
2492 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2493 ZwDeleteKey(hLevel2Key
);
2496 if (BootResourcesLength
> 0)
2498 /* Save boot resources to 'LogConf\BootConfig' */
2499 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
2500 if (!NT_SUCCESS(Status
))
2502 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2504 ZwDeleteKey(hLevel2Key
);
2511 if (BootResources
&& BootResources
!= ParentBootResources
)
2512 ExFreePool(BootResources
);
2515 ZwClose(hLevel2Key
);
2520 ZwClose(hDeviceKey
);
2525 Status
= STATUS_SUCCESS
;
2528 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2529 ZwClose(hDevicesKey
);
2531 ZwClose(hDeviceKey
);
2532 if (pDeviceInformation
)
2533 ExFreePool(pDeviceInformation
);
2534 if (pValueInformation
)
2535 ExFreePool(pValueInformation
);
2539 static BOOLEAN INIT_FUNCTION
2540 IopIsAcpiComputer(VOID
)
2545 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2546 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2547 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2548 OBJECT_ATTRIBUTES ObjectAttributes
;
2549 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2550 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2551 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2552 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2554 ULONG IndexDevice
= 0;
2555 UNICODE_STRING DeviceName
, ValueName
;
2556 HANDLE hDevicesKey
= NULL
;
2557 HANDLE hDeviceKey
= NULL
;
2559 BOOLEAN ret
= FALSE
;
2561 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
2562 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2563 if (!NT_SUCCESS(Status
))
2565 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2569 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2570 if (!pDeviceInformation
)
2572 DPRINT("ExAllocatePool() failed\n");
2573 Status
= STATUS_NO_MEMORY
;
2577 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2578 if (!pDeviceInformation
)
2580 DPRINT("ExAllocatePool() failed\n");
2581 Status
= STATUS_NO_MEMORY
;
2587 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2588 if (Status
== STATUS_NO_MORE_ENTRIES
)
2590 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2592 ExFreePool(pDeviceInformation
);
2593 DeviceInfoLength
= RequiredSize
;
2594 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2595 if (!pDeviceInformation
)
2597 DPRINT("ExAllocatePool() failed\n");
2598 Status
= STATUS_NO_MEMORY
;
2601 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2603 if (!NT_SUCCESS(Status
))
2605 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2610 /* Open device key */
2611 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2612 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2613 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2618 if (!NT_SUCCESS(Status
))
2620 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2624 /* Read identifier */
2625 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2626 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2628 ExFreePool(pValueInformation
);
2629 ValueInfoLength
= RequiredSize
;
2630 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2631 if (!pValueInformation
)
2633 DPRINT("ExAllocatePool() failed\n");
2634 Status
= STATUS_NO_MEMORY
;
2637 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2639 if (!NT_SUCCESS(Status
))
2641 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2644 else if (pValueInformation
->Type
!= REG_SZ
)
2646 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2650 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2651 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2652 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2653 ValueName
.Length
-= sizeof(WCHAR
);
2654 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
2656 DPRINT("Found ACPI BIOS\n");
2662 ZwClose(hDeviceKey
);
2667 if (pDeviceInformation
)
2668 ExFreePool(pDeviceInformation
);
2669 if (pValueInformation
)
2670 ExFreePool(pValueInformation
);
2672 ZwClose(hDevicesKey
);
2674 ZwClose(hDeviceKey
);
2679 static NTSTATUS INIT_FUNCTION
2680 IopUpdateRootKey(VOID
)
2682 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2683 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2684 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2685 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2686 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2687 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2688 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
2689 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
2690 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
2691 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2692 OBJECT_ATTRIBUTES ObjectAttributes
;
2693 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
2696 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2697 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2698 if (!NT_SUCCESS(Status
))
2700 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2704 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2705 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2707 if (!NT_SUCCESS(Status
))
2709 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2713 if (IopIsAcpiComputer())
2715 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
2716 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2718 if (!NT_SUCCESS(Status
))
2720 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
2721 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2722 ZwClose(hHalAcpiDevice
);
2723 if (!NT_SUCCESS(Status
))
2725 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
2726 if (NT_SUCCESS(Status
))
2727 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
2728 if (NT_SUCCESS(Status
))
2730 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
2731 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2732 if (NT_SUCCESS(Status
))
2735 ZwClose(hHalAcpiId
);
2740 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2741 if (!NT_SUCCESS(Status
))
2743 /* Nothing to do, don't return with an error status */
2744 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2746 return STATUS_SUCCESS
;
2748 Status
= IopEnumerateDetectedDevices(
2763 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2765 PUNICODE_STRING Name
,
2766 ACCESS_MASK DesiredAccess
)
2768 OBJECT_ATTRIBUTES ObjectAttributes
;
2775 InitializeObjectAttributes(&ObjectAttributes
,
2777 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2781 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2788 IopGetRegistryValue(IN HANDLE Handle
,
2790 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
2792 UNICODE_STRING ValueString
;
2794 PKEY_VALUE_FULL_INFORMATION FullInformation
;
2798 RtlInitUnicodeString(&ValueString
, ValueName
);
2800 Status
= ZwQueryValueKey(Handle
,
2802 KeyValueFullInformation
,
2806 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
2807 (Status
!= STATUS_BUFFER_TOO_SMALL
))
2812 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
2813 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
2815 Status
= ZwQueryValueKey(Handle
,
2817 KeyValueFullInformation
,
2821 if (!NT_SUCCESS(Status
))
2823 ExFreePool(FullInformation
);
2827 *Information
= FullInformation
;
2828 return STATUS_SUCCESS
;
2831 static NTSTATUS INIT_FUNCTION
2833 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
2835 return STATUS_SUCCESS
;
2844 DPRINT("PnpInit()\n");
2846 KeInitializeSpinLock(&IopDeviceTreeLock
);
2847 ExInitializeFastMutex(&IopBusTypeGuidListLock
);
2849 /* Initialize the Bus Type GUID List */
2850 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2851 if (!IopBusTypeGuidList
) {
2852 DPRINT1("ExAllocatePool() failed\n");
2853 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
2856 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2857 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2859 /* Initialize PnP-Event notification support */
2860 Status
= IopInitPlugPlayEvents();
2861 if (!NT_SUCCESS(Status
))
2863 DPRINT1("IopInitPlugPlayEvents() failed\n");
2864 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2868 * Create root device node
2871 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
2872 if (!NT_SUCCESS(Status
))
2874 DPRINT1("IoCreateDriverObject() failed\n");
2875 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2878 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2880 if (!NT_SUCCESS(Status
))
2882 DPRINT1("IoCreateDevice() failed\n");
2883 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2886 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
2887 if (!NT_SUCCESS(Status
))
2889 DPRINT1("Insufficient resources\n");
2890 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2893 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2896 DPRINT1("Failed to create the instance path!\n");
2897 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
2900 /* Report the device to the user-mode pnp manager */
2901 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2902 &IopRootDeviceNode
->InstancePath
);
2904 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2905 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2906 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2907 IopRootDriverObject
->DriverExtension
->AddDevice(
2908 IopRootDriverObject
,
2909 IopRootDeviceNode
->PhysicalDeviceObject
);
2911 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
2912 Status
= IopUpdateRootKey();
2913 if (!NT_SUCCESS(Status
))
2915 DPRINT1("IopUpdateRootKey() failed\n");
2916 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2920 RTL_GENERIC_COMPARE_RESULTS
2922 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
2923 IN PVOID FirstStruct
,
2924 IN PVOID SecondStruct
)
2932 // The allocation function is called by the generic table package whenever
2933 // it needs to allocate memory for the table.
2938 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
2948 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
2957 PpInitializeDeviceReferenceTable(VOID
)
2959 /* Setup the guarded mutex and AVL table */
2960 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
2961 RtlInitializeGenericTableAvl(
2962 &PpDeviceReferenceTable
,
2963 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
2964 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
2965 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
2973 /* Initialize the resource when accessing device registry data */
2974 ExInitializeResourceLite(&PpRegistryDeviceResource
);
2976 /* Setup the device reference AVL table */
2977 PpInitializeDeviceReferenceTable();
2985 /* Check the initialization phase */
2986 switch (ExpInitializationPhase
)
2991 return PiInitPhase0();
2997 //return PiInitPhase1();
3001 /* Don't know any other phase! Bugcheck! */
3002 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3007 /* PUBLIC FUNCTIONS **********************************************************/
3014 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3015 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3016 IN ULONG BufferLength
,
3017 OUT PVOID PropertyBuffer
,
3018 OUT PULONG ResultLength
)
3020 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3021 DEVICE_CAPABILITIES DeviceCaps
;
3027 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3031 if (DeviceNode
== NULL
)
3032 return STATUS_INVALID_DEVICE_REQUEST
;
3034 switch (DeviceProperty
)
3036 case DevicePropertyBusNumber
:
3037 Length
= sizeof(ULONG
);
3038 Data
= &DeviceNode
->ChildBusNumber
;
3041 /* Complete, untested */
3042 case DevicePropertyBusTypeGuid
:
3044 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
3045 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
3047 /* Return the GUID */
3048 *ResultLength
= sizeof(GUID
);
3050 /* Check if the buffer given was large enough */
3051 if (BufferLength
< *ResultLength
)
3053 return STATUS_BUFFER_TOO_SMALL
;
3057 RtlCopyMemory(PropertyBuffer
,
3058 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
3060 return STATUS_SUCCESS
;
3064 return STATUS_OBJECT_NAME_NOT_FOUND
;
3068 case DevicePropertyLegacyBusType
:
3069 Length
= sizeof(INTERFACE_TYPE
);
3070 Data
= &DeviceNode
->ChildInterfaceType
;
3073 case DevicePropertyAddress
:
3074 /* Query the device caps */
3075 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3076 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
3079 *ResultLength
= sizeof(ULONG
);
3081 /* Check if the buffer given was large enough */
3082 if (BufferLength
< *ResultLength
)
3084 return STATUS_BUFFER_TOO_SMALL
;
3087 /* Return address */
3088 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
3089 return STATUS_SUCCESS
;
3093 return STATUS_OBJECT_NAME_NOT_FOUND
;
3097 // case DevicePropertyUINumber:
3098 // if (DeviceNode->CapabilityFlags == NULL)
3099 // return STATUS_INVALID_DEVICE_REQUEST;
3100 // Length = sizeof(ULONG);
3101 // Data = &DeviceNode->CapabilityFlags->UINumber;
3104 case DevicePropertyClassName
:
3105 case DevicePropertyClassGuid
:
3106 case DevicePropertyDriverKeyName
:
3107 case DevicePropertyManufacturer
:
3108 case DevicePropertyFriendlyName
:
3109 case DevicePropertyHardwareID
:
3110 case DevicePropertyCompatibleIDs
:
3111 case DevicePropertyDeviceDescription
:
3112 case DevicePropertyLocationInformation
:
3113 case DevicePropertyUINumber
:
3115 LPCWSTR RegistryPropertyName
;
3116 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
3117 UNICODE_STRING ValueName
;
3118 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
3119 ULONG ValueInformationLength
;
3120 HANDLE KeyHandle
, EnumRootHandle
;
3123 switch (DeviceProperty
)
3125 case DevicePropertyClassName
:
3126 RegistryPropertyName
= L
"Class"; break;
3127 case DevicePropertyClassGuid
:
3128 RegistryPropertyName
= L
"ClassGuid"; break;
3129 case DevicePropertyDriverKeyName
:
3130 RegistryPropertyName
= L
"Driver"; break;
3131 case DevicePropertyManufacturer
:
3132 RegistryPropertyName
= L
"Mfg"; break;
3133 case DevicePropertyFriendlyName
:
3134 RegistryPropertyName
= L
"FriendlyName"; break;
3135 case DevicePropertyHardwareID
:
3136 RegistryPropertyName
= L
"HardwareID"; break;
3137 case DevicePropertyCompatibleIDs
:
3138 RegistryPropertyName
= L
"CompatibleIDs"; break;
3139 case DevicePropertyDeviceDescription
:
3140 RegistryPropertyName
= L
"DeviceDesc"; break;
3141 case DevicePropertyLocationInformation
:
3142 RegistryPropertyName
= L
"LocationInformation"; break;
3143 case DevicePropertyUINumber
:
3144 RegistryPropertyName
= L
"UINumber"; break;
3146 /* Should not happen */
3148 return STATUS_UNSUCCESSFUL
;
3151 DPRINT("Registry property %S\n", RegistryPropertyName
);
3154 Status
= IopOpenRegistryKeyEx(&EnumRootHandle
, NULL
,
3155 &EnumRoot
, KEY_READ
);
3156 if (!NT_SUCCESS(Status
))
3158 DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status
);
3162 /* Open instance key */
3163 Status
= IopOpenRegistryKeyEx(&KeyHandle
, EnumRootHandle
,
3164 &DeviceNode
->InstancePath
, KEY_READ
);
3165 if (!NT_SUCCESS(Status
))
3167 DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status
);
3168 ZwClose(EnumRootHandle
);
3172 /* Allocate buffer to read as much data as required by the caller */
3173 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
3174 Data
[0]) + BufferLength
;
3175 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
3176 if (!ValueInformation
)
3179 return STATUS_INSUFFICIENT_RESOURCES
;
3182 /* Read the value */
3183 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
3184 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
3185 KeyValuePartialInformation
, ValueInformation
,
3186 ValueInformationLength
,
3187 &ValueInformationLength
);
3191 *ResultLength
= ValueInformation
->DataLength
;
3193 if (!NT_SUCCESS(Status
))
3195 ExFreePool(ValueInformation
);
3196 if (Status
== STATUS_BUFFER_OVERFLOW
)
3197 return STATUS_BUFFER_TOO_SMALL
;
3198 DPRINT1("Problem: Status=0x%08x, ResultLength = %d\n", Status
, *ResultLength
);
3202 /* FIXME: Verify the value (NULL-terminated, correct format). */
3203 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
3204 ValueInformation
->DataLength
);
3205 ExFreePool(ValueInformation
);
3207 return STATUS_SUCCESS
;
3210 case DevicePropertyBootConfiguration
:
3212 if (DeviceNode
->BootResources
->Count
!= 0)
3214 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
3216 Data
= &DeviceNode
->BootResources
;
3219 /* FIXME: use a translated boot configuration instead */
3220 case DevicePropertyBootConfigurationTranslated
:
3222 if (DeviceNode
->BootResources
->Count
!= 0)
3224 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
3226 Data
= &DeviceNode
->BootResources
;
3229 case DevicePropertyEnumeratorName
:
3230 /* A buffer overflow can't happen here, since InstancePath
3231 * always contains the enumerator name followed by \\ */
3232 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
3234 Length
= (Ptr
- DeviceNode
->InstancePath
.Buffer
+ 1) * sizeof(WCHAR
);
3235 Data
= DeviceNode
->InstancePath
.Buffer
;
3238 case DevicePropertyPhysicalDeviceObjectName
:
3239 /* InstancePath buffer is NULL terminated, so we can do this */
3240 Length
= DeviceNode
->InstancePath
.MaximumLength
;
3241 Data
= DeviceNode
->InstancePath
.Buffer
;
3245 return STATUS_INVALID_PARAMETER_2
;
3248 /* Prepare returned values */
3249 *ResultLength
= Length
;
3250 if (BufferLength
< Length
)
3251 return STATUS_BUFFER_TOO_SMALL
;
3252 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
3254 /* NULL terminate the string (if required) */
3255 if (DeviceProperty
== DevicePropertyEnumeratorName
)
3256 ((LPWSTR
)PropertyBuffer
)[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3258 return STATUS_SUCCESS
;
3266 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3272 * @name IoOpenDeviceRegistryKey
3274 * Open a registry key unique for a specified driver or device instance.
3276 * @param DeviceObject Device to get the registry key for.
3277 * @param DevInstKeyType Type of the key to return.
3278 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
3279 * @param DevInstRegKey Handle to the opened registry key on
3280 * successful return.
3288 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
3289 IN ULONG DevInstKeyType
,
3290 IN ACCESS_MASK DesiredAccess
,
3291 OUT PHANDLE DevInstRegKey
)
3293 static WCHAR RootKeyName
[] =
3294 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
3295 static WCHAR ProfileKeyName
[] =
3296 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
3297 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
3298 static WCHAR EnumKeyName
[] = L
"Enum\\";
3299 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
3300 ULONG KeyNameLength
;
3301 LPWSTR KeyNameBuffer
;
3302 UNICODE_STRING KeyName
;
3303 ULONG DriverKeyLength
;
3304 OBJECT_ATTRIBUTES ObjectAttributes
;
3305 PDEVICE_NODE DeviceNode
= NULL
;
3308 DPRINT("IoOpenDeviceRegistryKey() called\n");
3310 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
3312 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
3313 return STATUS_INVALID_PARAMETER
;
3317 * Calculate the length of the base key name. This is the full
3318 * name for driver key or the name excluding "Device Parameters"
3319 * subkey for device key.
3322 KeyNameLength
= sizeof(RootKeyName
);
3323 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3324 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
3325 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3327 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
3328 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3329 0, NULL
, &DriverKeyLength
);
3330 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
3332 KeyNameLength
+= DriverKeyLength
;
3336 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3337 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
3338 DeviceNode
->InstancePath
.Length
;
3342 * Now allocate the buffer for the key name...
3345 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
3346 if (KeyNameBuffer
== NULL
)
3347 return STATUS_INSUFFICIENT_RESOURCES
;
3350 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
3351 KeyName
.Buffer
= KeyNameBuffer
;
3354 * ...and build the key name.
3357 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
3358 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
3360 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3361 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
3363 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3365 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
3366 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3367 DriverKeyLength
, KeyNameBuffer
+
3368 (KeyName
.Length
/ sizeof(WCHAR
)),
3370 if (!NT_SUCCESS(Status
))
3372 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
3373 ExFreePool(KeyNameBuffer
);
3376 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
3380 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
3381 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
3382 if (DeviceNode
->InstancePath
.Length
== 0)
3384 ExFreePool(KeyNameBuffer
);
3390 * Open the base key.
3392 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
3393 if (!NT_SUCCESS(Status
))
3395 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
3396 ExFreePool(KeyNameBuffer
);
3399 ExFreePool(KeyNameBuffer
);
3402 * For driver key we're done now.
3405 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3409 * Let's go further. For device key we must open "Device Parameters"
3410 * subkey and create it if it doesn't exist yet.
3413 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
3414 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
3415 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
3416 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
3417 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
3418 ZwClose(ObjectAttributes
.RootDirectory
);
3428 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3438 IoInvalidateDeviceRelations(
3439 IN PDEVICE_OBJECT DeviceObject
,
3440 IN DEVICE_RELATION_TYPE Type
)
3442 PIO_WORKITEM WorkItem
;
3443 PINVALIDATE_DEVICE_RELATION_DATA Data
;
3445 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
3448 WorkItem
= IoAllocateWorkItem(DeviceObject
);
3455 ObReferenceObject(DeviceObject
);
3456 Data
->DeviceObject
= DeviceObject
;
3458 Data
->WorkItem
= WorkItem
;
3462 IopAsynchronousInvalidateDeviceRelations
,
3472 IoSynchronousInvalidateDeviceRelations(
3473 IN PDEVICE_OBJECT DeviceObject
,
3474 IN DEVICE_RELATION_TYPE Type
)
3481 /* Enumerate the device */
3482 return IopEnumerateDevice(DeviceObject
);
3483 case PowerRelations
:
3484 /* Not handled yet */
3485 return STATUS_NOT_IMPLEMENTED
;
3486 case TargetDeviceRelation
:
3488 return STATUS_SUCCESS
;
3490 /* Ejection relations are not supported */
3491 return STATUS_NOT_SUPPORTED
;
3500 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
3502 IN PHYSICAL_ADDRESS BusAddress
,
3503 IN OUT PULONG AddressSpace
,
3504 OUT PPHYSICAL_ADDRESS TranslatedAddress
)