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 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
36 PDEVICE_OBJECT DeviceObject
;
37 DEVICE_RELATION_TYPE Type
;
38 PIO_WORKITEM WorkItem
;
39 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
41 /* FUNCTIONS *****************************************************************/
44 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
45 IN ULONG CreateOptions
,
50 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
52 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
57 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
58 PDRIVER_OBJECT DriverObject
)
65 /* Special case for bus driven devices */
66 DeviceNode
->Flags
|= DNF_ADDED
;
67 return STATUS_SUCCESS
;
70 if (!DriverObject
->DriverExtension
->AddDevice
)
72 DeviceNode
->Flags
|= DNF_LEGACY_DRIVER
;
75 if (DeviceNode
->Flags
& DNF_LEGACY_DRIVER
)
77 DeviceNode
->Flags
|= DNF_ADDED
+ DNF_STARTED
;
78 return STATUS_SUCCESS
;
81 /* This is a Plug and Play driver */
82 DPRINT("Plug and Play driver found\n");
83 ASSERT(DeviceNode
->PhysicalDeviceObject
);
85 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
86 &DriverObject
->DriverName
,
87 &DeviceNode
->InstancePath
);
88 Status
= DriverObject
->DriverExtension
->AddDevice(
89 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
90 if (!NT_SUCCESS(Status
))
92 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
96 /* Check if driver added a FDO above the PDO */
97 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
98 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
100 /* FIXME: What do we do? Unload the driver or just disable the device? */
101 DPRINT1("An FDO was not attached\n");
102 ObDereferenceObject(Fdo
);
103 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
104 return STATUS_UNSUCCESSFUL
;
107 /* Check if we have a ACPI device (needed for power management) */
108 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
110 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
112 /* There can be only one system power device */
113 if (!SystemPowerDeviceNodeCreated
)
115 PopSystemPowerDeviceNode
= DeviceNode
;
116 ObReferenceObject(PopSystemPowerDeviceNode
);
117 SystemPowerDeviceNodeCreated
= TRUE
;
121 ObDereferenceObject(Fdo
);
123 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
125 return STATUS_SUCCESS
;
130 IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
132 IO_STACK_LOCATION Stack
;
135 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
136 Stack
.MajorFunction
= IRP_MJ_PNP
;
137 Stack
.MinorFunction
= IRP_MN_REMOVE_DEVICE
;
139 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
140 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
145 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject
)
147 IO_STACK_LOCATION Stack
;
148 PDEVICE_NODE DeviceNode
;
152 /* Get the device node */
153 DeviceNode
= IopGetDeviceNode(DeviceObject
);
155 /* Build the I/O stack locaiton */
156 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
157 Stack
.MajorFunction
= IRP_MJ_PNP
;
158 Stack
.MinorFunction
= IRP_MN_START_DEVICE
;
160 /* Check if we didn't already report the resources */
161 if (!(DeviceNode
->Flags
& DNF_RESOURCE_REPORTED
))
164 Stack
.Parameters
.StartDevice
.AllocatedResources
=
165 DeviceNode
->ResourceList
;
166 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
=
167 DeviceNode
->ResourceListTranslated
;
170 /* I don't think we set this flag yet */
171 ASSERT(!(DeviceNode
->Flags
& DNF_STOPPED
));
174 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
175 if (!NT_SUCCESS(Status
))
177 /* Send an IRP_MN_REMOVE_DEVICE request */
178 IopSendRemoveDevice(DeviceObject
);
180 /* Set the appropriate flag */
181 DeviceNode
->Flags
|= DNF_START_FAILED
;
183 DPRINT1("Warning: PnP Start failed (%wZ)\n", &DeviceNode
->InstancePath
);
187 /* Otherwise, mark us as started */
188 DeviceNode
->Flags
|= DNF_STARTED
;
190 /* We now need enumeration */
191 DeviceNode
->Flags
|= DNF_NEED_ENUMERATION_ONLY
;
196 IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode
)
198 PDEVICE_OBJECT DeviceObject
;
203 ASSERT((DeviceNode
->Flags
& DNF_ADDED
));
204 ASSERT((DeviceNode
->Flags
& (DNF_RESOURCE_ASSIGNED
|
205 DNF_RESOURCE_REPORTED
|
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 */
223 if (DeviceNode
->Flags
& DNF_NEED_QUERY_IDS
)
225 DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
226 /* And that case shouldn't happen yet */
231 /* Make sure we're started, and check if we need enumeration */
232 if ((DeviceNode
->Flags
& DNF_STARTED
) &&
233 (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
))
236 IoSynchronousInvalidateDeviceRelations(DeviceObject
, BusRelations
);
237 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
238 Status
= STATUS_SUCCESS
;
243 Status
= STATUS_SUCCESS
;
252 PDEVICE_NODE DeviceNode
)
255 HANDLE InstanceHandle
= INVALID_HANDLE_VALUE
, ControlHandle
= INVALID_HANDLE_VALUE
;
256 UNICODE_STRING KeyName
;
257 OBJECT_ATTRIBUTES ObjectAttributes
;
259 if (DeviceNode
->Flags
& (DNF_STARTED
| DNF_START_REQUEST_PENDING
))
261 /* Nothing to do here */
262 return STATUS_SUCCESS
;
265 Status
= IopAssignDeviceResources(DeviceNode
);
266 if (!NT_SUCCESS(Status
))
270 IopStartAndEnumerateDevice(DeviceNode
);
272 /* FIX: Should be done in new device instance code */
273 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceHandle
);
274 if (!NT_SUCCESS(Status
))
277 /* FIX: Should be done in IoXxxPrepareDriverLoading */
279 RtlInitUnicodeString(&KeyName
, L
"Control");
280 InitializeObjectAttributes(&ObjectAttributes
,
282 OBJ_CASE_INSENSITIVE
,
285 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
286 if (!NT_SUCCESS(Status
))
289 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
290 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
294 if (ControlHandle
!= INVALID_HANDLE_VALUE
)
295 ZwClose(ControlHandle
);
297 if (InstanceHandle
!= INVALID_HANDLE_VALUE
)
298 ZwClose(InstanceHandle
);
305 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
306 PDEVICE_CAPABILITIES DeviceCaps
)
308 IO_STATUS_BLOCK StatusBlock
;
309 IO_STACK_LOCATION Stack
;
311 /* Set up the Header */
312 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
313 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
314 DeviceCaps
->Version
= 1;
315 DeviceCaps
->Address
= -1;
316 DeviceCaps
->UINumber
= -1;
318 /* Set up the Stack */
319 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
320 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
323 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
325 IRP_MN_QUERY_CAPABILITIES
,
330 IopAsynchronousInvalidateDeviceRelations(
331 IN PDEVICE_OBJECT DeviceObject
,
332 IN PVOID InvalidateContext
)
334 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
336 IoSynchronousInvalidateDeviceRelations(
340 ObDereferenceObject(Data
->DeviceObject
);
341 IoFreeWorkItem(Data
->WorkItem
);
346 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
350 if (PopSystemPowerDeviceNode
)
352 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
353 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
354 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
356 return STATUS_SUCCESS
;
359 return STATUS_UNSUCCESSFUL
;
364 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
366 USHORT i
= 0, FoundIndex
= 0xFFFF;
370 /* Acquire the lock */
371 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
373 /* Loop all entries */
374 while (i
< PnpBusTypeGuidList
->GuidCount
)
376 /* Try to find a match */
377 if (RtlCompareMemory(BusTypeGuid
,
378 &PnpBusTypeGuidList
->Guids
[i
],
379 sizeof(GUID
)) == sizeof(GUID
))
388 /* Check if we have to grow the list */
389 if (PnpBusTypeGuidList
->GuidCount
)
391 /* Calculate the new size */
392 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
393 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
395 /* Allocate the new copy */
396 NewList
= ExAllocatePool(PagedPool
, NewSize
);
400 ExFreePool(PnpBusTypeGuidList
);
404 /* Now copy them, decrease the size too */
405 NewSize
-= sizeof(GUID
);
406 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
408 /* Free the old list */
409 ExFreePool(PnpBusTypeGuidList
);
411 /* Use the new buffer */
412 PnpBusTypeGuidList
= NewList
;
415 /* Copy the new GUID */
416 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
420 /* The new entry is the index */
421 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
422 PnpBusTypeGuidList
->GuidCount
++;
425 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
431 * Creates a device node
434 * ParentNode = Pointer to parent device node
435 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
436 * to have the root device node create one
437 * (eg. for legacy drivers)
438 * DeviceNode = Pointer to storage for created device node
444 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
445 PDEVICE_OBJECT PhysicalDeviceObject
,
446 PUNICODE_STRING ServiceName
,
447 PDEVICE_NODE
*DeviceNode
)
452 UNICODE_STRING FullServiceName
;
453 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
454 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
455 UNICODE_STRING KeyName
, ClassName
;
456 PUNICODE_STRING ServiceName1
;
459 UNICODE_STRING ClassGUID
;
461 HANDLE InstanceHandle
;
463 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
464 ParentNode
, PhysicalDeviceObject
, ServiceName
);
466 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
469 return STATUS_INSUFFICIENT_RESOURCES
;
472 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
475 ServiceName1
= &UnknownDeviceName
;
477 ServiceName1
= ServiceName
;
479 if (!PhysicalDeviceObject
)
481 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
482 FullServiceName
.Length
= 0;
483 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
484 if (!FullServiceName
.Buffer
)
487 return STATUS_INSUFFICIENT_RESOURCES
;
490 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
491 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
493 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
494 if (!NT_SUCCESS(Status
))
496 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
501 /* Create the device key for legacy drivers */
502 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
503 if (!NT_SUCCESS(Status
))
505 ZwClose(InstanceHandle
);
507 ExFreePool(FullServiceName
.Buffer
);
511 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
512 if (!Node
->ServiceName
.Buffer
)
514 ZwClose(InstanceHandle
);
516 ExFreePool(FullServiceName
.Buffer
);
520 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
521 Node
->ServiceName
.Length
= 0;
523 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
527 RtlInitUnicodeString(&KeyName
, L
"Service");
528 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
531 if (NT_SUCCESS(Status
))
533 RtlInitUnicodeString(&KeyName
, L
"Legacy");
536 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
537 if (NT_SUCCESS(Status
))
539 RtlInitUnicodeString(&KeyName
, L
"Class");
541 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
542 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
);
544 if (NT_SUCCESS(Status
))
546 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
548 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
549 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
);
555 ZwClose(InstanceHandle
);
556 ExFreePool(FullServiceName
.Buffer
);
558 if (!NT_SUCCESS(Status
))
564 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
565 IopDeviceNodeSetFlag(Node
, DNF_ADDED
);
566 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
569 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
571 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
575 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
576 Node
->Parent
= ParentNode
;
577 Node
->Sibling
= ParentNode
->Child
;
578 ParentNode
->Child
= Node
;
579 if (ParentNode
->LastChild
== NULL
)
580 ParentNode
->LastChild
= Node
;
581 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
582 Node
->Level
= ParentNode
->Level
+ 1;
585 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
589 return STATUS_SUCCESS
;
593 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
596 PDEVICE_NODE PrevSibling
= NULL
;
598 /* All children must be deleted before a parent is deleted */
599 ASSERT(!DeviceNode
->Child
);
601 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
603 ASSERT(DeviceNode
->PhysicalDeviceObject
);
605 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
607 /* Get previous sibling */
608 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
610 PrevSibling
= DeviceNode
->Parent
->Child
;
611 while (PrevSibling
->Sibling
!= DeviceNode
)
612 PrevSibling
= PrevSibling
->Sibling
;
615 /* Unlink from parent if it exists */
616 if (DeviceNode
->Parent
)
618 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
620 DeviceNode
->Parent
->LastChild
= PrevSibling
;
622 PrevSibling
->Sibling
= NULL
;
624 if (DeviceNode
->Parent
->Child
== DeviceNode
)
625 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
628 /* Unlink from sibling list */
630 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
632 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
634 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
636 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
638 if (DeviceNode
->ResourceList
)
640 ExFreePool(DeviceNode
->ResourceList
);
643 if (DeviceNode
->ResourceListTranslated
)
645 ExFreePool(DeviceNode
->ResourceListTranslated
);
648 if (DeviceNode
->ResourceRequirements
)
650 ExFreePool(DeviceNode
->ResourceRequirements
);
653 if (DeviceNode
->BootResources
)
655 ExFreePool(DeviceNode
->BootResources
);
658 ExFreePool(DeviceNode
);
660 return STATUS_SUCCESS
;
665 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
666 IN PIO_STACK_LOCATION IoStackLocation
,
667 OUT PVOID
*Information
)
670 PIO_STACK_LOCATION IrpStack
;
671 IO_STATUS_BLOCK IoStatusBlock
;
674 PDEVICE_OBJECT TopDeviceObject
;
677 /* Call the top of the device stack */
678 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
680 /* Allocate an IRP */
681 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
682 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
684 /* Initialize to failure */
685 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
686 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
688 /* Initialize the event */
689 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
692 Irp
->UserIosb
= &IoStatusBlock
;
693 Irp
->UserEvent
= &Event
;
696 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
697 IoQueueThreadIrp(Irp
);
699 /* Copy-in the stack */
700 IrpStack
= IoGetNextIrpStackLocation(Irp
);
701 *IrpStack
= *IoStackLocation
;
703 /* Call the driver */
704 Status
= IoCallDriver(TopDeviceObject
, Irp
);
705 if (Status
== STATUS_PENDING
)
708 KeWaitForSingleObject(&Event
,
713 Status
= IoStatusBlock
.Status
;
716 /* Return the information */
717 *Information
= (PVOID
)IoStatusBlock
.Information
;
723 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
724 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
725 IN ULONG MinorFunction
,
726 IN PIO_STACK_LOCATION Stack OPTIONAL
)
728 IO_STACK_LOCATION IoStackLocation
;
730 /* Fill out the stack information */
731 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
732 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
733 IoStackLocation
.MinorFunction
= MinorFunction
;
737 RtlCopyMemory(&IoStackLocation
.Parameters
,
739 sizeof(Stack
->Parameters
));
742 /* Do the PnP call */
743 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
745 (PVOID
)&IoStatusBlock
->Information
);
746 return IoStatusBlock
->Status
;
750 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
752 PDEVICE_NODE ParentDeviceNode
;
753 PDEVICE_NODE ChildDeviceNode
;
756 /* Copy context data so we don't overwrite it in subsequent calls to this function */
757 ParentDeviceNode
= Context
->DeviceNode
;
759 /* Call the action routine */
760 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
761 if (!NT_SUCCESS(Status
))
766 /* Traversal of all children nodes */
767 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
768 ChildDeviceNode
!= NULL
;
769 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
771 /* Pass the current device node to the action routine */
772 Context
->DeviceNode
= ChildDeviceNode
;
774 Status
= IopTraverseDeviceTreeNode(Context
);
775 if (!NT_SUCCESS(Status
))
786 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
790 DPRINT("Context 0x%p\n", Context
);
792 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
793 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
795 /* Start from the specified device node */
796 Context
->DeviceNode
= Context
->FirstDeviceNode
;
798 /* Recursively traverse the device tree */
799 Status
= IopTraverseDeviceTreeNode(Context
);
800 if (Status
== STATUS_UNSUCCESSFUL
)
802 /* The action routine just wanted to terminate the traversal with status
803 code STATUS_SUCCESS */
804 Status
= STATUS_SUCCESS
;
812 * IopCreateDeviceKeyPath
814 * Creates a registry key
818 * Name of the key to be created.
820 * Handle to the newly created key
823 * This method can create nested trees, so parent of RegistryPath can
824 * be not existant, and will be created if needed.
828 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
829 IN ULONG CreateOptions
,
832 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
833 HANDLE hParent
= NULL
, hKey
;
834 OBJECT_ATTRIBUTES ObjectAttributes
;
835 UNICODE_STRING KeyName
;
836 LPCWSTR Current
, Last
;
843 /* Open root key for device instances */
844 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
845 if (!NT_SUCCESS(Status
))
847 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
851 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
852 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
854 /* Go up to the end of the string */
855 while (Current
<= Last
)
857 if (Current
!= Last
&& *Current
!= '\\')
859 /* Not the end of the string and not a separator */
864 /* Prepare relative key name */
865 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
866 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
867 DPRINT("Create '%wZ'\n", &KeyName
);
870 InitializeObjectAttributes(&ObjectAttributes
,
872 OBJ_CASE_INSENSITIVE
,
875 Status
= ZwCreateKey(&hKey
,
876 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
883 /* Close parent key handle, we don't need it anymore */
887 /* Key opening/creating failed? */
888 if (!NT_SUCCESS(Status
))
890 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
894 /* Check if it is the end of the string */
897 /* Yes, return success */
899 return STATUS_SUCCESS
;
902 /* Start with this new parent key */
905 KeyName
.Buffer
= (LPWSTR
)Current
;
908 return STATUS_UNSUCCESSFUL
;
912 IopSetDeviceInstanceData(HANDLE InstanceKey
,
913 PDEVICE_NODE DeviceNode
)
915 OBJECT_ATTRIBUTES ObjectAttributes
;
916 UNICODE_STRING KeyName
;
921 HANDLE ControlHandle
;
923 DPRINT("IopSetDeviceInstanceData() called\n");
925 /* Create the 'LogConf' key */
926 RtlInitUnicodeString(&KeyName
, L
"LogConf");
927 InitializeObjectAttributes(&ObjectAttributes
,
929 OBJ_CASE_INSENSITIVE
,
932 Status
= ZwCreateKey(&LogConfKey
,
939 if (NT_SUCCESS(Status
))
941 /* Set 'BootConfig' value */
942 if (DeviceNode
->BootResources
!= NULL
)
944 ResCount
= DeviceNode
->BootResources
->Count
;
947 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
948 Status
= ZwSetValueKey(LogConfKey
,
952 DeviceNode
->BootResources
,
953 PnpDetermineResourceListSize(DeviceNode
->BootResources
));
957 /* Set 'BasicConfigVector' value */
958 if (DeviceNode
->ResourceRequirements
!= NULL
&&
959 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
961 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
962 Status
= ZwSetValueKey(LogConfKey
,
965 REG_RESOURCE_REQUIREMENTS_LIST
,
966 DeviceNode
->ResourceRequirements
,
967 DeviceNode
->ResourceRequirements
->ListSize
);
973 /* Set the 'ConfigFlags' value */
974 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
975 Status
= ZwQueryValueKey(InstanceKey
,
977 KeyValueBasicInformation
,
981 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
983 /* Write the default value */
984 ULONG DefaultConfigFlags
= 0;
985 Status
= ZwSetValueKey(InstanceKey
,
990 sizeof(DefaultConfigFlags
));
993 /* Create the 'Control' key */
994 RtlInitUnicodeString(&KeyName
, L
"Control");
995 InitializeObjectAttributes(&ObjectAttributes
,
997 OBJ_CASE_INSENSITIVE
,
1000 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1002 if (NT_SUCCESS(Status
))
1003 ZwClose(ControlHandle
);
1005 DPRINT("IopSetDeviceInstanceData() done\n");
1011 * IopGetParentIdPrefix
1013 * Retrieve (or create) a string which identifies a device.
1017 * Pointer to device node.
1019 * Pointer to the string where is returned the parent node identifier
1022 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1023 * valid and its Buffer field is NULL-terminated. The caller needs to
1024 * to free the string with RtlFreeUnicodeString when it is no longer
1029 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1030 PUNICODE_STRING ParentIdPrefix
)
1032 ULONG KeyNameBufferLength
;
1033 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1034 UNICODE_STRING KeyName
;
1035 UNICODE_STRING KeyValue
;
1036 UNICODE_STRING ValueName
;
1041 /* HACK: As long as some devices have a NULL device
1042 * instance path, the following test is required :(
1044 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1046 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1047 &DeviceNode
->InstancePath
);
1048 return STATUS_UNSUCCESSFUL
;
1051 /* 1. Try to retrieve ParentIdPrefix from registry */
1052 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1053 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1054 if (!ParentIdPrefixInformation
)
1056 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1061 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1062 if (!KeyName
.Buffer
)
1064 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1068 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1070 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1071 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1073 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1074 if (!NT_SUCCESS(Status
))
1076 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1077 Status
= ZwQueryValueKey(
1079 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1080 KeyNameBufferLength
, &KeyNameBufferLength
);
1081 if (NT_SUCCESS(Status
))
1083 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1084 Status
= STATUS_UNSUCCESSFUL
;
1087 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1088 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1092 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1094 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1095 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1099 /* 2. Create the ParentIdPrefix value */
1100 crc32
= RtlComputeCrc32(0,
1101 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1102 DeviceNode
->Parent
->InstancePath
.Length
);
1104 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1105 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1107 /* 3. Try to write the ParentIdPrefix to registry */
1108 Status
= ZwSetValueKey(hKey
,
1112 (PVOID
)KeyValue
.Buffer
,
1113 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1116 if (NT_SUCCESS(Status
))
1118 /* Duplicate the string to return it */
1119 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1121 ExFreePool(ParentIdPrefixInformation
);
1122 RtlFreeUnicodeString(&KeyName
);
1130 * IopActionInterrogateDeviceStack
1132 * Retrieve information for all (direct) child nodes of a parent node.
1136 * Pointer to device node.
1138 * Pointer to parent node to retrieve child node information for.
1141 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1142 * when we reach a device node which is not a direct child of the device
1143 * node for which we retrieve information of child nodes for. Any errors
1144 * that occur is logged instead so that all child services have a chance
1145 * of being interrogated.
1149 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1152 IO_STATUS_BLOCK IoStatusBlock
;
1153 PDEVICE_NODE ParentDeviceNode
;
1154 WCHAR InstancePath
[MAX_PATH
];
1155 IO_STACK_LOCATION Stack
;
1160 ULONG RequiredLength
;
1162 HANDLE InstanceKey
= NULL
;
1163 UNICODE_STRING ValueName
;
1164 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1165 DEVICE_CAPABILITIES DeviceCapabilities
;
1167 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1168 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1170 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1173 * We are called for the parent too, but we don't need to do special
1174 * handling for this node
1177 if (DeviceNode
== ParentDeviceNode
)
1179 DPRINT("Success\n");
1180 return STATUS_SUCCESS
;
1184 * Make sure this device node is a direct child of the parent device node
1185 * that is given as an argument
1188 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1190 /* Stop the traversal immediately and indicate successful operation */
1192 return STATUS_UNSUCCESSFUL
;
1196 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1197 if (!NT_SUCCESS(Status
))
1199 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1204 * FIXME: For critical errors, cleanup and disable device, but always
1205 * return STATUS_SUCCESS.
1208 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1210 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1211 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1215 if (NT_SUCCESS(Status
))
1217 /* Copy the device id string */
1218 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1221 * FIXME: Check for valid characters, if there is invalid characters
1227 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1230 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1232 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1233 if (!NT_SUCCESS(Status
))
1235 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1238 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1240 if (!DeviceCapabilities
.UniqueID
)
1242 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1243 DPRINT("Instance ID is not unique\n");
1244 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1245 if (!NT_SUCCESS(Status
))
1247 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1251 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1253 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1254 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1258 if (NT_SUCCESS(Status
))
1260 /* Append the instance id string */
1261 wcscat(InstancePath
, L
"\\");
1262 if (ParentIdPrefix
.Length
> 0)
1264 /* Add information from parent bus device to InstancePath */
1265 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1266 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1267 wcscat(InstancePath
, L
"&");
1269 if (IoStatusBlock
.Information
)
1270 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1273 * FIXME: Check for valid characters, if there is invalid characters
1279 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1281 RtlFreeUnicodeString(&ParentIdPrefix
);
1283 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1285 DPRINT("No resources\n");
1286 /* FIXME: Cleanup and disable device */
1289 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1292 * Create registry key for the instance id, if it doesn't exist yet
1294 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
1295 if (!NT_SUCCESS(Status
))
1297 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1301 /* Set 'Capabilities' value */
1302 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1303 Status
= ZwSetValueKey(InstanceKey
,
1307 (PVOID
)&DeviceNode
->CapabilityFlags
,
1310 /* Set 'UINumber' value */
1311 if (DeviceCapabilities
.UINumber
!= MAXULONG
)
1313 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1314 Status
= ZwSetValueKey(InstanceKey
,
1318 &DeviceCapabilities
.UINumber
,
1323 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1325 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1326 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1330 if (NT_SUCCESS(Status
))
1333 * FIXME: Check for valid characters, if there is invalid characters
1337 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1338 DPRINT("Hardware IDs:\n");
1341 DPRINT(" %S\n", Ptr
);
1342 Length
= wcslen(Ptr
) + 1;
1345 TotalLength
+= Length
;
1347 DPRINT("TotalLength: %hu\n", TotalLength
);
1350 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1351 Status
= ZwSetValueKey(InstanceKey
,
1355 (PVOID
)IoStatusBlock
.Information
,
1356 (TotalLength
+ 1) * sizeof(WCHAR
));
1357 if (!NT_SUCCESS(Status
))
1359 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1364 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1367 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1369 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1370 Status
= IopInitiatePnpIrp(
1371 DeviceNode
->PhysicalDeviceObject
,
1375 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1378 * FIXME: Check for valid characters, if there is invalid characters
1382 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1383 DPRINT("Compatible IDs:\n");
1386 DPRINT(" %S\n", Ptr
);
1387 Length
= wcslen(Ptr
) + 1;
1390 TotalLength
+= Length
;
1392 DPRINT("TotalLength: %hu\n", TotalLength
);
1395 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1396 Status
= ZwSetValueKey(InstanceKey
,
1400 (PVOID
)IoStatusBlock
.Information
,
1401 (TotalLength
+ 1) * sizeof(WCHAR
));
1402 if (!NT_SUCCESS(Status
))
1404 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1409 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1412 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1414 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1415 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1416 Status
= IopInitiatePnpIrp(
1417 DeviceNode
->PhysicalDeviceObject
,
1419 IRP_MN_QUERY_DEVICE_TEXT
,
1421 /* This key is mandatory, so even if the Irp fails, we still write it */
1422 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1423 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1425 if (NT_SUCCESS(Status
) &&
1426 IoStatusBlock
.Information
&&
1427 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1429 /* This key is overriden when a driver is installed. Don't write the
1430 * new description if another one already exists */
1431 Status
= ZwSetValueKey(InstanceKey
,
1435 (PVOID
)IoStatusBlock
.Information
,
1436 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1440 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1441 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1443 Status
= ZwSetValueKey(InstanceKey
,
1448 DeviceDesc
.MaximumLength
);
1450 if (!NT_SUCCESS(Status
))
1452 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1458 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1460 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1461 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1462 Status
= IopInitiatePnpIrp(
1463 DeviceNode
->PhysicalDeviceObject
,
1465 IRP_MN_QUERY_DEVICE_TEXT
,
1467 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1469 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1470 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1471 Status
= ZwSetValueKey(InstanceKey
,
1475 (PVOID
)IoStatusBlock
.Information
,
1476 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1477 if (!NT_SUCCESS(Status
))
1479 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1484 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1487 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1489 Status
= IopInitiatePnpIrp(
1490 DeviceNode
->PhysicalDeviceObject
,
1492 IRP_MN_QUERY_BUS_INFORMATION
,
1494 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1496 PPNP_BUS_INFORMATION BusInformation
=
1497 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1499 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1500 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1501 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1502 ExFreePool(BusInformation
);
1506 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1508 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1509 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1510 DeviceNode
->ChildBusTypeIndex
= -1;
1513 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1515 Status
= IopInitiatePnpIrp(
1516 DeviceNode
->PhysicalDeviceObject
,
1518 IRP_MN_QUERY_RESOURCES
,
1520 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1522 DeviceNode
->BootResources
=
1523 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1524 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
1528 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1529 DeviceNode
->BootResources
= NULL
;
1532 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1534 Status
= IopInitiatePnpIrp(
1535 DeviceNode
->PhysicalDeviceObject
,
1537 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1539 if (NT_SUCCESS(Status
))
1541 DeviceNode
->ResourceRequirements
=
1542 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1546 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1547 DeviceNode
->ResourceRequirements
= NULL
;
1550 if (InstanceKey
!= NULL
)
1552 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1555 ZwClose(InstanceKey
);
1557 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1559 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1561 /* Report the device to the user-mode pnp manager */
1562 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1563 &DeviceNode
->InstancePath
);
1566 return STATUS_SUCCESS
;
1572 IN PDEVICE_OBJECT DeviceObject
)
1574 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1575 DEVICETREE_TRAVERSE_CONTEXT Context
;
1576 PDEVICE_RELATIONS DeviceRelations
;
1577 PDEVICE_OBJECT ChildDeviceObject
;
1578 IO_STATUS_BLOCK IoStatusBlock
;
1579 PDEVICE_NODE ChildDeviceNode
;
1580 IO_STACK_LOCATION Stack
;
1584 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1586 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1588 /* Report the device to the user-mode pnp manager */
1589 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1590 &DeviceNode
->InstancePath
);
1592 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1594 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1596 Status
= IopInitiatePnpIrp(
1599 IRP_MN_QUERY_DEVICE_RELATIONS
,
1601 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1603 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1607 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1609 if (!DeviceRelations
)
1611 DPRINT("No PDOs\n");
1612 return STATUS_UNSUCCESSFUL
;
1615 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1618 * Create device nodes for all discovered devices
1620 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1622 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1623 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1625 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1626 if (!ChildDeviceNode
)
1628 /* One doesn't exist, create it */
1629 Status
= IopCreateDeviceNode(
1634 if (NT_SUCCESS(Status
))
1636 /* Mark the node as enumerated */
1637 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1639 /* Mark the DO as bus enumerated */
1640 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1644 /* Ignore this DO */
1645 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1646 ObDereferenceObject(ChildDeviceNode
);
1651 /* Mark it as enumerated */
1652 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1653 ObDereferenceObject(ChildDeviceObject
);
1656 ExFreePool(DeviceRelations
);
1659 * Retrieve information about all discovered children from the bus driver
1661 IopInitDeviceTreeTraverseContext(
1664 IopActionInterrogateDeviceStack
,
1667 Status
= IopTraverseDeviceTree(&Context
);
1668 if (!NT_SUCCESS(Status
))
1670 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1675 * Retrieve configuration from the registry for discovered children
1677 IopInitDeviceTreeTraverseContext(
1680 IopActionConfigureChildServices
,
1683 Status
= IopTraverseDeviceTree(&Context
);
1684 if (!NT_SUCCESS(Status
))
1686 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1691 * Initialize services for discovered children.
1693 Status
= IopInitializePnpServices(DeviceNode
);
1694 if (!NT_SUCCESS(Status
))
1696 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1700 DPRINT("IopEnumerateDevice() finished\n");
1701 return STATUS_SUCCESS
;
1706 * IopActionConfigureChildServices
1708 * Retrieve configuration for all (direct) child nodes of a parent node.
1712 * Pointer to device node.
1714 * Pointer to parent node to retrieve child node configuration for.
1717 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1718 * when we reach a device node which is not a direct child of the device
1719 * node for which we configure child services for. Any errors that occur is
1720 * logged instead so that all child services have a chance of beeing
1725 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1728 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1729 PDEVICE_NODE ParentDeviceNode
;
1730 PUNICODE_STRING Service
;
1731 UNICODE_STRING ClassGUID
;
1733 DEVICE_CAPABILITIES DeviceCaps
;
1735 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1737 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1740 * We are called for the parent too, but we don't need to do special
1741 * handling for this node
1743 if (DeviceNode
== ParentDeviceNode
)
1745 DPRINT("Success\n");
1746 return STATUS_SUCCESS
;
1750 * Make sure this device node is a direct child of the parent device node
1751 * that is given as an argument
1753 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1755 /* Stop the traversal immediately and indicate successful operation */
1757 return STATUS_UNSUCCESSFUL
;
1760 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1762 WCHAR RegKeyBuffer
[MAX_PATH
];
1763 UNICODE_STRING RegKey
;
1766 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1767 RegKey
.Buffer
= RegKeyBuffer
;
1770 * Retrieve configuration from Enum key
1773 Service
= &DeviceNode
->ServiceName
;
1775 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1776 RtlInitUnicodeString(Service
, NULL
);
1777 RtlInitUnicodeString(&ClassGUID
, NULL
);
1779 QueryTable
[0].Name
= L
"Service";
1780 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1781 QueryTable
[0].EntryContext
= Service
;
1783 QueryTable
[1].Name
= L
"ClassGUID";
1784 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1785 QueryTable
[1].EntryContext
= &ClassGUID
;
1786 QueryTable
[1].DefaultType
= REG_SZ
;
1787 QueryTable
[1].DefaultData
= L
"";
1788 QueryTable
[1].DefaultLength
= 0;
1790 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1791 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1793 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1794 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1796 if (!NT_SUCCESS(Status
))
1798 /* FIXME: Log the error */
1799 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
1800 &DeviceNode
->InstancePath
, Status
);
1801 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1802 return STATUS_SUCCESS
;
1805 if (Service
->Buffer
== NULL
)
1807 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
1808 DeviceCaps
.RawDeviceOK
)
1810 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
1812 DeviceNode
->ServiceName
.Length
= 0;
1813 DeviceNode
->ServiceName
.MaximumLength
= 0;
1814 DeviceNode
->ServiceName
.Buffer
= NULL
;
1816 else if (ClassGUID
.Length
!= 0)
1818 /* Device has a ClassGUID value, but no Service value.
1819 * Suppose it is using the NULL driver, so state the
1820 * device is started */
1821 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
1822 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1826 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1828 return STATUS_SUCCESS
;
1831 DPRINT("Got Service %S\n", Service
->Buffer
);
1834 return STATUS_SUCCESS
;
1838 * IopActionInitChildServices
1840 * Initialize the service for all (direct) child nodes of a parent node
1844 * Pointer to device node.
1846 * Pointer to parent node to initialize child node services for.
1849 * If the driver image for a service is not loaded and initialized
1850 * it is done here too. We only return a status code indicating an
1851 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1852 * not a direct child of the device node for which we initialize
1853 * child services for. Any errors that occur is logged instead so
1854 * that all child services have a chance of being initialized.
1858 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
1861 PDEVICE_NODE ParentDeviceNode
;
1863 BOOLEAN BootDrivers
= !PnpSystemInit
;
1865 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
1867 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1870 * We are called for the parent too, but we don't need to do special
1871 * handling for this node
1873 if (DeviceNode
== ParentDeviceNode
)
1875 DPRINT("Success\n");
1876 return STATUS_SUCCESS
;
1880 * Make sure this device node is a direct child of the parent device node
1881 * that is given as an argument
1884 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1887 * Stop the traversal immediately and indicate unsuccessful operation
1890 return STATUS_UNSUCCESSFUL
;
1893 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
1894 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
1895 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1896 return STATUS_SUCCESS
;
1898 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
1900 /* We don't need to worry about loading the driver because we're
1901 * being driven in raw mode so our parent must be loaded to get here */
1902 Status
= IopInitializeDevice(DeviceNode
, NULL
);
1903 if (NT_SUCCESS(Status
))
1905 Status
= IopStartDevice(DeviceNode
);
1906 if (!NT_SUCCESS(Status
))
1908 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
1909 &DeviceNode
->InstancePath
, Status
);
1915 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1916 PDRIVER_OBJECT DriverObject
;
1918 /* Get existing DriverObject pointer (in case the driver has
1919 already been loaded and initialized) */
1920 Status
= IopGetDriverObject(
1922 &DeviceNode
->ServiceName
,
1925 if (!NT_SUCCESS(Status
))
1927 /* Driver is not initialized, try to load it */
1928 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1930 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
1932 /* STATUS_IMAGE_ALREADY_LOADED means this driver
1933 was loaded by the bootloader */
1934 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
1935 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
1937 /* Initialize the driver */
1938 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
1939 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
1943 Status
= STATUS_SUCCESS
;
1948 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
1949 &DeviceNode
->ServiceName
, Status
);
1953 /* Driver is loaded and initialized at this point */
1954 if (NT_SUCCESS(Status
))
1956 /* Initialize the device, including all filters */
1957 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
1962 * Don't disable when trying to load only boot drivers
1966 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1967 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1968 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1969 DPRINT1("Initialization of service %S failed (Status %x)\n",
1970 DeviceNode
->ServiceName
.Buffer
, Status
);
1975 return STATUS_SUCCESS
;
1979 * IopInitializePnpServices
1981 * Initialize services for discovered children
1985 * Top device node to start initializing services.
1991 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
1993 DEVICETREE_TRAVERSE_CONTEXT Context
;
1995 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
1997 IopInitDeviceTreeTraverseContext(
2000 IopActionInitChildServices
,
2003 return IopTraverseDeviceTree(&Context
);
2006 static NTSTATUS INIT_FUNCTION
2007 IopEnumerateDetectedDevices(
2009 IN PUNICODE_STRING RelativePath OPTIONAL
,
2011 IN BOOLEAN EnumerateSubKeys
,
2012 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2013 IN ULONG ParentBootResourcesLength
)
2015 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2016 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2017 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2018 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2019 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2020 OBJECT_ATTRIBUTES ObjectAttributes
;
2021 HANDLE hDevicesKey
= NULL
;
2022 HANDLE hDeviceKey
= NULL
;
2023 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2024 UNICODE_STRING Level2NameU
;
2025 WCHAR Level2Name
[5];
2026 ULONG IndexDevice
= 0;
2028 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2029 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2030 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2031 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2032 UNICODE_STRING DeviceName
, ValueName
;
2034 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2035 ULONG BootResourcesLength
;
2038 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2039 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2040 static ULONG DeviceIndexPci
= 0;
2041 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2042 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2043 static ULONG DeviceIndexSerial
= 0;
2044 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2045 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2046 static ULONG DeviceIndexKeyboard
= 0;
2047 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2048 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2049 static ULONG DeviceIndexMouse
= 0;
2050 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2051 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2052 static ULONG DeviceIndexParallel
= 0;
2053 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2054 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2055 static ULONG DeviceIndexFloppy
= 0;
2056 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2057 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2058 static ULONG DeviceIndexIsa
= 0;
2059 UNICODE_STRING HardwareIdKey
;
2060 PUNICODE_STRING pHardwareId
;
2061 ULONG DeviceIndex
= 0;
2062 PUCHAR CmResourceList
;
2067 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2068 if (!NT_SUCCESS(Status
))
2070 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2075 hDevicesKey
= hBaseKey
;
2077 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2078 if (!pDeviceInformation
)
2080 DPRINT("ExAllocatePool() failed\n");
2081 Status
= STATUS_NO_MEMORY
;
2085 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2086 if (!pValueInformation
)
2088 DPRINT("ExAllocatePool() failed\n");
2089 Status
= STATUS_NO_MEMORY
;
2095 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2096 if (Status
== STATUS_NO_MORE_ENTRIES
)
2098 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2100 ExFreePool(pDeviceInformation
);
2101 DeviceInfoLength
= RequiredSize
;
2102 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2103 if (!pDeviceInformation
)
2105 DPRINT("ExAllocatePool() failed\n");
2106 Status
= STATUS_NO_MEMORY
;
2109 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2111 if (!NT_SUCCESS(Status
))
2113 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2118 /* Open device key */
2119 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2120 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2122 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2123 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2124 if (!NT_SUCCESS(Status
))
2126 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2130 /* Read boot resources, and add then to parent ones */
2131 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2132 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2134 ExFreePool(pValueInformation
);
2135 ValueInfoLength
= RequiredSize
;
2136 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2137 if (!pValueInformation
)
2139 DPRINT("ExAllocatePool() failed\n");
2140 ZwDeleteKey(hLevel2Key
);
2141 Status
= STATUS_NO_MEMORY
;
2144 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2146 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2148 BootResources
= ParentBootResources
;
2149 BootResourcesLength
= ParentBootResourcesLength
;
2151 else if (!NT_SUCCESS(Status
))
2153 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2156 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2158 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2163 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2165 /* Concatenate current resources and parent ones */
2166 if (ParentBootResourcesLength
== 0)
2167 BootResourcesLength
= pValueInformation
->DataLength
;
2169 BootResourcesLength
= ParentBootResourcesLength
2170 + pValueInformation
->DataLength
2172 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2175 DPRINT("ExAllocatePool() failed\n");
2178 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2180 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2182 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2184 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2186 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2187 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2188 ParentBootResourcesLength
- Header
);
2189 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2193 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2195 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2196 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2197 ParentBootResourcesLength
- Header
);
2199 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2200 pValueInformation
->Data
+ Header
,
2201 pValueInformation
->DataLength
- Header
);
2202 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2206 if (EnumerateSubKeys
)
2211 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2212 if (Status
== STATUS_NO_MORE_ENTRIES
)
2214 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2216 ExFreePool(pDeviceInformation
);
2217 DeviceInfoLength
= RequiredSize
;
2218 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2219 if (!pDeviceInformation
)
2221 DPRINT("ExAllocatePool() failed\n");
2222 Status
= STATUS_NO_MEMORY
;
2225 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2227 if (!NT_SUCCESS(Status
))
2229 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2233 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2234 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2236 Status
= IopEnumerateDetectedDevices(
2242 BootResourcesLength
);
2243 if (!NT_SUCCESS(Status
))
2248 /* Read identifier */
2249 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2250 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2252 ExFreePool(pValueInformation
);
2253 ValueInfoLength
= RequiredSize
;
2254 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2255 if (!pValueInformation
)
2257 DPRINT("ExAllocatePool() failed\n");
2258 Status
= STATUS_NO_MEMORY
;
2261 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2263 if (!NT_SUCCESS(Status
))
2265 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2267 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2270 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2272 else if (pValueInformation
->Type
!= REG_SZ
)
2274 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2279 /* Assign hardware id to this device */
2280 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2281 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2282 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2283 ValueName
.Length
-= sizeof(WCHAR
);
2286 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2288 pHardwareId
= &HardwareIdSerial
;
2289 DeviceIndex
= DeviceIndexSerial
++;
2291 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2293 pHardwareId
= &HardwareIdKeyboard
;
2294 DeviceIndex
= DeviceIndexKeyboard
++;
2296 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2298 pHardwareId
= &HardwareIdMouse
;
2299 DeviceIndex
= DeviceIndexMouse
++;
2301 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
2303 pHardwareId
= &HardwareIdParallel
;
2304 DeviceIndex
= DeviceIndexParallel
++;
2306 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
2308 pHardwareId
= &HardwareIdFloppy
;
2309 DeviceIndex
= DeviceIndexFloppy
++;
2311 else if (NT_SUCCESS(Status
))
2313 /* Try to also match the device identifier */
2314 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2316 pHardwareId
= &HardwareIdPci
;
2317 DeviceIndex
= DeviceIndexPci
++;
2319 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
2321 pHardwareId
= &HardwareIdIsa
;
2322 DeviceIndex
= DeviceIndexIsa
++;
2326 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2332 /* Unknown key path */
2333 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2337 /* Prepare hardware id key (hardware id value without final \0) */
2338 HardwareIdKey
= *pHardwareId
;
2339 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2341 /* Add the detected device to Root key */
2342 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2343 Status
= ZwCreateKey(
2349 REG_OPTION_NON_VOLATILE
,
2351 if (!NT_SUCCESS(Status
))
2353 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2356 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2357 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2358 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2359 Status
= ZwCreateKey(
2361 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2365 REG_OPTION_NON_VOLATILE
,
2367 ZwClose(hLevel1Key
);
2368 if (!NT_SUCCESS(Status
))
2370 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2373 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
2374 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2375 if (!NT_SUCCESS(Status
))
2377 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2378 ZwDeleteKey(hLevel2Key
);
2381 /* Create 'LogConf' subkey */
2382 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2383 Status
= ZwCreateKey(
2389 REG_OPTION_VOLATILE
,
2391 if (!NT_SUCCESS(Status
))
2393 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2394 ZwDeleteKey(hLevel2Key
);
2397 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2399 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
2400 if (!CmResourceList
)
2403 ZwDeleteKey(hLevel2Key
);
2407 /* Add the list count (1st member of CM_RESOURCE_LIST) */
2409 RtlCopyMemory(CmResourceList
,
2413 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
2414 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
2416 BootResourcesLength
);
2418 /* Save boot resources to 'LogConf\BootConfig' */
2419 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
2420 if (!NT_SUCCESS(Status
))
2422 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2424 ZwDeleteKey(hLevel2Key
);
2431 if (BootResources
&& BootResources
!= ParentBootResources
)
2433 ExFreePool(BootResources
);
2434 BootResources
= NULL
;
2438 ZwClose(hLevel2Key
);
2443 ZwClose(hDeviceKey
);
2448 Status
= STATUS_SUCCESS
;
2451 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2452 ZwClose(hDevicesKey
);
2454 ZwClose(hDeviceKey
);
2455 if (pDeviceInformation
)
2456 ExFreePool(pDeviceInformation
);
2457 if (pValueInformation
)
2458 ExFreePool(pValueInformation
);
2462 static BOOLEAN INIT_FUNCTION
2463 IopIsAcpiComputer(VOID
)
2468 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2469 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2470 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2471 OBJECT_ATTRIBUTES ObjectAttributes
;
2472 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2473 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2474 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2475 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2477 ULONG IndexDevice
= 0;
2478 UNICODE_STRING DeviceName
, ValueName
;
2479 HANDLE hDevicesKey
= NULL
;
2480 HANDLE hDeviceKey
= NULL
;
2482 BOOLEAN ret
= FALSE
;
2484 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2485 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2486 if (!NT_SUCCESS(Status
))
2488 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2492 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2493 if (!pDeviceInformation
)
2495 DPRINT("ExAllocatePool() failed\n");
2496 Status
= STATUS_NO_MEMORY
;
2500 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2501 if (!pDeviceInformation
)
2503 DPRINT("ExAllocatePool() failed\n");
2504 Status
= STATUS_NO_MEMORY
;
2510 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2511 if (Status
== STATUS_NO_MORE_ENTRIES
)
2513 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2515 ExFreePool(pDeviceInformation
);
2516 DeviceInfoLength
= RequiredSize
;
2517 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2518 if (!pDeviceInformation
)
2520 DPRINT("ExAllocatePool() failed\n");
2521 Status
= STATUS_NO_MEMORY
;
2524 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2526 if (!NT_SUCCESS(Status
))
2528 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2533 /* Open device key */
2534 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2535 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2536 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2541 if (!NT_SUCCESS(Status
))
2543 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2547 /* Read identifier */
2548 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2549 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2551 ExFreePool(pValueInformation
);
2552 ValueInfoLength
= RequiredSize
;
2553 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2554 if (!pValueInformation
)
2556 DPRINT("ExAllocatePool() failed\n");
2557 Status
= STATUS_NO_MEMORY
;
2560 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2562 if (!NT_SUCCESS(Status
))
2564 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2567 else if (pValueInformation
->Type
!= REG_SZ
)
2569 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2573 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2574 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2575 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2576 ValueName
.Length
-= sizeof(WCHAR
);
2577 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
2579 DPRINT("Found ACPI BIOS\n");
2585 ZwClose(hDeviceKey
);
2590 if (pDeviceInformation
)
2591 ExFreePool(pDeviceInformation
);
2592 if (pValueInformation
)
2593 ExFreePool(pValueInformation
);
2595 ZwClose(hDevicesKey
);
2597 ZwClose(hDeviceKey
);
2605 IopUpdateRootKey(VOID
)
2607 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2608 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2609 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2610 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2611 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2612 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2613 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
2614 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
2615 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
2616 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2617 OBJECT_ATTRIBUTES ObjectAttributes
;
2618 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
2622 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2623 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2624 if (!NT_SUCCESS(Status
))
2626 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2630 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2631 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2633 if (!NT_SUCCESS(Status
))
2635 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2639 if (IopIsAcpiComputer())
2641 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
2642 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2644 if (!NT_SUCCESS(Status
))
2646 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
2647 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, 0, &Disposition
);
2648 ZwClose(hHalAcpiDevice
);
2649 if (!NT_SUCCESS(Status
))
2651 if (Disposition
== REG_CREATED_NEW_KEY
)
2653 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
2654 if (NT_SUCCESS(Status
))
2655 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
2657 if (NT_SUCCESS(Status
))
2659 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
2660 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2661 if (NT_SUCCESS(Status
))
2664 ZwClose(hHalAcpiId
);
2669 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2670 if (!NT_SUCCESS(Status
))
2672 /* Nothing to do, don't return with an error status */
2673 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2675 return STATUS_SUCCESS
;
2677 Status
= IopEnumerateDetectedDevices(
2692 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2694 PUNICODE_STRING Name
,
2695 ACCESS_MASK DesiredAccess
)
2697 OBJECT_ATTRIBUTES ObjectAttributes
;
2704 InitializeObjectAttributes(&ObjectAttributes
,
2706 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2710 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2717 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
2718 IN HANDLE RootHandle OPTIONAL
,
2719 IN PUNICODE_STRING KeyName
,
2720 IN ACCESS_MASK DesiredAccess
,
2721 IN ULONG CreateOptions
,
2722 OUT PULONG Disposition OPTIONAL
)
2724 OBJECT_ATTRIBUTES ObjectAttributes
;
2725 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0, Length
;
2726 HANDLE HandleArray
[2];
2727 BOOLEAN Recursing
= TRUE
;
2729 UNICODE_STRING KeyString
;
2730 NTSTATUS Status
= STATUS_SUCCESS
;
2733 /* P1 is start, pp is end */
2734 p1
= KeyName
->Buffer
;
2735 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
2737 /* Create the target key */
2738 InitializeObjectAttributes(&ObjectAttributes
,
2740 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2743 Status
= ZwCreateKey(&HandleArray
[i
],
2751 /* Now we check if this failed */
2752 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
2754 /* Target key failed, so we'll need to create its parent. Setup array */
2755 HandleArray
[0] = NULL
;
2756 HandleArray
[1] = RootHandle
;
2758 /* Keep recursing for each missing parent */
2761 /* And if we're deep enough, close the last handle */
2762 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2764 /* We're setup to ping-pong between the two handle array entries */
2765 RootHandleIndex
= i
;
2768 /* Clear the one we're attempting to open now */
2769 HandleArray
[i
] = NULL
;
2771 /* Process the parent key name */
2772 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
2773 Length
= (p
- p1
) * sizeof(WCHAR
);
2775 /* Is there a parent name? */
2778 /* Build the unicode string for it */
2779 KeyString
.Buffer
= p1
;
2780 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
2782 /* Now try opening the parent */
2783 InitializeObjectAttributes(&ObjectAttributes
,
2785 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2786 HandleArray
[RootHandleIndex
],
2788 Status
= ZwCreateKey(&HandleArray
[i
],
2795 if (NT_SUCCESS(Status
))
2797 /* It worked, we have one more handle */
2802 /* Parent key creation failed, abandon loop */
2809 /* We don't have a parent name, probably corrupted key name */
2810 Status
= STATUS_INVALID_PARAMETER
;
2815 /* Now see if there's more parents to create */
2817 if ((p
== pp
) || (p1
== pp
))
2819 /* We're done, hopefully successfully, so stop */
2824 /* Outer loop check for handle nesting that requires closing the top handle */
2825 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2828 /* Check if we broke out of the loop due to success */
2829 if (NT_SUCCESS(Status
))
2831 /* Return the target handle (we closed all the parent ones) and disposition */
2832 *Handle
= HandleArray
[i
];
2833 if (Disposition
) *Disposition
= KeyDisposition
;
2836 /* Return the success state */
2842 IopGetRegistryValue(IN HANDLE Handle
,
2844 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
2846 UNICODE_STRING ValueString
;
2848 PKEY_VALUE_FULL_INFORMATION FullInformation
;
2852 RtlInitUnicodeString(&ValueString
, ValueName
);
2854 Status
= ZwQueryValueKey(Handle
,
2856 KeyValueFullInformation
,
2860 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
2861 (Status
!= STATUS_BUFFER_TOO_SMALL
))
2866 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
2867 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
2869 Status
= ZwQueryValueKey(Handle
,
2871 KeyValueFullInformation
,
2875 if (!NT_SUCCESS(Status
))
2877 ExFreePool(FullInformation
);
2881 *Information
= FullInformation
;
2882 return STATUS_SUCCESS
;
2885 RTL_GENERIC_COMPARE_RESULTS
2887 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
2888 IN PVOID FirstStruct
,
2889 IN PVOID SecondStruct
)
2897 // The allocation function is called by the generic table package whenever
2898 // it needs to allocate memory for the table.
2903 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
2913 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
2922 PpInitializeDeviceReferenceTable(VOID
)
2924 /* Setup the guarded mutex and AVL table */
2925 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
2926 RtlInitializeGenericTableAvl(
2927 &PpDeviceReferenceTable
,
2928 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
2929 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
2930 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
2938 /* Initialize the resource when accessing device registry data */
2939 ExInitializeResourceLite(&PpRegistryDeviceResource
);
2941 /* Setup the device reference AVL table */
2942 PpInitializeDeviceReferenceTable();
2950 /* Check the initialization phase */
2951 switch (ExpInitializationPhase
)
2956 return PiInitPhase0();
2962 //return PiInitPhase1();
2966 /* Don't know any other phase! Bugcheck! */
2967 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
2972 LONG IopNumberDeviceNodes
;
2976 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
2978 PDEVICE_NODE DeviceNode
;
2982 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), 'donD');
2983 if (!DeviceNode
) return DeviceNode
;
2986 InterlockedIncrement(&IopNumberDeviceNodes
);
2989 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
2990 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
2991 DeviceNode
->BusNumber
= -1;
2992 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2993 DeviceNode
->ChildBusNumber
= -1;
2994 DeviceNode
->ChildBusTypeIndex
= -1;
2995 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
2996 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
2997 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
2998 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
2999 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
3000 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
3002 /* Check if there is a PDO */
3003 if (PhysicalDeviceObject
)
3005 /* Link it and remove the init flag */
3006 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
3007 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
3008 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3011 /* Return the node */
3015 /* PUBLIC FUNCTIONS **********************************************************/
3019 PnpBusTypeGuidGet(IN USHORT Index
,
3020 IN LPGUID BusTypeGuid
)
3022 NTSTATUS Status
= STATUS_SUCCESS
;
3024 /* Acquire the lock */
3025 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
3028 if (Index
< PnpBusTypeGuidList
->GuidCount
)
3031 RtlCopyMemory(BusTypeGuid
, &PnpBusTypeGuidList
->Guids
[Index
], sizeof(GUID
));
3036 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
3039 /* Release lock and return status */
3040 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
3046 PpIrpQueryCapabilities(IN PDEVICE_OBJECT DeviceObject
,
3047 OUT PDEVICE_CAPABILITIES DeviceCaps
)
3050 IO_STACK_LOCATION Stack
;
3054 /* Set up the Header */
3055 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
3056 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
3057 DeviceCaps
->Version
= 1;
3058 DeviceCaps
->Address
= -1;
3059 DeviceCaps
->UINumber
= -1;
3061 /* Set up the Stack */
3062 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
3063 Stack
.MajorFunction
= IRP_MJ_PNP
;
3064 Stack
.MinorFunction
= IRP_MN_QUERY_CAPABILITIES
;
3065 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
3068 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
3073 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject
,
3074 IN PHANDLE DeviceInstanceHandle
,
3075 IN ACCESS_MASK DesiredAccess
)
3079 PDEVICE_NODE DeviceNode
;
3080 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
3083 /* Open the enum key */
3084 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
3088 if (!NT_SUCCESS(Status
)) return Status
;
3090 /* Make sure we have an instance path */
3091 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3092 if ((DeviceNode
) && (DeviceNode
->InstancePath
.Length
))
3094 /* Get the instance key */
3095 Status
= IopOpenRegistryKeyEx(DeviceInstanceHandle
,
3097 &DeviceNode
->InstancePath
,
3103 Status
= STATUS_INVALID_DEVICE_REQUEST
;
3106 /* Close the handle and return status */
3113 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList
)
3115 ULONG FinalSize
, PartialSize
, EntrySize
, i
, j
;
3116 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
3117 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
3119 /* If we don't have one, that's easy */
3120 if (!ResourceList
) return 0;
3122 /* Start with the minimum size possible */
3123 FinalSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
3125 /* Loop each full descriptor */
3126 FullDescriptor
= ResourceList
->List
;
3127 for (i
= 0; i
< ResourceList
->Count
; i
++)
3129 /* Start with the minimum size possible */
3130 PartialSize
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
) +
3131 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
);
3133 /* Loop each partial descriptor */
3134 PartialDescriptor
= FullDescriptor
->PartialResourceList
.PartialDescriptors
;
3135 for (j
= 0; j
< FullDescriptor
->PartialResourceList
.Count
; j
++)
3137 /* Start with the minimum size possible */
3138 EntrySize
= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
3140 /* Check if there is extra data */
3141 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
3144 EntrySize
+= PartialDescriptor
->u
.DeviceSpecificData
.DataSize
;
3147 /* The size of partial descriptors is bigger */
3148 PartialSize
+= EntrySize
;
3150 /* Go to the next partial descriptor */
3151 PartialDescriptor
= (PVOID
)((ULONG_PTR
)PartialDescriptor
+ EntrySize
);
3154 /* The size of full descriptors is bigger */
3155 FinalSize
+= PartialSize
;
3157 /* Go to the next full descriptor */
3158 FullDescriptor
= (PVOID
)((ULONG_PTR
)FullDescriptor
+ PartialSize
);
3161 /* Return the final size */
3167 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject
,
3172 IN PULONG BufferLength
)
3175 HANDLE KeyHandle
, SubHandle
;
3176 UNICODE_STRING KeyString
;
3177 PKEY_VALUE_FULL_INFORMATION KeyValueInfo
= NULL
;
3181 /* Find the instance key */
3182 Status
= PnpDeviceObjectToDeviceInstance(DeviceObject
, &KeyHandle
, KEY_READ
);
3183 if (NT_SUCCESS(Status
))
3185 /* Check for name given by caller */
3189 RtlInitUnicodeString(&KeyString
, KeyName
);
3190 Status
= IopOpenRegistryKeyEx(&SubHandle
,
3194 if (NT_SUCCESS(Status
))
3196 /* And use this handle instead */
3198 KeyHandle
= SubHandle
;
3202 /* Check if sub-key handle succeeded (or no-op if no key name given) */
3203 if (NT_SUCCESS(Status
))
3205 /* Now get the size of the property */
3206 Status
= IopGetRegistryValue(KeyHandle
,
3215 /* Fail if any of the registry operations failed */
3216 if (!NT_SUCCESS(Status
)) return Status
;
3218 /* Check how much data we have to copy */
3219 Length
= KeyValueInfo
->DataLength
;
3220 if (*BufferLength
>= Length
)
3222 /* Check for a match in the value type */
3223 if (KeyValueInfo
->Type
== ValueType
)
3226 RtlCopyMemory(Buffer
,
3227 (PVOID
)((ULONG_PTR
)KeyValueInfo
+
3228 KeyValueInfo
->DataOffset
),
3233 /* Invalid registry property type, fail */
3234 Status
= STATUS_INVALID_PARAMETER_2
;
3239 /* Buffer is too small to hold data */
3240 Status
= STATUS_BUFFER_TOO_SMALL
;
3243 /* Return the required buffer length, free the buffer, and return status */
3244 *BufferLength
= Length
;
3245 ExFreePool(KeyValueInfo
);
3249 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
3250 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
3251 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED; while(TRUE); break;}
3258 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3259 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3260 IN ULONG BufferLength
,
3261 OUT PVOID PropertyBuffer
,
3262 OUT PULONG ResultLength
)
3264 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3265 DEVICE_CAPABILITIES DeviceCaps
;
3266 ULONG ReturnLength
= 0, Length
= 0, ValueType
;
3267 PWCHAR ValueName
= NULL
, EnumeratorNameEnd
, DeviceInstanceName
;
3269 NTSTATUS Status
= STATUS_BUFFER_TOO_SMALL
;
3271 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
3272 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3274 /* Assume failure */
3277 /* Only PDOs can call this */
3278 if (!DeviceNode
) return STATUS_INVALID_DEVICE_REQUEST
;
3280 /* Handle all properties */
3281 switch (DeviceProperty
)
3283 case DevicePropertyBusTypeGuid
:
3285 /* Get the GUID from the internal cache */
3286 Status
= PnpBusTypeGuidGet(DeviceNode
->ChildBusTypeIndex
, &BusTypeGuid
);
3287 if (!NT_SUCCESS(Status
)) return Status
;
3289 /* This is the format of the returned data */
3290 PIP_RETURN_DATA(sizeof(GUID
), &BusTypeGuid
);
3292 case DevicePropertyLegacyBusType
:
3294 /* Validate correct interface type */
3295 if (DeviceNode
->ChildInterfaceType
== InterfaceTypeUndefined
)
3296 return STATUS_OBJECT_NAME_NOT_FOUND
;
3298 /* This is the format of the returned data */
3299 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE
), &DeviceNode
->ChildInterfaceType
);
3301 case DevicePropertyBusNumber
:
3303 /* Validate correct bus number */
3304 if ((DeviceNode
->ChildBusNumber
& 0x80000000) == 0x80000000)
3305 return STATUS_OBJECT_NAME_NOT_FOUND
;
3307 /* This is the format of the returned data */
3308 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceNode
->ChildBusNumber
);
3310 case DevicePropertyEnumeratorName
:
3312 /* Get the instance path */
3313 DeviceInstanceName
= DeviceNode
->InstancePath
.Buffer
;
3316 ASSERT((BufferLength
& 1) == 0);
3317 ASSERT(DeviceInstanceName
!= NULL
);
3319 /* Get the name from the path */
3320 EnumeratorNameEnd
= wcschr(DeviceInstanceName
, OBJ_NAME_PATH_SEPARATOR
);
3321 ASSERT(EnumeratorNameEnd
);
3323 /* This is the format of the returned data */
3324 PIP_RETURN_DATA((EnumeratorNameEnd
- DeviceInstanceName
) * sizeof(WCHAR
),
3325 DeviceInstanceName
);
3327 case DevicePropertyAddress
:
3329 /* Query the device caps */
3330 Status
= PpIrpQueryCapabilities(DeviceObject
, &DeviceCaps
);
3331 if (!NT_SUCCESS(Status
) || (DeviceCaps
.Address
== MAXULONG
))
3332 return STATUS_OBJECT_NAME_NOT_FOUND
;
3334 /* This is the format of the returned data */
3335 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceCaps
.Address
);
3337 case DevicePropertyBootConfigurationTranslated
:
3339 /* Validate we have resources */
3340 if (!DeviceNode
->BootResources
)
3341 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
3343 /* No resources will still fake success, but with 0 bytes */
3345 return STATUS_SUCCESS
;
3348 /* This is the format of the returned data */
3349 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode
->BootResources
), // FIXFIX: Should use BootResourcesTranslated
3350 DeviceNode
->BootResources
); // FIXFIX: Should use BootResourcesTranslated
3352 case DevicePropertyPhysicalDeviceObjectName
:
3354 /* Sanity check for Unicode-sized string */
3355 ASSERT((BufferLength
& 1) == 0);
3357 /* Allocate name buffer */
3358 Length
= BufferLength
+ sizeof(OBJECT_NAME_INFORMATION
);
3359 ObjectNameInfo
= ExAllocatePool(PagedPool
, Length
);
3360 if (!ObjectNameInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
3362 /* Query the PDO name */
3363 Status
= ObQueryNameString(DeviceObject
,
3367 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
3369 /* It's up to the caller to try again */
3370 Status
= STATUS_BUFFER_TOO_SMALL
;
3373 /* Return if successful */
3374 if (NT_SUCCESS(Status
)) PIP_RETURN_DATA(ObjectNameInfo
->Name
.Length
,
3375 ObjectNameInfo
->Name
.Buffer
);
3377 /* Let the caller know how big the name is */
3378 *ResultLength
-= sizeof(OBJECT_NAME_INFORMATION
);
3381 /* Handle the registry-based properties */
3382 case DevicePropertyUINumber
:
3383 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER
, REG_DWORD
);
3384 case DevicePropertyLocationInformation
:
3385 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION
, REG_SZ
);
3386 case DevicePropertyDeviceDescription
:
3387 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC
, REG_SZ
);
3388 case DevicePropertyHardwareID
:
3389 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID
, REG_MULTI_SZ
);
3390 case DevicePropertyCompatibleIDs
:
3391 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS
, REG_MULTI_SZ
);
3392 case DevicePropertyBootConfiguration
:
3393 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG
, REG_RESOURCE_LIST
);
3394 case DevicePropertyClassName
:
3395 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS
, REG_SZ
);
3396 case DevicePropertyClassGuid
:
3397 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID
, REG_SZ
);
3398 case DevicePropertyDriverKeyName
:
3399 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER
, REG_SZ
);
3400 case DevicePropertyManufacturer
:
3401 PIP_REGISTRY_DATA(REGSTR_VAL_MFG
, REG_SZ
);
3402 case DevicePropertyFriendlyName
:
3403 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME
, REG_SZ
);
3404 case DevicePropertyContainerID
:
3405 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
3406 PIP_UNIMPLEMENTED();
3407 case DevicePropertyRemovalPolicy
:
3408 PIP_UNIMPLEMENTED();
3409 case DevicePropertyInstallState
:
3410 PIP_UNIMPLEMENTED();
3411 case DevicePropertyResourceRequirements
:
3412 PIP_UNIMPLEMENTED();
3413 case DevicePropertyAllocatedResources
:
3414 PIP_UNIMPLEMENTED();
3416 return STATUS_INVALID_PARAMETER_2
;
3419 /* Having a registry value name implies registry data */
3422 /* We know up-front how much data to expect */
3423 *ResultLength
= BufferLength
;
3425 /* Go get the data, use the LogConf subkey if necessary */
3426 Status
= PiGetDeviceRegistryProperty(DeviceObject
,
3430 DevicePropertyBootConfiguration
) ?
3435 else if (NT_SUCCESS(Status
))
3437 /* We know up-front how much data to expect, check the caller's buffer */
3438 *ResultLength
= ReturnLength
;
3439 if (ReturnLength
<= BufferLength
)
3441 /* Buffer is all good, copy the data */
3442 RtlCopyMemory(PropertyBuffer
, Data
, ReturnLength
);
3444 /* Check for properties that require a null-terminated string */
3445 if ((DeviceProperty
== DevicePropertyEnumeratorName
) ||
3446 (DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
))
3448 /* Terminate the string */
3449 ((PWCHAR
)PropertyBuffer
)[ReturnLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3452 /* This is the success path */
3453 Status
= STATUS_SUCCESS
;
3458 Status
= STATUS_BUFFER_TOO_SMALL
;
3462 /* Free any allocation we may have made, and return the status code */
3463 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
3472 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3478 * @name IoOpenDeviceRegistryKey
3480 * Open a registry key unique for a specified driver or device instance.
3482 * @param DeviceObject Device to get the registry key for.
3483 * @param DevInstKeyType Type of the key to return.
3484 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
3485 * @param DevInstRegKey Handle to the opened registry key on
3486 * successful return.
3494 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
3495 IN ULONG DevInstKeyType
,
3496 IN ACCESS_MASK DesiredAccess
,
3497 OUT PHANDLE DevInstRegKey
)
3499 static WCHAR RootKeyName
[] =
3500 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
3501 static WCHAR ProfileKeyName
[] =
3502 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
3503 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
3504 static WCHAR EnumKeyName
[] = L
"Enum\\";
3505 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
3506 ULONG KeyNameLength
;
3507 LPWSTR KeyNameBuffer
;
3508 UNICODE_STRING KeyName
;
3509 ULONG DriverKeyLength
;
3510 OBJECT_ATTRIBUTES ObjectAttributes
;
3511 PDEVICE_NODE DeviceNode
= NULL
;
3514 DPRINT("IoOpenDeviceRegistryKey() called\n");
3516 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
3518 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
3519 return STATUS_INVALID_PARAMETER
;
3522 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
3523 return STATUS_INVALID_DEVICE_REQUEST
;
3524 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3527 * Calculate the length of the base key name. This is the full
3528 * name for driver key or the name excluding "Device Parameters"
3529 * subkey for device key.
3532 KeyNameLength
= sizeof(RootKeyName
);
3533 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3534 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
3535 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3537 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
3538 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3539 0, NULL
, &DriverKeyLength
);
3540 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
3542 KeyNameLength
+= DriverKeyLength
;
3546 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
3547 DeviceNode
->InstancePath
.Length
;
3551 * Now allocate the buffer for the key name...
3554 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
3555 if (KeyNameBuffer
== NULL
)
3556 return STATUS_INSUFFICIENT_RESOURCES
;
3559 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
3560 KeyName
.Buffer
= KeyNameBuffer
;
3563 * ...and build the key name.
3566 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
3567 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
3569 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3570 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
3572 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3574 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
3575 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3576 DriverKeyLength
, KeyNameBuffer
+
3577 (KeyName
.Length
/ sizeof(WCHAR
)),
3579 if (!NT_SUCCESS(Status
))
3581 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
3582 ExFreePool(KeyNameBuffer
);
3585 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
3589 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
3590 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
3591 if (DeviceNode
->InstancePath
.Length
== 0)
3593 ExFreePool(KeyNameBuffer
);
3599 * Open the base key.
3601 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
3602 if (!NT_SUCCESS(Status
))
3604 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
3605 ExFreePool(KeyNameBuffer
);
3608 ExFreePool(KeyNameBuffer
);
3611 * For driver key we're done now.
3614 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3618 * Let's go further. For device key we must open "Device Parameters"
3619 * subkey and create it if it doesn't exist yet.
3622 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
3623 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
3624 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
3625 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
3626 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
3627 ZwClose(ObjectAttributes
.RootDirectory
);
3637 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3647 IoInvalidateDeviceRelations(
3648 IN PDEVICE_OBJECT DeviceObject
,
3649 IN DEVICE_RELATION_TYPE Type
)
3651 PIO_WORKITEM WorkItem
;
3652 PINVALIDATE_DEVICE_RELATION_DATA Data
;
3654 Data
= ExAllocatePool(NonPagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
3657 WorkItem
= IoAllocateWorkItem(DeviceObject
);
3664 ObReferenceObject(DeviceObject
);
3665 Data
->DeviceObject
= DeviceObject
;
3667 Data
->WorkItem
= WorkItem
;
3671 IopAsynchronousInvalidateDeviceRelations
,
3681 IoSynchronousInvalidateDeviceRelations(
3682 IN PDEVICE_OBJECT DeviceObject
,
3683 IN DEVICE_RELATION_TYPE Type
)
3690 /* Enumerate the device */
3691 return IopEnumerateDevice(DeviceObject
);
3692 case PowerRelations
:
3693 /* Not handled yet */
3694 return STATUS_NOT_IMPLEMENTED
;
3695 case TargetDeviceRelation
:
3697 return STATUS_SUCCESS
;
3699 /* Ejection relations are not supported */
3700 return STATUS_NOT_SUPPORTED
;
3709 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
3711 IN PHYSICAL_ADDRESS BusAddress
,
3712 IN OUT PULONG AddressSpace
,
3713 OUT PPHYSICAL_ADDRESS TranslatedAddress
)