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 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject
)
145 IO_STACK_LOCATION Stack
;
146 PDEVICE_NODE DeviceNode
;
150 /* Get the device node */
151 DeviceNode
= IopGetDeviceNode(DeviceObject
);
153 /* Build the I/O stack locaiton */
154 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
155 Stack
.MajorFunction
= IRP_MJ_PNP
;
156 Stack
.MinorFunction
= IRP_MN_START_DEVICE
;
158 /* Check if we didn't already report the resources */
159 // if (!DeviceNode->Flags & DNF_RESOURCE_REPORTED)
162 if (DeviceNode
->Flags
& DNF_RESOURCE_REPORTED
)
164 DPRINT1("Warning: Setting resource pointers even though DNF_RESOURCE_REPORTED is set\n");
166 Stack
.Parameters
.StartDevice
.AllocatedResources
=
167 DeviceNode
->ResourceList
;
168 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
=
169 DeviceNode
->ResourceListTranslated
;
172 /* I don't think we set this flag yet */
173 ASSERT(!(DeviceNode
->Flags
& DNF_STOPPED
));
176 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
177 if (!NT_SUCCESS(Status
))
180 DPRINT1("Warning: PnP Start failed\n");
185 /* Otherwise, mark us as started */
186 DeviceNode
->Flags
|= DNF_STARTED
;
188 /* We now need enumeration */
189 DeviceNode
->Flags
|= DNF_NEED_ENUMERATION_ONLY
;
194 IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode
)
196 PDEVICE_OBJECT DeviceObject
;
201 // ASSERT((DeviceNode->Flags & DNF_ADDED));
202 if (!(DeviceNode
->Flags
& DNF_ADDED
)) DPRINT1("Warning: Starting a device node without DNF_ADDED\n");
203 ASSERT((DeviceNode
->Flags
& (DNF_RESOURCE_ASSIGNED
|
204 DNF_RESOURCE_REPORTED
|
205 DNF_NO_RESOURCE_REQUIRED
|
206 DNF_NO_RESOURCE_REQUIRED
)));
207 ASSERT((!(DeviceNode
->Flags
& (DNF_HAS_PROBLEM
|
209 DNF_START_REQUEST_PENDING
))));
211 /* Get the device object */
212 DeviceObject
= DeviceNode
->PhysicalDeviceObject
;
214 /* Check if we're not started yet */
215 //if (!DeviceNode->Flags & DNF_STARTED)
218 IopStartDevice2(DeviceObject
);
221 /* Do we need to query IDs? This happens in the case of manual reporting */
222 //if (DeviceNode->Flags & DNF_NEED_QUERY_IDS)
224 // DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
225 /* And that case shouldn't happen yet */
229 /* Make sure we're started, and check if we need enumeration */
230 if ((DeviceNode
->Flags
& DNF_STARTED
) &&
231 (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
))
234 //Status = IopEnumerateDevice(DeviceObject);
235 IoSynchronousInvalidateDeviceRelations(DeviceObject
, BusRelations
);
236 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
237 Status
= STATUS_SUCCESS
;
242 Status
= STATUS_SUCCESS
;
251 PDEVICE_NODE DeviceNode
)
253 IO_STATUS_BLOCK IoStatusBlock
;
254 IO_STACK_LOCATION Stack
;
255 ULONG RequiredLength
;
257 HANDLE InstanceHandle
= INVALID_HANDLE_VALUE
, ControlHandle
= INVALID_HANDLE_VALUE
;
258 UNICODE_STRING KeyName
;
259 OBJECT_ATTRIBUTES ObjectAttributes
;
261 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
262 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
263 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
264 Status
= IopInitiatePnpIrp(
265 DeviceNode
->PhysicalDeviceObject
,
267 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
269 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
271 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
272 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
275 else if (NT_SUCCESS(Status
))
277 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
280 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
281 if (NT_SUCCESS(Status
))
283 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
284 if (NT_SUCCESS(Status
))
286 Status
= IopUpdateResourceMapForPnPDevice(DeviceNode
);
287 if (!NT_SUCCESS(Status
))
289 DPRINT("IopUpdateResourceMap() failed (Status 0x%08lx)\n", Status
);
294 DPRINT("IopTranslateDeviceResources() failed (Status 0x%08lx)\n", Status
);
299 DPRINT("IopAssignDeviceResources() failed (Status 0x%08lx)\n", Status
);
301 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
303 if (!NT_SUCCESS(Status
))
307 IopStartAndEnumerateDevice(DeviceNode
);
309 /* FIX: Should be done in new device instance code */
310 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceHandle
);
311 if (!NT_SUCCESS(Status
))
314 /* FIX: Should be done in IoXxxPrepareDriverLoading */
316 RtlInitUnicodeString(&KeyName
, L
"Control");
317 InitializeObjectAttributes(&ObjectAttributes
,
319 OBJ_CASE_INSENSITIVE
,
322 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
323 if (!NT_SUCCESS(Status
))
326 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
327 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
330 /* FIX: Should be done somewhere in resoure code? */
331 if (NT_SUCCESS(Status
) && DeviceNode
->ResourceList
)
333 RtlInitUnicodeString(&KeyName
, L
"AllocConfig");
334 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_RESOURCE_LIST
,
335 DeviceNode
->ResourceList
, CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceList
));
339 if (NT_SUCCESS(Status
))
340 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
342 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
344 if (ControlHandle
!= INVALID_HANDLE_VALUE
)
345 ZwClose(ControlHandle
);
347 if (InstanceHandle
!= INVALID_HANDLE_VALUE
)
348 ZwClose(InstanceHandle
);
355 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
356 PDEVICE_CAPABILITIES DeviceCaps
)
358 IO_STATUS_BLOCK StatusBlock
;
359 IO_STACK_LOCATION Stack
;
361 /* Set up the Header */
362 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
363 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
364 DeviceCaps
->Version
= 1;
365 DeviceCaps
->Address
= -1;
366 DeviceCaps
->UINumber
= -1;
368 /* Set up the Stack */
369 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
370 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
373 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
375 IRP_MN_QUERY_CAPABILITIES
,
380 IopAsynchronousInvalidateDeviceRelations(
381 IN PDEVICE_OBJECT DeviceObject
,
382 IN PVOID InvalidateContext
)
384 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
386 IoSynchronousInvalidateDeviceRelations(
390 ObDereferenceObject(Data
->DeviceObject
);
391 IoFreeWorkItem(Data
->WorkItem
);
396 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
400 if (PopSystemPowerDeviceNode
)
402 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
403 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
404 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
406 return STATUS_SUCCESS
;
409 return STATUS_UNSUCCESSFUL
;
414 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
416 USHORT i
= 0, FoundIndex
= 0xFFFF;
420 /* Acquire the lock */
421 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
423 /* Loop all entries */
424 while (i
< PnpBusTypeGuidList
->GuidCount
)
426 /* Try to find a match */
427 if (RtlCompareMemory(BusTypeGuid
,
428 &PnpBusTypeGuidList
->Guids
[i
],
429 sizeof(GUID
)) == sizeof(GUID
))
438 /* Check if we have to grow the list */
439 if (PnpBusTypeGuidList
->GuidCount
)
441 /* Calculate the new size */
442 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
443 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
445 /* Allocate the new copy */
446 NewList
= ExAllocatePool(PagedPool
, NewSize
);
450 ExFreePool(PnpBusTypeGuidList
);
454 /* Now copy them, decrease the size too */
455 NewSize
-= sizeof(GUID
);
456 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
458 /* Free the old list */
459 ExFreePool(PnpBusTypeGuidList
);
461 /* Use the new buffer */
462 PnpBusTypeGuidList
= NewList
;
465 /* Copy the new GUID */
466 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
470 /* The new entry is the index */
471 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
472 PnpBusTypeGuidList
->GuidCount
++;
475 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
481 * Creates a device node
484 * ParentNode = Pointer to parent device node
485 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
486 * to have the root device node create one
487 * (eg. for legacy drivers)
488 * DeviceNode = Pointer to storage for created device node
494 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
495 PDEVICE_OBJECT PhysicalDeviceObject
,
496 PUNICODE_STRING ServiceName
,
497 PDEVICE_NODE
*DeviceNode
)
502 UNICODE_STRING FullServiceName
;
503 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
504 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
505 UNICODE_STRING KeyName
, ClassName
;
506 PUNICODE_STRING ServiceName1
;
509 UNICODE_STRING ClassGUID
;
511 HANDLE InstanceHandle
;
513 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
514 ParentNode
, PhysicalDeviceObject
, ServiceName
);
516 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
519 return STATUS_INSUFFICIENT_RESOURCES
;
522 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
525 ServiceName1
= &UnknownDeviceName
;
527 ServiceName1
= ServiceName
;
529 if (!PhysicalDeviceObject
)
531 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
532 FullServiceName
.Length
= 0;
533 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
534 if (!FullServiceName
.Buffer
)
537 return STATUS_INSUFFICIENT_RESOURCES
;
540 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
541 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
543 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
544 if (!NT_SUCCESS(Status
))
546 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
551 /* Create the device key for legacy drivers */
552 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
553 if (!NT_SUCCESS(Status
))
555 ZwClose(InstanceHandle
);
557 ExFreePool(FullServiceName
.Buffer
);
561 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
562 if (!Node
->ServiceName
.Buffer
)
564 ZwClose(InstanceHandle
);
566 ExFreePool(FullServiceName
.Buffer
);
570 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
571 Node
->ServiceName
.Length
= 0;
573 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
577 RtlInitUnicodeString(&KeyName
, L
"Service");
578 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
581 if (NT_SUCCESS(Status
))
583 RtlInitUnicodeString(&KeyName
, L
"Legacy");
586 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
587 if (NT_SUCCESS(Status
))
589 RtlInitUnicodeString(&KeyName
, L
"Class");
591 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
592 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
);
594 if (NT_SUCCESS(Status
))
596 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
598 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
599 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
);
605 ZwClose(InstanceHandle
);
606 ExFreePool(FullServiceName
.Buffer
);
608 if (!NT_SUCCESS(Status
))
614 /* This is for drivers passed on the command line to ntoskrnl.exe */
615 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
618 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
620 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
624 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
625 Node
->Parent
= ParentNode
;
626 Node
->Sibling
= ParentNode
->Child
;
627 ParentNode
->Child
= Node
;
628 if (ParentNode
->LastChild
== NULL
)
629 ParentNode
->LastChild
= Node
;
630 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
631 Node
->Level
= ParentNode
->Level
+ 1;
634 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
638 return STATUS_SUCCESS
;
642 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
645 PDEVICE_NODE PrevSibling
= NULL
;
647 /* All children must be deleted before a parent is deleted */
648 ASSERT(!DeviceNode
->Child
);
650 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
652 ASSERT(DeviceNode
->PhysicalDeviceObject
);
654 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
656 /* Get previous sibling */
657 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
659 PrevSibling
= DeviceNode
->Parent
->Child
;
660 while (PrevSibling
->Sibling
!= DeviceNode
)
661 PrevSibling
= PrevSibling
->Sibling
;
664 /* Unlink from parent if it exists */
665 if (DeviceNode
->Parent
)
667 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
669 DeviceNode
->Parent
->LastChild
= PrevSibling
;
671 PrevSibling
->Sibling
= NULL
;
673 if (DeviceNode
->Parent
->Child
== DeviceNode
)
674 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
677 /* Unlink from sibling list */
679 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
681 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
683 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
685 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
687 if (DeviceNode
->ResourceList
)
689 ExFreePool(DeviceNode
->ResourceList
);
692 if (DeviceNode
->ResourceListTranslated
)
694 ExFreePool(DeviceNode
->ResourceListTranslated
);
697 if (DeviceNode
->ResourceRequirements
)
699 ExFreePool(DeviceNode
->ResourceRequirements
);
702 if (DeviceNode
->BootResources
)
704 ExFreePool(DeviceNode
->BootResources
);
707 ExFreePool(DeviceNode
);
709 return STATUS_SUCCESS
;
714 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
715 IN PIO_STACK_LOCATION IoStackLocation
,
716 OUT PVOID
*Information
)
719 PIO_STACK_LOCATION IrpStack
;
720 IO_STATUS_BLOCK IoStatusBlock
;
723 PDEVICE_OBJECT TopDeviceObject
;
726 /* Call the top of the device stack */
727 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
729 /* Allocate an IRP */
730 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
731 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
733 /* Initialize to failure */
734 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
735 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
737 /* Initialize the event */
738 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
741 Irp
->UserIosb
= &IoStatusBlock
;
742 Irp
->UserEvent
= &Event
;
745 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
746 IoQueueThreadIrp(Irp
);
748 /* Copy-in the stack */
749 IrpStack
= IoGetNextIrpStackLocation(Irp
);
750 *IrpStack
= *IoStackLocation
;
752 /* Call the driver */
753 Status
= IoCallDriver(TopDeviceObject
, Irp
);
754 if (Status
== STATUS_PENDING
)
757 KeWaitForSingleObject(&Event
,
762 Status
= IoStatusBlock
.Status
;
765 /* Return the information */
766 *Information
= (PVOID
)IoStatusBlock
.Information
;
772 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
773 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
774 IN ULONG MinorFunction
,
775 IN PIO_STACK_LOCATION Stack OPTIONAL
)
777 IO_STACK_LOCATION IoStackLocation
;
779 /* Fill out the stack information */
780 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
781 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
782 IoStackLocation
.MinorFunction
= MinorFunction
;
786 RtlCopyMemory(&IoStackLocation
.Parameters
,
788 sizeof(Stack
->Parameters
));
791 /* Do the PnP call */
792 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
794 (PVOID
)&IoStatusBlock
->Information
);
795 return IoStatusBlock
->Status
;
799 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
801 PDEVICE_NODE ParentDeviceNode
;
802 PDEVICE_NODE ChildDeviceNode
;
805 /* Copy context data so we don't overwrite it in subsequent calls to this function */
806 ParentDeviceNode
= Context
->DeviceNode
;
808 /* Call the action routine */
809 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
810 if (!NT_SUCCESS(Status
))
815 /* Traversal of all children nodes */
816 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
817 ChildDeviceNode
!= NULL
;
818 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
820 /* Pass the current device node to the action routine */
821 Context
->DeviceNode
= ChildDeviceNode
;
823 Status
= IopTraverseDeviceTreeNode(Context
);
824 if (!NT_SUCCESS(Status
))
835 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
839 DPRINT("Context 0x%p\n", Context
);
841 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
842 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
844 /* Start from the specified device node */
845 Context
->DeviceNode
= Context
->FirstDeviceNode
;
847 /* Recursively traverse the device tree */
848 Status
= IopTraverseDeviceTreeNode(Context
);
849 if (Status
== STATUS_UNSUCCESSFUL
)
851 /* The action routine just wanted to terminate the traversal with status
852 code STATUS_SUCCESS */
853 Status
= STATUS_SUCCESS
;
861 * IopCreateDeviceKeyPath
863 * Creates a registry key
867 * Name of the key to be created.
869 * Handle to the newly created key
872 * This method can create nested trees, so parent of RegistryPath can
873 * be not existant, and will be created if needed.
877 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
878 IN ULONG CreateOptions
,
881 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
882 HANDLE hParent
= NULL
, hKey
;
883 OBJECT_ATTRIBUTES ObjectAttributes
;
884 UNICODE_STRING KeyName
;
885 LPCWSTR Current
, Last
;
892 /* Open root key for device instances */
893 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
894 if (!NT_SUCCESS(Status
))
896 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
900 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
901 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
903 /* Go up to the end of the string */
904 while (Current
<= Last
)
906 if (Current
!= Last
&& *Current
!= '\\')
908 /* Not the end of the string and not a separator */
913 /* Prepare relative key name */
914 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
915 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
916 DPRINT("Create '%wZ'\n", &KeyName
);
919 InitializeObjectAttributes(&ObjectAttributes
,
921 OBJ_CASE_INSENSITIVE
,
924 Status
= ZwCreateKey(&hKey
,
925 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
932 /* Close parent key handle, we don't need it anymore */
936 /* Key opening/creating failed? */
937 if (!NT_SUCCESS(Status
))
939 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
943 /* Check if it is the end of the string */
946 /* Yes, return success */
948 return STATUS_SUCCESS
;
951 /* Start with this new parent key */
954 KeyName
.Buffer
= (LPWSTR
)Current
;
957 return STATUS_UNSUCCESSFUL
;
961 IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode
, PWCHAR Level1Key
, PWCHAR Level2Key
)
965 HANDLE PnpMgrLevel1
, PnpMgrLevel2
, ResourceMapKey
;
966 UNICODE_STRING KeyName
;
967 OBJECT_ATTRIBUTES ObjectAttributes
;
969 RtlInitUnicodeString(&KeyName
,
970 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
971 InitializeObjectAttributes(&ObjectAttributes
,
973 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
976 Status
= ZwCreateKey(&ResourceMapKey
,
983 if (!NT_SUCCESS(Status
))
986 RtlInitUnicodeString(&KeyName
, Level1Key
);
987 InitializeObjectAttributes(&ObjectAttributes
,
989 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
992 Status
= ZwCreateKey(&PnpMgrLevel1
,
999 ZwClose(ResourceMapKey
);
1000 if (!NT_SUCCESS(Status
))
1003 RtlInitUnicodeString(&KeyName
, Level2Key
);
1004 InitializeObjectAttributes(&ObjectAttributes
,
1006 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1009 Status
= ZwCreateKey(&PnpMgrLevel2
,
1014 REG_OPTION_VOLATILE
,
1016 ZwClose(PnpMgrLevel1
);
1017 if (!NT_SUCCESS(Status
))
1020 if (DeviceNode
->ResourceList
)
1022 WCHAR NameBuff
[256];
1023 UNICODE_STRING NameU
;
1024 UNICODE_STRING Suffix
;
1027 ASSERT(DeviceNode
->ResourceListTranslated
);
1029 NameU
.Buffer
= NameBuff
;
1031 NameU
.MaximumLength
= 256 * sizeof(WCHAR
);
1033 Status
= IoGetDeviceProperty(DeviceNode
->PhysicalDeviceObject
,
1034 DevicePropertyPhysicalDeviceObjectName
,
1035 NameU
.MaximumLength
,
1038 ASSERT(Status
== STATUS_SUCCESS
);
1040 NameU
.Length
= (USHORT
)OldLength
;
1042 RtlInitUnicodeString(&Suffix
, L
".Raw");
1043 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
1045 Status
= ZwSetValueKey(PnpMgrLevel2
,
1049 DeviceNode
->ResourceList
,
1050 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceList
));
1051 if (!NT_SUCCESS(Status
))
1053 ZwClose(PnpMgrLevel2
);
1057 /* "Remove" the suffix by setting the length back to what it used to be */
1058 NameU
.Length
= (USHORT
)OldLength
;
1060 RtlInitUnicodeString(&Suffix
, L
".Translated");
1061 RtlAppendUnicodeStringToString(&NameU
, &Suffix
);
1063 Status
= ZwSetValueKey(PnpMgrLevel2
,
1067 DeviceNode
->ResourceListTranslated
,
1068 CM_RESOURCE_LIST_SIZE(DeviceNode
->ResourceListTranslated
));
1069 ZwClose(PnpMgrLevel2
);
1070 if (!NT_SUCCESS(Status
))
1075 ZwClose(PnpMgrLevel2
);
1078 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
1080 return STATUS_SUCCESS
;
1084 IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode
)
1086 return IopUpdateResourceMap(DeviceNode
, L
"PnP Manager", L
"PnpManager");
1090 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1091 PDEVICE_NODE DeviceNode
)
1093 OBJECT_ATTRIBUTES ObjectAttributes
;
1094 UNICODE_STRING KeyName
;
1097 ULONG ListSize
, ResultLength
;
1099 HANDLE ControlHandle
;
1101 DPRINT("IopSetDeviceInstanceData() called\n");
1103 /* Create the 'LogConf' key */
1104 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1105 InitializeObjectAttributes(&ObjectAttributes
,
1107 OBJ_CASE_INSENSITIVE
,
1110 Status
= ZwCreateKey(&LogConfKey
,
1117 if (NT_SUCCESS(Status
))
1119 /* Set 'BootConfig' value */
1120 if (DeviceNode
->BootResources
!= NULL
)
1122 ResCount
= DeviceNode
->BootResources
->Count
;
1125 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1127 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1128 Status
= ZwSetValueKey(LogConfKey
,
1132 DeviceNode
->BootResources
,
1137 /* Set 'BasicConfigVector' value */
1138 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1139 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1141 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1142 Status
= ZwSetValueKey(LogConfKey
,
1145 REG_RESOURCE_REQUIREMENTS_LIST
,
1146 DeviceNode
->ResourceRequirements
,
1147 DeviceNode
->ResourceRequirements
->ListSize
);
1150 ZwClose(LogConfKey
);
1153 /* Set the 'ConfigFlags' value */
1154 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1155 Status
= ZwQueryValueKey(InstanceKey
,
1157 KeyValueBasicInformation
,
1161 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1163 /* Write the default value */
1164 ULONG DefaultConfigFlags
= 0;
1165 Status
= ZwSetValueKey(InstanceKey
,
1169 &DefaultConfigFlags
,
1170 sizeof(DefaultConfigFlags
));
1173 /* Create the 'Control' key */
1174 RtlInitUnicodeString(&KeyName
, L
"Control");
1175 InitializeObjectAttributes(&ObjectAttributes
,
1177 OBJ_CASE_INSENSITIVE
,
1180 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1182 if (NT_SUCCESS(Status
))
1183 ZwClose(ControlHandle
);
1185 DPRINT("IopSetDeviceInstanceData() done\n");
1191 IopCheckResourceDescriptor(
1192 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
,
1193 IN PCM_RESOURCE_LIST ResourceList
,
1195 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1198 BOOLEAN Result
= FALSE
;
1200 if (ResDesc
->ShareDisposition
== CmResourceShareShared
)
1203 for (i
= 0; i
< ResourceList
->Count
; i
++)
1205 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList
->List
[i
].PartialResourceList
;
1206 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1208 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2
= &ResList
->PartialDescriptors
[ii
];
1210 /* We don't care about shared resources */
1211 if (ResDesc
->ShareDisposition
== CmResourceShareShared
&&
1212 ResDesc2
->ShareDisposition
== CmResourceShareShared
)
1215 /* Make sure we're comparing the same types */
1216 if (ResDesc
->Type
!= ResDesc2
->Type
)
1219 switch (ResDesc
->Type
)
1221 case CmResourceTypeMemory
:
1222 if ((ResDesc
->u
.Memory
.Start
.QuadPart
< ResDesc2
->u
.Memory
.Start
.QuadPart
&&
1223 ResDesc
->u
.Memory
.Start
.QuadPart
+ ResDesc
->u
.Memory
.Length
>
1224 ResDesc2
->u
.Memory
.Start
.QuadPart
) || (ResDesc2
->u
.Memory
.Start
.QuadPart
<
1225 ResDesc
->u
.Memory
.Start
.QuadPart
&& ResDesc2
->u
.Memory
.Start
.QuadPart
+
1226 ResDesc2
->u
.Memory
.Length
> ResDesc
->u
.Memory
.Start
.QuadPart
))
1230 DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1231 ResDesc
->u
.Memory
.Start
.QuadPart
, ResDesc
->u
.Memory
.Start
.QuadPart
+
1232 ResDesc
->u
.Memory
.Length
, ResDesc2
->u
.Memory
.Start
.QuadPart
,
1233 ResDesc2
->u
.Memory
.Start
.QuadPart
+ ResDesc2
->u
.Memory
.Length
);
1242 case CmResourceTypePort
:
1243 if ((ResDesc
->u
.Port
.Start
.QuadPart
< ResDesc2
->u
.Port
.Start
.QuadPart
&&
1244 ResDesc
->u
.Port
.Start
.QuadPart
+ ResDesc
->u
.Port
.Length
>
1245 ResDesc2
->u
.Port
.Start
.QuadPart
) || (ResDesc2
->u
.Port
.Start
.QuadPart
<
1246 ResDesc
->u
.Port
.Start
.QuadPart
&& ResDesc2
->u
.Port
.Start
.QuadPart
+
1247 ResDesc2
->u
.Port
.Length
> ResDesc
->u
.Port
.Start
.QuadPart
))
1251 DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1252 ResDesc
->u
.Port
.Start
.QuadPart
, ResDesc
->u
.Port
.Start
.QuadPart
+
1253 ResDesc
->u
.Port
.Length
, ResDesc2
->u
.Port
.Start
.QuadPart
,
1254 ResDesc2
->u
.Port
.Start
.QuadPart
+ ResDesc2
->u
.Port
.Length
);
1263 case CmResourceTypeInterrupt
:
1264 if (ResDesc
->u
.Interrupt
.Vector
== ResDesc2
->u
.Interrupt
.Vector
)
1268 DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
1269 ResDesc
->u
.Interrupt
.Vector
, ResDesc
->u
.Interrupt
.Level
,
1270 ResDesc2
->u
.Interrupt
.Vector
, ResDesc2
->u
.Interrupt
.Level
);
1279 case CmResourceTypeBusNumber
:
1280 if ((ResDesc
->u
.BusNumber
.Start
< ResDesc2
->u
.BusNumber
.Start
&&
1281 ResDesc
->u
.BusNumber
.Start
+ ResDesc
->u
.BusNumber
.Length
>
1282 ResDesc2
->u
.BusNumber
.Start
) || (ResDesc2
->u
.BusNumber
.Start
<
1283 ResDesc
->u
.BusNumber
.Start
&& ResDesc2
->u
.BusNumber
.Start
+
1284 ResDesc2
->u
.BusNumber
.Length
> ResDesc
->u
.BusNumber
.Start
))
1288 DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
1289 ResDesc
->u
.BusNumber
.Start
, ResDesc
->u
.BusNumber
.Start
+
1290 ResDesc
->u
.BusNumber
.Length
, ResDesc2
->u
.BusNumber
.Start
,
1291 ResDesc2
->u
.BusNumber
.Start
+ ResDesc2
->u
.BusNumber
.Length
);
1300 case CmResourceTypeDma
:
1301 if (ResDesc
->u
.Dma
.Channel
== ResDesc2
->u
.Dma
.Channel
)
1305 DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
1306 ResDesc
->u
.Dma
.Channel
, ResDesc
->u
.Dma
.Port
,
1307 ResDesc2
->u
.Dma
.Channel
, ResDesc2
->u
.Dma
.Port
);
1321 if (Result
&& ConflictingDescriptor
)
1323 RtlCopyMemory(ConflictingDescriptor
,
1325 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1333 IopCheckForResourceConflict(
1334 IN PCM_RESOURCE_LIST ResourceList1
,
1335 IN PCM_RESOURCE_LIST ResourceList2
,
1337 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1340 BOOLEAN Result
= FALSE
;
1342 for (i
= 0; i
< ResourceList1
->Count
; i
++)
1344 PCM_PARTIAL_RESOURCE_LIST ResList
= &ResourceList1
->List
[i
].PartialResourceList
;
1345 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1347 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
= &ResList
->PartialDescriptors
[ii
];
1349 Result
= IopCheckResourceDescriptor(ResDesc
,
1352 ConflictingDescriptor
);
1353 if (Result
) goto ByeBye
;
1364 IopDetectResourceConflict(
1365 IN PCM_RESOURCE_LIST ResourceList
,
1367 OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1369 OBJECT_ATTRIBUTES ObjectAttributes
;
1370 UNICODE_STRING KeyName
;
1371 HANDLE ResourceMapKey
= INVALID_HANDLE_VALUE
, ChildKey2
= INVALID_HANDLE_VALUE
, ChildKey3
= INVALID_HANDLE_VALUE
;
1372 ULONG KeyInformationLength
, RequiredLength
, KeyValueInformationLength
, KeyNameInformationLength
;
1373 PKEY_BASIC_INFORMATION KeyInformation
;
1374 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
1375 PKEY_VALUE_BASIC_INFORMATION KeyNameInformation
;
1376 ULONG ChildKeyIndex1
= 0, ChildKeyIndex2
= 0, ChildKeyIndex3
= 0;
1379 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1380 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
1381 Status
= ZwOpenKey(&ResourceMapKey
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1382 if (!NT_SUCCESS(Status
))
1384 /* The key is missing which means we are the first device */
1385 return STATUS_SUCCESS
;
1390 Status
= ZwEnumerateKey(ResourceMapKey
,
1392 KeyBasicInformation
,
1396 if (Status
== STATUS_NO_MORE_ENTRIES
)
1398 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1400 KeyInformationLength
= RequiredLength
;
1401 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1402 if (!KeyInformation
)
1404 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1408 Status
= ZwEnumerateKey(ResourceMapKey
,
1410 KeyBasicInformation
,
1412 KeyInformationLength
,
1418 if (!NT_SUCCESS(Status
))
1421 KeyName
.Buffer
= KeyInformation
->Name
;
1422 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1423 InitializeObjectAttributes(&ObjectAttributes
,
1425 OBJ_CASE_INSENSITIVE
,
1428 Status
= ZwOpenKey(&ChildKey2
, KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
, &ObjectAttributes
);
1429 ExFreePool(KeyInformation
);
1430 if (!NT_SUCCESS(Status
))
1435 Status
= ZwEnumerateKey(ChildKey2
,
1437 KeyBasicInformation
,
1441 if (Status
== STATUS_NO_MORE_ENTRIES
)
1443 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1445 KeyInformationLength
= RequiredLength
;
1446 KeyInformation
= ExAllocatePool(PagedPool
, KeyInformationLength
);
1447 if (!KeyInformation
)
1449 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1453 Status
= ZwEnumerateKey(ChildKey2
,
1455 KeyBasicInformation
,
1457 KeyInformationLength
,
1463 if (!NT_SUCCESS(Status
))
1466 KeyName
.Buffer
= KeyInformation
->Name
;
1467 KeyName
.MaximumLength
= KeyName
.Length
= KeyInformation
->NameLength
;
1468 InitializeObjectAttributes(&ObjectAttributes
,
1470 OBJ_CASE_INSENSITIVE
,
1473 Status
= ZwOpenKey(&ChildKey3
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1474 ExFreePool(KeyInformation
);
1475 if (!NT_SUCCESS(Status
))
1480 Status
= ZwEnumerateValueKey(ChildKey3
,
1482 KeyValuePartialInformation
,
1486 if (Status
== STATUS_NO_MORE_ENTRIES
)
1488 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1490 KeyValueInformationLength
= RequiredLength
;
1491 KeyValueInformation
= ExAllocatePool(PagedPool
, KeyValueInformationLength
);
1492 if (!KeyValueInformation
)
1494 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1498 Status
= ZwEnumerateValueKey(ChildKey3
,
1500 KeyValuePartialInformation
,
1501 KeyValueInformation
,
1502 KeyValueInformationLength
,
1507 if (!NT_SUCCESS(Status
))
1510 Status
= ZwEnumerateValueKey(ChildKey3
,
1512 KeyValueBasicInformation
,
1516 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1518 KeyNameInformationLength
= RequiredLength
;
1519 KeyNameInformation
= ExAllocatePool(PagedPool
, KeyNameInformationLength
+ sizeof(WCHAR
));
1520 if (!KeyNameInformation
)
1522 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1526 Status
= ZwEnumerateValueKey(ChildKey3
,
1528 KeyValueBasicInformation
,
1530 KeyNameInformationLength
,
1538 if (!NT_SUCCESS(Status
))
1541 KeyNameInformation
->Name
[KeyNameInformation
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1543 /* Skip translated entries */
1544 if (wcsstr(KeyNameInformation
->Name
, L
".Translated"))
1546 ExFreePool(KeyNameInformation
);
1550 ExFreePool(KeyNameInformation
);
1552 if (IopCheckForResourceConflict(ResourceList
,
1553 (PCM_RESOURCE_LIST
)KeyValueInformation
->Data
,
1555 ConflictingDescriptor
))
1557 ExFreePool(KeyValueInformation
);
1558 Status
= STATUS_CONFLICTING_ADDRESSES
;
1562 ExFreePool(KeyValueInformation
);
1568 if (ResourceMapKey
!= INVALID_HANDLE_VALUE
)
1569 ZwClose(ResourceMapKey
);
1570 if (ChildKey2
!= INVALID_HANDLE_VALUE
)
1572 if (ChildKey3
!= INVALID_HANDLE_VALUE
)
1575 if (Status
== STATUS_NO_MORE_ENTRIES
)
1576 Status
= STATUS_SUCCESS
;
1582 IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
)
1584 CM_RESOURCE_LIST CmList
;
1588 CmList
.List
[0].InterfaceType
= InterfaceTypeUndefined
;
1589 CmList
.List
[0].BusNumber
= 0;
1590 CmList
.List
[0].PartialResourceList
.Version
= 1;
1591 CmList
.List
[0].PartialResourceList
.Revision
= 1;
1592 CmList
.List
[0].PartialResourceList
.Count
= 1;
1593 CmList
.List
[0].PartialResourceList
.PartialDescriptors
[0] = *CmDesc
;
1595 Status
= IopDetectResourceConflict(&CmList
, TRUE
, ConflictingDescriptor
);
1596 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
1603 IopFindBusNumberResource(
1604 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1605 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1608 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1610 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1611 ASSERT(IoDesc
->Type
== CmResourceTypeBusNumber
);
1613 for (Start
= IoDesc
->u
.BusNumber
.MinBusNumber
;
1614 Start
< IoDesc
->u
.BusNumber
.MaxBusNumber
;
1617 CmDesc
->u
.BusNumber
.Length
= IoDesc
->u
.BusNumber
.Length
;
1618 CmDesc
->u
.BusNumber
.Start
= Start
;
1620 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1622 Start
+= ConflictingDesc
.u
.BusNumber
.Start
+ ConflictingDesc
.u
.BusNumber
.Length
;
1634 IopFindMemoryResource(
1635 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1636 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1639 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1641 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1642 ASSERT(IoDesc
->Type
== CmResourceTypeMemory
);
1644 for (Start
= IoDesc
->u
.Memory
.MinimumAddress
.QuadPart
;
1645 Start
< IoDesc
->u
.Memory
.MaximumAddress
.QuadPart
;
1648 CmDesc
->u
.Memory
.Length
= IoDesc
->u
.Memory
.Length
;
1649 CmDesc
->u
.Memory
.Start
.QuadPart
= Start
;
1651 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1653 Start
+= ConflictingDesc
.u
.Memory
.Start
.QuadPart
+ ConflictingDesc
.u
.Memory
.Length
;
1665 IopFindPortResource(
1666 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1667 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1670 CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc
;
1672 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1673 ASSERT(IoDesc
->Type
== CmResourceTypePort
);
1675 for (Start
= IoDesc
->u
.Port
.MinimumAddress
.QuadPart
;
1676 Start
< IoDesc
->u
.Port
.MaximumAddress
.QuadPart
;
1679 CmDesc
->u
.Port
.Length
= IoDesc
->u
.Port
.Length
;
1680 CmDesc
->u
.Port
.Start
.QuadPart
= Start
;
1682 if (IopCheckDescriptorForConflict(CmDesc
, &ConflictingDesc
))
1684 Start
+= ConflictingDesc
.u
.Port
.Start
.QuadPart
+ ConflictingDesc
.u
.Port
.Length
;
1697 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1698 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1702 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1703 ASSERT(IoDesc
->Type
== CmResourceTypeDma
);
1705 for (Channel
= IoDesc
->u
.Dma
.MinimumChannel
;
1706 Channel
< IoDesc
->u
.Dma
.MaximumChannel
;
1709 CmDesc
->u
.Dma
.Channel
= Channel
;
1710 CmDesc
->u
.Dma
.Port
= 0;
1712 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
1720 IopFindInterruptResource(
1721 IN PIO_RESOURCE_DESCRIPTOR IoDesc
,
1722 OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc
)
1726 ASSERT(IoDesc
->Type
== CmDesc
->Type
);
1727 ASSERT(IoDesc
->Type
== CmResourceTypeInterrupt
);
1729 for (Vector
= IoDesc
->u
.Interrupt
.MinimumVector
;
1730 Vector
< IoDesc
->u
.Interrupt
.MaximumVector
;
1733 CmDesc
->u
.Interrupt
.Vector
= Vector
;
1734 CmDesc
->u
.Interrupt
.Level
= Vector
;
1735 CmDesc
->u
.Interrupt
.Affinity
= (KAFFINITY
)-1;
1737 if (!IopCheckDescriptorForConflict(CmDesc
, NULL
))
1745 IopCreateResourceListFromRequirements(
1746 IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList
,
1747 OUT PCM_RESOURCE_LIST
*ResourceList
)
1750 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc
;
1752 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1753 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
1755 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
1756 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1757 + ResList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1760 *ResourceList
= ExAllocatePool(PagedPool
, Size
);
1762 return STATUS_INSUFFICIENT_RESOURCES
;
1764 (*ResourceList
)->Count
= 1;
1765 (*ResourceList
)->List
[0].BusNumber
= RequirementsList
->BusNumber
;
1766 (*ResourceList
)->List
[0].InterfaceType
= RequirementsList
->InterfaceType
;
1767 (*ResourceList
)->List
[0].PartialResourceList
.Version
= 1;
1768 (*ResourceList
)->List
[0].PartialResourceList
.Revision
= 1;
1769 (*ResourceList
)->List
[0].PartialResourceList
.Count
= 0;
1771 ResDesc
= &(*ResourceList
)->List
[0].PartialResourceList
.PartialDescriptors
[0];
1773 for (i
= 0; i
< RequirementsList
->AlternativeLists
; i
++)
1775 PIO_RESOURCE_LIST ResList
= &RequirementsList
->List
[i
];
1776 for (ii
= 0; ii
< ResList
->Count
; ii
++)
1778 PIO_RESOURCE_DESCRIPTOR ReqDesc
= &ResList
->Descriptors
[ii
];
1780 /* FIXME: Handle alternate ranges */
1781 if (ReqDesc
->Option
== IO_RESOURCE_ALTERNATIVE
)
1784 ResDesc
->Type
= ReqDesc
->Type
;
1785 ResDesc
->Flags
= ReqDesc
->Flags
;
1786 ResDesc
->ShareDisposition
= ReqDesc
->ShareDisposition
;
1788 switch (ReqDesc
->Type
)
1790 case CmResourceTypeInterrupt
:
1791 if (!IopFindInterruptResource(ReqDesc
, ResDesc
))
1793 DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n",
1794 ReqDesc
->u
.Interrupt
.MinimumVector
, ReqDesc
->u
.Interrupt
.MaximumVector
);
1796 if (ReqDesc
->Option
== 0)
1798 ExFreePool(*ResourceList
);
1799 return STATUS_CONFLICTING_ADDRESSES
;
1804 case CmResourceTypePort
:
1805 if (!IopFindPortResource(ReqDesc
, ResDesc
))
1807 DPRINT1("Failed to find an available port resource (0x%x to 0x%x length: 0x%x)\n",
1808 ReqDesc
->u
.Port
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Port
.MaximumAddress
.QuadPart
,
1809 ReqDesc
->u
.Port
.Length
);
1811 if (ReqDesc
->Option
== 0)
1813 ExFreePool(*ResourceList
);
1814 return STATUS_CONFLICTING_ADDRESSES
;
1819 case CmResourceTypeMemory
:
1820 if (!IopFindMemoryResource(ReqDesc
, ResDesc
))
1822 DPRINT1("Failed to find an available memory resource (0x%x to 0x%x length: 0x%x)\n",
1823 ReqDesc
->u
.Memory
.MinimumAddress
.QuadPart
, ReqDesc
->u
.Memory
.MaximumAddress
.QuadPart
,
1824 ReqDesc
->u
.Memory
.Length
);
1826 if (ReqDesc
->Option
== 0)
1828 ExFreePool(*ResourceList
);
1829 return STATUS_CONFLICTING_ADDRESSES
;
1834 case CmResourceTypeBusNumber
:
1835 if (!IopFindBusNumberResource(ReqDesc
, ResDesc
))
1837 DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n",
1838 ReqDesc
->u
.BusNumber
.MinBusNumber
, ReqDesc
->u
.BusNumber
.MaxBusNumber
,
1839 ReqDesc
->u
.BusNumber
.Length
);
1841 if (ReqDesc
->Option
== 0)
1843 ExFreePool(*ResourceList
);
1844 return STATUS_CONFLICTING_ADDRESSES
;
1849 case CmResourceTypeDma
:
1850 if (!IopFindDmaResource(ReqDesc
, ResDesc
))
1852 DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n",
1853 ReqDesc
->u
.Dma
.MinimumChannel
, ReqDesc
->u
.Dma
.MaximumChannel
);
1855 if (ReqDesc
->Option
== 0)
1857 ExFreePool(*ResourceList
);
1858 return STATUS_CONFLICTING_ADDRESSES
;
1864 DPRINT1("Unsupported resource type: %x\n", ReqDesc
->Type
);
1868 (*ResourceList
)->List
[0].PartialResourceList
.Count
++;
1873 return STATUS_SUCCESS
;
1877 IopAssignDeviceResources(
1878 IN PDEVICE_NODE DeviceNode
,
1879 OUT ULONG
*pRequiredSize
)
1881 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1887 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1889 /* No resource needed for this device */
1890 DeviceNode
->ResourceList
= NULL
;
1892 return STATUS_SUCCESS
;
1895 /* Fill DeviceNode->ResourceList
1896 * FIXME: the PnP arbiter should go there!
1897 * Actually, use the BootResources if provided, else the resource requirements
1900 if (DeviceNode
->BootResources
)
1902 /* Browse the boot resources to know if we have some custom structures */
1903 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1904 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1906 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1907 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
) +
1908 pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1909 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1911 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1912 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1916 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1917 if (!DeviceNode
->ResourceList
)
1919 Status
= STATUS_NO_MEMORY
;
1922 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1924 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
1925 if (NT_SUCCESS(Status
) || !DeviceNode
->ResourceRequirements
)
1927 if (!NT_SUCCESS(Status
) && !DeviceNode
->ResourceRequirements
)
1929 DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
1932 *pRequiredSize
= Size
;
1933 return STATUS_SUCCESS
;
1937 DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode
->InstancePath
);
1938 ExFreePool(DeviceNode
->ResourceList
);
1942 Status
= IopCreateResourceListFromRequirements(DeviceNode
->ResourceRequirements
,
1943 &DeviceNode
->ResourceList
);
1944 if (!NT_SUCCESS(Status
))
1947 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1948 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1950 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1951 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
) +
1952 pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1955 Status
= IopDetectResourceConflict(DeviceNode
->ResourceList
, FALSE
, NULL
);
1956 if (!NT_SUCCESS(Status
))
1959 *pRequiredSize
= Size
;
1960 return STATUS_SUCCESS
;
1963 if (DeviceNode
->ResourceList
)
1965 ExFreePool(DeviceNode
->ResourceList
);
1966 DeviceNode
->ResourceList
= NULL
;
1974 IopTranslateDeviceResources(
1975 IN PDEVICE_NODE DeviceNode
,
1976 IN ULONG RequiredSize
)
1978 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1979 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1983 if (!DeviceNode
->ResourceList
)
1985 DeviceNode
->ResourceListTranslated
= NULL
;
1986 return STATUS_SUCCESS
;
1989 /* That's easy to translate a resource list. Just copy the
1990 * untranslated one and change few fields in the copy
1992 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1993 if (!DeviceNode
->ResourceListTranslated
)
1995 Status
=STATUS_NO_MEMORY
;
1998 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
2000 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
2002 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
2003 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
2005 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
2006 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
2007 switch (DescriptorRaw
->Type
)
2009 case CmResourceTypePort
:
2011 ULONG AddressSpace
= 1; /* IO space */
2012 if (!HalTranslateBusAddress(
2013 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
2014 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
2015 DescriptorRaw
->u
.Port
.Start
,
2017 &DescriptorTranslated
->u
.Port
.Start
))
2019 Status
= STATUS_UNSUCCESSFUL
;
2024 case CmResourceTypeInterrupt
:
2026 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
2027 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
2028 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
2029 DescriptorRaw
->u
.Interrupt
.Level
,
2030 DescriptorRaw
->u
.Interrupt
.Vector
,
2031 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
2032 &DescriptorRaw
->u
.Interrupt
.Affinity
);
2035 case CmResourceTypeMemory
:
2037 ULONG AddressSpace
= 0; /* Memory space */
2038 if (!HalTranslateBusAddress(
2039 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
2040 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
2041 DescriptorRaw
->u
.Memory
.Start
,
2043 &DescriptorTranslated
->u
.Memory
.Start
))
2045 Status
= STATUS_UNSUCCESSFUL
;
2050 case CmResourceTypeDma
:
2051 case CmResourceTypeBusNumber
:
2052 case CmResourceTypeDeviceSpecific
:
2056 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
2057 Status
= STATUS_NOT_IMPLEMENTED
;
2062 return STATUS_SUCCESS
;
2065 /* Yes! Also delete ResourceList because ResourceList and
2066 * ResourceListTranslated should be a pair! */
2067 ExFreePool(DeviceNode
->ResourceList
);
2068 DeviceNode
->ResourceList
= NULL
;
2069 if (DeviceNode
->ResourceListTranslated
)
2071 ExFreePool(DeviceNode
->ResourceListTranslated
);
2072 DeviceNode
->ResourceList
= NULL
;
2079 * IopGetParentIdPrefix
2081 * Retrieve (or create) a string which identifies a device.
2085 * Pointer to device node.
2087 * Pointer to the string where is returned the parent node identifier
2090 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
2091 * valid and its Buffer field is NULL-terminated. The caller needs to
2092 * to free the string with RtlFreeUnicodeString when it is no longer
2097 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
2098 PUNICODE_STRING ParentIdPrefix
)
2100 ULONG KeyNameBufferLength
;
2101 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
2102 UNICODE_STRING KeyName
;
2103 UNICODE_STRING KeyValue
;
2104 UNICODE_STRING ValueName
;
2109 /* HACK: As long as some devices have a NULL device
2110 * instance path, the following test is required :(
2112 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
2114 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
2115 &DeviceNode
->InstancePath
);
2116 return STATUS_UNSUCCESSFUL
;
2119 /* 1. Try to retrieve ParentIdPrefix from registry */
2120 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
2121 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
2122 if (!ParentIdPrefixInformation
)
2124 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2129 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
2130 if (!KeyName
.Buffer
)
2132 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2136 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
2138 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2139 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
2141 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
2142 if (!NT_SUCCESS(Status
))
2144 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
2145 Status
= ZwQueryValueKey(
2147 KeyValuePartialInformation
, ParentIdPrefixInformation
,
2148 KeyNameBufferLength
, &KeyNameBufferLength
);
2149 if (NT_SUCCESS(Status
))
2151 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
2152 Status
= STATUS_UNSUCCESSFUL
;
2155 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
2156 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
2160 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2162 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
2163 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
2167 /* 2. Create the ParentIdPrefix value */
2168 crc32
= RtlComputeCrc32(0,
2169 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
2170 DeviceNode
->Parent
->InstancePath
.Length
);
2172 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
2173 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
2175 /* 3. Try to write the ParentIdPrefix to registry */
2176 Status
= ZwSetValueKey(hKey
,
2180 (PVOID
)KeyValue
.Buffer
,
2181 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
2184 if (NT_SUCCESS(Status
))
2186 /* Duplicate the string to return it */
2187 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
2189 ExFreePool(ParentIdPrefixInformation
);
2190 RtlFreeUnicodeString(&KeyName
);
2198 * IopActionInterrogateDeviceStack
2200 * Retrieve information for all (direct) child nodes of a parent node.
2204 * Pointer to device node.
2206 * Pointer to parent node to retrieve child node information for.
2209 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2210 * when we reach a device node which is not a direct child of the device
2211 * node for which we retrieve information of child nodes for. Any errors
2212 * that occur is logged instead so that all child services have a chance
2213 * of being interrogated.
2217 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
2220 IO_STATUS_BLOCK IoStatusBlock
;
2221 PDEVICE_NODE ParentDeviceNode
;
2222 WCHAR InstancePath
[MAX_PATH
];
2223 IO_STACK_LOCATION Stack
;
2228 ULONG RequiredLength
;
2230 HANDLE InstanceKey
= NULL
;
2231 UNICODE_STRING ValueName
;
2232 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
2233 DEVICE_CAPABILITIES DeviceCapabilities
;
2235 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
2236 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
2238 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2241 * We are called for the parent too, but we don't need to do special
2242 * handling for this node
2245 if (DeviceNode
== ParentDeviceNode
)
2247 DPRINT("Success\n");
2248 return STATUS_SUCCESS
;
2252 * Make sure this device node is a direct child of the parent device node
2253 * that is given as an argument
2256 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2258 /* Stop the traversal immediately and indicate successful operation */
2260 return STATUS_UNSUCCESSFUL
;
2264 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
2265 if (!NT_SUCCESS(Status
))
2267 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
2272 * FIXME: For critical errors, cleanup and disable device, but always
2273 * return STATUS_SUCCESS.
2276 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
2278 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
2279 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2283 if (NT_SUCCESS(Status
))
2285 /* Copy the device id string */
2286 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
2289 * FIXME: Check for valid characters, if there is invalid characters
2295 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2298 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
2300 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
2301 if (!NT_SUCCESS(Status
))
2303 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
2306 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
2308 if (!DeviceCapabilities
.UniqueID
)
2310 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
2311 DPRINT("Instance ID is not unique\n");
2312 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
2313 if (!NT_SUCCESS(Status
))
2315 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
2319 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
2321 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
2322 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2326 if (NT_SUCCESS(Status
))
2328 /* Append the instance id string */
2329 wcscat(InstancePath
, L
"\\");
2330 if (ParentIdPrefix
.Length
> 0)
2332 /* Add information from parent bus device to InstancePath */
2333 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
2334 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
2335 wcscat(InstancePath
, L
"&");
2337 if (IoStatusBlock
.Information
)
2338 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
2341 * FIXME: Check for valid characters, if there is invalid characters
2347 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2349 RtlFreeUnicodeString(&ParentIdPrefix
);
2351 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
2353 DPRINT("No resources\n");
2354 /* FIXME: Cleanup and disable device */
2357 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
2360 * Create registry key for the instance id, if it doesn't exist yet
2362 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
2363 if (!NT_SUCCESS(Status
))
2365 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2369 /* Set 'Capabilities' value */
2370 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
2371 Status
= ZwSetValueKey(InstanceKey
,
2375 (PVOID
)&DeviceNode
->CapabilityFlags
,
2378 /* Set 'UINumber' value */
2379 if (DeviceCapabilities
.UINumber
!= MAXULONG
)
2381 RtlInitUnicodeString(&ValueName
, L
"UINumber");
2382 Status
= ZwSetValueKey(InstanceKey
,
2386 &DeviceCapabilities
.UINumber
,
2391 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
2393 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
2394 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2398 if (NT_SUCCESS(Status
))
2401 * FIXME: Check for valid characters, if there is invalid characters
2405 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
2406 DPRINT("Hardware IDs:\n");
2409 DPRINT(" %S\n", Ptr
);
2410 Length
= wcslen(Ptr
) + 1;
2413 TotalLength
+= Length
;
2415 DPRINT("TotalLength: %hu\n", TotalLength
);
2418 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
2419 Status
= ZwSetValueKey(InstanceKey
,
2423 (PVOID
)IoStatusBlock
.Information
,
2424 (TotalLength
+ 1) * sizeof(WCHAR
));
2425 if (!NT_SUCCESS(Status
))
2427 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2432 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2435 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
2437 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
2438 Status
= IopInitiatePnpIrp(
2439 DeviceNode
->PhysicalDeviceObject
,
2443 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2446 * FIXME: Check for valid characters, if there is invalid characters
2450 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
2451 DPRINT("Compatible IDs:\n");
2454 DPRINT(" %S\n", Ptr
);
2455 Length
= wcslen(Ptr
) + 1;
2458 TotalLength
+= Length
;
2460 DPRINT("TotalLength: %hu\n", TotalLength
);
2463 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
2464 Status
= ZwSetValueKey(InstanceKey
,
2468 (PVOID
)IoStatusBlock
.Information
,
2469 (TotalLength
+ 1) * sizeof(WCHAR
));
2470 if (!NT_SUCCESS(Status
))
2472 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
2477 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2480 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2482 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2483 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2484 Status
= IopInitiatePnpIrp(
2485 DeviceNode
->PhysicalDeviceObject
,
2487 IRP_MN_QUERY_DEVICE_TEXT
,
2489 /* This key is mandatory, so even if the Irp fails, we still write it */
2490 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2491 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2493 if (NT_SUCCESS(Status
) &&
2494 IoStatusBlock
.Information
&&
2495 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2497 /* This key is overriden when a driver is installed. Don't write the
2498 * new description if another one already exists */
2499 Status
= ZwSetValueKey(InstanceKey
,
2503 (PVOID
)IoStatusBlock
.Information
,
2504 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2508 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2509 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2511 Status
= ZwSetValueKey(InstanceKey
,
2516 DeviceDesc
.MaximumLength
);
2518 if (!NT_SUCCESS(Status
))
2520 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2526 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2528 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2529 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2530 Status
= IopInitiatePnpIrp(
2531 DeviceNode
->PhysicalDeviceObject
,
2533 IRP_MN_QUERY_DEVICE_TEXT
,
2535 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2537 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2538 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2539 Status
= ZwSetValueKey(InstanceKey
,
2543 (PVOID
)IoStatusBlock
.Information
,
2544 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2545 if (!NT_SUCCESS(Status
))
2547 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2552 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2555 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2557 Status
= IopInitiatePnpIrp(
2558 DeviceNode
->PhysicalDeviceObject
,
2560 IRP_MN_QUERY_BUS_INFORMATION
,
2562 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2564 PPNP_BUS_INFORMATION BusInformation
=
2565 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2567 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2568 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2569 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2570 ExFreePool(BusInformation
);
2574 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2576 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2577 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2578 DeviceNode
->ChildBusTypeIndex
= -1;
2581 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2583 Status
= IopInitiatePnpIrp(
2584 DeviceNode
->PhysicalDeviceObject
,
2586 IRP_MN_QUERY_RESOURCES
,
2588 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2590 DeviceNode
->BootResources
=
2591 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2592 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
2596 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2597 DeviceNode
->BootResources
= NULL
;
2600 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2602 Status
= IopInitiatePnpIrp(
2603 DeviceNode
->PhysicalDeviceObject
,
2605 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2607 if (NT_SUCCESS(Status
))
2609 DeviceNode
->ResourceRequirements
=
2610 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2611 if (IoStatusBlock
.Information
)
2612 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2614 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2618 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2619 DeviceNode
->ResourceRequirements
= NULL
;
2623 if (InstanceKey
!= NULL
)
2625 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2628 ZwClose(InstanceKey
);
2630 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
2632 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
2634 /* Report the device to the user-mode pnp manager */
2635 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
2636 &DeviceNode
->InstancePath
);
2639 return STATUS_SUCCESS
;
2645 IN PDEVICE_OBJECT DeviceObject
)
2647 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2648 DEVICETREE_TRAVERSE_CONTEXT Context
;
2649 PDEVICE_RELATIONS DeviceRelations
;
2650 PDEVICE_OBJECT ChildDeviceObject
;
2651 IO_STATUS_BLOCK IoStatusBlock
;
2652 PDEVICE_NODE ChildDeviceNode
;
2653 IO_STACK_LOCATION Stack
;
2657 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2659 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
2661 /* Report the device to the user-mode pnp manager */
2662 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2663 &DeviceNode
->InstancePath
);
2665 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2667 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
2669 Status
= IopInitiatePnpIrp(
2672 IRP_MN_QUERY_DEVICE_RELATIONS
,
2674 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
2676 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2680 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2682 if (!DeviceRelations
)
2684 DPRINT("No PDOs\n");
2685 return STATUS_UNSUCCESSFUL
;
2688 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
2691 * Create device nodes for all discovered devices
2693 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2695 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
2696 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
2698 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
2699 if (!ChildDeviceNode
)
2701 /* One doesn't exist, create it */
2702 Status
= IopCreateDeviceNode(
2707 if (NT_SUCCESS(Status
))
2709 /* Mark the node as enumerated */
2710 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2712 /* Mark the DO as bus enumerated */
2713 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2717 /* Ignore this DO */
2718 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
2719 ObDereferenceObject(ChildDeviceNode
);
2724 /* Mark it as enumerated */
2725 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2726 ObDereferenceObject(ChildDeviceObject
);
2729 ExFreePool(DeviceRelations
);
2732 * Retrieve information about all discovered children from the bus driver
2734 IopInitDeviceTreeTraverseContext(
2737 IopActionInterrogateDeviceStack
,
2740 Status
= IopTraverseDeviceTree(&Context
);
2741 if (!NT_SUCCESS(Status
))
2743 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2748 * Retrieve configuration from the registry for discovered children
2750 IopInitDeviceTreeTraverseContext(
2753 IopActionConfigureChildServices
,
2756 Status
= IopTraverseDeviceTree(&Context
);
2757 if (!NT_SUCCESS(Status
))
2759 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2764 * Initialize services for discovered children.
2766 Status
= IopInitializePnpServices(DeviceNode
);
2767 if (!NT_SUCCESS(Status
))
2769 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2773 DPRINT("IopEnumerateDevice() finished\n");
2774 return STATUS_SUCCESS
;
2779 * IopActionConfigureChildServices
2781 * Retrieve configuration for all (direct) child nodes of a parent node.
2785 * Pointer to device node.
2787 * Pointer to parent node to retrieve child node configuration for.
2790 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2791 * when we reach a device node which is not a direct child of the device
2792 * node for which we configure child services for. Any errors that occur is
2793 * logged instead so that all child services have a chance of beeing
2798 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2801 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2802 PDEVICE_NODE ParentDeviceNode
;
2803 PUNICODE_STRING Service
;
2804 UNICODE_STRING ClassGUID
;
2806 DEVICE_CAPABILITIES DeviceCaps
;
2808 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2810 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2813 * We are called for the parent too, but we don't need to do special
2814 * handling for this node
2816 if (DeviceNode
== ParentDeviceNode
)
2818 DPRINT("Success\n");
2819 return STATUS_SUCCESS
;
2823 * Make sure this device node is a direct child of the parent device node
2824 * that is given as an argument
2826 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2828 /* Stop the traversal immediately and indicate successful operation */
2830 return STATUS_UNSUCCESSFUL
;
2833 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2835 WCHAR RegKeyBuffer
[MAX_PATH
];
2836 UNICODE_STRING RegKey
;
2839 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2840 RegKey
.Buffer
= RegKeyBuffer
;
2843 * Retrieve configuration from Enum key
2846 Service
= &DeviceNode
->ServiceName
;
2848 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2849 RtlInitUnicodeString(Service
, NULL
);
2850 RtlInitUnicodeString(&ClassGUID
, NULL
);
2852 QueryTable
[0].Name
= L
"Service";
2853 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2854 QueryTable
[0].EntryContext
= Service
;
2856 QueryTable
[1].Name
= L
"ClassGUID";
2857 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2858 QueryTable
[1].EntryContext
= &ClassGUID
;
2859 QueryTable
[1].DefaultType
= REG_SZ
;
2860 QueryTable
[1].DefaultData
= L
"";
2861 QueryTable
[1].DefaultLength
= 0;
2863 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2864 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2866 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2867 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2869 if (!NT_SUCCESS(Status
))
2871 /* FIXME: Log the error */
2872 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2873 &DeviceNode
->InstancePath
, Status
);
2874 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2875 return STATUS_SUCCESS
;
2878 if (Service
->Buffer
== NULL
)
2880 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
2881 DeviceCaps
.RawDeviceOK
)
2883 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
2885 DeviceNode
->ServiceName
.Length
= 0;
2886 DeviceNode
->ServiceName
.MaximumLength
= 0;
2887 DeviceNode
->ServiceName
.Buffer
= NULL
;
2889 else if (ClassGUID
.Length
!= 0)
2891 /* Device has a ClassGUID value, but no Service value.
2892 * Suppose it is using the NULL driver, so state the
2893 * device is started */
2894 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2895 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2899 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2901 return STATUS_SUCCESS
;
2904 DPRINT("Got Service %S\n", Service
->Buffer
);
2907 return STATUS_SUCCESS
;
2911 * IopActionInitChildServices
2913 * Initialize the service for all (direct) child nodes of a parent node
2917 * Pointer to device node.
2919 * Pointer to parent node to initialize child node services for.
2922 * If the driver image for a service is not loaded and initialized
2923 * it is done here too. We only return a status code indicating an
2924 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2925 * not a direct child of the device node for which we initialize
2926 * child services for. Any errors that occur is logged instead so
2927 * that all child services have a chance of being initialized.
2931 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2934 PDEVICE_NODE ParentDeviceNode
;
2936 BOOLEAN BootDrivers
= !PnpSystemInit
;
2938 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2940 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2943 * We are called for the parent too, but we don't need to do special
2944 * handling for this node
2946 if (DeviceNode
== ParentDeviceNode
)
2948 DPRINT("Success\n");
2949 return STATUS_SUCCESS
;
2953 * Make sure this device node is a direct child of the parent device node
2954 * that is given as an argument
2957 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2960 * Stop the traversal immediately and indicate unsuccessful operation
2963 return STATUS_UNSUCCESSFUL
;
2966 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
2967 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
2968 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2969 return STATUS_SUCCESS
;
2971 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
2973 /* We don't need to worry about loading the driver because we're
2974 * being driven in raw mode so our parent must be loaded to get here */
2975 Status
= IopStartDevice(DeviceNode
);
2976 if (!NT_SUCCESS(Status
))
2978 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
2979 &DeviceNode
->InstancePath
, Status
);
2984 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2985 PDRIVER_OBJECT DriverObject
;
2987 /* Get existing DriverObject pointer (in case the driver has
2988 already been loaded and initialized) */
2989 Status
= IopGetDriverObject(
2991 &DeviceNode
->ServiceName
,
2994 if (!NT_SUCCESS(Status
))
2996 /* Driver is not initialized, try to load it */
2997 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2999 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
3001 /* STATUS_IMAGE_ALREADY_LOADED means this driver
3002 was loaded by the bootloader */
3003 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
3004 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
3006 /* Initialize the driver */
3007 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
3008 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
3012 Status
= STATUS_SUCCESS
;
3017 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
3018 &DeviceNode
->ServiceName
, Status
);
3022 /* Driver is loaded and initialized at this point */
3023 if (NT_SUCCESS(Status
))
3025 /* Initialize the device, including all filters */
3026 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
3031 * Don't disable when trying to load only boot drivers
3035 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
3036 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
3037 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
3038 DPRINT1("Initialization of service %S failed (Status %x)\n",
3039 DeviceNode
->ServiceName
.Buffer
, Status
);
3044 return STATUS_SUCCESS
;
3048 * IopInitializePnpServices
3050 * Initialize services for discovered children
3054 * Top device node to start initializing services.
3060 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
3062 DEVICETREE_TRAVERSE_CONTEXT Context
;
3064 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
3066 IopInitDeviceTreeTraverseContext(
3069 IopActionInitChildServices
,
3072 return IopTraverseDeviceTree(&Context
);
3075 static NTSTATUS INIT_FUNCTION
3076 IopEnumerateDetectedDevices(
3078 IN PUNICODE_STRING RelativePath OPTIONAL
,
3080 IN BOOLEAN EnumerateSubKeys
,
3081 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
3082 IN ULONG ParentBootResourcesLength
)
3084 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3085 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3086 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
3087 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
3088 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
3089 OBJECT_ATTRIBUTES ObjectAttributes
;
3090 HANDLE hDevicesKey
= NULL
;
3091 HANDLE hDeviceKey
= NULL
;
3092 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
3093 UNICODE_STRING Level2NameU
;
3094 WCHAR Level2Name
[5];
3095 ULONG IndexDevice
= 0;
3097 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3098 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3099 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3100 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3101 UNICODE_STRING DeviceName
, ValueName
;
3103 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
3104 ULONG BootResourcesLength
;
3107 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
3108 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
3109 static ULONG DeviceIndexPci
= 0;
3110 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
3111 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
3112 static ULONG DeviceIndexSerial
= 0;
3113 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
3114 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
3115 static ULONG DeviceIndexKeyboard
= 0;
3116 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
3117 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
3118 static ULONG DeviceIndexMouse
= 0;
3119 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
3120 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
3121 static ULONG DeviceIndexParallel
= 0;
3122 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
3123 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
3124 static ULONG DeviceIndexFloppy
= 0;
3125 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
3126 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
3127 static ULONG DeviceIndexIsa
= 0;
3128 UNICODE_STRING HardwareIdKey
;
3129 PUNICODE_STRING pHardwareId
;
3130 ULONG DeviceIndex
= 0;
3131 PUCHAR CmResourceList
;
3136 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
3137 if (!NT_SUCCESS(Status
))
3139 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3144 hDevicesKey
= hBaseKey
;
3146 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3147 if (!pDeviceInformation
)
3149 DPRINT("ExAllocatePool() failed\n");
3150 Status
= STATUS_NO_MEMORY
;
3154 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3155 if (!pValueInformation
)
3157 DPRINT("ExAllocatePool() failed\n");
3158 Status
= STATUS_NO_MEMORY
;
3164 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3165 if (Status
== STATUS_NO_MORE_ENTRIES
)
3167 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3169 ExFreePool(pDeviceInformation
);
3170 DeviceInfoLength
= RequiredSize
;
3171 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3172 if (!pDeviceInformation
)
3174 DPRINT("ExAllocatePool() failed\n");
3175 Status
= STATUS_NO_MEMORY
;
3178 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3180 if (!NT_SUCCESS(Status
))
3182 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3187 /* Open device key */
3188 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
3189 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3191 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
3192 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
3193 if (!NT_SUCCESS(Status
))
3195 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3199 /* Read boot resources, and add then to parent ones */
3200 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3201 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3203 ExFreePool(pValueInformation
);
3204 ValueInfoLength
= RequiredSize
;
3205 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3206 if (!pValueInformation
)
3208 DPRINT("ExAllocatePool() failed\n");
3209 ZwDeleteKey(hLevel2Key
);
3210 Status
= STATUS_NO_MEMORY
;
3213 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3215 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3217 BootResources
= ParentBootResources
;
3218 BootResourcesLength
= ParentBootResourcesLength
;
3220 else if (!NT_SUCCESS(Status
))
3222 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3225 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
3227 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
3232 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
3234 /* Concatenate current resources and parent ones */
3235 if (ParentBootResourcesLength
== 0)
3236 BootResourcesLength
= pValueInformation
->DataLength
;
3238 BootResourcesLength
= ParentBootResourcesLength
3239 + pValueInformation
->DataLength
3241 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
3244 DPRINT("ExAllocatePool() failed\n");
3247 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
3249 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
3251 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
3253 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
3255 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
3256 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
3257 ParentBootResourcesLength
- Header
);
3258 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
3262 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
3264 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
3265 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
3266 ParentBootResourcesLength
- Header
);
3268 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
3269 pValueInformation
->Data
+ Header
,
3270 pValueInformation
->DataLength
- Header
);
3271 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
3275 if (EnumerateSubKeys
)
3280 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3281 if (Status
== STATUS_NO_MORE_ENTRIES
)
3283 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3285 ExFreePool(pDeviceInformation
);
3286 DeviceInfoLength
= RequiredSize
;
3287 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3288 if (!pDeviceInformation
)
3290 DPRINT("ExAllocatePool() failed\n");
3291 Status
= STATUS_NO_MEMORY
;
3294 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3296 if (!NT_SUCCESS(Status
))
3298 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3302 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
3303 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3305 Status
= IopEnumerateDetectedDevices(
3311 BootResourcesLength
);
3312 if (!NT_SUCCESS(Status
))
3317 /* Read identifier */
3318 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3319 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3321 ExFreePool(pValueInformation
);
3322 ValueInfoLength
= RequiredSize
;
3323 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3324 if (!pValueInformation
)
3326 DPRINT("ExAllocatePool() failed\n");
3327 Status
= STATUS_NO_MEMORY
;
3330 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3332 if (!NT_SUCCESS(Status
))
3334 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
3336 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3339 ValueName
.Length
= ValueName
.MaximumLength
= 0;
3341 else if (pValueInformation
->Type
!= REG_SZ
)
3343 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3348 /* Assign hardware id to this device */
3349 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
3350 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3351 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3352 ValueName
.Length
-= sizeof(WCHAR
);
3355 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
3357 pHardwareId
= &HardwareIdSerial
;
3358 DeviceIndex
= DeviceIndexSerial
++;
3360 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
3362 pHardwareId
= &HardwareIdKeyboard
;
3363 DeviceIndex
= DeviceIndexKeyboard
++;
3365 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
3367 pHardwareId
= &HardwareIdMouse
;
3368 DeviceIndex
= DeviceIndexMouse
++;
3370 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
3372 pHardwareId
= &HardwareIdParallel
;
3373 DeviceIndex
= DeviceIndexParallel
++;
3375 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
3377 pHardwareId
= &HardwareIdFloppy
;
3378 DeviceIndex
= DeviceIndexFloppy
++;
3380 else if (NT_SUCCESS(Status
))
3382 /* Try to also match the device identifier */
3383 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
3385 pHardwareId
= &HardwareIdPci
;
3386 DeviceIndex
= DeviceIndexPci
++;
3388 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
3390 pHardwareId
= &HardwareIdIsa
;
3391 DeviceIndex
= DeviceIndexIsa
++;
3395 DPRINT("Unknown device '%wZ'\n", &ValueName
);
3401 /* Unknown key path */
3402 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
3406 /* Prepare hardware id key (hardware id value without final \0) */
3407 HardwareIdKey
= *pHardwareId
;
3408 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
3410 /* Add the detected device to Root key */
3411 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
3412 Status
= ZwCreateKey(
3418 REG_OPTION_NON_VOLATILE
,
3420 if (!NT_SUCCESS(Status
))
3422 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3425 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
3426 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
3427 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
3428 Status
= ZwCreateKey(
3430 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3434 REG_OPTION_NON_VOLATILE
,
3436 ZwClose(hLevel1Key
);
3437 if (!NT_SUCCESS(Status
))
3439 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3442 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
3443 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3444 if (!NT_SUCCESS(Status
))
3446 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3447 ZwDeleteKey(hLevel2Key
);
3450 /* Create 'LogConf' subkey */
3451 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3452 Status
= ZwCreateKey(
3458 REG_OPTION_VOLATILE
,
3460 if (!NT_SUCCESS(Status
))
3462 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3463 ZwDeleteKey(hLevel2Key
);
3466 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
3468 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
3469 if (!CmResourceList
)
3472 ZwDeleteKey(hLevel2Key
);
3476 /* Add the list count (1st member of CM_RESOURCE_LIST) */
3478 RtlCopyMemory(CmResourceList
,
3482 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
3483 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
3485 BootResourcesLength
);
3487 /* Save boot resources to 'LogConf\BootConfig' */
3488 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
3489 if (!NT_SUCCESS(Status
))
3491 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3493 ZwDeleteKey(hLevel2Key
);
3500 if (BootResources
&& BootResources
!= ParentBootResources
)
3502 ExFreePool(BootResources
);
3503 BootResources
= NULL
;
3507 ZwClose(hLevel2Key
);
3512 ZwClose(hDeviceKey
);
3517 Status
= STATUS_SUCCESS
;
3520 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
3521 ZwClose(hDevicesKey
);
3523 ZwClose(hDeviceKey
);
3524 if (pDeviceInformation
)
3525 ExFreePool(pDeviceInformation
);
3526 if (pValueInformation
)
3527 ExFreePool(pValueInformation
);
3531 static BOOLEAN INIT_FUNCTION
3532 IopIsAcpiComputer(VOID
)
3537 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3538 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3539 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3540 OBJECT_ATTRIBUTES ObjectAttributes
;
3541 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3542 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3543 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3544 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3546 ULONG IndexDevice
= 0;
3547 UNICODE_STRING DeviceName
, ValueName
;
3548 HANDLE hDevicesKey
= NULL
;
3549 HANDLE hDeviceKey
= NULL
;
3551 BOOLEAN ret
= FALSE
;
3553 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3554 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3555 if (!NT_SUCCESS(Status
))
3557 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3561 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3562 if (!pDeviceInformation
)
3564 DPRINT("ExAllocatePool() failed\n");
3565 Status
= STATUS_NO_MEMORY
;
3569 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3570 if (!pDeviceInformation
)
3572 DPRINT("ExAllocatePool() failed\n");
3573 Status
= STATUS_NO_MEMORY
;
3579 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3580 if (Status
== STATUS_NO_MORE_ENTRIES
)
3582 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3584 ExFreePool(pDeviceInformation
);
3585 DeviceInfoLength
= RequiredSize
;
3586 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3587 if (!pDeviceInformation
)
3589 DPRINT("ExAllocatePool() failed\n");
3590 Status
= STATUS_NO_MEMORY
;
3593 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3595 if (!NT_SUCCESS(Status
))
3597 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3602 /* Open device key */
3603 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3604 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3605 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3610 if (!NT_SUCCESS(Status
))
3612 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3616 /* Read identifier */
3617 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3618 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3620 ExFreePool(pValueInformation
);
3621 ValueInfoLength
= RequiredSize
;
3622 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3623 if (!pValueInformation
)
3625 DPRINT("ExAllocatePool() failed\n");
3626 Status
= STATUS_NO_MEMORY
;
3629 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3631 if (!NT_SUCCESS(Status
))
3633 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3636 else if (pValueInformation
->Type
!= REG_SZ
)
3638 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3642 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3643 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3644 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3645 ValueName
.Length
-= sizeof(WCHAR
);
3646 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3648 DPRINT("Found ACPI BIOS\n");
3654 ZwClose(hDeviceKey
);
3659 if (pDeviceInformation
)
3660 ExFreePool(pDeviceInformation
);
3661 if (pValueInformation
)
3662 ExFreePool(pValueInformation
);
3664 ZwClose(hDevicesKey
);
3666 ZwClose(hDeviceKey
);
3673 IopUpdateRootKey(VOID
)
3675 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
3676 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
3677 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3678 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3679 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3680 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
3681 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3682 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3683 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3684 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3685 OBJECT_ATTRIBUTES ObjectAttributes
;
3686 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
3689 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3690 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3691 if (!NT_SUCCESS(Status
))
3693 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3697 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
3698 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3700 if (!NT_SUCCESS(Status
))
3702 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3706 if (IopIsAcpiComputer())
3708 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
3709 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3711 if (!NT_SUCCESS(Status
))
3713 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
3714 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3715 ZwClose(hHalAcpiDevice
);
3716 if (!NT_SUCCESS(Status
))
3718 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3719 if (NT_SUCCESS(Status
))
3720 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3721 if (NT_SUCCESS(Status
))
3723 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
3724 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3725 if (NT_SUCCESS(Status
))
3728 ZwClose(hHalAcpiId
);
3733 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
3734 if (!NT_SUCCESS(Status
))
3736 /* Nothing to do, don't return with an error status */
3737 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3739 return STATUS_SUCCESS
;
3741 Status
= IopEnumerateDetectedDevices(
3756 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
3758 PUNICODE_STRING Name
,
3759 ACCESS_MASK DesiredAccess
)
3761 OBJECT_ATTRIBUTES ObjectAttributes
;
3768 InitializeObjectAttributes(&ObjectAttributes
,
3770 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3774 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
3781 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
3782 IN HANDLE RootHandle OPTIONAL
,
3783 IN PUNICODE_STRING KeyName
,
3784 IN ACCESS_MASK DesiredAccess
,
3785 IN ULONG CreateOptions
,
3786 OUT PULONG Disposition OPTIONAL
)
3788 OBJECT_ATTRIBUTES ObjectAttributes
;
3789 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0, Length
;
3790 HANDLE HandleArray
[2];
3791 BOOLEAN Recursing
= TRUE
;
3793 UNICODE_STRING KeyString
;
3794 NTSTATUS Status
= STATUS_SUCCESS
;
3797 /* P1 is start, pp is end */
3798 p1
= KeyName
->Buffer
;
3799 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
3801 /* Create the target key */
3802 InitializeObjectAttributes(&ObjectAttributes
,
3804 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3807 Status
= ZwCreateKey(&HandleArray
[i
],
3815 /* Now we check if this failed */
3816 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
3818 /* Target key failed, so we'll need to create its parent. Setup array */
3819 HandleArray
[0] = NULL
;
3820 HandleArray
[1] = RootHandle
;
3822 /* Keep recursing for each missing parent */
3825 /* And if we're deep enough, close the last handle */
3826 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3828 /* We're setup to ping-pong between the two handle array entries */
3829 RootHandleIndex
= i
;
3832 /* Clear the one we're attempting to open now */
3833 HandleArray
[i
] = NULL
;
3835 /* Process the parent key name */
3836 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
3837 Length
= (p
- p1
) * sizeof(WCHAR
);
3839 /* Is there a parent name? */
3842 /* Build the unicode string for it */
3843 KeyString
.Buffer
= p1
;
3844 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
3846 /* Now try opening the parent */
3847 InitializeObjectAttributes(&ObjectAttributes
,
3849 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3850 HandleArray
[RootHandleIndex
],
3852 Status
= ZwCreateKey(&HandleArray
[i
],
3859 if (NT_SUCCESS(Status
))
3861 /* It worked, we have one more handle */
3866 /* Parent key creation failed, abandon loop */
3873 /* We don't have a parent name, probably corrupted key name */
3874 Status
= STATUS_INVALID_PARAMETER
;
3879 /* Now see if there's more parents to create */
3881 if ((p
== pp
) || (p1
== pp
))
3883 /* We're done, hopefully successfully, so stop */
3888 /* Outer loop check for handle nesting that requires closing the top handle */
3889 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3892 /* Check if we broke out of the loop due to success */
3893 if (NT_SUCCESS(Status
))
3895 /* Return the target handle (we closed all the parent ones) and disposition */
3896 *Handle
= HandleArray
[i
];
3897 if (Disposition
) *Disposition
= KeyDisposition
;
3900 /* Return the success state */
3906 IopGetRegistryValue(IN HANDLE Handle
,
3908 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
3910 UNICODE_STRING ValueString
;
3912 PKEY_VALUE_FULL_INFORMATION FullInformation
;
3916 RtlInitUnicodeString(&ValueString
, ValueName
);
3918 Status
= ZwQueryValueKey(Handle
,
3920 KeyValueFullInformation
,
3924 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
3925 (Status
!= STATUS_BUFFER_TOO_SMALL
))
3930 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
3931 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
3933 Status
= ZwQueryValueKey(Handle
,
3935 KeyValueFullInformation
,
3939 if (!NT_SUCCESS(Status
))
3941 ExFreePool(FullInformation
);
3945 *Information
= FullInformation
;
3946 return STATUS_SUCCESS
;
3949 RTL_GENERIC_COMPARE_RESULTS
3951 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3952 IN PVOID FirstStruct
,
3953 IN PVOID SecondStruct
)
3961 // The allocation function is called by the generic table package whenever
3962 // it needs to allocate memory for the table.
3967 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3977 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3986 PpInitializeDeviceReferenceTable(VOID
)
3988 /* Setup the guarded mutex and AVL table */
3989 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3990 RtlInitializeGenericTableAvl(
3991 &PpDeviceReferenceTable
,
3992 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3993 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3994 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
4002 /* Initialize the resource when accessing device registry data */
4003 ExInitializeResourceLite(&PpRegistryDeviceResource
);
4005 /* Setup the device reference AVL table */
4006 PpInitializeDeviceReferenceTable();
4014 /* Check the initialization phase */
4015 switch (ExpInitializationPhase
)
4020 return PiInitPhase0();
4026 //return PiInitPhase1();
4030 /* Don't know any other phase! Bugcheck! */
4031 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
4036 LONG IopNumberDeviceNodes
;
4040 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4042 PDEVICE_NODE DeviceNode
;
4046 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), 'donD');
4047 if (!DeviceNode
) return DeviceNode
;
4050 InterlockedIncrement(&IopNumberDeviceNodes
);
4053 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
4054 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
4055 DeviceNode
->BusNumber
= -1;
4056 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
4057 DeviceNode
->ChildBusNumber
= -1;
4058 DeviceNode
->ChildBusTypeIndex
= -1;
4059 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
4060 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
4061 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
4062 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
4063 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
4064 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
4066 /* Check if there is a PDO */
4067 if (PhysicalDeviceObject
)
4069 /* Link it and remove the init flag */
4070 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
4071 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
4072 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
4075 /* Return the node */
4079 /* PUBLIC FUNCTIONS **********************************************************/
4086 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
4087 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
4088 IN ULONG BufferLength
,
4089 OUT PVOID PropertyBuffer
,
4090 OUT PULONG ResultLength
)
4092 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
4093 DEVICE_CAPABILITIES DeviceCaps
;
4098 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
4099 ULONG RequiredLength
, ObjectNameInfoLength
;
4101 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
4105 if (DeviceNode
== NULL
)
4106 return STATUS_INVALID_DEVICE_REQUEST
;
4108 switch (DeviceProperty
)
4110 case DevicePropertyBusNumber
:
4111 Length
= sizeof(ULONG
);
4112 Data
= &DeviceNode
->ChildBusNumber
;
4115 /* Complete, untested */
4116 case DevicePropertyBusTypeGuid
:
4118 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
4119 (DeviceNode
->ChildBusTypeIndex
< PnpBusTypeGuidList
->GuidCount
))
4121 /* Return the GUID */
4122 *ResultLength
= sizeof(GUID
);
4124 /* Check if the buffer given was large enough */
4125 if (BufferLength
< *ResultLength
)
4127 return STATUS_BUFFER_TOO_SMALL
;
4131 RtlCopyMemory(PropertyBuffer
,
4132 &(PnpBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
4134 return STATUS_SUCCESS
;
4138 return STATUS_OBJECT_NAME_NOT_FOUND
;
4142 case DevicePropertyLegacyBusType
:
4143 Length
= sizeof(INTERFACE_TYPE
);
4144 Data
= &DeviceNode
->ChildInterfaceType
;
4147 case DevicePropertyAddress
:
4148 /* Query the device caps */
4149 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
4150 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= MAXULONG
))
4153 *ResultLength
= sizeof(ULONG
);
4155 /* Check if the buffer given was large enough */
4156 if (BufferLength
< *ResultLength
)
4158 return STATUS_BUFFER_TOO_SMALL
;
4161 /* Return address */
4162 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
4163 return STATUS_SUCCESS
;
4167 return STATUS_OBJECT_NAME_NOT_FOUND
;
4171 // case DevicePropertyUINumber:
4172 // if (DeviceNode->CapabilityFlags == NULL)
4173 // return STATUS_INVALID_DEVICE_REQUEST;
4174 // Length = sizeof(ULONG);
4175 // Data = &DeviceNode->CapabilityFlags->UINumber;
4178 case DevicePropertyClassName
:
4179 case DevicePropertyClassGuid
:
4180 case DevicePropertyDriverKeyName
:
4181 case DevicePropertyManufacturer
:
4182 case DevicePropertyFriendlyName
:
4183 case DevicePropertyHardwareID
:
4184 case DevicePropertyCompatibleIDs
:
4185 case DevicePropertyDeviceDescription
:
4186 case DevicePropertyLocationInformation
:
4187 case DevicePropertyUINumber
:
4189 LPCWSTR RegistryPropertyName
;
4190 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
4191 UNICODE_STRING ValueName
;
4192 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
4193 ULONG ValueInformationLength
;
4194 HANDLE KeyHandle
, EnumRootHandle
;
4197 switch (DeviceProperty
)
4199 case DevicePropertyClassName
:
4200 RegistryPropertyName
= L
"Class"; break;
4201 case DevicePropertyClassGuid
:
4202 RegistryPropertyName
= L
"ClassGuid"; break;
4203 case DevicePropertyDriverKeyName
:
4204 RegistryPropertyName
= L
"Driver"; break;
4205 case DevicePropertyManufacturer
:
4206 RegistryPropertyName
= L
"Mfg"; break;
4207 case DevicePropertyFriendlyName
:
4208 RegistryPropertyName
= L
"FriendlyName"; break;
4209 case DevicePropertyHardwareID
:
4210 RegistryPropertyName
= L
"HardwareID"; break;
4211 case DevicePropertyCompatibleIDs
:
4212 RegistryPropertyName
= L
"CompatibleIDs"; break;
4213 case DevicePropertyDeviceDescription
:
4214 RegistryPropertyName
= L
"DeviceDesc"; break;
4215 case DevicePropertyLocationInformation
:
4216 RegistryPropertyName
= L
"LocationInformation"; break;
4217 case DevicePropertyUINumber
:
4218 RegistryPropertyName
= L
"UINumber"; break;
4220 /* Should not happen */
4222 return STATUS_UNSUCCESSFUL
;
4225 DPRINT("Registry property %S\n", RegistryPropertyName
);
4228 Status
= IopOpenRegistryKeyEx(&EnumRootHandle
, NULL
,
4229 &EnumRoot
, KEY_READ
);
4230 if (!NT_SUCCESS(Status
))
4232 DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status
);
4236 /* Open instance key */
4237 Status
= IopOpenRegistryKeyEx(&KeyHandle
, EnumRootHandle
,
4238 &DeviceNode
->InstancePath
, KEY_READ
);
4239 if (!NT_SUCCESS(Status
))
4241 DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status
);
4242 ZwClose(EnumRootHandle
);
4246 /* Allocate buffer to read as much data as required by the caller */
4247 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
4248 Data
[0]) + BufferLength
;
4249 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
4250 if (!ValueInformation
)
4253 return STATUS_INSUFFICIENT_RESOURCES
;
4256 /* Read the value */
4257 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
4258 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
4259 KeyValuePartialInformation
, ValueInformation
,
4260 ValueInformationLength
,
4261 &ValueInformationLength
);
4265 *ResultLength
= ValueInformation
->DataLength
;
4267 if (!NT_SUCCESS(Status
))
4269 ExFreePool(ValueInformation
);
4270 if (Status
== STATUS_BUFFER_OVERFLOW
)
4271 return STATUS_BUFFER_TOO_SMALL
;
4272 DPRINT1("Problem: Status=0x%08x, ResultLength = %d\n", Status
, *ResultLength
);
4276 /* FIXME: Verify the value (NULL-terminated, correct format). */
4277 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
4278 ValueInformation
->DataLength
);
4279 ExFreePool(ValueInformation
);
4281 return STATUS_SUCCESS
;
4284 case DevicePropertyBootConfiguration
:
4286 if (DeviceNode
->BootResources
->Count
!= 0)
4288 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
4290 Data
= DeviceNode
->BootResources
;
4293 /* FIXME: use a translated boot configuration instead */
4294 case DevicePropertyBootConfigurationTranslated
:
4296 if (DeviceNode
->BootResources
->Count
!= 0)
4298 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
4300 Data
= DeviceNode
->BootResources
;
4303 case DevicePropertyEnumeratorName
:
4304 /* A buffer overflow can't happen here, since InstancePath
4305 * always contains the enumerator name followed by \\ */
4306 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
4308 Length
= (Ptr
- DeviceNode
->InstancePath
.Buffer
) * sizeof(WCHAR
);
4309 Data
= DeviceNode
->InstancePath
.Buffer
;
4312 case DevicePropertyPhysicalDeviceObjectName
:
4313 Status
= ObQueryNameString(DeviceNode
->PhysicalDeviceObject
,
4317 if (Status
== STATUS_SUCCESS
)
4322 else if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
4324 ObjectNameInfoLength
= RequiredLength
;
4325 ObjectNameInfo
= ExAllocatePool(PagedPool
, ObjectNameInfoLength
);
4326 if (!ObjectNameInfo
)
4327 return STATUS_INSUFFICIENT_RESOURCES
;
4329 Status
= ObQueryNameString(DeviceNode
->PhysicalDeviceObject
,
4331 ObjectNameInfoLength
,
4333 if (NT_SUCCESS(Status
))
4335 Length
= ObjectNameInfo
->Name
.Length
;
4336 Data
= ObjectNameInfo
->Name
.Buffer
;
4346 return STATUS_INVALID_PARAMETER_2
;
4349 /* Prepare returned values */
4350 *ResultLength
= Length
;
4351 if (BufferLength
< Length
)
4353 if (ObjectNameInfo
!= NULL
)
4354 ExFreePool(ObjectNameInfo
);
4356 return STATUS_BUFFER_TOO_SMALL
;
4358 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
4360 /* NULL terminate the string (if required) */
4361 if (DeviceProperty
== DevicePropertyEnumeratorName
||
4362 DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
4363 ((LPWSTR
)PropertyBuffer
)[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
4365 if (ObjectNameInfo
!= NULL
)
4366 ExFreePool(ObjectNameInfo
);
4368 return STATUS_SUCCESS
;
4376 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4382 * @name IoOpenDeviceRegistryKey
4384 * Open a registry key unique for a specified driver or device instance.
4386 * @param DeviceObject Device to get the registry key for.
4387 * @param DevInstKeyType Type of the key to return.
4388 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
4389 * @param DevInstRegKey Handle to the opened registry key on
4390 * successful return.
4398 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
4399 IN ULONG DevInstKeyType
,
4400 IN ACCESS_MASK DesiredAccess
,
4401 OUT PHANDLE DevInstRegKey
)
4403 static WCHAR RootKeyName
[] =
4404 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
4405 static WCHAR ProfileKeyName
[] =
4406 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
4407 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
4408 static WCHAR EnumKeyName
[] = L
"Enum\\";
4409 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
4410 ULONG KeyNameLength
;
4411 LPWSTR KeyNameBuffer
;
4412 UNICODE_STRING KeyName
;
4413 ULONG DriverKeyLength
;
4414 OBJECT_ATTRIBUTES ObjectAttributes
;
4415 PDEVICE_NODE DeviceNode
= NULL
;
4418 DPRINT("IoOpenDeviceRegistryKey() called\n");
4420 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
4422 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
4423 return STATUS_INVALID_PARAMETER
;
4427 * Calculate the length of the base key name. This is the full
4428 * name for driver key or the name excluding "Device Parameters"
4429 * subkey for device key.
4432 KeyNameLength
= sizeof(RootKeyName
);
4433 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4434 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
4435 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4437 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
4438 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4439 0, NULL
, &DriverKeyLength
);
4440 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
4442 KeyNameLength
+= DriverKeyLength
;
4446 DeviceNode
= IopGetDeviceNode(DeviceObject
);
4447 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
4448 DeviceNode
->InstancePath
.Length
;
4452 * Now allocate the buffer for the key name...
4455 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
4456 if (KeyNameBuffer
== NULL
)
4457 return STATUS_INSUFFICIENT_RESOURCES
;
4460 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
4461 KeyName
.Buffer
= KeyNameBuffer
;
4464 * ...and build the key name.
4467 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
4468 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
4470 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4471 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
4473 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4475 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
4476 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4477 DriverKeyLength
, KeyNameBuffer
+
4478 (KeyName
.Length
/ sizeof(WCHAR
)),
4480 if (!NT_SUCCESS(Status
))
4482 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
4483 ExFreePool(KeyNameBuffer
);
4486 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
4490 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
4491 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
4492 if (DeviceNode
->InstancePath
.Length
== 0)
4494 ExFreePool(KeyNameBuffer
);
4500 * Open the base key.
4502 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
4503 if (!NT_SUCCESS(Status
))
4505 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
4506 ExFreePool(KeyNameBuffer
);
4509 ExFreePool(KeyNameBuffer
);
4512 * For driver key we're done now.
4515 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4519 * Let's go further. For device key we must open "Device Parameters"
4520 * subkey and create it if it doesn't exist yet.
4523 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
4524 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
4525 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
4526 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
4527 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
4528 ZwClose(ObjectAttributes
.RootDirectory
);
4538 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4548 IoInvalidateDeviceRelations(
4549 IN PDEVICE_OBJECT DeviceObject
,
4550 IN DEVICE_RELATION_TYPE Type
)
4552 PIO_WORKITEM WorkItem
;
4553 PINVALIDATE_DEVICE_RELATION_DATA Data
;
4555 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
4558 WorkItem
= IoAllocateWorkItem(DeviceObject
);
4565 ObReferenceObject(DeviceObject
);
4566 Data
->DeviceObject
= DeviceObject
;
4568 Data
->WorkItem
= WorkItem
;
4572 IopAsynchronousInvalidateDeviceRelations
,
4582 IoSynchronousInvalidateDeviceRelations(
4583 IN PDEVICE_OBJECT DeviceObject
,
4584 IN DEVICE_RELATION_TYPE Type
)
4591 /* Enumerate the device */
4592 return IopEnumerateDevice(DeviceObject
);
4593 case PowerRelations
:
4594 /* Not handled yet */
4595 return STATUS_NOT_IMPLEMENTED
;
4596 case TargetDeviceRelation
:
4598 return STATUS_SUCCESS
;
4600 /* Ejection relations are not supported */
4601 return STATUS_NOT_SUPPORTED
;
4610 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
4612 IN PHYSICAL_ADDRESS BusAddress
,
4613 IN OUT PULONG AddressSpace
,
4614 OUT PPHYSICAL_ADDRESS TranslatedAddress
)