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 PnpBusTypeGuidList
= 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
);
54 IopTranslateDeviceResources(
55 IN PDEVICE_NODE DeviceNode
,
56 IN ULONG RequiredSize
);
59 IopUpdateResourceMapForPnPDevice(
60 IN PDEVICE_NODE DeviceNode
);
64 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
65 IN ULONG CreateOptions
,
70 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
72 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
77 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
78 PDRIVER_OBJECT DriverObject
)
83 if (!DriverObject
->DriverExtension
->AddDevice
)
84 return STATUS_SUCCESS
;
86 /* This is a Plug and Play driver */
87 DPRINT("Plug and Play driver found\n");
88 ASSERT(DeviceNode
->PhysicalDeviceObject
);
90 /* Check if this plug-and-play driver is used as a legacy one for this device node */
91 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
93 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
94 return STATUS_SUCCESS
;
97 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
98 &DriverObject
->DriverName
,
99 &DeviceNode
->InstancePath
);
100 Status
= DriverObject
->DriverExtension
->AddDevice(
101 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
102 if (!NT_SUCCESS(Status
))
104 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
108 /* Check if driver added a FDO above the PDO */
109 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
110 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
112 /* FIXME: What do we do? Unload the driver or just disable the device? */
113 DPRINT1("An FDO was not attached\n");
114 ObDereferenceObject(Fdo
);
115 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
116 return STATUS_UNSUCCESSFUL
;
119 /* Check if we have a ACPI device (needed for power management) */
120 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
122 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
124 /* There can be only one system power device */
125 if (!SystemPowerDeviceNodeCreated
)
127 PopSystemPowerDeviceNode
= DeviceNode
;
128 ObReferenceObject(PopSystemPowerDeviceNode
);
129 SystemPowerDeviceNodeCreated
= TRUE
;
133 ObDereferenceObject(Fdo
);
135 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
136 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
138 return STATUS_SUCCESS
;
143 PDEVICE_NODE DeviceNode
)
145 IO_STATUS_BLOCK IoStatusBlock
;
146 IO_STACK_LOCATION Stack
;
147 ULONG RequiredLength
;
149 HANDLE InstanceHandle
= INVALID_HANDLE_VALUE
, ControlHandle
= INVALID_HANDLE_VALUE
;
150 UNICODE_STRING KeyName
;
151 OBJECT_ATTRIBUTES ObjectAttributes
;
153 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
154 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
155 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
156 Status
= IopInitiatePnpIrp(
157 DeviceNode
->PhysicalDeviceObject
,
159 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
161 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
163 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
164 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
167 else if (NT_SUCCESS(Status
))
169 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
172 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
173 if (NT_SUCCESS(Status
))
175 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
176 if (NT_SUCCESS(Status
))
178 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
179 if (!NT_SUCCESS(Status
))
181 DPRINT("IopUpdateResourceMap() failed (Status 0x%08lx)\n", Status
);
186 DPRINT("IopTranslateDeviceResources() failed (Status 0x%08lx)\n", Status
);
191 DPRINT("IopAssignDeviceResources() failed (Status 0x%08lx)\n", Status
);
193 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
195 if (!NT_SUCCESS(Status
))
198 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
199 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
200 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
203 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and
204 * actually _depend_ on this!. This is because NT will lock the Device Node
205 * with an ERESOURCE, which of course requires APCs to be disabled.
207 KeEnterCriticalRegion();
209 Status
= IopInitiatePnpIrp(
210 DeviceNode
->PhysicalDeviceObject
,
215 KeLeaveCriticalRegion();
217 if (!NT_SUCCESS(Status
))
219 DPRINT1("IRP_MN_START_DEVICE failed for %wZ\n", &DeviceNode
->InstancePath
);
220 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
225 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
227 DPRINT("Device needs enumeration, invalidating bus relations\n");
228 /* Invalidate device relations synchronously
229 (otherwise there will be dirty read of DeviceNode) */
230 IopEnumerateDevice(DeviceNode
->PhysicalDeviceObject
);
231 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
235 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceHandle
);
236 if (!NT_SUCCESS(Status
))
239 RtlInitUnicodeString(&KeyName
, L
"Control");
240 InitializeObjectAttributes(&ObjectAttributes
,
242 OBJ_CASE_INSENSITIVE
,
245 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
246 if (!NT_SUCCESS(Status
))
249 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
250 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
252 if (NT_SUCCESS(Status
) && DeviceNode
->ResourceList
)
254 RtlInitUnicodeString(&KeyName
, L
"AllocConfig");
255 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_RESOURCE_LIST
,
256 DeviceNode
->ResourceList
, CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceList
));
260 if (NT_SUCCESS(Status
))
261 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
263 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
265 if (ControlHandle
!= INVALID_HANDLE_VALUE
)
266 ZwClose(ControlHandle
);
268 if (InstanceHandle
!= INVALID_HANDLE_VALUE
)
269 ZwClose(InstanceHandle
);
276 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
277 PDEVICE_CAPABILITIES DeviceCaps
)
279 IO_STATUS_BLOCK StatusBlock
;
280 IO_STACK_LOCATION Stack
;
282 /* Set up the Header */
283 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
284 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
285 DeviceCaps
->Version
= 1;
286 DeviceCaps
->Address
= -1;
287 DeviceCaps
->UINumber
= -1;
289 /* Set up the Stack */
290 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
291 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
294 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
296 IRP_MN_QUERY_CAPABILITIES
,
301 IopAsynchronousInvalidateDeviceRelations(
302 IN PDEVICE_OBJECT DeviceObject
,
303 IN PVOID InvalidateContext
)
305 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
307 IoSynchronousInvalidateDeviceRelations(
311 ObDereferenceObject(Data
->DeviceObject
);
312 IoFreeWorkItem(Data
->WorkItem
);
317 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
321 if (PopSystemPowerDeviceNode
)
323 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
324 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
325 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
327 return STATUS_SUCCESS
;
330 return STATUS_UNSUCCESSFUL
;
335 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
337 USHORT i
= 0, FoundIndex
= 0xFFFF;
341 /* Acquire the lock */
342 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
344 /* Loop all entries */
345 while (i
< PnpBusTypeGuidList
->GuidCount
)
347 /* Try to find a match */
348 if (RtlCompareMemory(BusTypeGuid
,
349 &PnpBusTypeGuidList
->Guids
[i
],
350 sizeof(GUID
)) == sizeof(GUID
))
359 /* Check if we have to grow the list */
360 if (PnpBusTypeGuidList
->GuidCount
)
362 /* Calculate the new size */
363 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
364 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
366 /* Allocate the new copy */
367 NewList
= ExAllocatePool(PagedPool
, NewSize
);
371 ExFreePool(PnpBusTypeGuidList
);
375 /* Now copy them, decrease the size too */
376 NewSize
-= sizeof(GUID
);
377 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
379 /* Free the old list */
380 ExFreePool(PnpBusTypeGuidList
);
382 /* Use the new buffer */
383 PnpBusTypeGuidList
= NewList
;
386 /* Copy the new GUID */
387 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
391 /* The new entry is the index */
392 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
393 PnpBusTypeGuidList
->GuidCount
++;
396 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
402 * Creates a device node
405 * ParentNode = Pointer to parent device node
406 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
407 * to have the root device node create one
408 * (eg. for legacy drivers)
409 * DeviceNode = Pointer to storage for created device node
415 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
416 PDEVICE_OBJECT PhysicalDeviceObject
,
417 PUNICODE_STRING ServiceName
,
418 PDEVICE_NODE
*DeviceNode
)
423 UNICODE_STRING FullServiceName
;
424 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
425 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
426 UNICODE_STRING KeyName
, ClassName
, ClassGUID
;
427 PUNICODE_STRING ServiceName1
;
429 HANDLE InstanceHandle
;
431 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
432 ParentNode
, PhysicalDeviceObject
, ServiceName
);
434 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
437 return STATUS_INSUFFICIENT_RESOURCES
;
440 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
443 ServiceName1
= &UnknownDeviceName
;
445 ServiceName1
= ServiceName
;
447 if (!PhysicalDeviceObject
)
449 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
450 FullServiceName
.Length
= 0;
451 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
452 if (!FullServiceName
.Buffer
)
455 return STATUS_INSUFFICIENT_RESOURCES
;
458 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
459 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
461 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
462 if (!NT_SUCCESS(Status
))
464 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
469 /* Create the device key for legacy drivers */
470 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
471 if (!NT_SUCCESS(Status
))
473 ZwClose(InstanceHandle
);
475 ExFreePool(FullServiceName
.Buffer
);
479 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
480 if (!Node
->ServiceName
.Buffer
)
482 ZwClose(InstanceHandle
);
484 ExFreePool(FullServiceName
.Buffer
);
488 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
489 Node
->ServiceName
.Length
= 0;
491 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
495 RtlInitUnicodeString(&KeyName
, L
"Service");
496 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
499 if (NT_SUCCESS(Status
))
501 RtlInitUnicodeString(&KeyName
, L
"Legacy");
504 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
505 if (NT_SUCCESS(Status
))
507 RtlInitUnicodeString(&KeyName
, L
"Class");
509 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
510 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
);
511 if (NT_SUCCESS(Status
))
513 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
515 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
516 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
);
521 ZwClose(InstanceHandle
);
522 ExFreePool(FullServiceName
.Buffer
);
524 if (!NT_SUCCESS(Status
))
530 /* This is for drivers passed on the command line to ntoskrnl.exe */
531 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
534 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
536 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
540 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
541 Node
->Parent
= ParentNode
;
542 Node
->Sibling
= ParentNode
->Child
;
543 ParentNode
->Child
= Node
;
544 if (ParentNode
->LastChild
== NULL
)
545 ParentNode
->LastChild
= Node
;
546 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
547 Node
->Level
= ParentNode
->Level
+ 1;
550 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
554 return STATUS_SUCCESS
;
558 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
561 PDEVICE_NODE PrevSibling
= NULL
;
563 /* All children must be deleted before a parent is deleted */
564 ASSERT(!DeviceNode
->Child
);
566 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
568 ASSERT(DeviceNode
->PhysicalDeviceObject
);
570 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
572 /* Get previous sibling */
573 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
575 PrevSibling
= DeviceNode
->Parent
->Child
;
576 while (PrevSibling
->Sibling
!= DeviceNode
)
577 PrevSibling
= PrevSibling
->Sibling
;
580 /* Unlink from parent if it exists */
581 if (DeviceNode
->Parent
)
583 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
585 DeviceNode
->Parent
->LastChild
= PrevSibling
;
587 PrevSibling
->Sibling
= NULL
;
589 if (DeviceNode
->Parent
->Child
== DeviceNode
)
590 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
593 /* Unlink from sibling list */
595 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
597 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
599 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
601 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
603 if (DeviceNode
->ResourceList
)
605 ExFreePool(DeviceNode
->ResourceList
);
608 if (DeviceNode
->ResourceListTranslated
)
610 ExFreePool(DeviceNode
->ResourceListTranslated
);
613 if (DeviceNode
->ResourceRequirements
)
615 ExFreePool(DeviceNode
->ResourceRequirements
);
618 if (DeviceNode
->BootResources
)
620 ExFreePool(DeviceNode
->BootResources
);
623 ExFreePool(DeviceNode
);
625 return STATUS_SUCCESS
;
630 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
631 IN PIO_STACK_LOCATION IoStackLocation
,
632 OUT PVOID
*Information
)
635 PIO_STACK_LOCATION IrpStack
;
636 IO_STATUS_BLOCK IoStatusBlock
;
639 PDEVICE_OBJECT TopDeviceObject
;
642 /* Call the top of the device stack */
643 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
645 /* Allocate an IRP */
646 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
647 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
649 /* Initialize to failure */
650 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
651 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
653 /* Initialize the event */
654 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
657 Irp
->UserIosb
= &IoStatusBlock
;
658 Irp
->UserEvent
= &Event
;
661 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
662 IoQueueThreadIrp(Irp
);
664 /* Copy-in the stack */
665 IrpStack
= IoGetNextIrpStackLocation(Irp
);
666 *IrpStack
= *IoStackLocation
;
668 /* Call the driver */
669 Status
= IoCallDriver(TopDeviceObject
, Irp
);
670 if (Status
== STATUS_PENDING
)
673 KeWaitForSingleObject(&Event
,
678 Status
= IoStatusBlock
.Status
;
681 /* Return the information */
682 *Information
= (PVOID
)IoStatusBlock
.Information
;
688 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
689 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
690 IN ULONG MinorFunction
,
691 IN PIO_STACK_LOCATION Stack OPTIONAL
)
693 IO_STACK_LOCATION IoStackLocation
;
695 /* Fill out the stack information */
696 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
697 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
698 IoStackLocation
.MinorFunction
= MinorFunction
;
702 RtlCopyMemory(&IoStackLocation
.Parameters
,
704 sizeof(Stack
->Parameters
));
707 /* Do the PnP call */
708 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
710 (PVOID
)&IoStatusBlock
->Information
);
711 return IoStatusBlock
->Status
;
715 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
717 PDEVICE_NODE ParentDeviceNode
;
718 PDEVICE_NODE ChildDeviceNode
;
721 /* Copy context data so we don't overwrite it in subsequent calls to this function */
722 ParentDeviceNode
= Context
->DeviceNode
;
724 /* Call the action routine */
725 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
726 if (!NT_SUCCESS(Status
))
731 /* Traversal of all children nodes */
732 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
733 ChildDeviceNode
!= NULL
;
734 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
736 /* Pass the current device node to the action routine */
737 Context
->DeviceNode
= ChildDeviceNode
;
739 Status
= IopTraverseDeviceTreeNode(Context
);
740 if (!NT_SUCCESS(Status
))
751 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
755 DPRINT("Context 0x%p\n", Context
);
757 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
758 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
760 /* Start from the specified device node */
761 Context
->DeviceNode
= Context
->FirstDeviceNode
;
763 /* Recursively traverse the device tree */
764 Status
= IopTraverseDeviceTreeNode(Context
);
765 if (Status
== STATUS_UNSUCCESSFUL
)
767 /* The action routine just wanted to terminate the traversal with status
768 code STATUS_SUCCESS */
769 Status
= STATUS_SUCCESS
;
777 * IopCreateDeviceKeyPath
779 * Creates a registry key
783 * Name of the key to be created.
785 * Handle to the newly created key
788 * This method can create nested trees, so parent of RegistryPath can
789 * be not existant, and will be created if needed.
793 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
794 IN ULONG CreateOptions
,
797 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
798 HANDLE hParent
= NULL
, hKey
;
799 OBJECT_ATTRIBUTES ObjectAttributes
;
800 UNICODE_STRING KeyName
;
801 LPCWSTR Current
, Last
;
808 /* Open root key for device instances */
809 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
810 if (!NT_SUCCESS(Status
))
812 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
816 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
817 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
819 /* Go up to the end of the string */
820 while (Current
<= Last
)
822 if (Current
!= Last
&& *Current
!= '\\')
824 /* Not the end of the string and not a separator */
829 /* Prepare relative key name */
830 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
831 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
832 DPRINT("Create '%wZ'\n", &KeyName
);
835 InitializeObjectAttributes(&ObjectAttributes
,
837 OBJ_CASE_INSENSITIVE
,
840 Status
= ZwCreateKey(&hKey
,
841 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
848 /* Close parent key handle, we don't need it anymore */
852 /* Key opening/creating failed? */
853 if (!NT_SUCCESS(Status
))
855 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
859 /* Check if it is the end of the string */
862 /* Yes, return success */
864 return STATUS_SUCCESS
;
867 /* Start with this new parent key */
870 KeyName
.Buffer
= (LPWSTR
)Current
;
873 return STATUS_UNSUCCESSFUL
;
877 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode
, PWCHAR Level1Key
, PWCHAR Level2Key
)
881 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
882 UNICODE_STRING KeyName
;
883 OBJECT_ATTRIBUTES ObjectAttributes
;
885 RtlInitUnicodeString(&KeyName
,
886 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
887 InitializeObjectAttributes(&ObjectAttributes
,
889 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
892 Status
= ZwCreateKey(&ResourceMapKey
,
899 if (!NT_SUCCESS(Status
))
902 RtlInitUnicodeString(&KeyName
, Level1Key
);
903 InitializeObjectAttributes(&ObjectAttributes
,
905 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
908 Status
= ZwCreateKey(&PnpMgrLevel1
,
915 ZwClose(ResourceMapKey
);
916 if (!NT_SUCCESS(Status
))
919 RtlInitUnicodeString(&KeyName
, Level2Key
);
920 InitializeObjectAttributes(&ObjectAttributes
,
922 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
925 Status
= ZwCreateKey(&PnpMgrLevel2
,
932 ZwClose(PnpMgrLevel1
);
933 if (!NT_SUCCESS(Status
))
936 if (DeviceNode
->ResourceList
)
939 UNICODE_STRING NameU
;
940 UNICODE_STRING Suffix
;
943 ASSERT(DeviceNode
->ResourceListTranslated
);
945 NameU
.Buffer
= NameBuff
;
947 NameU
.MaximumLength
= 256 * sizeof(WCHAR
);
949 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
950 DevicePropertyPhysicalDeviceObjectName
,
954 ASSERT(Status
== STATUS_SUCCESS
);
956 NameU
.Length
= (USHORT
)OldLength
;
958 RtlInitUnicodeString(&Suffix
, L
".Raw");
959 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
961 Status
= ZwSetValueKey(PnpMgrLevel2
,
965 DeviceNode
->ResourceList
,
966 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceList
));
967 if (!NT_SUCCESS(Status
))
969 ZwClose(PnpMgrLevel2
);
973 /* "Remove" the suffix by setting the length back to what it used to be */
974 NameU
.Length
= (USHORT
)OldLength
;
976 RtlInitUnicodeString(&Suffix
, L
".Translated");
977 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
979 Status
= ZwSetValueKey(PnpMgrLevel2
,
983 DeviceNode
->ResourceListTranslated
,
984 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceListTranslated
));
985 ZwClose(PnpMgrLevel2
);
986 if (!NT_SUCCESS(Status
))
991 ZwClose(PnpMgrLevel2
);
994 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
996 return STATUS_SUCCESS
;
1000 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode
)
1002 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
1006 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1007 PDEVICE_NODE DeviceNode
)
1009 OBJECT_ATTRIBUTES ObjectAttributes
;
1010 UNICODE_STRING KeyName
;
1013 ULONG ListSize
, ResultLength
;
1015 HANDLE ControlHandle
;
1017 DPRINT("IopSetDeviceInstanceData() called\n");
1019 /* Create the 'LogConf' key */
1020 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1021 InitializeObjectAttributes(&ObjectAttributes
,
1023 OBJ_CASE_INSENSITIVE
,
1026 Status
= ZwCreateKey(&LogConfKey
,
1033 if (NT_SUCCESS(Status
))
1035 /* Set 'BootConfig' value */
1036 if (DeviceNode
->BootResources
!= NULL
)
1038 ResCount
= DeviceNode
->BootResources
->Count
;
1041 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1043 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1044 Status
= ZwSetValueKey(LogConfKey
,
1048 DeviceNode
->BootResources
,
1053 /* Set 'BasicConfigVector' value */
1054 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1055 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1057 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1058 Status
= ZwSetValueKey(LogConfKey
,
1061 REG_RESOURCE_REQUIREMENTS_LIST
,
1062 DeviceNode
->ResourceRequirements
,
1063 DeviceNode
->ResourceRequirements
->ListSize
);
1066 ZwClose(LogConfKey
);
1069 /* Set the 'ConfigFlags' value */
1070 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1071 Status
= ZwQueryValueKey(InstanceKey
,
1073 KeyValueBasicInformation
,
1077 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1079 /* Write the default value */
1080 ULONG DefaultConfigFlags
= 0;
1081 Status
= ZwSetValueKey(InstanceKey
,
1085 &DefaultConfigFlags
,
1086 sizeof(DefaultConfigFlags
));
1089 /* Create the 'Control' key */
1090 RtlInitUnicodeString(&KeyName
, L
"Control");
1091 InitializeObjectAttributes(&ObjectAttributes
,
1093 OBJ_CASE_INSENSITIVE
,
1096 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1098 if (NT_SUCCESS(Status
))
1099 ZwClose(ControlHandle
);
1101 DPRINT("IopSetDeviceInstanceData() done\n");
1107 IopCheckResourceDescriptor(
1108 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
1109 IN PCM_RESOURCE_LIST ResourceList
,
1111 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1114 BOOLEAN Result
= FALSE
;
1116 if (ResDesc
->ShareDisposition
== CmResourceShareShared
)
1119 for (i
= 0; i
< ResourceList
->Count
; i
++)
1121 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList
->List
[i
].PartialResourceList
;
1122 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1124 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
1126 /* We don't care about shared resources */
1127 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
1128 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
1131 /* Make sure we're comparing the same types */
1132 if (ResDesc
->Type
!= ResDesc2
->Type
)
1135 switch (ResDesc
->Type
)
1137 case CmResourceTypeMemory
:
1138 if ((ResDesc
->u
.Memory
.Start
.QuadPart
< ResDesc2
->u
.Memory
.Start
.QuadPart
&&
1139 ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
1140 ResDesc2
->u
.Memory
.Start
.QuadPart
) || (ResDesc2
->u
.Memory
.Start
.QuadPart
<
1141 ResDesc
->u
.Memory
.Start
.QuadPart
&& ResDesc2
->u
.Memory
.Start
.QuadPart
+
1142 ResDesc2
->u
.Memory
.Length
> ResDesc
->u
.Memory
.Start
.QuadPart
))
1146 DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1147 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
1148 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
1149 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
1158 case CmResourceTypePort
:
1159 if ((ResDesc
->u
.Port
.Start
.QuadPart
< ResDesc2
->u
.Port
.Start
.QuadPart
&&
1160 ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
1161 ResDesc2
->u
.Port
.Start
.QuadPart
) || (ResDesc2
->u
.Port
.Start
.QuadPart
<
1162 ResDesc
->u
.Port
.Start
.QuadPart
&& ResDesc2
->u
.Port
.Start
.QuadPart
+
1163 ResDesc2
->u
.Port
.Length
> ResDesc
->u
.Port
.Start
.QuadPart
))
1167 DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1168 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
1169 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
1170 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
1179 case CmResourceTypeInterrupt
:
1180 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
1184 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
1185 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
1186 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
1195 case CmResourceTypeBusNumber
:
1196 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
1197 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
1198 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
1199 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
1200 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
1204 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1205 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
1206 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
1207 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
1216 case CmResourceTypeDma
:
1217 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
1221 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
1222 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
1223 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
1237 if (Result
&& ConflictingDescriptor
)
1239 RtlCopyMemory(ConflictingDescriptor
,
1241 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1249 IopCheckForResourceConflict(
1250 IN PCM_RESOURCE_LIST ResourceList1
,
1251 IN PCM_RESOURCE_LIST ResourceList2
,
1253 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1256 BOOLEAN Result
= FALSE
;
1258 for (i
= 0; i
< ResourceList1
->Count
; i
++)
1260 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
1261 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1263 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
1265 Result
= IopCheckResourceDescriptor(ResDesc
,
1268 ConflictingDescriptor
);
1269 if (Result
) goto ByeBye
;
1280 IopDetectResourceConflict(
1281 IN PCM_RESOURCE_LIST ResourceList
,
1283 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1285 OBJECT_ATTRIBUTES ObjectAttributes
;
1286 UNICODE_STRING KeyName
;
1287 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
1288 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
1289 PKEY_BASIC_INFORMATION KeyInformation
;
1290 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
1291 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
1292 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
1295 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1296 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
1297 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1298 if (!NT_SUCCESS(Status
))
1300 /* The key is missing which means we are the first device */
1301 return STATUS_SUCCESS
;
1306 Status
= ZwEnumerateKey(ResourceMapKey
,
1308 KeyBasicInformation
,
1312 if (Status
== STATUS_NO_MORE_ENTRIES
)
1314 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1316 KeyInformationLength
= RequiredLength
;
1317 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1318 if (!KeyInformation
)
1320 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1324 Status
= ZwEnumerateKey(ResourceMapKey
,
1326 KeyBasicInformation
,
1328 KeyInformationLength
,
1334 if (!NT_SUCCESS(Status
))
1337 KeyName
.Buffer
= KeyInformation
->Name
;
1338 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1339 InitializeObjectAttributes(&ObjectAttributes
,
1341 OBJ_CASE_INSENSITIVE
,
1344 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1345 ExFreePool(KeyInformation
);
1346 if (!NT_SUCCESS(Status
))
1351 Status
= ZwEnumerateKey(ChildKey2
,
1353 KeyBasicInformation
,
1357 if (Status
== STATUS_NO_MORE_ENTRIES
)
1359 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1361 KeyInformationLength
= RequiredLength
;
1362 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1363 if (!KeyInformation
)
1365 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1369 Status
= ZwEnumerateKey(ChildKey2
,
1371 KeyBasicInformation
,
1373 KeyInformationLength
,
1379 if (!NT_SUCCESS(Status
))
1382 KeyName
.Buffer
= KeyInformation
->Name
;
1383 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1384 InitializeObjectAttributes(&ObjectAttributes
,
1386 OBJ_CASE_INSENSITIVE
,
1389 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1390 ExFreePool(KeyInformation
);
1391 if (!NT_SUCCESS(Status
))
1396 Status
= ZwEnumerateValueKey(ChildKey3
,
1398 KeyValuePartialInformation
,
1402 if (Status
== STATUS_NO_MORE_ENTRIES
)
1404 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1406 KeyValueInformationLength
= RequiredLength
;
1407 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1408 if (!KeyValueInformation
)
1410 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1414 Status
= ZwEnumerateValueKey(ChildKey3
,
1416 KeyValuePartialInformation
,
1417 KeyValueInformation
,
1418 KeyValueInformationLength
,
1423 if (!NT_SUCCESS(Status
))
1426 Status
= ZwEnumerateValueKey(ChildKey3
,
1428 KeyValueBasicInformation
,
1432 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1434 KeyNameInformationLength
= RequiredLength
;
1435 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1436 if (!KeyNameInformation
)
1438 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1442 Status
= ZwEnumerateValueKey(ChildKey3
,
1444 KeyValueBasicInformation
,
1446 KeyNameInformationLength
,
1454 if (!NT_SUCCESS(Status
))
1457 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1459 /* Skip translated entries */
1460 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1462 ExFreePool(KeyNameInformation
);
1466 ExFreePool(KeyNameInformation
);
1468 if (IopCheckForResourceConflict(ResourceList
,
1469 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1471 ConflictingDescriptor
))
1473 ExFreePool(KeyValueInformation
);
1474 Status
= STATUS_CONFLICTING_ADDRESSES
;
1478 ExFreePool(KeyValueInformation
);
1484 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1485 ZwClose(ResourceMapKey
);
1486 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1488 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1491 if (Status
== STATUS_NO_MORE_ENTRIES
)
1492 Status
= STATUS_SUCCESS
;
1498 IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1500 CM_RESOURCE_LIST CmList
;
1504 CmList
.List
[0].InterfaceType
= InterfaceTypeUndefined
;
1505 CmList
.List
[0].BusNumber
= 0;
1506 CmList
.List
[0].PartialResourceList
.Version
= 1;
1507 CmList
.List
[0].PartialResourceList
.Revision
= 1;
1508 CmList
.List
[0].PartialResourceList
.Count
= 1;
1509 CmList
.List
[0].PartialResourceList
.PartialDescriptors
[0] = *CmDesc
;
1511 Status
= IopDetectResourceConflict(&CmList
, TRUE
, ConflictingDescriptor
);
1512 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
1519 IopFindBusNumberResource(
1520 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1521 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1524 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1526 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1527 ASSERT(IoDesc
->Type
== CmResourceTypeBusNumber
);
1529 for (Start
= IoDesc
->u
.BusNumber
.MinBusNumber
;
1530 Start
< IoDesc
->u
.BusNumber
.MaxBusNumber
;
1533 CmDesc
->u
.BusNumber
.Length
= IoDesc
->u
.BusNumber
.Length
;
1534 CmDesc
->u
.BusNumber
.Start
= Start
;
1536 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1538 Start
+= ConflictingDesc
.u
.BusNumber
.Start
+ ConflictingDesc
.u
.BusNumber
.Length
;
1550 IopFindMemoryResource(
1551 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1552 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1555 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1557 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1558 ASSERT(IoDesc
->Type
== CmResourceTypeMemory
);
1560 for (Start
= IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
;
1561 Start
< IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
;
1564 CmDesc
->u
.Memory
.Length
= IoDesc
->u
.Memory
.Length
;
1565 CmDesc
->u
.Memory
.Start
.QuadPart
= Start
;
1567 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1569 Start
+= ConflictingDesc
.u
.Memory
.Start
.QuadPart
+ ConflictingDesc
.u
.Memory
.Length
;
1581 IopFindPortResource(
1582 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1583 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1586 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1588 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1589 ASSERT(IoDesc
->Type
== CmResourceTypePort
);
1591 for (Start
= IoDesc
->u
.Port
.MinimumAddress
.QuadPart
;
1592 Start
< IoDesc
->u
.Port
.MaximumAddress
.QuadPart
;
1595 CmDesc
->u
.Port
.Length
= IoDesc
->u
.Port
.Length
;
1596 CmDesc
->u
.Port
.Start
.QuadPart
= Start
;
1598 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1600 Start
+= ConflictingDesc
.u
.Port
.Start
.QuadPart
+ ConflictingDesc
.u
.Port
.Length
;
1613 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1614 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1618 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1619 ASSERT(IoDesc
->Type
== CmResourceTypeDma
);
1621 for (Channel
= IoDesc
->u
.Dma
.MinimumChannel
;
1622 Channel
< IoDesc
->u
.Dma
.MaximumChannel
;
1625 CmDesc
->u
.Dma
.Channel
= Channel
;
1626 CmDesc
->u
.Dma
.Port
= 0;
1628 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
1636 IopFindInterruptResource(
1637 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1638 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1642 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1643 ASSERT(IoDesc
->Type
== CmResourceTypeInterrupt
);
1645 for (Vector
= IoDesc
->u
.Interrupt
.MinimumVector
;
1646 Vector
< IoDesc
->u
.Interrupt
.MaximumVector
;
1649 CmDesc
->u
.Interrupt
.Vector
= Vector
;
1650 CmDesc
->u
.Interrupt
.Level
= Vector
;
1651 CmDesc
->u
.Interrupt
.Affinity
= (KAFFINITY
)-1;
1653 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
1661 IopCreateResourceListFromRequirements(
1662 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
,
1663 OUT PCM_RESOURCE_LIST
*ResourceList
)
1666 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
;
1668 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1669 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
1671 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
1672 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1673 + ResList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1676 *ResourceList
= ExAllocatePool(PagedPool
, Size
);
1678 return STATUS_INSUFFICIENT_RESOURCES
;
1680 (*ResourceList
)->Count
= 1;
1681 (*ResourceList
)->List
[0].BusNumber
= RequirementsList
->BusNumber
;
1682 (*ResourceList
)->List
[0].InterfaceType
= RequirementsList
->InterfaceType
;
1683 (*ResourceList
)->List
[0].PartialResourceList
.Version
= 1;
1684 (*ResourceList
)->List
[0].PartialResourceList
.Revision
= 1;
1685 (*ResourceList
)->List
[0].PartialResourceList
.Count
= 0;
1687 ResDesc
= &(*ResourceList
)->List
[0].PartialResourceList
.PartialDescriptors
[0];
1689 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
1691 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
1692 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1694 PIO_RESOURCE_DESCRIPTOR ReqDesc
= &ResList
->Descriptors
[ii
];
1696 /* FIXME: Handle alternate ranges */
1697 if (ReqDesc
->Option
== IO_RESOURCE_ALTERNATIVE
)
1700 ResDesc
->Type
= ReqDesc
->Type
;
1701 ResDesc
->Flags
= ReqDesc
->Flags
;
1702 ResDesc
->ShareDisposition
= ReqDesc
->ShareDisposition
;
1704 switch (ReqDesc
->Type
)
1706 case CmResourceTypeInterrupt
:
1707 if (!IopFindInterruptResource(ReqDesc
, ResDesc
))
1709 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
1710 ReqDesc
->u
.Interrupt
.MinimumVector
, ReqDesc
->u
.Interrupt
.MaximumVector
);
1712 if (ReqDesc
->Option
== 0)
1714 ExFreePool(*ResourceList
);
1715 return STATUS_CONFLICTING_ADDRESSES
;
1720 case CmResourceTypePort
:
1721 if (!IopFindPortResource(ReqDesc
, ResDesc
))
1723 DPRINT1("Failed to find an available port resource (0x%x to 0x%x length: 0x%x)\n",
1724 ReqDesc
->u
.Port
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Port
.MaximumAddress
.QuadPart
,
1725 ReqDesc
->u
.Port
.Length
);
1727 if (ReqDesc
->Option
== 0)
1729 ExFreePool(*ResourceList
);
1730 return STATUS_CONFLICTING_ADDRESSES
;
1735 case CmResourceTypeMemory
:
1736 if (!IopFindMemoryResource(ReqDesc
, ResDesc
))
1738 DPRINT1("Failed to find an available memory resource (0x%x to 0x%x length: 0x%x)\n",
1739 ReqDesc
->u
.Memory
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
1740 ReqDesc
->u
.Memory
.Length
);
1742 if (ReqDesc
->Option
== 0)
1744 ExFreePool(*ResourceList
);
1745 return STATUS_CONFLICTING_ADDRESSES
;
1750 case CmResourceTypeBusNumber
:
1751 if (!IopFindBusNumberResource(ReqDesc
, ResDesc
))
1753 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
1754 ReqDesc
->u
.BusNumber
.MinBusNumber
, ReqDesc
->u
.BusNumber
.MaxBusNumber
,
1755 ReqDesc
->u
.BusNumber
.Length
);
1757 if (ReqDesc
->Option
== 0)
1759 ExFreePool(*ResourceList
);
1760 return STATUS_CONFLICTING_ADDRESSES
;
1765 case CmResourceTypeDma
:
1766 if (!IopFindDmaResource(ReqDesc
, ResDesc
))
1768 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
1769 ReqDesc
->u
.Dma
.MinimumChannel
, ReqDesc
->u
.Dma
.MaximumChannel
);
1771 if (ReqDesc
->Option
== 0)
1773 ExFreePool(*ResourceList
);
1774 return STATUS_CONFLICTING_ADDRESSES
;
1780 DPRINT1("Unsupported resource type: %x\n", ReqDesc
->Type
);
1784 (*ResourceList
)->List
[0].PartialResourceList
.Count
++;
1789 return STATUS_SUCCESS
;
1793 IopAssignDeviceResources(
1794 IN PDEVICE_NODE DeviceNode
,
1795 OUT ULONG
*pRequiredSize
)
1797 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1803 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1805 /* No resource needed for this device */
1806 DeviceNode
->ResourceList
= NULL
;
1808 return STATUS_SUCCESS
;
1811 /* Fill DeviceNode->ResourceList
1812 * FIXME: the PnP arbiter should go there!
1813 * Actually, use the BootResources if provided, else the resource requirements
1816 if (DeviceNode
->BootResources
)
1818 /* Browse the boot resources to know if we have some custom structures */
1819 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1820 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1822 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1823 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
) +
1824 pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1825 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1827 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1828 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1832 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1833 if (!DeviceNode
->ResourceList
)
1835 Status
= STATUS_NO_MEMORY
;
1838 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1840 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
1841 if (NT_SUCCESS(Status
) || !DeviceNode
->ResourceRequirements
)
1843 if (!NT_SUCCESS(Status
) && !DeviceNode
->ResourceRequirements
)
1845 DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
1848 *pRequiredSize
= Size
;
1849 return STATUS_SUCCESS
;
1853 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
1854 ExFreePool(DeviceNode
->ResourceList
);
1858 Status
= IopCreateResourceListFromRequirements(DeviceNode
->ResourceRequirements
,
1859 &DeviceNode
->ResourceList
);
1860 if (!NT_SUCCESS(Status
))
1863 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1864 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1866 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1867 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
) +
1868 pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1871 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
1872 if (!NT_SUCCESS(Status
))
1875 *pRequiredSize
= Size
;
1876 return STATUS_SUCCESS
;
1879 if (DeviceNode
->ResourceList
)
1881 ExFreePool(DeviceNode
->ResourceList
);
1882 DeviceNode
->ResourceList
= NULL
;
1890 IopTranslateDeviceResources(
1891 IN PDEVICE_NODE DeviceNode
,
1892 IN ULONG RequiredSize
)
1894 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1895 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1899 if (!DeviceNode
->ResourceList
)
1901 DeviceNode
->ResourceListTranslated
= NULL
;
1902 return STATUS_SUCCESS
;
1905 /* That's easy to translate a resource list. Just copy the
1906 * untranslated one and change few fields in the copy
1908 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1909 if (!DeviceNode
->ResourceListTranslated
)
1911 Status
=STATUS_NO_MEMORY
;
1914 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1916 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1918 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1919 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1921 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1922 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1923 switch (DescriptorRaw
->Type
)
1925 case CmResourceTypePort
:
1927 ULONG AddressSpace
= 1; /* IO space */
1928 if (!HalTranslateBusAddress(
1929 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1930 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1931 DescriptorRaw
->u
.Port
.Start
,
1933 &DescriptorTranslated
->u
.Port
.Start
))
1935 Status
= STATUS_UNSUCCESSFUL
;
1940 case CmResourceTypeInterrupt
:
1942 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1943 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1944 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1945 DescriptorRaw
->u
.Interrupt
.Level
,
1946 DescriptorRaw
->u
.Interrupt
.Vector
,
1947 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1948 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1951 case CmResourceTypeMemory
:
1953 ULONG AddressSpace
= 0; /* Memory space */
1954 if (!HalTranslateBusAddress(
1955 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1956 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1957 DescriptorRaw
->u
.Memory
.Start
,
1959 &DescriptorTranslated
->u
.Memory
.Start
))
1961 Status
= STATUS_UNSUCCESSFUL
;
1966 case CmResourceTypeDma
:
1967 case CmResourceTypeBusNumber
:
1968 case CmResourceTypeDeviceSpecific
:
1972 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1973 Status
= STATUS_NOT_IMPLEMENTED
;
1978 return STATUS_SUCCESS
;
1981 /* Yes! Also delete ResourceList because ResourceList and
1982 * ResourceListTranslated should be a pair! */
1983 ExFreePool(DeviceNode
->ResourceList
);
1984 DeviceNode
->ResourceList
= NULL
;
1985 if (DeviceNode
->ResourceListTranslated
)
1987 ExFreePool(DeviceNode
->ResourceListTranslated
);
1988 DeviceNode
->ResourceList
= NULL
;
1995 * IopGetParentIdPrefix
1997 * Retrieve (or create) a string which identifies a device.
2001 * Pointer to device node.
2003 * Pointer to the string where is returned the parent node identifier
2006 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
2007 * valid and its Buffer field is NULL-terminated. The caller needs to
2008 * to free the string with RtlFreeUnicodeString when it is no longer
2013 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
2014 PUNICODE_STRING ParentIdPrefix
)
2016 ULONG KeyNameBufferLength
;
2017 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
2018 UNICODE_STRING KeyName
;
2019 UNICODE_STRING KeyValue
;
2020 UNICODE_STRING ValueName
;
2025 /* HACK: As long as some devices have a NULL device
2026 * instance path, the following test is required :(
2028 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
2030 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
2031 &DeviceNode
->InstancePath
);
2032 return STATUS_UNSUCCESSFUL
;
2035 /* 1. Try to retrieve ParentIdPrefix from registry */
2036 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
2037 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
2038 if (!ParentIdPrefixInformation
)
2040 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2045 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
2046 if (!KeyName
.Buffer
)
2048 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2052 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
2054 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2055 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
2057 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
2058 if (!NT_SUCCESS(Status
))
2060 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
2061 Status
= ZwQueryValueKey(
2063 KeyValuePartialInformation
, ParentIdPrefixInformation
,
2064 KeyNameBufferLength
, &KeyNameBufferLength
);
2065 if (NT_SUCCESS(Status
))
2067 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
2068 Status
= STATUS_UNSUCCESSFUL
;
2071 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
2072 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
2076 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2078 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
2079 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
2083 /* 2. Create the ParentIdPrefix value */
2084 crc32
= RtlComputeCrc32(0,
2085 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
2086 DeviceNode
->Parent
->InstancePath
.Length
);
2088 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
2089 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
2091 /* 3. Try to write the ParentIdPrefix to registry */
2092 Status
= ZwSetValueKey(hKey
,
2096 (PVOID
)KeyValue
.Buffer
,
2097 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
2100 if (NT_SUCCESS(Status
))
2102 /* Duplicate the string to return it */
2103 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
2105 ExFreePool(ParentIdPrefixInformation
);
2106 RtlFreeUnicodeString(&KeyName
);
2114 * IopActionInterrogateDeviceStack
2116 * Retrieve information for all (direct) child nodes of a parent node.
2120 * Pointer to device node.
2122 * Pointer to parent node to retrieve child node information for.
2125 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2126 * when we reach a device node which is not a direct child of the device
2127 * node for which we retrieve information of child nodes for. Any errors
2128 * that occur is logged instead so that all child services have a chance
2129 * of being interrogated.
2133 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
2136 IO_STATUS_BLOCK IoStatusBlock
;
2137 PDEVICE_NODE ParentDeviceNode
;
2138 WCHAR InstancePath
[MAX_PATH
];
2139 IO_STACK_LOCATION Stack
;
2144 ULONG RequiredLength
;
2146 HANDLE InstanceKey
= NULL
;
2147 UNICODE_STRING ValueName
;
2148 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
2149 DEVICE_CAPABILITIES DeviceCapabilities
;
2151 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
2152 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
2154 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2157 * We are called for the parent too, but we don't need to do special
2158 * handling for this node
2161 if (DeviceNode
== ParentDeviceNode
)
2163 DPRINT("Success\n");
2164 return STATUS_SUCCESS
;
2168 * Make sure this device node is a direct child of the parent device node
2169 * that is given as an argument
2172 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2174 /* Stop the traversal immediately and indicate successful operation */
2176 return STATUS_UNSUCCESSFUL
;
2180 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
2181 if (!NT_SUCCESS(Status
))
2183 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
2188 * FIXME: For critical errors, cleanup and disable device, but always
2189 * return STATUS_SUCCESS.
2192 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
2194 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
2195 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2199 if (NT_SUCCESS(Status
))
2201 /* Copy the device id string */
2202 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
2205 * FIXME: Check for valid characters, if there is invalid characters
2211 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2214 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
2216 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
2217 if (!NT_SUCCESS(Status
))
2219 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
2222 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
2224 if (!DeviceCapabilities
.UniqueID
)
2226 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
2227 DPRINT("Instance ID is not unique\n");
2228 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
2229 if (!NT_SUCCESS(Status
))
2231 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
2235 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
2237 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
2238 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2242 if (NT_SUCCESS(Status
))
2244 /* Append the instance id string */
2245 wcscat(InstancePath
, L
"\\");
2246 if (ParentIdPrefix
.Length
> 0)
2248 /* Add information from parent bus device to InstancePath */
2249 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
2250 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
2251 wcscat(InstancePath
, L
"&");
2253 if (IoStatusBlock
.Information
)
2254 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
2257 * FIXME: Check for valid characters, if there is invalid characters
2263 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2265 RtlFreeUnicodeString(&ParentIdPrefix
);
2267 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
2269 DPRINT("No resources\n");
2270 /* FIXME: Cleanup and disable device */
2273 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
2276 * Create registry key for the instance id, if it doesn't exist yet
2278 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
2279 if (!NT_SUCCESS(Status
))
2281 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2285 /* Set 'Capabilities' value */
2286 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
2287 Status
= ZwSetValueKey(InstanceKey
,
2291 (PVOID
)&DeviceNode
->CapabilityFlags
,
2294 /* Set 'UINumber' value */
2295 if (DeviceCapabilities
.UINumber
!= MAXULONG
)
2297 RtlInitUnicodeString(&ValueName
, L
"UINumber");
2298 Status
= ZwSetValueKey(InstanceKey
,
2302 &DeviceCapabilities
.UINumber
,
2307 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
2309 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
2310 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2314 if (NT_SUCCESS(Status
))
2317 * FIXME: Check for valid characters, if there is invalid characters
2321 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
2322 DPRINT("Hardware IDs:\n");
2325 DPRINT(" %S\n", Ptr
);
2326 Length
= wcslen(Ptr
) + 1;
2329 TotalLength
+= Length
;
2331 DPRINT("TotalLength: %hu\n", TotalLength
);
2334 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
2335 Status
= ZwSetValueKey(InstanceKey
,
2339 (PVOID
)IoStatusBlock
.Information
,
2340 (TotalLength
+ 1) * sizeof(WCHAR
));
2341 if (!NT_SUCCESS(Status
))
2343 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2348 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2351 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
2353 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
2354 Status
= IopInitiatePnpIrp(
2355 DeviceNode
->PhysicalDeviceObject
,
2359 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2362 * FIXME: Check for valid characters, if there is invalid characters
2366 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
2367 DPRINT("Compatible IDs:\n");
2370 DPRINT(" %S\n", Ptr
);
2371 Length
= wcslen(Ptr
) + 1;
2374 TotalLength
+= Length
;
2376 DPRINT("TotalLength: %hu\n", TotalLength
);
2379 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
2380 Status
= ZwSetValueKey(InstanceKey
,
2384 (PVOID
)IoStatusBlock
.Information
,
2385 (TotalLength
+ 1) * sizeof(WCHAR
));
2386 if (!NT_SUCCESS(Status
))
2388 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
2393 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2396 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2398 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2399 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2400 Status
= IopInitiatePnpIrp(
2401 DeviceNode
->PhysicalDeviceObject
,
2403 IRP_MN_QUERY_DEVICE_TEXT
,
2405 /* This key is mandatory, so even if the Irp fails, we still write it */
2406 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2407 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2409 if (NT_SUCCESS(Status
) &&
2410 IoStatusBlock
.Information
&&
2411 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2413 /* This key is overriden when a driver is installed. Don't write the
2414 * new description if another one already exists */
2415 Status
= ZwSetValueKey(InstanceKey
,
2419 (PVOID
)IoStatusBlock
.Information
,
2420 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2424 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2425 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2427 Status
= ZwSetValueKey(InstanceKey
,
2432 DeviceDesc
.MaximumLength
);
2434 if (!NT_SUCCESS(Status
))
2436 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2442 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2444 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2445 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2446 Status
= IopInitiatePnpIrp(
2447 DeviceNode
->PhysicalDeviceObject
,
2449 IRP_MN_QUERY_DEVICE_TEXT
,
2451 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2453 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2454 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2455 Status
= ZwSetValueKey(InstanceKey
,
2459 (PVOID
)IoStatusBlock
.Information
,
2460 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2461 if (!NT_SUCCESS(Status
))
2463 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2468 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2471 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2473 Status
= IopInitiatePnpIrp(
2474 DeviceNode
->PhysicalDeviceObject
,
2476 IRP_MN_QUERY_BUS_INFORMATION
,
2478 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2480 PPNP_BUS_INFORMATION BusInformation
=
2481 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2483 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2484 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2485 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2486 ExFreePool(BusInformation
);
2490 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2492 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2493 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2494 DeviceNode
->ChildBusTypeIndex
= -1;
2497 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2499 Status
= IopInitiatePnpIrp(
2500 DeviceNode
->PhysicalDeviceObject
,
2502 IRP_MN_QUERY_RESOURCES
,
2504 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2506 DeviceNode
->BootResources
=
2507 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2508 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
2512 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2513 DeviceNode
->BootResources
= NULL
;
2516 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2518 Status
= IopInitiatePnpIrp(
2519 DeviceNode
->PhysicalDeviceObject
,
2521 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2523 if (NT_SUCCESS(Status
))
2525 DeviceNode
->ResourceRequirements
=
2526 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2527 if (IoStatusBlock
.Information
)
2528 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2530 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2534 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2535 DeviceNode
->ResourceRequirements
= NULL
;
2539 if (InstanceKey
!= NULL
)
2541 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2544 ZwClose(InstanceKey
);
2546 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
2548 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
2550 /* Report the device to the user-mode pnp manager */
2551 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
2552 &DeviceNode
->InstancePath
);
2555 return STATUS_SUCCESS
;
2561 IN PDEVICE_OBJECT DeviceObject
)
2563 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2564 DEVICETREE_TRAVERSE_CONTEXT Context
;
2565 PDEVICE_RELATIONS DeviceRelations
;
2566 PDEVICE_OBJECT ChildDeviceObject
;
2567 IO_STATUS_BLOCK IoStatusBlock
;
2568 PDEVICE_NODE ChildDeviceNode
;
2569 IO_STACK_LOCATION Stack
;
2573 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2575 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
2577 /* Report the device to the user-mode pnp manager */
2578 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2579 &DeviceNode
->InstancePath
);
2581 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2583 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
2585 Status
= IopInitiatePnpIrp(
2588 IRP_MN_QUERY_DEVICE_RELATIONS
,
2590 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
2592 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2596 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2598 if (!DeviceRelations
)
2600 DPRINT("No PDOs\n");
2601 return STATUS_UNSUCCESSFUL
;
2604 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
2607 * Create device nodes for all discovered devices
2609 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2611 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
2612 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
2614 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
2615 if (!ChildDeviceNode
)
2617 /* One doesn't exist, create it */
2618 Status
= IopCreateDeviceNode(
2623 if (NT_SUCCESS(Status
))
2625 /* Mark the node as enumerated */
2626 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2628 /* Mark the DO as bus enumerated */
2629 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2633 /* Ignore this DO */
2634 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
2635 ObDereferenceObject(ChildDeviceNode
);
2640 /* Mark it as enumerated */
2641 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2642 ObDereferenceObject(ChildDeviceObject
);
2645 ExFreePool(DeviceRelations
);
2648 * Retrieve information about all discovered children from the bus driver
2650 IopInitDeviceTreeTraverseContext(
2653 IopActionInterrogateDeviceStack
,
2656 Status
= IopTraverseDeviceTree(&Context
);
2657 if (!NT_SUCCESS(Status
))
2659 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2664 * Retrieve configuration from the registry for discovered children
2666 IopInitDeviceTreeTraverseContext(
2669 IopActionConfigureChildServices
,
2672 Status
= IopTraverseDeviceTree(&Context
);
2673 if (!NT_SUCCESS(Status
))
2675 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2680 * Initialize services for discovered children.
2682 Status
= IopInitializePnpServices(DeviceNode
);
2683 if (!NT_SUCCESS(Status
))
2685 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2689 DPRINT("IopEnumerateDevice() finished\n");
2690 return STATUS_SUCCESS
;
2695 * IopActionConfigureChildServices
2697 * Retrieve configuration for all (direct) child nodes of a parent node.
2701 * Pointer to device node.
2703 * Pointer to parent node to retrieve child node configuration for.
2706 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2707 * when we reach a device node which is not a direct child of the device
2708 * node for which we configure child services for. Any errors that occur is
2709 * logged instead so that all child services have a chance of beeing
2714 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2717 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2718 PDEVICE_NODE ParentDeviceNode
;
2719 PUNICODE_STRING Service
;
2720 UNICODE_STRING ClassGUID
;
2722 DEVICE_CAPABILITIES DeviceCaps
;
2724 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2726 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2729 * We are called for the parent too, but we don't need to do special
2730 * handling for this node
2732 if (DeviceNode
== ParentDeviceNode
)
2734 DPRINT("Success\n");
2735 return STATUS_SUCCESS
;
2739 * Make sure this device node is a direct child of the parent device node
2740 * that is given as an argument
2742 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2744 /* Stop the traversal immediately and indicate successful operation */
2746 return STATUS_UNSUCCESSFUL
;
2749 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2751 WCHAR RegKeyBuffer
[MAX_PATH
];
2752 UNICODE_STRING RegKey
;
2755 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2756 RegKey
.Buffer
= RegKeyBuffer
;
2759 * Retrieve configuration from Enum key
2762 Service
= &DeviceNode
->ServiceName
;
2764 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2765 RtlInitUnicodeString(Service
, NULL
);
2766 RtlInitUnicodeString(&ClassGUID
, NULL
);
2768 QueryTable
[0].Name
= L
"Service";
2769 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2770 QueryTable
[0].EntryContext
= Service
;
2772 QueryTable
[1].Name
= L
"ClassGUID";
2773 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2774 QueryTable
[1].EntryContext
= &ClassGUID
;
2775 QueryTable
[1].DefaultType
= REG_SZ
;
2776 QueryTable
[1].DefaultData
= L
"";
2777 QueryTable
[1].DefaultLength
= 0;
2779 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2780 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2782 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2783 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2785 if (!NT_SUCCESS(Status
))
2787 /* FIXME: Log the error */
2788 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2789 &DeviceNode
->InstancePath
, Status
);
2790 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2791 return STATUS_SUCCESS
;
2794 if (Service
->Buffer
== NULL
)
2796 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
2797 DeviceCaps
.RawDeviceOK
)
2799 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
2801 DeviceNode
->ServiceName
.Length
= 0;
2802 DeviceNode
->ServiceName
.MaximumLength
= 0;
2803 DeviceNode
->ServiceName
.Buffer
= NULL
;
2805 else if (ClassGUID
.Length
!= 0)
2807 /* Device has a ClassGUID value, but no Service value.
2808 * Suppose it is using the NULL driver, so state the
2809 * device is started */
2810 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2811 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2815 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2817 return STATUS_SUCCESS
;
2820 DPRINT("Got Service %S\n", Service
->Buffer
);
2823 return STATUS_SUCCESS
;
2827 * IopActionInitChildServices
2829 * Initialize the service for all (direct) child nodes of a parent node
2833 * Pointer to device node.
2835 * Pointer to parent node to initialize child node services for.
2838 * If the driver image for a service is not loaded and initialized
2839 * it is done here too. We only return a status code indicating an
2840 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2841 * not a direct child of the device node for which we initialize
2842 * child services for. Any errors that occur is logged instead so
2843 * that all child services have a chance of being initialized.
2847 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2850 PDEVICE_NODE ParentDeviceNode
;
2852 BOOLEAN BootDrivers
= !PnpSystemInit
;
2854 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2856 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2859 * We are called for the parent too, but we don't need to do special
2860 * handling for this node
2862 if (DeviceNode
== ParentDeviceNode
)
2864 DPRINT("Success\n");
2865 return STATUS_SUCCESS
;
2869 * Make sure this device node is a direct child of the parent device node
2870 * that is given as an argument
2873 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2876 * Stop the traversal immediately and indicate unsuccessful operation
2879 return STATUS_UNSUCCESSFUL
;
2882 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
2883 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
2884 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2885 return STATUS_SUCCESS
;
2887 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
2889 /* We don't need to worry about loading the driver because we're
2890 * being driven in raw mode so our parent must be loaded to get here */
2891 Status
= IopStartDevice(DeviceNode
);
2892 if (!NT_SUCCESS(Status
))
2894 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
2895 &DeviceNode
->InstancePath
, Status
);
2900 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2901 PDRIVER_OBJECT DriverObject
;
2903 /* Get existing DriverObject pointer (in case the driver has
2904 already been loaded and initialized) */
2905 Status
= IopGetDriverObject(
2907 &DeviceNode
->ServiceName
,
2910 if (!NT_SUCCESS(Status
))
2912 /* Driver is not initialized, try to load it */
2913 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2915 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2917 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2918 was loaded by the bootloader */
2919 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2920 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2922 /* Initialize the driver */
2923 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2924 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2928 Status
= STATUS_SUCCESS
;
2933 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2934 &DeviceNode
->ServiceName
, Status
);
2938 /* Driver is loaded and initialized at this point */
2939 if (NT_SUCCESS(Status
))
2941 /* Initialize the device, including all filters */
2942 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
2947 * Don't disable when trying to load only boot drivers
2951 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2952 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2953 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2954 DPRINT1("Initialization of service %S failed (Status %x)\n",
2955 DeviceNode
->ServiceName
.Buffer
, Status
);
2960 return STATUS_SUCCESS
;
2964 * IopInitializePnpServices
2966 * Initialize services for discovered children
2970 * Top device node to start initializing services.
2976 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2978 DEVICETREE_TRAVERSE_CONTEXT Context
;
2980 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2982 IopInitDeviceTreeTraverseContext(
2985 IopActionInitChildServices
,
2988 return IopTraverseDeviceTree(&Context
);
2991 static NTSTATUS INIT_FUNCTION
2992 IopEnumerateDetectedDevices(
2994 IN PUNICODE_STRING RelativePath OPTIONAL
,
2996 IN BOOLEAN EnumerateSubKeys
,
2997 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2998 IN ULONG ParentBootResourcesLength
)
3000 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3001 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3002 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
3003 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
3004 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
3005 OBJECT_ATTRIBUTES ObjectAttributes
;
3006 HANDLE hDevicesKey
= NULL
;
3007 HANDLE hDeviceKey
= NULL
;
3008 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
3009 UNICODE_STRING Level2NameU
;
3010 WCHAR Level2Name
[5];
3011 ULONG IndexDevice
= 0;
3013 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3014 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3015 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3016 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3017 UNICODE_STRING DeviceName
, ValueName
;
3019 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
3020 ULONG BootResourcesLength
;
3023 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
3024 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
3025 static ULONG DeviceIndexPci
= 0;
3026 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
3027 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
3028 static ULONG DeviceIndexSerial
= 0;
3029 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
3030 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
3031 static ULONG DeviceIndexKeyboard
= 0;
3032 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
3033 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
3034 static ULONG DeviceIndexMouse
= 0;
3035 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
3036 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
3037 static ULONG DeviceIndexParallel
= 0;
3038 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
3039 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
3040 static ULONG DeviceIndexFloppy
= 0;
3041 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
3042 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
3043 static ULONG DeviceIndexIsa
= 0;
3044 UNICODE_STRING HardwareIdKey
;
3045 PUNICODE_STRING pHardwareId
;
3046 ULONG DeviceIndex
= 0;
3047 PUCHAR CmResourceList
;
3052 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
3053 if (!NT_SUCCESS(Status
))
3055 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3060 hDevicesKey
= hBaseKey
;
3062 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3063 if (!pDeviceInformation
)
3065 DPRINT("ExAllocatePool() failed\n");
3066 Status
= STATUS_NO_MEMORY
;
3070 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3071 if (!pValueInformation
)
3073 DPRINT("ExAllocatePool() failed\n");
3074 Status
= STATUS_NO_MEMORY
;
3080 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3081 if (Status
== STATUS_NO_MORE_ENTRIES
)
3083 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3085 ExFreePool(pDeviceInformation
);
3086 DeviceInfoLength
= RequiredSize
;
3087 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3088 if (!pDeviceInformation
)
3090 DPRINT("ExAllocatePool() failed\n");
3091 Status
= STATUS_NO_MEMORY
;
3094 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3096 if (!NT_SUCCESS(Status
))
3098 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3103 /* Open device key */
3104 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
3105 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3107 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
3108 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
3109 if (!NT_SUCCESS(Status
))
3111 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3115 /* Read boot resources, and add then to parent ones */
3116 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3117 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3119 ExFreePool(pValueInformation
);
3120 ValueInfoLength
= RequiredSize
;
3121 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3122 if (!pValueInformation
)
3124 DPRINT("ExAllocatePool() failed\n");
3125 ZwDeleteKey(hLevel2Key
);
3126 Status
= STATUS_NO_MEMORY
;
3129 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3131 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3133 BootResources
= ParentBootResources
;
3134 BootResourcesLength
= ParentBootResourcesLength
;
3136 else if (!NT_SUCCESS(Status
))
3138 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3141 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
3143 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
3148 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
3150 /* Concatenate current resources and parent ones */
3151 if (ParentBootResourcesLength
== 0)
3152 BootResourcesLength
= pValueInformation
->DataLength
;
3154 BootResourcesLength
= ParentBootResourcesLength
3155 + pValueInformation
->DataLength
3157 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
3160 DPRINT("ExAllocatePool() failed\n");
3163 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
3165 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
3167 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
3169 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
3171 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
3172 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
3173 ParentBootResourcesLength
- Header
);
3174 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
3178 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
3180 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
3181 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
3182 ParentBootResourcesLength
- Header
);
3184 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
3185 pValueInformation
->Data
+ Header
,
3186 pValueInformation
->DataLength
- Header
);
3187 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
3191 if (EnumerateSubKeys
)
3196 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3197 if (Status
== STATUS_NO_MORE_ENTRIES
)
3199 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3201 ExFreePool(pDeviceInformation
);
3202 DeviceInfoLength
= RequiredSize
;
3203 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3204 if (!pDeviceInformation
)
3206 DPRINT("ExAllocatePool() failed\n");
3207 Status
= STATUS_NO_MEMORY
;
3210 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3212 if (!NT_SUCCESS(Status
))
3214 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3218 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
3219 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3221 Status
= IopEnumerateDetectedDevices(
3227 BootResourcesLength
);
3228 if (!NT_SUCCESS(Status
))
3233 /* Read identifier */
3234 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3235 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3237 ExFreePool(pValueInformation
);
3238 ValueInfoLength
= RequiredSize
;
3239 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3240 if (!pValueInformation
)
3242 DPRINT("ExAllocatePool() failed\n");
3243 Status
= STATUS_NO_MEMORY
;
3246 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3248 if (!NT_SUCCESS(Status
))
3250 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
3252 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3255 ValueName
.Length
= ValueName
.MaximumLength
= 0;
3257 else if (pValueInformation
->Type
!= REG_SZ
)
3259 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3264 /* Assign hardware id to this device */
3265 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
3266 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3267 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3268 ValueName
.Length
-= sizeof(WCHAR
);
3271 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
3273 pHardwareId
= &HardwareIdSerial
;
3274 DeviceIndex
= DeviceIndexSerial
++;
3276 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
3278 pHardwareId
= &HardwareIdKeyboard
;
3279 DeviceIndex
= DeviceIndexKeyboard
++;
3281 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
3283 pHardwareId
= &HardwareIdMouse
;
3284 DeviceIndex
= DeviceIndexMouse
++;
3286 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
3288 pHardwareId
= &HardwareIdParallel
;
3289 DeviceIndex
= DeviceIndexParallel
++;
3291 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
3293 pHardwareId
= &HardwareIdFloppy
;
3294 DeviceIndex
= DeviceIndexFloppy
++;
3296 else if (NT_SUCCESS(Status
))
3298 /* Try to also match the device identifier */
3299 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
3301 pHardwareId
= &HardwareIdPci
;
3302 DeviceIndex
= DeviceIndexPci
++;
3304 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
3306 pHardwareId
= &HardwareIdIsa
;
3307 DeviceIndex
= DeviceIndexIsa
++;
3311 DPRINT("Unknown device '%wZ'\n", &ValueName
);
3317 /* Unknown key path */
3318 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
3322 /* Prepare hardware id key (hardware id value without final \0) */
3323 HardwareIdKey
= *pHardwareId
;
3324 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
3326 /* Add the detected device to Root key */
3327 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
3328 Status
= ZwCreateKey(
3334 REG_OPTION_NON_VOLATILE
,
3336 if (!NT_SUCCESS(Status
))
3338 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3341 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
3342 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
3343 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
3344 Status
= ZwCreateKey(
3346 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3350 REG_OPTION_NON_VOLATILE
,
3352 ZwClose(hLevel1Key
);
3353 if (!NT_SUCCESS(Status
))
3355 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3358 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
3359 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3360 if (!NT_SUCCESS(Status
))
3362 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3363 ZwDeleteKey(hLevel2Key
);
3366 /* Create 'LogConf' subkey */
3367 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3368 Status
= ZwCreateKey(
3374 REG_OPTION_VOLATILE
,
3376 if (!NT_SUCCESS(Status
))
3378 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3379 ZwDeleteKey(hLevel2Key
);
3382 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
3384 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
3385 if (!CmResourceList
)
3388 ZwDeleteKey(hLevel2Key
);
3392 /* Add the list count (1st member of CM_RESOURCE_LIST) */
3394 RtlCopyMemory(CmResourceList
,
3398 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
3399 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
3401 BootResourcesLength
);
3403 /* Save boot resources to 'LogConf\BootConfig' */
3404 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
3405 if (!NT_SUCCESS(Status
))
3407 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3409 ZwDeleteKey(hLevel2Key
);
3416 if (BootResources
&& BootResources
!= ParentBootResources
)
3418 ExFreePool(BootResources
);
3419 BootResources
= NULL
;
3423 ZwClose(hLevel2Key
);
3428 ZwClose(hDeviceKey
);
3433 Status
= STATUS_SUCCESS
;
3436 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
3437 ZwClose(hDevicesKey
);
3439 ZwClose(hDeviceKey
);
3440 if (pDeviceInformation
)
3441 ExFreePool(pDeviceInformation
);
3442 if (pValueInformation
)
3443 ExFreePool(pValueInformation
);
3447 static BOOLEAN INIT_FUNCTION
3448 IopIsAcpiComputer(VOID
)
3453 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3454 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3455 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3456 OBJECT_ATTRIBUTES ObjectAttributes
;
3457 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3458 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3459 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3460 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3462 ULONG IndexDevice
= 0;
3463 UNICODE_STRING DeviceName
, ValueName
;
3464 HANDLE hDevicesKey
= NULL
;
3465 HANDLE hDeviceKey
= NULL
;
3467 BOOLEAN ret
= FALSE
;
3469 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3470 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3471 if (!NT_SUCCESS(Status
))
3473 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3477 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3478 if (!pDeviceInformation
)
3480 DPRINT("ExAllocatePool() failed\n");
3481 Status
= STATUS_NO_MEMORY
;
3485 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3486 if (!pDeviceInformation
)
3488 DPRINT("ExAllocatePool() failed\n");
3489 Status
= STATUS_NO_MEMORY
;
3495 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3496 if (Status
== STATUS_NO_MORE_ENTRIES
)
3498 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3500 ExFreePool(pDeviceInformation
);
3501 DeviceInfoLength
= RequiredSize
;
3502 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3503 if (!pDeviceInformation
)
3505 DPRINT("ExAllocatePool() failed\n");
3506 Status
= STATUS_NO_MEMORY
;
3509 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3511 if (!NT_SUCCESS(Status
))
3513 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3518 /* Open device key */
3519 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3520 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3521 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3526 if (!NT_SUCCESS(Status
))
3528 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3532 /* Read identifier */
3533 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3534 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3536 ExFreePool(pValueInformation
);
3537 ValueInfoLength
= RequiredSize
;
3538 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3539 if (!pValueInformation
)
3541 DPRINT("ExAllocatePool() failed\n");
3542 Status
= STATUS_NO_MEMORY
;
3545 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3547 if (!NT_SUCCESS(Status
))
3549 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3552 else if (pValueInformation
->Type
!= REG_SZ
)
3554 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3558 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3559 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3560 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3561 ValueName
.Length
-= sizeof(WCHAR
);
3562 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3564 DPRINT("Found ACPI BIOS\n");
3570 ZwClose(hDeviceKey
);
3575 if (pDeviceInformation
)
3576 ExFreePool(pDeviceInformation
);
3577 if (pValueInformation
)
3578 ExFreePool(pValueInformation
);
3580 ZwClose(hDevicesKey
);
3582 ZwClose(hDeviceKey
);
3589 IopUpdateRootKey(VOID
)
3591 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
3592 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
3593 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3594 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3595 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3596 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
3597 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3598 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3599 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3600 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3601 OBJECT_ATTRIBUTES ObjectAttributes
;
3602 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
3605 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3606 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3607 if (!NT_SUCCESS(Status
))
3609 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3613 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
3614 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3616 if (!NT_SUCCESS(Status
))
3618 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3622 if (IopIsAcpiComputer())
3624 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
3625 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3627 if (!NT_SUCCESS(Status
))
3629 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
3630 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3631 ZwClose(hHalAcpiDevice
);
3632 if (!NT_SUCCESS(Status
))
3634 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3635 if (NT_SUCCESS(Status
))
3636 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3637 if (NT_SUCCESS(Status
))
3639 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
3640 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3641 if (NT_SUCCESS(Status
))
3644 ZwClose(hHalAcpiId
);
3649 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
3650 if (!NT_SUCCESS(Status
))
3652 /* Nothing to do, don't return with an error status */
3653 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3655 return STATUS_SUCCESS
;
3657 Status
= IopEnumerateDetectedDevices(
3672 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
3674 PUNICODE_STRING Name
,
3675 ACCESS_MASK DesiredAccess
)
3677 OBJECT_ATTRIBUTES ObjectAttributes
;
3684 InitializeObjectAttributes(&ObjectAttributes
,
3686 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3690 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
3697 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
3698 IN HANDLE RootHandle OPTIONAL
,
3699 IN PUNICODE_STRING KeyName
,
3700 IN ACCESS_MASK DesiredAccess
,
3701 IN ULONG CreateOptions
,
3702 OUT PULONG Disposition OPTIONAL
)
3704 OBJECT_ATTRIBUTES ObjectAttributes
;
3705 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0, Length
;
3706 HANDLE HandleArray
[2];
3707 BOOLEAN Recursing
= TRUE
;
3709 UNICODE_STRING KeyString
;
3710 NTSTATUS Status
= STATUS_SUCCESS
;
3713 /* P1 is start, pp is end */
3714 p1
= KeyName
->Buffer
;
3715 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
3717 /* Create the target key */
3718 InitializeObjectAttributes(&ObjectAttributes
,
3720 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3723 Status
= ZwCreateKey(&HandleArray
[i
],
3731 /* Now we check if this failed */
3732 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
3734 /* Target key failed, so we'll need to create its parent. Setup array */
3735 HandleArray
[0] = NULL
;
3736 HandleArray
[1] = RootHandle
;
3738 /* Keep recursing for each missing parent */
3741 /* And if we're deep enough, close the last handle */
3742 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3744 /* We're setup to ping-pong between the two handle array entries */
3745 RootHandleIndex
= i
;
3748 /* Clear the one we're attempting to open now */
3749 HandleArray
[i
] = NULL
;
3751 /* Process the parent key name */
3752 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
3753 Length
= (p
- p1
) * sizeof(WCHAR
);
3755 /* Is there a parent name? */
3758 /* Build the unicode string for it */
3759 KeyString
.Buffer
= p1
;
3760 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
3762 /* Now try opening the parent */
3763 InitializeObjectAttributes(&ObjectAttributes
,
3765 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3766 HandleArray
[RootHandleIndex
],
3768 Status
= ZwCreateKey(&HandleArray
[i
],
3775 if (NT_SUCCESS(Status
))
3777 /* It worked, we have one more handle */
3782 /* Parent key creation failed, abandon loop */
3789 /* We don't have a parent name, probably corrupted key name */
3790 Status
= STATUS_INVALID_PARAMETER
;
3795 /* Now see if there's more parents to create */
3797 if ((p
== pp
) || (p1
== pp
))
3799 /* We're done, hopefully successfully, so stop */
3804 /* Outer loop check for handle nesting that requires closing the top handle */
3805 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3808 /* Check if we broke out of the loop due to success */
3809 if (NT_SUCCESS(Status
))
3811 /* Return the target handle (we closed all the parent ones) and disposition */
3812 *Handle
= HandleArray
[i
];
3813 if (Disposition
) *Disposition
= KeyDisposition
;
3816 /* Return the success state */
3822 IopGetRegistryValue(IN HANDLE Handle
,
3824 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
3826 UNICODE_STRING ValueString
;
3828 PKEY_VALUE_FULL_INFORMATION FullInformation
;
3832 RtlInitUnicodeString(&ValueString
, ValueName
);
3834 Status
= ZwQueryValueKey(Handle
,
3836 KeyValueFullInformation
,
3840 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
3841 (Status
!= STATUS_BUFFER_TOO_SMALL
))
3846 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
3847 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
3849 Status
= ZwQueryValueKey(Handle
,
3851 KeyValueFullInformation
,
3855 if (!NT_SUCCESS(Status
))
3857 ExFreePool(FullInformation
);
3861 *Information
= FullInformation
;
3862 return STATUS_SUCCESS
;
3865 RTL_GENERIC_COMPARE_RESULTS
3867 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3868 IN PVOID FirstStruct
,
3869 IN PVOID SecondStruct
)
3877 // The allocation function is called by the generic table package whenever
3878 // it needs to allocate memory for the table.
3883 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3893 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3902 PpInitializeDeviceReferenceTable(VOID
)
3904 /* Setup the guarded mutex and AVL table */
3905 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3906 RtlInitializeGenericTableAvl(
3907 &PpDeviceReferenceTable
,
3908 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3909 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3910 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3918 /* Initialize the resource when accessing device registry data */
3919 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3921 /* Setup the device reference AVL table */
3922 PpInitializeDeviceReferenceTable();
3930 /* Check the initialization phase */
3931 switch (ExpInitializationPhase
)
3936 return PiInitPhase0();
3942 //return PiInitPhase1();
3946 /* Don't know any other phase! Bugcheck! */
3947 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3952 LONG IopNumberDeviceNodes
;
3956 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3958 PDEVICE_NODE DeviceNode
;
3962 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), 'donD');
3963 if (!DeviceNode
) return DeviceNode
;
3966 InterlockedIncrement(&IopNumberDeviceNodes
);
3969 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
3970 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
3971 DeviceNode
->BusNumber
= -1;
3972 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
3973 DeviceNode
->ChildBusNumber
= -1;
3974 DeviceNode
->ChildBusTypeIndex
= -1;
3975 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
3976 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
3977 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
3978 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
3979 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
3980 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
3982 /* Check if there is a PDO */
3983 if (PhysicalDeviceObject
)
3985 /* Link it and remove the init flag */
3986 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
3987 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
3988 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3991 /* Return the node */
3995 /* PUBLIC FUNCTIONS **********************************************************/
4002 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
4003 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
4004 IN ULONG BufferLength
,
4005 OUT PVOID PropertyBuffer
,
4006 OUT PULONG ResultLength
)
4008 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
4009 DEVICE_CAPABILITIES DeviceCaps
;
4014 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
4015 ULONG RequiredLength
, ObjectNameInfoLength
;
4017 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
4021 if (DeviceNode
== NULL
)
4022 return STATUS_INVALID_DEVICE_REQUEST
;
4024 switch (DeviceProperty
)
4026 case DevicePropertyBusNumber
:
4027 Length
= sizeof(ULONG
);
4028 Data
= &DeviceNode
->ChildBusNumber
;
4031 /* Complete, untested */
4032 case DevicePropertyBusTypeGuid
:
4034 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
4035 (DeviceNode
->ChildBusTypeIndex
< PnpBusTypeGuidList
->GuidCount
))
4037 /* Return the GUID */
4038 *ResultLength
= sizeof(GUID
);
4040 /* Check if the buffer given was large enough */
4041 if (BufferLength
< *ResultLength
)
4043 return STATUS_BUFFER_TOO_SMALL
;
4047 RtlCopyMemory(PropertyBuffer
,
4048 &(PnpBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
4050 return STATUS_SUCCESS
;
4054 return STATUS_OBJECT_NAME_NOT_FOUND
;
4058 case DevicePropertyLegacyBusType
:
4059 Length
= sizeof(INTERFACE_TYPE
);
4060 Data
= &DeviceNode
->ChildInterfaceType
;
4063 case DevicePropertyAddress
:
4064 /* Query the device caps */
4065 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
4066 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= MAXULONG
))
4069 *ResultLength
= sizeof(ULONG
);
4071 /* Check if the buffer given was large enough */
4072 if (BufferLength
< *ResultLength
)
4074 return STATUS_BUFFER_TOO_SMALL
;
4077 /* Return address */
4078 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
4079 return STATUS_SUCCESS
;
4083 return STATUS_OBJECT_NAME_NOT_FOUND
;
4087 // case DevicePropertyUINumber:
4088 // if (DeviceNode->CapabilityFlags == NULL)
4089 // return STATUS_INVALID_DEVICE_REQUEST;
4090 // Length = sizeof(ULONG);
4091 // Data = &DeviceNode->CapabilityFlags->UINumber;
4094 case DevicePropertyClassName
:
4095 case DevicePropertyClassGuid
:
4096 case DevicePropertyDriverKeyName
:
4097 case DevicePropertyManufacturer
:
4098 case DevicePropertyFriendlyName
:
4099 case DevicePropertyHardwareID
:
4100 case DevicePropertyCompatibleIDs
:
4101 case DevicePropertyDeviceDescription
:
4102 case DevicePropertyLocationInformation
:
4103 case DevicePropertyUINumber
:
4105 LPCWSTR RegistryPropertyName
;
4106 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
4107 UNICODE_STRING ValueName
;
4108 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
4109 ULONG ValueInformationLength
;
4110 HANDLE KeyHandle
, EnumRootHandle
;
4113 switch (DeviceProperty
)
4115 case DevicePropertyClassName
:
4116 RegistryPropertyName
= L
"Class"; break;
4117 case DevicePropertyClassGuid
:
4118 RegistryPropertyName
= L
"ClassGuid"; break;
4119 case DevicePropertyDriverKeyName
:
4120 RegistryPropertyName
= L
"Driver"; break;
4121 case DevicePropertyManufacturer
:
4122 RegistryPropertyName
= L
"Mfg"; break;
4123 case DevicePropertyFriendlyName
:
4124 RegistryPropertyName
= L
"FriendlyName"; break;
4125 case DevicePropertyHardwareID
:
4126 RegistryPropertyName
= L
"HardwareID"; break;
4127 case DevicePropertyCompatibleIDs
:
4128 RegistryPropertyName
= L
"CompatibleIDs"; break;
4129 case DevicePropertyDeviceDescription
:
4130 RegistryPropertyName
= L
"DeviceDesc"; break;
4131 case DevicePropertyLocationInformation
:
4132 RegistryPropertyName
= L
"LocationInformation"; break;
4133 case DevicePropertyUINumber
:
4134 RegistryPropertyName
= L
"UINumber"; break;
4136 /* Should not happen */
4138 return STATUS_UNSUCCESSFUL
;
4141 DPRINT("Registry property %S\n", RegistryPropertyName
);
4144 Status
= IopOpenRegistryKeyEx(&EnumRootHandle
, NULL
,
4145 &EnumRoot
, KEY_READ
);
4146 if (!NT_SUCCESS(Status
))
4148 DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status
);
4152 /* Open instance key */
4153 Status
= IopOpenRegistryKeyEx(&KeyHandle
, EnumRootHandle
,
4154 &DeviceNode
->InstancePath
, KEY_READ
);
4155 if (!NT_SUCCESS(Status
))
4157 DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status
);
4158 ZwClose(EnumRootHandle
);
4162 /* Allocate buffer to read as much data as required by the caller */
4163 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
4164 Data
[0]) + BufferLength
;
4165 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
4166 if (!ValueInformation
)
4169 return STATUS_INSUFFICIENT_RESOURCES
;
4172 /* Read the value */
4173 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
4174 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
4175 KeyValuePartialInformation
, ValueInformation
,
4176 ValueInformationLength
,
4177 &ValueInformationLength
);
4181 *ResultLength
= ValueInformation
->DataLength
;
4183 if (!NT_SUCCESS(Status
))
4185 ExFreePool(ValueInformation
);
4186 if (Status
== STATUS_BUFFER_OVERFLOW
)
4187 return STATUS_BUFFER_TOO_SMALL
;
4188 DPRINT1("Problem: Status=0x%08x, ResultLength = %d\n", Status
, *ResultLength
);
4192 /* FIXME: Verify the value (NULL-terminated, correct format). */
4193 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
4194 ValueInformation
->DataLength
);
4195 ExFreePool(ValueInformation
);
4197 return STATUS_SUCCESS
;
4200 case DevicePropertyBootConfiguration
:
4202 if (DeviceNode
->BootResources
->Count
!= 0)
4204 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
4206 Data
= DeviceNode
->BootResources
;
4209 /* FIXME: use a translated boot configuration instead */
4210 case DevicePropertyBootConfigurationTranslated
:
4212 if (DeviceNode
->BootResources
->Count
!= 0)
4214 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
4216 Data
= DeviceNode
->BootResources
;
4219 case DevicePropertyEnumeratorName
:
4220 /* A buffer overflow can't happen here, since InstancePath
4221 * always contains the enumerator name followed by \\ */
4222 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
4224 Length
= (Ptr
- DeviceNode
->InstancePath
.Buffer
) * sizeof(WCHAR
);
4225 Data
= DeviceNode
->InstancePath
.Buffer
;
4228 case DevicePropertyPhysicalDeviceObjectName
:
4229 Status
= ObQueryNameString(DeviceNode
->PhysicalDeviceObject
,
4233 if (Status
== STATUS_SUCCESS
)
4238 else if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
4240 ObjectNameInfoLength
= RequiredLength
;
4241 ObjectNameInfo
= ExAllocatePool(PagedPool
, ObjectNameInfoLength
);
4242 if (!ObjectNameInfo
)
4243 return STATUS_INSUFFICIENT_RESOURCES
;
4245 Status
= ObQueryNameString(DeviceNode
->PhysicalDeviceObject
,
4247 ObjectNameInfoLength
,
4249 if (NT_SUCCESS(Status
))
4251 Length
= ObjectNameInfo
->Name
.Length
;
4252 Data
= ObjectNameInfo
->Name
.Buffer
;
4262 return STATUS_INVALID_PARAMETER_2
;
4265 /* Prepare returned values */
4266 *ResultLength
= Length
;
4267 if (BufferLength
< Length
)
4269 if (ObjectNameInfo
!= NULL
)
4270 ExFreePool(ObjectNameInfo
);
4272 return STATUS_BUFFER_TOO_SMALL
;
4274 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
4276 /* NULL terminate the string (if required) */
4277 if (DeviceProperty
== DevicePropertyEnumeratorName
||
4278 DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
4279 ((LPWSTR
)PropertyBuffer
)[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
4281 if (ObjectNameInfo
!= NULL
)
4282 ExFreePool(ObjectNameInfo
);
4284 return STATUS_SUCCESS
;
4292 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4298 * @name IoOpenDeviceRegistryKey
4300 * Open a registry key unique for a specified driver or device instance.
4302 * @param DeviceObject Device to get the registry key for.
4303 * @param DevInstKeyType Type of the key to return.
4304 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
4305 * @param DevInstRegKey Handle to the opened registry key on
4306 * successful return.
4314 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
4315 IN ULONG DevInstKeyType
,
4316 IN ACCESS_MASK DesiredAccess
,
4317 OUT PHANDLE DevInstRegKey
)
4319 static WCHAR RootKeyName
[] =
4320 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
4321 static WCHAR ProfileKeyName
[] =
4322 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
4323 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
4324 static WCHAR EnumKeyName
[] = L
"Enum\\";
4325 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
4326 ULONG KeyNameLength
;
4327 LPWSTR KeyNameBuffer
;
4328 UNICODE_STRING KeyName
;
4329 ULONG DriverKeyLength
;
4330 OBJECT_ATTRIBUTES ObjectAttributes
;
4331 PDEVICE_NODE DeviceNode
= NULL
;
4334 DPRINT("IoOpenDeviceRegistryKey() called\n");
4336 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
4338 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
4339 return STATUS_INVALID_PARAMETER
;
4343 * Calculate the length of the base key name. This is the full
4344 * name for driver key or the name excluding "Device Parameters"
4345 * subkey for device key.
4348 KeyNameLength
= sizeof(RootKeyName
);
4349 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4350 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
4351 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4353 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
4354 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4355 0, NULL
, &DriverKeyLength
);
4356 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
4358 KeyNameLength
+= DriverKeyLength
;
4362 DeviceNode
= IopGetDeviceNode(DeviceObject
);
4363 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
4364 DeviceNode
->InstancePath
.Length
;
4368 * Now allocate the buffer for the key name...
4371 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
4372 if (KeyNameBuffer
== NULL
)
4373 return STATUS_INSUFFICIENT_RESOURCES
;
4376 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
4377 KeyName
.Buffer
= KeyNameBuffer
;
4380 * ...and build the key name.
4383 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
4384 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
4386 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4387 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
4389 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4391 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
4392 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4393 DriverKeyLength
, KeyNameBuffer
+
4394 (KeyName
.Length
/ sizeof(WCHAR
)),
4396 if (!NT_SUCCESS(Status
))
4398 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
4399 ExFreePool(KeyNameBuffer
);
4402 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
4406 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
4407 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
4408 if (DeviceNode
->InstancePath
.Length
== 0)
4410 ExFreePool(KeyNameBuffer
);
4416 * Open the base key.
4418 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
4419 if (!NT_SUCCESS(Status
))
4421 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
4422 ExFreePool(KeyNameBuffer
);
4425 ExFreePool(KeyNameBuffer
);
4428 * For driver key we're done now.
4431 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4435 * Let's go further. For device key we must open "Device Parameters"
4436 * subkey and create it if it doesn't exist yet.
4439 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
4440 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
4441 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
4442 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
4443 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
4444 ZwClose(ObjectAttributes
.RootDirectory
);
4454 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4464 IoInvalidateDeviceRelations(
4465 IN PDEVICE_OBJECT DeviceObject
,
4466 IN DEVICE_RELATION_TYPE Type
)
4468 PIO_WORKITEM WorkItem
;
4469 PINVALIDATE_DEVICE_RELATION_DATA Data
;
4471 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
4474 WorkItem
= IoAllocateWorkItem(DeviceObject
);
4481 ObReferenceObject(DeviceObject
);
4482 Data
->DeviceObject
= DeviceObject
;
4484 Data
->WorkItem
= WorkItem
;
4488 IopAsynchronousInvalidateDeviceRelations
,
4498 IoSynchronousInvalidateDeviceRelations(
4499 IN PDEVICE_OBJECT DeviceObject
,
4500 IN DEVICE_RELATION_TYPE Type
)
4507 /* Enumerate the device */
4508 return IopEnumerateDevice(DeviceObject
);
4509 case PowerRelations
:
4510 /* Not handled yet */
4511 return STATUS_NOT_IMPLEMENTED
;
4512 case TargetDeviceRelation
:
4514 return STATUS_SUCCESS
;
4516 /* Ejection relations are not supported */
4517 return STATUS_NOT_SUPPORTED
;
4526 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
4528 IN PHYSICAL_ADDRESS BusAddress
,
4529 IN OUT PULONG AddressSpace
,
4530 OUT PPHYSICAL_ADDRESS TranslatedAddress
)