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 PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList
= NULL
;
34 #if defined (ALLOC_PRAGMA)
35 #pragma alloc_text(INIT, PnpInit)
36 #pragma alloc_text(INIT, PnpInit2)
39 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
41 PDEVICE_OBJECT DeviceObject
;
42 DEVICE_RELATION_TYPE Type
;
43 PIO_WORKITEM WorkItem
;
44 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
46 /* FUNCTIONS *****************************************************************/
49 IopAssignDeviceResources(
50 IN PDEVICE_NODE DeviceNode
,
51 OUT ULONG
*pRequiredSize
);
53 IopTranslateDeviceResources(
54 IN PDEVICE_NODE DeviceNode
,
55 IN ULONG RequiredSize
);
59 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
61 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
66 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
67 PDRIVER_OBJECT DriverObject
)
72 if (!DriverObject
->DriverExtension
->AddDevice
)
73 return STATUS_SUCCESS
;
75 /* This is a Plug and Play driver */
76 DPRINT("Plug and Play driver found\n");
77 ASSERT(DeviceNode
->PhysicalDeviceObject
);
79 /* Check if this plug-and-play driver is used as a legacy one for this device node */
80 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
82 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
83 return STATUS_SUCCESS
;
86 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
87 &DriverObject
->DriverName
,
88 &DeviceNode
->InstancePath
);
89 Status
= DriverObject
->DriverExtension
->AddDevice(
90 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
91 if (!NT_SUCCESS(Status
))
93 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
97 /* Check if driver added a FDO above the PDO */
98 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
99 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
101 /* FIXME: What do we do? Unload the driver or just disable the device? */
102 DPRINT1("An FDO was not attached\n");
103 ObDereferenceObject(Fdo
);
104 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
105 return STATUS_UNSUCCESSFUL
;
108 /* Check if we have a ACPI device (needed for power management) */
109 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
111 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
113 /* There can be only one system power device */
114 if (!SystemPowerDeviceNodeCreated
)
116 PopSystemPowerDeviceNode
= DeviceNode
;
117 ObReferenceObject(PopSystemPowerDeviceNode
);
118 SystemPowerDeviceNodeCreated
= TRUE
;
122 ObDereferenceObject(Fdo
);
124 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
125 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
127 return STATUS_SUCCESS
;
132 PDEVICE_NODE DeviceNode
)
134 IO_STATUS_BLOCK IoStatusBlock
;
135 IO_STACK_LOCATION Stack
;
136 ULONG RequiredLength
;
139 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
140 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
141 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
142 Status
= IopInitiatePnpIrp(
143 DeviceNode
->PhysicalDeviceObject
,
145 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
147 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
149 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
152 DeviceNode
->ResourceRequirements
= Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
154 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
155 if (NT_SUCCESS(Status
))
157 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
158 if (NT_SUCCESS(Status
))
160 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
164 DPRINT("IopTranslateDeviceResources() failed (Status 0x%08lx)\n", Status
);
169 DPRINT("IopAssignDeviceResources() failed (Status 0x%08lx)\n", Status
);
171 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
173 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
174 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
175 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
178 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and
179 * actually _depend_ on this!. This is because NT will lock the Device Node
180 * with an ERESOURCE, which of course requires APCs to be disabled.
182 KeEnterCriticalRegion();
184 Status
= IopInitiatePnpIrp(
185 DeviceNode
->PhysicalDeviceObject
,
190 KeLeaveCriticalRegion();
192 if (!NT_SUCCESS(Status
))
194 DPRINT("IopInitiatePnpIrp() failed\n");
198 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
200 DPRINT("Device needs enumeration, invalidating bus relations\n");
201 /* Invalidate device relations synchronously
202 (otherwise there will be dirty read of DeviceNode) */
203 IopEnumerateDevice(DeviceNode
->PhysicalDeviceObject
);
204 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
208 if (NT_SUCCESS(Status
))
209 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
216 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
217 PDEVICE_CAPABILITIES DeviceCaps
)
219 IO_STATUS_BLOCK StatusBlock
;
220 IO_STACK_LOCATION Stack
;
222 /* Set up the Header */
223 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
224 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
225 DeviceCaps
->Version
= 1;
226 DeviceCaps
->Address
= -1;
227 DeviceCaps
->UINumber
= -1;
229 /* Set up the Stack */
230 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
231 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
234 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
236 IRP_MN_QUERY_CAPABILITIES
,
241 IopAsynchronousInvalidateDeviceRelations(
242 IN PDEVICE_OBJECT DeviceObject
,
243 IN PVOID InvalidateContext
)
245 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
247 IoSynchronousInvalidateDeviceRelations(
251 ObDereferenceObject(Data
->DeviceObject
);
252 IoFreeWorkItem(Data
->WorkItem
);
257 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
261 if (PopSystemPowerDeviceNode
)
263 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
264 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
265 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
267 return STATUS_SUCCESS
;
270 return STATUS_UNSUCCESSFUL
;
275 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
277 USHORT i
= 0, FoundIndex
= 0xFFFF;
281 /* Acquire the lock */
282 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
284 /* Loop all entries */
285 while (i
< IopBusTypeGuidList
->GuidCount
)
287 /* Try to find a match */
288 if (RtlCompareMemory(BusTypeGuid
,
289 &IopBusTypeGuidList
->Guids
[i
],
290 sizeof(GUID
)) == sizeof(GUID
))
299 /* Check if we have to grow the list */
300 if (IopBusTypeGuidList
->GuidCount
)
302 /* Calculate the new size */
303 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
304 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
306 /* Allocate the new copy */
307 NewList
= ExAllocatePool(PagedPool
, NewSize
);
311 ExFreePool(IopBusTypeGuidList
);
315 /* Now copy them, decrease the size too */
316 NewSize
-= sizeof(GUID
);
317 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
319 /* Free the old list */
320 ExFreePool(IopBusTypeGuidList
);
322 /* Use the new buffer */
323 IopBusTypeGuidList
= NewList
;
326 /* Copy the new GUID */
327 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
331 /* The new entry is the index */
332 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
333 IopBusTypeGuidList
->GuidCount
++;
336 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
342 * Creates a device node
345 * ParentNode = Pointer to parent device node
346 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
347 * to have the root device node create one
348 * (eg. for legacy drivers)
349 * DeviceNode = Pointer to storage for created device node
355 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
356 PDEVICE_OBJECT PhysicalDeviceObject
,
357 PUNICODE_STRING ServiceName
,
358 PDEVICE_NODE
*DeviceNode
)
364 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
365 ParentNode
, PhysicalDeviceObject
, ServiceName
);
367 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
370 return STATUS_INSUFFICIENT_RESOURCES
;
373 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
375 if (!PhysicalDeviceObject
)
377 Status
= PnpRootCreateDevice(ServiceName
, &PhysicalDeviceObject
);
378 if (!NT_SUCCESS(Status
))
380 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
385 /* This is for drivers passed on the command line to ntoskrnl.exe */
386 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
387 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
390 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
392 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
396 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
397 Node
->Parent
= ParentNode
;
398 Node
->Sibling
= ParentNode
->Child
;
399 ParentNode
->Child
= Node
;
400 if (ParentNode
->LastChild
== NULL
)
401 ParentNode
->LastChild
= Node
;
402 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
403 Node
->Level
= ParentNode
->Level
+ 1;
406 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
410 return STATUS_SUCCESS
;
414 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
417 PDEVICE_NODE PrevSibling
= NULL
;
419 /* All children must be deleted before a parent is deleted */
420 ASSERT(!DeviceNode
->Child
);
422 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
424 ASSERT(DeviceNode
->PhysicalDeviceObject
);
426 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
428 /* Get previous sibling */
429 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
431 PrevSibling
= DeviceNode
->Parent
->Child
;
432 while (PrevSibling
->Sibling
!= DeviceNode
)
433 PrevSibling
= PrevSibling
->Sibling
;
436 /* Unlink from parent if it exists */
437 if (DeviceNode
->Parent
)
439 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
441 DeviceNode
->Parent
->LastChild
= PrevSibling
;
443 PrevSibling
->Sibling
= NULL
;
445 if (DeviceNode
->Parent
->Child
== DeviceNode
)
446 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
449 /* Unlink from sibling list */
451 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
453 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
455 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
457 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
459 if (DeviceNode
->ResourceList
)
461 ExFreePool(DeviceNode
->ResourceList
);
464 if (DeviceNode
->ResourceListTranslated
)
466 ExFreePool(DeviceNode
->ResourceListTranslated
);
469 if (DeviceNode
->ResourceRequirements
)
471 ExFreePool(DeviceNode
->ResourceRequirements
);
474 if (DeviceNode
->BootResources
)
476 ExFreePool(DeviceNode
->BootResources
);
479 ExFreePool(DeviceNode
);
481 return STATUS_SUCCESS
;
485 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
486 PIO_STATUS_BLOCK IoStatusBlock
,
488 PIO_STACK_LOCATION Stack OPTIONAL
)
490 PDEVICE_OBJECT TopDeviceObject
;
491 PIO_STACK_LOCATION IrpSp
;
496 /* Always call the top of the device stack */
497 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
504 Irp
= IoBuildSynchronousFsdRequest(
513 /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */
514 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
515 Irp
->IoStatus
.Information
= 0;
517 IrpSp
= IoGetNextIrpStackLocation(Irp
);
518 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
522 RtlCopyMemory(&IrpSp
->Parameters
,
524 sizeof(Stack
->Parameters
));
527 Status
= IoCallDriver(TopDeviceObject
, Irp
);
528 if (Status
== STATUS_PENDING
)
530 KeWaitForSingleObject(&Event
,
535 Status
= IoStatusBlock
->Status
;
538 ObDereferenceObject(TopDeviceObject
);
545 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
547 PDEVICE_NODE ParentDeviceNode
;
548 PDEVICE_NODE ChildDeviceNode
;
551 /* Copy context data so we don't overwrite it in subsequent calls to this function */
552 ParentDeviceNode
= Context
->DeviceNode
;
554 /* Call the action routine */
555 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
556 if (!NT_SUCCESS(Status
))
561 /* Traversal of all children nodes */
562 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
563 ChildDeviceNode
!= NULL
;
564 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
566 /* Pass the current device node to the action routine */
567 Context
->DeviceNode
= ChildDeviceNode
;
569 Status
= IopTraverseDeviceTreeNode(Context
);
570 if (!NT_SUCCESS(Status
))
581 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
585 DPRINT("Context 0x%p\n", Context
);
587 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
588 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
590 /* Start from the specified device node */
591 Context
->DeviceNode
= Context
->FirstDeviceNode
;
593 /* Recursively traverse the device tree */
594 Status
= IopTraverseDeviceTreeNode(Context
);
595 if (Status
== STATUS_UNSUCCESSFUL
)
597 /* The action routine just wanted to terminate the traversal with status
598 code STATUS_SUCCESS */
599 Status
= STATUS_SUCCESS
;
607 * IopCreateDeviceKeyPath
609 * Creates a registry key
613 * Name of the key to be created.
615 * Handle to the newly created key
618 * This method can create nested trees, so parent of RegistryPath can
619 * be not existant, and will be created if needed.
623 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
626 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
627 HANDLE hParent
= NULL
, hKey
;
628 OBJECT_ATTRIBUTES ObjectAttributes
;
629 UNICODE_STRING KeyName
;
630 LPCWSTR Current
, Last
;
637 /* Open root key for device instances */
638 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
639 if (!NT_SUCCESS(Status
))
641 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
645 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
646 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
648 /* Go up to the end of the string */
649 while (Current
<= Last
)
651 if (Current
!= Last
&& *Current
!= '\\')
653 /* Not the end of the string and not a separator */
658 /* Prepare relative key name */
659 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
660 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
661 DPRINT("Create '%wZ'\n", &KeyName
);
664 InitializeObjectAttributes(&ObjectAttributes
,
666 OBJ_CASE_INSENSITIVE
,
669 Status
= ZwCreateKey(&hKey
,
670 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
677 /* Close parent key handle, we don't need it anymore */
681 /* Key opening/creating failed? */
682 if (!NT_SUCCESS(Status
))
684 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
688 /* Check if it is the end of the string */
691 /* Yes, return success */
693 return STATUS_SUCCESS
;
696 /* Start with this new parent key */
699 KeyName
.Buffer
= (LPWSTR
)Current
;
702 return STATUS_UNSUCCESSFUL
;
708 IopSetDeviceInstanceData(HANDLE InstanceKey
,
709 PDEVICE_NODE DeviceNode
)
711 OBJECT_ATTRIBUTES ObjectAttributes
;
712 UNICODE_STRING KeyName
;
715 ULONG ListSize
, ResultLength
;
718 DPRINT("IopSetDeviceInstanceData() called\n");
720 /* Create the 'LogConf' key */
721 RtlInitUnicodeString(&KeyName
, L
"LogConf");
722 InitializeObjectAttributes(&ObjectAttributes
,
724 OBJ_CASE_INSENSITIVE
,
727 Status
= ZwCreateKey(&LogConfKey
,
734 if (NT_SUCCESS(Status
))
736 /* Set 'BootConfig' value */
737 if (DeviceNode
->BootResources
!= NULL
)
739 ResCount
= DeviceNode
->BootResources
->Count
;
742 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
744 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
745 Status
= ZwSetValueKey(LogConfKey
,
749 &DeviceNode
->BootResources
,
754 /* Set 'BasicConfigVector' value */
755 if (DeviceNode
->ResourceRequirements
!= NULL
&&
756 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
758 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
759 Status
= ZwSetValueKey(LogConfKey
,
762 REG_RESOURCE_REQUIREMENTS_LIST
,
763 DeviceNode
->ResourceRequirements
,
764 DeviceNode
->ResourceRequirements
->ListSize
);
770 /* Set the 'ConfigFlags' value */
771 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
772 Status
= ZwQueryValueKey(InstanceKey
,
774 KeyValueBasicInformation
,
778 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
780 /* Write the default value */
781 ULONG DefaultConfigFlags
= 0;
782 Status
= ZwSetValueKey(InstanceKey
,
787 sizeof(DefaultConfigFlags
));
790 DPRINT("IopSetDeviceInstanceData() done\n");
792 return STATUS_SUCCESS
;
797 IopAssignDeviceResources(
798 IN PDEVICE_NODE DeviceNode
,
799 OUT ULONG
*pRequiredSize
)
801 PIO_RESOURCE_LIST ResourceList
;
802 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
803 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
804 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
805 ULONG NumberOfResources
= 0;
810 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
812 /* No resource needed for this device */
813 DeviceNode
->ResourceList
= NULL
;
815 return STATUS_SUCCESS
;
818 /* Fill DeviceNode->ResourceList
819 * FIXME: the PnP arbiter should go there!
820 * Actually, use the BootResources if provided, else the resource list #0
823 if (DeviceNode
->BootResources
)
825 /* Browse the boot resources to know if we have some custom structures */
826 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
827 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
829 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
830 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
831 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
832 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
834 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
835 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
839 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
840 if (!DeviceNode
->ResourceList
)
842 Status
= STATUS_NO_MEMORY
;
845 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
847 *pRequiredSize
= Size
;
848 return STATUS_SUCCESS
;
851 /* Ok, here, we have to use the device requirement list */
852 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
853 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
855 Status
= STATUS_REVISION_MISMATCH
;
859 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
860 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
861 if (!DeviceNode
->ResourceList
)
863 Status
= STATUS_NO_MEMORY
;
867 DeviceNode
->ResourceList
->Count
= 1;
868 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
869 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
870 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
871 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
873 for (i
= 0; i
< ResourceList
->Count
; i
++)
875 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
877 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
879 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
882 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
883 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
884 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
885 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
886 switch (ResourceDescriptor
->Type
)
888 case CmResourceTypePort
:
890 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
891 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
894 case CmResourceTypeInterrupt
:
896 INTERFACE_TYPE BusType
;
901 DescriptorRaw
->u
.Interrupt
.Level
= 0;
902 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
903 /* FIXME: HACK: if we have a PCI device, we try
904 * to keep the IRQ assigned by the BIOS */
905 if (NT_SUCCESS(IoGetDeviceProperty(
906 DeviceNode
->PhysicalDeviceObject
,
907 DevicePropertyLegacyBusType
,
908 sizeof(INTERFACE_TYPE
),
910 &ret
)) && BusType
== PCIBus
)
912 /* We have a PCI bus */
913 if (NT_SUCCESS(IoGetDeviceProperty(
914 DeviceNode
->PhysicalDeviceObject
,
915 DevicePropertyAddress
,
918 &ret
)) && SlotNumber
> 0)
920 /* We have a good slot number */
921 ret
= HalGetBusDataByOffset(PCIConfiguration
,
922 DeviceNode
->ResourceRequirements
->BusNumber
,
925 0x3c /* PCI_INTERRUPT_LINE */,
927 if (ret
!= 0 && ret
!= 2
928 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
929 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
931 /* The device already has an assigned IRQ */
932 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
936 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
937 DescriptorRaw
->u
.Interrupt
.Vector
,
938 &DeviceNode
->InstancePath
);
939 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
940 ret
= HalSetBusDataByOffset(PCIConfiguration
,
941 DeviceNode
->ResourceRequirements
->BusNumber
,
944 0x3c /* PCI_INTERRUPT_LINE */,
946 if (ret
== 0 || ret
== 2)
953 case CmResourceTypeMemory
:
955 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
956 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
959 case CmResourceTypeDma
:
961 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
962 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
963 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
966 case CmResourceTypeBusNumber
:
968 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
969 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
970 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
973 /*CmResourceTypeDevicePrivate:
974 case CmResourceTypePcCardConfig:
975 case CmResourceTypeMfCardConfig:
978 &DescriptorRaw->u.DevicePrivate,
979 &ResourceDescriptor->u.DevicePrivate,
980 sizeof(ResourceDescriptor->u.DevicePrivate));
982 &DescriptorTranslated->u.DevicePrivate,
983 &ResourceDescriptor->u.DevicePrivate,
984 sizeof(ResourceDescriptor->u.DevicePrivate));
988 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
995 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
997 *pRequiredSize
= Size
;
998 return STATUS_SUCCESS
;
1001 if (DeviceNode
->ResourceList
)
1003 ExFreePool(DeviceNode
->ResourceList
);
1004 DeviceNode
->ResourceList
= NULL
;
1012 IopTranslateDeviceResources(
1013 IN PDEVICE_NODE DeviceNode
,
1014 IN ULONG RequiredSize
)
1016 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1017 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1021 if (!DeviceNode
->ResourceList
)
1023 DeviceNode
->ResourceListTranslated
= NULL
;
1024 return STATUS_SUCCESS
;
1027 /* That's easy to translate a resource list. Just copy the
1028 * untranslated one and change few fields in the copy
1030 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1031 if (!DeviceNode
->ResourceListTranslated
)
1033 Status
=STATUS_NO_MEMORY
;
1036 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1038 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1040 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1041 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1043 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1044 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1045 switch (DescriptorRaw
->Type
)
1047 case CmResourceTypePort
:
1049 ULONG AddressSpace
= 0; /* IO space */
1050 if (!HalTranslateBusAddress(
1051 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1052 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1053 DescriptorRaw
->u
.Port
.Start
,
1055 &DescriptorTranslated
->u
.Port
.Start
))
1057 Status
= STATUS_UNSUCCESSFUL
;
1062 case CmResourceTypeInterrupt
:
1064 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1065 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1066 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1067 DescriptorRaw
->u
.Interrupt
.Level
,
1068 DescriptorRaw
->u
.Interrupt
.Vector
,
1069 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1070 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1073 case CmResourceTypeMemory
:
1075 ULONG AddressSpace
= 1; /* Memory space */
1076 if (!HalTranslateBusAddress(
1077 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1078 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1079 DescriptorRaw
->u
.Memory
.Start
,
1081 &DescriptorTranslated
->u
.Memory
.Start
))
1083 Status
= STATUS_UNSUCCESSFUL
;
1088 case CmResourceTypeDma
:
1089 case CmResourceTypeBusNumber
:
1090 case CmResourceTypeDeviceSpecific
:
1094 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1095 Status
= STATUS_NOT_IMPLEMENTED
;
1100 return STATUS_SUCCESS
;
1103 /* Yes! Also delete ResourceList because ResourceList and
1104 * ResourceListTranslated should be a pair! */
1105 ExFreePool(DeviceNode
->ResourceList
);
1106 DeviceNode
->ResourceList
= NULL
;
1107 if (DeviceNode
->ResourceListTranslated
)
1109 ExFreePool(DeviceNode
->ResourceListTranslated
);
1110 DeviceNode
->ResourceList
= NULL
;
1117 * IopGetParentIdPrefix
1119 * Retrieve (or create) a string which identifies a device.
1123 * Pointer to device node.
1125 * Pointer to the string where is returned the parent node identifier
1128 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1129 * valid and its Buffer field is NULL-terminated. The caller needs to
1130 * to free the string with RtlFreeUnicodeString when it is no longer
1135 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1136 PUNICODE_STRING ParentIdPrefix
)
1138 ULONG KeyNameBufferLength
;
1139 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1140 UNICODE_STRING KeyName
;
1141 UNICODE_STRING KeyValue
;
1142 UNICODE_STRING ValueName
;
1147 /* HACK: As long as some devices have a NULL device
1148 * instance path, the following test is required :(
1150 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1152 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1153 &DeviceNode
->InstancePath
);
1154 return STATUS_UNSUCCESSFUL
;
1157 /* 1. Try to retrieve ParentIdPrefix from registry */
1158 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1159 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1160 if (!ParentIdPrefixInformation
)
1162 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1167 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1168 if (!KeyName
.Buffer
)
1170 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1174 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1176 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1177 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1179 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1180 if (!NT_SUCCESS(Status
))
1182 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1183 Status
= ZwQueryValueKey(
1185 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1186 KeyNameBufferLength
, &KeyNameBufferLength
);
1187 if (NT_SUCCESS(Status
))
1189 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1190 Status
= STATUS_UNSUCCESSFUL
;
1193 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1194 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1198 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1200 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1201 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1205 /* 2. Create the ParentIdPrefix value */
1206 crc32
= RtlComputeCrc32(0,
1207 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1208 DeviceNode
->Parent
->InstancePath
.Length
);
1210 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1211 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1213 /* 3. Try to write the ParentIdPrefix to registry */
1214 Status
= ZwSetValueKey(hKey
,
1218 (PVOID
)KeyValue
.Buffer
,
1219 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1222 if (NT_SUCCESS(Status
))
1224 /* Duplicate the string to return it */
1225 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1227 ExFreePool(ParentIdPrefixInformation
);
1228 RtlFreeUnicodeString(&KeyName
);
1236 * IopActionInterrogateDeviceStack
1238 * Retrieve information for all (direct) child nodes of a parent node.
1242 * Pointer to device node.
1244 * Pointer to parent node to retrieve child node information for.
1247 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1248 * when we reach a device node which is not a direct child of the device
1249 * node for which we retrieve information of child nodes for. Any errors
1250 * that occur is logged instead so that all child services have a chance
1251 * of being interrogated.
1255 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1258 IO_STATUS_BLOCK IoStatusBlock
;
1259 PDEVICE_NODE ParentDeviceNode
;
1260 WCHAR InstancePath
[MAX_PATH
];
1261 IO_STACK_LOCATION Stack
;
1266 ULONG RequiredLength
;
1268 HANDLE InstanceKey
= NULL
;
1269 UNICODE_STRING ValueName
;
1270 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1271 DEVICE_CAPABILITIES DeviceCapabilities
;
1273 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1274 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1276 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1279 * We are called for the parent too, but we don't need to do special
1280 * handling for this node
1283 if (DeviceNode
== ParentDeviceNode
)
1285 DPRINT("Success\n");
1286 return STATUS_SUCCESS
;
1290 * Make sure this device node is a direct child of the parent device node
1291 * that is given as an argument
1294 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1296 /* Stop the traversal immediately and indicate successful operation */
1298 return STATUS_UNSUCCESSFUL
;
1302 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1303 if (!NT_SUCCESS(Status
))
1305 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1310 * FIXME: For critical errors, cleanup and disable device, but always
1311 * return STATUS_SUCCESS.
1314 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1316 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1317 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1321 if (NT_SUCCESS(Status
))
1323 /* Copy the device id string */
1324 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1327 * FIXME: Check for valid characters, if there is invalid characters
1333 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1336 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1338 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1339 if (!NT_SUCCESS(Status
))
1341 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1344 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1346 if (!DeviceCapabilities
.UniqueID
)
1348 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1349 DPRINT("Instance ID is not unique\n");
1350 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1351 if (!NT_SUCCESS(Status
))
1353 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1357 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1359 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1360 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1364 if (NT_SUCCESS(Status
))
1366 /* Append the instance id string */
1367 wcscat(InstancePath
, L
"\\");
1368 if (ParentIdPrefix
.Length
> 0)
1370 /* Add information from parent bus device to InstancePath */
1371 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1372 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1373 wcscat(InstancePath
, L
"&");
1375 if (IoStatusBlock
.Information
)
1376 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1379 * FIXME: Check for valid characters, if there is invalid characters
1385 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1387 RtlFreeUnicodeString(&ParentIdPrefix
);
1389 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1391 DPRINT("No resources\n");
1392 /* FIXME: Cleanup and disable device */
1395 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1398 * Create registry key for the instance id, if it doesn't exist yet
1400 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, &InstanceKey
);
1401 if (!NT_SUCCESS(Status
))
1403 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1407 /* Set 'Capabilities' value */
1408 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1409 Status
= ZwSetValueKey(InstanceKey
,
1413 (PVOID
)&DeviceNode
->CapabilityFlags
,
1416 /* Set 'UINumber' value */
1417 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1419 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1420 Status
= ZwSetValueKey(InstanceKey
,
1424 &DeviceCapabilities
.UINumber
,
1429 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1431 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1432 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1436 if (NT_SUCCESS(Status
))
1439 * FIXME: Check for valid characters, if there is invalid characters
1443 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1444 DPRINT("Hardware IDs:\n");
1447 DPRINT(" %S\n", Ptr
);
1448 Length
= wcslen(Ptr
) + 1;
1451 TotalLength
+= Length
;
1453 DPRINT("TotalLength: %hu\n", TotalLength
);
1456 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1457 Status
= ZwSetValueKey(InstanceKey
,
1461 (PVOID
)IoStatusBlock
.Information
,
1462 (TotalLength
+ 1) * sizeof(WCHAR
));
1463 if (!NT_SUCCESS(Status
))
1465 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1470 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1473 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1475 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1476 Status
= IopInitiatePnpIrp(
1477 DeviceNode
->PhysicalDeviceObject
,
1481 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1484 * FIXME: Check for valid characters, if there is invalid characters
1488 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1489 DPRINT("Compatible IDs:\n");
1492 DPRINT(" %S\n", Ptr
);
1493 Length
= wcslen(Ptr
) + 1;
1496 TotalLength
+= Length
;
1498 DPRINT("TotalLength: %hu\n", TotalLength
);
1501 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1502 Status
= ZwSetValueKey(InstanceKey
,
1506 (PVOID
)IoStatusBlock
.Information
,
1507 (TotalLength
+ 1) * sizeof(WCHAR
));
1508 if (!NT_SUCCESS(Status
))
1510 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1515 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1518 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1520 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1521 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1522 Status
= IopInitiatePnpIrp(
1523 DeviceNode
->PhysicalDeviceObject
,
1525 IRP_MN_QUERY_DEVICE_TEXT
,
1527 /* This key is mandatory, so even if the Irp fails, we still write it */
1528 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1529 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1531 if (NT_SUCCESS(Status
) &&
1532 IoStatusBlock
.Information
&&
1533 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1535 /* This key is overriden when a driver is installed. Don't write the
1536 * new description if another one already exists */
1537 Status
= ZwSetValueKey(InstanceKey
,
1541 (PVOID
)IoStatusBlock
.Information
,
1542 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1546 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1547 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1549 Status
= ZwSetValueKey(InstanceKey
,
1554 DeviceDesc
.MaximumLength
);
1556 if (!NT_SUCCESS(Status
))
1558 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1564 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1566 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1567 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1568 Status
= IopInitiatePnpIrp(
1569 DeviceNode
->PhysicalDeviceObject
,
1571 IRP_MN_QUERY_DEVICE_TEXT
,
1573 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1575 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1576 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1577 Status
= ZwSetValueKey(InstanceKey
,
1581 (PVOID
)IoStatusBlock
.Information
,
1582 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1583 if (!NT_SUCCESS(Status
))
1585 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1590 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1593 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1595 Status
= IopInitiatePnpIrp(
1596 DeviceNode
->PhysicalDeviceObject
,
1598 IRP_MN_QUERY_BUS_INFORMATION
,
1600 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1602 PPNP_BUS_INFORMATION BusInformation
=
1603 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1605 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1606 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1607 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1608 ExFreePool(BusInformation
);
1612 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1614 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1615 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1616 DeviceNode
->ChildBusTypeIndex
= -1;
1619 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1621 Status
= IopInitiatePnpIrp(
1622 DeviceNode
->PhysicalDeviceObject
,
1624 IRP_MN_QUERY_RESOURCES
,
1626 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1628 DeviceNode
->BootResources
=
1629 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1630 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1634 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1635 DeviceNode
->BootResources
= NULL
;
1638 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1640 Status
= IopInitiatePnpIrp(
1641 DeviceNode
->PhysicalDeviceObject
,
1643 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1645 if (NT_SUCCESS(Status
))
1647 DeviceNode
->ResourceRequirements
=
1648 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1649 if (IoStatusBlock
.Information
)
1650 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
1652 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
1656 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1657 DeviceNode
->ResourceRequirements
= NULL
;
1661 if (InstanceKey
!= NULL
)
1663 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1666 ZwClose(InstanceKey
);
1668 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1670 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1672 /* Report the device to the user-mode pnp manager */
1673 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1674 &DeviceNode
->InstancePath
);
1677 return STATUS_SUCCESS
;
1683 IN PDEVICE_OBJECT DeviceObject
)
1685 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1686 DEVICETREE_TRAVERSE_CONTEXT Context
;
1687 PDEVICE_RELATIONS DeviceRelations
;
1688 PDEVICE_OBJECT ChildDeviceObject
;
1689 IO_STATUS_BLOCK IoStatusBlock
;
1690 PDEVICE_NODE ChildDeviceNode
;
1691 IO_STACK_LOCATION Stack
;
1695 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1697 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1699 /* Report the device to the user-mode pnp manager */
1700 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1701 &DeviceNode
->InstancePath
);
1703 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1705 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1707 Status
= IopInitiatePnpIrp(
1710 IRP_MN_QUERY_DEVICE_RELATIONS
,
1712 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1714 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1718 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1720 if (!DeviceRelations
)
1722 DPRINT("No PDOs\n");
1723 return STATUS_UNSUCCESSFUL
;
1726 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1729 * Create device nodes for all discovered devices
1731 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1733 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1734 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1736 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1737 if (!ChildDeviceNode
)
1739 /* One doesn't exist, create it */
1740 Status
= IopCreateDeviceNode(
1745 if (NT_SUCCESS(Status
))
1747 /* Mark the node as enumerated */
1748 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1750 /* Mark the DO as bus enumerated */
1751 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1755 /* Ignore this DO */
1756 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1757 ObDereferenceObject(ChildDeviceNode
);
1762 /* Mark it as enumerated */
1763 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1764 ObDereferenceObject(ChildDeviceObject
);
1767 ExFreePool(DeviceRelations
);
1770 * Retrieve information about all discovered children from the bus driver
1772 IopInitDeviceTreeTraverseContext(
1775 IopActionInterrogateDeviceStack
,
1778 Status
= IopTraverseDeviceTree(&Context
);
1779 if (!NT_SUCCESS(Status
))
1781 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1786 * Retrieve configuration from the registry for discovered children
1788 IopInitDeviceTreeTraverseContext(
1791 IopActionConfigureChildServices
,
1794 Status
= IopTraverseDeviceTree(&Context
);
1795 if (!NT_SUCCESS(Status
))
1797 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1802 * Initialize services for discovered children.
1804 Status
= IopInitializePnpServices(DeviceNode
);
1805 if (!NT_SUCCESS(Status
))
1807 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1811 DPRINT("IopEnumerateDevice() finished\n");
1812 return STATUS_SUCCESS
;
1817 * IopActionConfigureChildServices
1819 * Retrieve configuration for all (direct) child nodes of a parent node.
1823 * Pointer to device node.
1825 * Pointer to parent node to retrieve child node configuration for.
1828 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1829 * when we reach a device node which is not a direct child of the device
1830 * node for which we configure child services for. Any errors that occur is
1831 * logged instead so that all child services have a chance of beeing
1836 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1839 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1840 PDEVICE_NODE ParentDeviceNode
;
1841 PUNICODE_STRING Service
;
1842 UNICODE_STRING ClassGUID
;
1845 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1847 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1850 * We are called for the parent too, but we don't need to do special
1851 * handling for this node
1853 if (DeviceNode
== ParentDeviceNode
)
1855 DPRINT("Success\n");
1856 return STATUS_SUCCESS
;
1860 * Make sure this device node is a direct child of the parent device node
1861 * that is given as an argument
1863 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1865 /* Stop the traversal immediately and indicate successful operation */
1867 return STATUS_UNSUCCESSFUL
;
1870 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1872 WCHAR RegKeyBuffer
[MAX_PATH
];
1873 UNICODE_STRING RegKey
;
1876 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1877 RegKey
.Buffer
= RegKeyBuffer
;
1880 * Retrieve configuration from Enum key
1883 Service
= &DeviceNode
->ServiceName
;
1885 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1886 RtlInitUnicodeString(Service
, NULL
);
1887 RtlInitUnicodeString(&ClassGUID
, NULL
);
1889 QueryTable
[0].Name
= L
"Service";
1890 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
1891 QueryTable
[0].EntryContext
= Service
;
1893 QueryTable
[1].Name
= L
"ClassGUID";
1894 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1895 QueryTable
[1].EntryContext
= &ClassGUID
;
1896 QueryTable
[1].DefaultType
= REG_SZ
;
1897 QueryTable
[1].DefaultData
= L
"";
1898 QueryTable
[1].DefaultLength
= 0;
1900 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1901 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1903 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1904 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1906 if (!NT_SUCCESS(Status
))
1908 /* FIXME: Log the error */
1909 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
1910 &DeviceNode
->InstancePath
, Status
);
1911 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1912 return STATUS_SUCCESS
;
1915 if (Service
->Buffer
== NULL
)
1917 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1919 if (ClassGUID
.Length
!= 0)
1921 /* Device has a ClassGUID value, but no Service value.
1922 * Suppose it is using the NULL driver, so state the
1923 * device is started */
1924 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
1925 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1927 return STATUS_SUCCESS
;
1930 DPRINT("Got Service %S\n", Service
->Buffer
);
1933 return STATUS_SUCCESS
;
1937 * IopActionInitChildServices
1939 * Initialize the service for all (direct) child nodes of a parent node
1943 * Pointer to device node.
1945 * Pointer to parent node to initialize child node services for.
1948 * If the driver image for a service is not loaded and initialized
1949 * it is done here too. We only return a status code indicating an
1950 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1951 * not a direct child of the device node for which we initialize
1952 * child services for. Any errors that occur is logged instead so
1953 * that all child services have a chance of being initialized.
1957 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
1960 PDEVICE_NODE ParentDeviceNode
;
1962 BOOLEAN BootDrivers
= !PnpSystemInit
;
1964 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
1966 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1969 * We are called for the parent too, but we don't need to do special
1970 * handling for this node
1972 if (DeviceNode
== ParentDeviceNode
)
1974 DPRINT("Success\n");
1975 return STATUS_SUCCESS
;
1979 * Make sure this device node is a direct child of the parent device node
1980 * that is given as an argument
1983 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1986 * Stop the traversal immediately and indicate unsuccessful operation
1989 return STATUS_UNSUCCESSFUL
;
1993 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1994 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1995 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1997 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1998 PDRIVER_OBJECT DriverObject
;
2000 /* Get existing DriverObject pointer (in case the driver has
2001 already been loaded and initialized) */
2002 Status
= IopGetDriverObject(
2004 &DeviceNode
->ServiceName
,
2007 if (!NT_SUCCESS(Status
))
2009 /* Driver is not initialized, try to load it */
2010 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2012 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2014 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2015 was loaded by the bootloader */
2016 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2017 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2019 /* Initialize the driver */
2020 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2021 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2025 Status
= STATUS_SUCCESS
;
2030 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2031 &DeviceNode
->ServiceName
, Status
);
2035 /* Driver is loaded and initialized at this point */
2036 if (NT_SUCCESS(Status
))
2038 /* Attach lower level filter drivers. */
2039 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2040 /* Initialize the function driver for the device node */
2041 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2043 if (NT_SUCCESS(Status
))
2045 /* Attach upper level filter drivers. */
2046 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2047 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2049 Status
= IopStartDevice(DeviceNode
);
2053 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2054 &DeviceNode
->InstancePath
, Status
);
2060 * Don't disable when trying to load only boot drivers
2064 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2065 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2066 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2067 DPRINT1("Initialization of service %S failed (Status %x)\n",
2068 DeviceNode
->ServiceName
.Buffer
, Status
);
2074 DPRINT("Device %wZ is disabled or already initialized\n",
2075 &DeviceNode
->InstancePath
);
2078 return STATUS_SUCCESS
;
2082 * IopInitializePnpServices
2084 * Initialize services for discovered children
2088 * Top device node to start initializing services.
2094 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2096 DEVICETREE_TRAVERSE_CONTEXT Context
;
2098 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2100 IopInitDeviceTreeTraverseContext(
2103 IopActionInitChildServices
,
2106 return IopTraverseDeviceTree(&Context
);
2109 static NTSTATUS INIT_FUNCTION
2110 IopEnumerateDetectedDevices(
2112 IN PUNICODE_STRING RelativePath OPTIONAL
,
2114 IN BOOLEAN EnumerateSubKeys
,
2115 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2116 IN ULONG ParentBootResourcesLength
)
2118 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2119 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2120 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2121 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2122 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2123 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2124 OBJECT_ATTRIBUTES ObjectAttributes
;
2125 HANDLE hDevicesKey
= NULL
;
2126 HANDLE hDeviceKey
= NULL
;
2127 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2128 UNICODE_STRING Level2NameU
;
2129 WCHAR Level2Name
[5];
2130 ULONG IndexDevice
= 0;
2132 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2133 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2134 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2135 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2136 UNICODE_STRING DeviceName
, ValueName
;
2138 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2139 ULONG BootResourcesLength
;
2142 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2143 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2144 static ULONG DeviceIndexPci
= 0;
2146 const UNICODE_STRING IdentifierAcpi
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2147 UNICODE_STRING HardwareIdAcpi
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2148 static ULONG DeviceIndexAcpi
= 0;
2150 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2151 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2152 static ULONG DeviceIndexSerial
= 0;
2153 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2154 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2155 static ULONG DeviceIndexKeyboard
= 0;
2156 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2157 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2158 static ULONG DeviceIndexMouse
= 0;
2159 UNICODE_STRING HardwareIdKey
;
2160 PUNICODE_STRING pHardwareId
;
2161 ULONG DeviceIndex
= 0;
2165 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2166 if (!NT_SUCCESS(Status
))
2168 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2173 hDevicesKey
= hBaseKey
;
2175 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2176 if (!pDeviceInformation
)
2178 DPRINT("ExAllocatePool() failed\n");
2179 Status
= STATUS_NO_MEMORY
;
2183 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2184 if (!pValueInformation
)
2186 DPRINT("ExAllocatePool() failed\n");
2187 Status
= STATUS_NO_MEMORY
;
2193 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2194 if (Status
== STATUS_NO_MORE_ENTRIES
)
2196 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2198 ExFreePool(pDeviceInformation
);
2199 DeviceInfoLength
= RequiredSize
;
2200 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2201 if (!pDeviceInformation
)
2203 DPRINT("ExAllocatePool() failed\n");
2204 Status
= STATUS_NO_MEMORY
;
2207 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2209 if (!NT_SUCCESS(Status
))
2211 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2216 /* Open device key */
2217 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2218 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2220 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2221 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2222 if (!NT_SUCCESS(Status
))
2224 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2228 /* Read boot resources, and add then to parent ones */
2229 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2230 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2232 ExFreePool(pValueInformation
);
2233 ValueInfoLength
= RequiredSize
;
2234 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2235 if (!pValueInformation
)
2237 DPRINT("ExAllocatePool() failed\n");
2238 ZwDeleteKey(hLevel2Key
);
2239 Status
= STATUS_NO_MEMORY
;
2242 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2244 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2246 BootResources
= ParentBootResources
;
2247 BootResourcesLength
= ParentBootResourcesLength
;
2249 else if (!NT_SUCCESS(Status
))
2251 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2254 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2256 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2261 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2263 /* Concatenate current resources and parent ones */
2264 if (ParentBootResourcesLength
== 0)
2265 BootResourcesLength
= pValueInformation
->DataLength
;
2267 BootResourcesLength
= ParentBootResourcesLength
2268 + pValueInformation
->DataLength
2270 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2273 DPRINT("ExAllocatePool() failed\n");
2276 if (ParentBootResourcesLength
== 0)
2278 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2280 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2282 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2284 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2285 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2286 ParentBootResourcesLength
- Header
);
2287 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2291 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2293 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2294 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2295 ParentBootResourcesLength
- Header
);
2297 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2298 pValueInformation
->Data
+ Header
,
2299 pValueInformation
->DataLength
- Header
);
2300 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2304 if (EnumerateSubKeys
)
2309 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2310 if (Status
== STATUS_NO_MORE_ENTRIES
)
2312 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2314 ExFreePool(pDeviceInformation
);
2315 DeviceInfoLength
= RequiredSize
;
2316 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2317 if (!pDeviceInformation
)
2319 DPRINT("ExAllocatePool() failed\n");
2320 Status
= STATUS_NO_MEMORY
;
2323 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2325 if (!NT_SUCCESS(Status
))
2327 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2331 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2332 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2334 Status
= IopEnumerateDetectedDevices(
2340 BootResourcesLength
);
2341 if (!NT_SUCCESS(Status
))
2346 /* Read identifier */
2347 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2348 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2350 ExFreePool(pValueInformation
);
2351 ValueInfoLength
= RequiredSize
;
2352 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2353 if (!pValueInformation
)
2355 DPRINT("ExAllocatePool() failed\n");
2356 Status
= STATUS_NO_MEMORY
;
2359 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2361 if (!NT_SUCCESS(Status
))
2363 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2365 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2368 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2370 else if (pValueInformation
->Type
!= REG_SZ
)
2372 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2377 /* Assign hardware id to this device */
2378 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2379 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2380 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2381 ValueName
.Length
-= sizeof(WCHAR
);
2384 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2386 pHardwareId
= &HardwareIdSerial
;
2387 DeviceIndex
= DeviceIndexSerial
++;
2389 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2391 pHardwareId
= &HardwareIdKeyboard
;
2392 DeviceIndex
= DeviceIndexKeyboard
++;
2394 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2396 pHardwareId
= &HardwareIdMouse
;
2397 DeviceIndex
= DeviceIndexMouse
++;
2399 else if (NT_SUCCESS(Status
))
2401 /* Try to also match the device identifier */
2402 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2404 pHardwareId
= &HardwareIdPci
;
2405 DeviceIndex
= DeviceIndexPci
++;
2408 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierAcpi
, FALSE
) == 0)
2410 pHardwareId
= &HardwareIdAcpi
;
2411 DeviceIndex
= DeviceIndexAcpi
++;
2416 /* Unknown device */
2417 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2423 /* Unknown key path */
2424 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2428 /* Prepare hardware id key (hardware id value without final \0) */
2429 HardwareIdKey
= *pHardwareId
;
2430 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2432 /* Add the detected device to Root key */
2433 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2434 Status
= ZwCreateKey(
2440 REG_OPTION_NON_VOLATILE
,
2442 if (!NT_SUCCESS(Status
))
2444 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2447 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2448 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2449 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2450 Status
= ZwCreateKey(
2452 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2456 REG_OPTION_NON_VOLATILE
,
2458 ZwClose(hLevel1Key
);
2459 if (!NT_SUCCESS(Status
))
2461 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2464 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
2465 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
2466 if (!NT_SUCCESS(Status
))
2468 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2469 ZwDeleteKey(hLevel2Key
);
2472 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2473 if (!NT_SUCCESS(Status
))
2475 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2476 ZwDeleteKey(hLevel2Key
);
2479 /* Create 'LogConf' subkey */
2480 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2481 Status
= ZwCreateKey(
2487 REG_OPTION_VOLATILE
,
2489 if (!NT_SUCCESS(Status
))
2491 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2492 ZwDeleteKey(hLevel2Key
);
2495 if (BootResourcesLength
> 0)
2497 /* Save boot resources to 'LogConf\BootConfig' */
2498 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
2499 if (!NT_SUCCESS(Status
))
2501 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2503 ZwDeleteKey(hLevel2Key
);
2510 if (BootResources
&& BootResources
!= ParentBootResources
)
2511 ExFreePool(BootResources
);
2514 ZwClose(hLevel2Key
);
2519 ZwClose(hDeviceKey
);
2524 Status
= STATUS_SUCCESS
;
2527 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2528 ZwClose(hDevicesKey
);
2530 ZwClose(hDeviceKey
);
2531 if (pDeviceInformation
)
2532 ExFreePool(pDeviceInformation
);
2533 if (pValueInformation
)
2534 ExFreePool(pValueInformation
);
2538 static BOOLEAN INIT_FUNCTION
2539 IopIsAcpiComputer(VOID
)
2544 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2545 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2546 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2547 OBJECT_ATTRIBUTES ObjectAttributes
;
2548 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2549 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2550 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2551 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2553 ULONG IndexDevice
= 0;
2554 UNICODE_STRING DeviceName
, ValueName
;
2555 HANDLE hDevicesKey
= NULL
;
2556 HANDLE hDeviceKey
= NULL
;
2558 BOOLEAN ret
= FALSE
;
2560 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
2561 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2562 if (!NT_SUCCESS(Status
))
2564 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2568 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2569 if (!pDeviceInformation
)
2571 DPRINT("ExAllocatePool() failed\n");
2572 Status
= STATUS_NO_MEMORY
;
2576 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2577 if (!pDeviceInformation
)
2579 DPRINT("ExAllocatePool() failed\n");
2580 Status
= STATUS_NO_MEMORY
;
2586 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2587 if (Status
== STATUS_NO_MORE_ENTRIES
)
2589 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2591 ExFreePool(pDeviceInformation
);
2592 DeviceInfoLength
= RequiredSize
;
2593 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2594 if (!pDeviceInformation
)
2596 DPRINT("ExAllocatePool() failed\n");
2597 Status
= STATUS_NO_MEMORY
;
2600 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2602 if (!NT_SUCCESS(Status
))
2604 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2609 /* Open device key */
2610 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2611 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2612 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2617 if (!NT_SUCCESS(Status
))
2619 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2623 /* Read identifier */
2624 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2625 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2627 ExFreePool(pValueInformation
);
2628 ValueInfoLength
= RequiredSize
;
2629 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2630 if (!pValueInformation
)
2632 DPRINT("ExAllocatePool() failed\n");
2633 Status
= STATUS_NO_MEMORY
;
2636 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2638 if (!NT_SUCCESS(Status
))
2640 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2643 else if (pValueInformation
->Type
!= REG_SZ
)
2645 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2649 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2650 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2651 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2652 ValueName
.Length
-= sizeof(WCHAR
);
2653 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
2655 DPRINT("Found ACPI BIOS\n");
2661 ZwClose(hDeviceKey
);
2666 if (pDeviceInformation
)
2667 ExFreePool(pDeviceInformation
);
2668 if (pValueInformation
)
2669 ExFreePool(pValueInformation
);
2671 ZwClose(hDevicesKey
);
2673 ZwClose(hDeviceKey
);
2678 static NTSTATUS INIT_FUNCTION
2679 IopUpdateRootKey(VOID
)
2681 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2682 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2683 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2684 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2685 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2686 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2687 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
2688 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
2689 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
2690 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2691 OBJECT_ATTRIBUTES ObjectAttributes
;
2692 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
2695 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2696 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2697 if (!NT_SUCCESS(Status
))
2699 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2703 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2704 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2706 if (!NT_SUCCESS(Status
))
2708 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2712 if (IopIsAcpiComputer())
2714 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
2715 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2717 if (!NT_SUCCESS(Status
))
2719 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
2720 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2721 ZwClose(hHalAcpiDevice
);
2722 if (!NT_SUCCESS(Status
))
2724 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
2725 if (NT_SUCCESS(Status
))
2726 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
2727 if (NT_SUCCESS(Status
))
2729 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
2730 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2731 if (NT_SUCCESS(Status
))
2734 ZwClose(hHalAcpiId
);
2739 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2740 if (!NT_SUCCESS(Status
))
2742 /* Nothing to do, don't return with an error status */
2743 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2745 return STATUS_SUCCESS
;
2747 Status
= IopEnumerateDetectedDevices(
2762 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2764 PUNICODE_STRING Name
,
2765 ACCESS_MASK DesiredAccess
)
2767 OBJECT_ATTRIBUTES ObjectAttributes
;
2774 InitializeObjectAttributes(&ObjectAttributes
,
2776 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2780 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2787 IopGetRegistryValue(IN HANDLE Handle
,
2789 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
2791 UNICODE_STRING ValueString
;
2793 PKEY_VALUE_FULL_INFORMATION FullInformation
;
2797 RtlInitUnicodeString(&ValueString
, ValueName
);
2799 Status
= ZwQueryValueKey(Handle
,
2801 KeyValueFullInformation
,
2805 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
2806 (Status
!= STATUS_BUFFER_TOO_SMALL
))
2811 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
2812 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
2814 Status
= ZwQueryValueKey(Handle
,
2816 KeyValueFullInformation
,
2820 if (!NT_SUCCESS(Status
))
2822 ExFreePool(FullInformation
);
2826 *Information
= FullInformation
;
2827 return STATUS_SUCCESS
;
2830 static NTSTATUS INIT_FUNCTION
2832 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
2834 return STATUS_SUCCESS
;
2843 DPRINT("PnpInit()\n");
2845 KeInitializeSpinLock(&IopDeviceTreeLock
);
2847 /* Initialize the Bus Type GUID List */
2848 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2849 if (!IopBusTypeGuidList
) {
2850 DPRINT1("ExAllocatePool() failed\n");
2851 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
2854 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2855 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2857 /* Initialize PnP-Event notification support */
2858 Status
= IopInitPlugPlayEvents();
2859 if (!NT_SUCCESS(Status
))
2861 DPRINT1("IopInitPlugPlayEvents() failed\n");
2862 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2866 * Create root device node
2869 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
2870 if (!NT_SUCCESS(Status
))
2872 DPRINT1("IoCreateDriverObject() failed\n");
2873 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2876 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2878 if (!NT_SUCCESS(Status
))
2880 DPRINT1("IoCreateDevice() failed\n");
2881 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2884 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
2885 if (!NT_SUCCESS(Status
))
2887 DPRINT1("Insufficient resources\n");
2888 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2891 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2894 DPRINT1("Failed to create the instance path!\n");
2895 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
2898 /* Report the device to the user-mode pnp manager */
2899 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2900 &IopRootDeviceNode
->InstancePath
);
2902 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2903 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2904 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2905 IopRootDriverObject
->DriverExtension
->AddDevice(
2906 IopRootDriverObject
,
2907 IopRootDeviceNode
->PhysicalDeviceObject
);
2909 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
2910 Status
= IopUpdateRootKey();
2911 if (!NT_SUCCESS(Status
))
2913 DPRINT1("IopUpdateRootKey() failed\n");
2914 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2918 RTL_GENERIC_COMPARE_RESULTS
2920 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
2921 IN PVOID FirstStruct
,
2922 IN PVOID SecondStruct
)
2930 // The allocation function is called by the generic table package whenever
2931 // it needs to allocate memory for the table.
2936 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
2946 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
2955 PpInitializeDeviceReferenceTable(VOID
)
2957 /* Setup the guarded mutex and AVL table */
2958 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
2959 RtlInitializeGenericTableAvl(
2960 &PpDeviceReferenceTable
,
2961 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
2962 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
2963 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
2971 /* Initialize the resource when accessing device registry data */
2972 ExInitializeResourceLite(&PpRegistryDeviceResource
);
2974 /* Setup the device reference AVL table */
2975 PpInitializeDeviceReferenceTable();
2983 /* Check the initialization phase */
2984 switch (ExpInitializationPhase
)
2989 return PiInitPhase0();
2995 //return PiInitPhase1();
2999 /* Don't know any other phase! Bugcheck! */
3000 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3005 /* PUBLIC FUNCTIONS **********************************************************/
3012 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3013 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3014 IN ULONG BufferLength
,
3015 OUT PVOID PropertyBuffer
,
3016 OUT PULONG ResultLength
)
3018 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3019 DEVICE_CAPABILITIES DeviceCaps
;
3025 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3029 if (DeviceNode
== NULL
)
3030 return STATUS_INVALID_DEVICE_REQUEST
;
3032 switch (DeviceProperty
)
3034 case DevicePropertyBusNumber
:
3035 Length
= sizeof(ULONG
);
3036 Data
= &DeviceNode
->ChildBusNumber
;
3039 /* Complete, untested */
3040 case DevicePropertyBusTypeGuid
:
3042 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
3043 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
3045 /* Return the GUID */
3046 *ResultLength
= sizeof(GUID
);
3048 /* Check if the buffer given was large enough */
3049 if (BufferLength
< *ResultLength
)
3051 return STATUS_BUFFER_TOO_SMALL
;
3055 RtlCopyMemory(PropertyBuffer
,
3056 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
3058 return STATUS_SUCCESS
;
3062 return STATUS_OBJECT_NAME_NOT_FOUND
;
3066 case DevicePropertyLegacyBusType
:
3067 Length
= sizeof(INTERFACE_TYPE
);
3068 Data
= &DeviceNode
->ChildInterfaceType
;
3071 case DevicePropertyAddress
:
3072 /* Query the device caps */
3073 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3074 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
3077 *ResultLength
= sizeof(ULONG
);
3079 /* Check if the buffer given was large enough */
3080 if (BufferLength
< *ResultLength
)
3082 return STATUS_BUFFER_TOO_SMALL
;
3085 /* Return address */
3086 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
3087 return STATUS_SUCCESS
;
3091 return STATUS_OBJECT_NAME_NOT_FOUND
;
3095 // case DevicePropertyUINumber:
3096 // if (DeviceNode->CapabilityFlags == NULL)
3097 // return STATUS_INVALID_DEVICE_REQUEST;
3098 // Length = sizeof(ULONG);
3099 // Data = &DeviceNode->CapabilityFlags->UINumber;
3102 case DevicePropertyClassName
:
3103 case DevicePropertyClassGuid
:
3104 case DevicePropertyDriverKeyName
:
3105 case DevicePropertyManufacturer
:
3106 case DevicePropertyFriendlyName
:
3107 case DevicePropertyHardwareID
:
3108 case DevicePropertyCompatibleIDs
:
3109 case DevicePropertyDeviceDescription
:
3110 case DevicePropertyLocationInformation
:
3111 case DevicePropertyUINumber
:
3113 LPCWSTR RegistryPropertyName
;
3114 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
3115 UNICODE_STRING ValueName
;
3116 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
3117 ULONG ValueInformationLength
;
3118 HANDLE KeyHandle
, EnumRootHandle
;
3121 switch (DeviceProperty
)
3123 case DevicePropertyClassName
:
3124 RegistryPropertyName
= L
"Class"; break;
3125 case DevicePropertyClassGuid
:
3126 RegistryPropertyName
= L
"ClassGuid"; break;
3127 case DevicePropertyDriverKeyName
:
3128 RegistryPropertyName
= L
"Driver"; break;
3129 case DevicePropertyManufacturer
:
3130 RegistryPropertyName
= L
"Mfg"; break;
3131 case DevicePropertyFriendlyName
:
3132 RegistryPropertyName
= L
"FriendlyName"; break;
3133 case DevicePropertyHardwareID
:
3134 RegistryPropertyName
= L
"HardwareID"; break;
3135 case DevicePropertyCompatibleIDs
:
3136 RegistryPropertyName
= L
"CompatibleIDs"; break;
3137 case DevicePropertyDeviceDescription
:
3138 RegistryPropertyName
= L
"DeviceDesc"; break;
3139 case DevicePropertyLocationInformation
:
3140 RegistryPropertyName
= L
"LocationInformation"; break;
3141 case DevicePropertyUINumber
:
3142 RegistryPropertyName
= L
"UINumber"; break;
3144 /* Should not happen */
3146 return STATUS_UNSUCCESSFUL
;
3149 DPRINT("Registry property %S\n", RegistryPropertyName
);
3152 Status
= IopOpenRegistryKeyEx(&EnumRootHandle
, NULL
,
3153 &EnumRoot
, KEY_READ
);
3154 if (!NT_SUCCESS(Status
))
3156 DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status
);
3160 /* Open instance key */
3161 Status
= IopOpenRegistryKeyEx(&KeyHandle
, EnumRootHandle
,
3162 &DeviceNode
->InstancePath
, KEY_READ
);
3163 if (!NT_SUCCESS(Status
))
3165 DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status
);
3166 ZwClose(EnumRootHandle
);
3170 /* Allocate buffer to read as much data as required by the caller */
3171 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
3172 Data
[0]) + BufferLength
;
3173 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
3174 if (!ValueInformation
)
3177 return STATUS_INSUFFICIENT_RESOURCES
;
3180 /* Read the value */
3181 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
3182 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
3183 KeyValuePartialInformation
, ValueInformation
,
3184 ValueInformationLength
,
3185 &ValueInformationLength
);
3189 *ResultLength
= ValueInformation
->DataLength
;
3191 if (!NT_SUCCESS(Status
))
3193 ExFreePool(ValueInformation
);
3194 if (Status
== STATUS_BUFFER_OVERFLOW
)
3195 return STATUS_BUFFER_TOO_SMALL
;
3196 DPRINT1("Problem: Status=0x%08x, ResultLength = %d\n", Status
, *ResultLength
);
3200 /* FIXME: Verify the value (NULL-terminated, correct format). */
3201 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
3202 ValueInformation
->DataLength
);
3203 ExFreePool(ValueInformation
);
3205 return STATUS_SUCCESS
;
3208 case DevicePropertyBootConfiguration
:
3210 if (DeviceNode
->BootResources
->Count
!= 0)
3212 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
3214 Data
= &DeviceNode
->BootResources
;
3217 /* FIXME: use a translated boot configuration instead */
3218 case DevicePropertyBootConfigurationTranslated
:
3220 if (DeviceNode
->BootResources
->Count
!= 0)
3222 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
3224 Data
= &DeviceNode
->BootResources
;
3227 case DevicePropertyEnumeratorName
:
3228 /* A buffer overflow can't happen here, since InstancePath
3229 * always contains the enumerator name followed by \\ */
3230 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
3232 Length
= (Ptr
- DeviceNode
->InstancePath
.Buffer
+ 1) * sizeof(WCHAR
);
3233 Data
= DeviceNode
->InstancePath
.Buffer
;
3236 case DevicePropertyPhysicalDeviceObjectName
:
3237 /* InstancePath buffer is NULL terminated, so we can do this */
3238 Length
= DeviceNode
->InstancePath
.MaximumLength
;
3239 Data
= DeviceNode
->InstancePath
.Buffer
;
3243 return STATUS_INVALID_PARAMETER_2
;
3246 /* Prepare returned values */
3247 *ResultLength
= Length
;
3248 if (BufferLength
< Length
)
3249 return STATUS_BUFFER_TOO_SMALL
;
3250 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
3252 /* NULL terminate the string (if required) */
3253 if (DeviceProperty
== DevicePropertyEnumeratorName
)
3254 ((LPWSTR
)PropertyBuffer
)[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3256 return STATUS_SUCCESS
;
3264 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3270 * @name IoOpenDeviceRegistryKey
3272 * Open a registry key unique for a specified driver or device instance.
3274 * @param DeviceObject Device to get the registry key for.
3275 * @param DevInstKeyType Type of the key to return.
3276 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
3277 * @param DevInstRegKey Handle to the opened registry key on
3278 * successful return.
3286 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
3287 IN ULONG DevInstKeyType
,
3288 IN ACCESS_MASK DesiredAccess
,
3289 OUT PHANDLE DevInstRegKey
)
3291 static WCHAR RootKeyName
[] =
3292 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
3293 static WCHAR ProfileKeyName
[] =
3294 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
3295 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
3296 static WCHAR EnumKeyName
[] = L
"Enum\\";
3297 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
3298 ULONG KeyNameLength
;
3299 LPWSTR KeyNameBuffer
;
3300 UNICODE_STRING KeyName
;
3301 ULONG DriverKeyLength
;
3302 OBJECT_ATTRIBUTES ObjectAttributes
;
3303 PDEVICE_NODE DeviceNode
= NULL
;
3306 DPRINT("IoOpenDeviceRegistryKey() called\n");
3308 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
3310 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
3311 return STATUS_INVALID_PARAMETER
;
3315 * Calculate the length of the base key name. This is the full
3316 * name for driver key or the name excluding "Device Parameters"
3317 * subkey for device key.
3320 KeyNameLength
= sizeof(RootKeyName
);
3321 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3322 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
3323 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3325 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
3326 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3327 0, NULL
, &DriverKeyLength
);
3328 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
3330 KeyNameLength
+= DriverKeyLength
;
3334 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3335 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
3336 DeviceNode
->InstancePath
.Length
;
3340 * Now allocate the buffer for the key name...
3343 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
3344 if (KeyNameBuffer
== NULL
)
3345 return STATUS_INSUFFICIENT_RESOURCES
;
3348 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
3349 KeyName
.Buffer
= KeyNameBuffer
;
3352 * ...and build the key name.
3355 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
3356 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
3358 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3359 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
3361 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3363 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
3364 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3365 DriverKeyLength
, KeyNameBuffer
+
3366 (KeyName
.Length
/ sizeof(WCHAR
)),
3368 if (!NT_SUCCESS(Status
))
3370 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
3371 ExFreePool(KeyNameBuffer
);
3374 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
3378 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
3379 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
3380 if (DeviceNode
->InstancePath
.Length
== 0)
3382 ExFreePool(KeyNameBuffer
);
3388 * Open the base key.
3390 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
3391 if (!NT_SUCCESS(Status
))
3393 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
3394 ExFreePool(KeyNameBuffer
);
3397 ExFreePool(KeyNameBuffer
);
3400 * For driver key we're done now.
3403 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3407 * Let's go further. For device key we must open "Device Parameters"
3408 * subkey and create it if it doesn't exist yet.
3411 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
3412 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
3413 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
3414 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
3415 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
3416 ZwClose(ObjectAttributes
.RootDirectory
);
3426 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3436 IoInvalidateDeviceRelations(
3437 IN PDEVICE_OBJECT DeviceObject
,
3438 IN DEVICE_RELATION_TYPE Type
)
3440 PIO_WORKITEM WorkItem
;
3441 PINVALIDATE_DEVICE_RELATION_DATA Data
;
3443 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
3446 WorkItem
= IoAllocateWorkItem(DeviceObject
);
3453 ObReferenceObject(DeviceObject
);
3454 Data
->DeviceObject
= DeviceObject
;
3456 Data
->WorkItem
= WorkItem
;
3460 IopAsynchronousInvalidateDeviceRelations
,
3470 IoSynchronousInvalidateDeviceRelations(
3471 IN PDEVICE_OBJECT DeviceObject
,
3472 IN DEVICE_RELATION_TYPE Type
)
3479 /* Enumerate the device */
3480 return IopEnumerateDevice(DeviceObject
);
3481 case PowerRelations
:
3482 /* Not handled yet */
3483 return STATUS_NOT_IMPLEMENTED
;
3484 case TargetDeviceRelation
:
3486 return STATUS_SUCCESS
;
3488 /* Ejection relations are not supported */
3489 return STATUS_NOT_SUPPORTED
;
3498 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
3500 IN PHYSICAL_ADDRESS BusAddress
,
3501 IN OUT PULONG AddressSpace
,
3502 OUT PPHYSICAL_ADDRESS TranslatedAddress
)