2 * PROJECT: ReactOS Kernel
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnpmgr.c
5 * PURPOSE: Initializes the PnP manager
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Copyright 2007 Hervé Poussineau (hpoussin@reactos.org)
10 /* INCLUDES ******************************************************************/
18 /* GLOBALS *******************************************************************/
20 PDEVICE_NODE IopRootDeviceNode
;
21 KSPIN_LOCK IopDeviceTreeLock
;
22 ERESOURCE PpRegistryDeviceResource
;
23 KGUARDED_MUTEX PpDeviceReferenceTableLock
;
24 RTL_AVL_TABLE PpDeviceReferenceTable
;
26 extern ULONG ExpInitializationPhase
;
27 extern BOOLEAN PnpSystemInit
;
29 /* DATA **********************************************************************/
31 PDRIVER_OBJECT IopRootDriverObject
;
32 PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList
= NULL
;
34 #if defined (ALLOC_PRAGMA)
35 #pragma alloc_text(INIT, PnpInit)
36 #pragma alloc_text(INIT, PnpInit2)
39 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
41 PDEVICE_OBJECT DeviceObject
;
42 DEVICE_RELATION_TYPE Type
;
43 PIO_WORKITEM WorkItem
;
44 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
46 /* FUNCTIONS *****************************************************************/
49 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
50 IN ULONG CreateOptions
,
55 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
57 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
62 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
63 PDRIVER_OBJECT DriverObject
)
70 /* Special case for bus driven devices */
71 DeviceNode
->Flags
|= DNF_ADDED
;
72 return STATUS_SUCCESS
;
75 if (!DriverObject
->DriverExtension
->AddDevice
)
77 DeviceNode
->Flags
|= DNF_LEGACY_DRIVER
;
80 if (DeviceNode
->Flags
& DNF_LEGACY_DRIVER
)
82 DeviceNode
->Flags
|= DNF_ADDED
+ DNF_STARTED
;
83 return STATUS_SUCCESS
;
86 /* This is a Plug and Play driver */
87 DPRINT("Plug and Play driver found\n");
88 ASSERT(DeviceNode
->PhysicalDeviceObject
);
90 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
91 &DriverObject
->DriverName
,
92 &DeviceNode
->InstancePath
);
93 Status
= DriverObject
->DriverExtension
->AddDevice(
94 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
95 if (!NT_SUCCESS(Status
))
97 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
101 /* Check if driver added a FDO above the PDO */
102 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
103 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
105 /* FIXME: What do we do? Unload the driver or just disable the device? */
106 DPRINT1("An FDO was not attached\n");
107 ObDereferenceObject(Fdo
);
108 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
109 return STATUS_UNSUCCESSFUL
;
112 /* Check if we have a ACPI device (needed for power management) */
113 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
115 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
117 /* There can be only one system power device */
118 if (!SystemPowerDeviceNodeCreated
)
120 PopSystemPowerDeviceNode
= DeviceNode
;
121 ObReferenceObject(PopSystemPowerDeviceNode
);
122 SystemPowerDeviceNodeCreated
= TRUE
;
126 ObDereferenceObject(Fdo
);
128 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
130 return STATUS_SUCCESS
;
135 IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
137 IO_STACK_LOCATION Stack
;
140 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
141 Stack
.MajorFunction
= IRP_MJ_PNP
;
142 Stack
.MinorFunction
= IRP_MN_REMOVE_DEVICE
;
144 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
145 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
150 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject
)
152 IO_STACK_LOCATION Stack
;
153 PDEVICE_NODE DeviceNode
;
157 /* Get the device node */
158 DeviceNode
= IopGetDeviceNode(DeviceObject
);
160 /* Build the I/O stack locaiton */
161 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
162 Stack
.MajorFunction
= IRP_MJ_PNP
;
163 Stack
.MinorFunction
= IRP_MN_START_DEVICE
;
165 /* Check if we didn't already report the resources */
166 if (!(DeviceNode
->Flags
& DNF_RESOURCE_REPORTED
))
169 Stack
.Parameters
.StartDevice
.AllocatedResources
=
170 DeviceNode
->ResourceList
;
171 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
=
172 DeviceNode
->ResourceListTranslated
;
175 /* I don't think we set this flag yet */
176 ASSERT(!(DeviceNode
->Flags
& DNF_STOPPED
));
179 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
180 if (!NT_SUCCESS(Status
))
182 /* Send an IRP_MN_REMOVE_DEVICE request */
183 IopSendRemoveDevice(DeviceObject
);
185 /* Set the appropriate flag */
186 DeviceNode
->Flags
|= DNF_START_FAILED
;
188 DPRINT1("Warning: PnP Start failed (%wZ)\n", &DeviceNode
->InstancePath
);
192 /* Otherwise, mark us as started */
193 DeviceNode
->Flags
|= DNF_STARTED
;
195 /* We now need enumeration */
196 DeviceNode
->Flags
|= DNF_NEED_ENUMERATION_ONLY
;
201 IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode
)
203 PDEVICE_OBJECT DeviceObject
;
208 ASSERT((DeviceNode
->Flags
& DNF_ADDED
));
209 ASSERT((DeviceNode
->Flags
& (DNF_RESOURCE_ASSIGNED
|
210 DNF_RESOURCE_REPORTED
|
211 DNF_NO_RESOURCE_REQUIRED
)));
212 ASSERT((!(DeviceNode
->Flags
& (DNF_HAS_PROBLEM
|
214 DNF_START_REQUEST_PENDING
))));
216 /* Get the device object */
217 DeviceObject
= DeviceNode
->PhysicalDeviceObject
;
219 /* Check if we're not started yet */
220 if (!(DeviceNode
->Flags
& DNF_STARTED
))
223 IopStartDevice2(DeviceObject
);
226 /* Do we need to query IDs? This happens in the case of manual reporting */
228 if (DeviceNode
->Flags
& DNF_NEED_QUERY_IDS
)
230 DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
231 /* And that case shouldn't happen yet */
236 /* Make sure we're started, and check if we need enumeration */
237 if ((DeviceNode
->Flags
& DNF_STARTED
) &&
238 (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
))
241 IoSynchronousInvalidateDeviceRelations(DeviceObject
, BusRelations
);
242 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
243 Status
= STATUS_SUCCESS
;
248 Status
= STATUS_SUCCESS
;
257 PDEVICE_NODE DeviceNode
)
260 HANDLE InstanceHandle
= INVALID_HANDLE_VALUE
, ControlHandle
= INVALID_HANDLE_VALUE
;
261 UNICODE_STRING KeyName
;
262 OBJECT_ATTRIBUTES ObjectAttributes
;
264 if (DeviceNode
->Flags
& (DNF_STARTED
| DNF_START_REQUEST_PENDING
))
266 /* Nothing to do here */
267 return STATUS_SUCCESS
;
270 Status
= IopAssignDeviceResources(DeviceNode
);
271 if (!NT_SUCCESS(Status
))
275 IopStartAndEnumerateDevice(DeviceNode
);
277 /* FIX: Should be done in new device instance code */
278 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceHandle
);
279 if (!NT_SUCCESS(Status
))
282 /* FIX: Should be done in IoXxxPrepareDriverLoading */
284 RtlInitUnicodeString(&KeyName
, L
"Control");
285 InitializeObjectAttributes(&ObjectAttributes
,
287 OBJ_CASE_INSENSITIVE
,
290 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
291 if (!NT_SUCCESS(Status
))
294 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
295 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
299 if (ControlHandle
!= INVALID_HANDLE_VALUE
)
300 ZwClose(ControlHandle
);
302 if (InstanceHandle
!= INVALID_HANDLE_VALUE
)
303 ZwClose(InstanceHandle
);
310 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
311 PDEVICE_CAPABILITIES DeviceCaps
)
313 IO_STATUS_BLOCK StatusBlock
;
314 IO_STACK_LOCATION Stack
;
316 /* Set up the Header */
317 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
318 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
319 DeviceCaps
->Version
= 1;
320 DeviceCaps
->Address
= -1;
321 DeviceCaps
->UINumber
= -1;
323 /* Set up the Stack */
324 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
325 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
328 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
330 IRP_MN_QUERY_CAPABILITIES
,
335 IopAsynchronousInvalidateDeviceRelations(
336 IN PDEVICE_OBJECT DeviceObject
,
337 IN PVOID InvalidateContext
)
339 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
341 IoSynchronousInvalidateDeviceRelations(
345 ObDereferenceObject(Data
->DeviceObject
);
346 IoFreeWorkItem(Data
->WorkItem
);
351 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
355 if (PopSystemPowerDeviceNode
)
357 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
358 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
359 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
361 return STATUS_SUCCESS
;
364 return STATUS_UNSUCCESSFUL
;
369 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
371 USHORT i
= 0, FoundIndex
= 0xFFFF;
375 /* Acquire the lock */
376 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
378 /* Loop all entries */
379 while (i
< PnpBusTypeGuidList
->GuidCount
)
381 /* Try to find a match */
382 if (RtlCompareMemory(BusTypeGuid
,
383 &PnpBusTypeGuidList
->Guids
[i
],
384 sizeof(GUID
)) == sizeof(GUID
))
393 /* Check if we have to grow the list */
394 if (PnpBusTypeGuidList
->GuidCount
)
396 /* Calculate the new size */
397 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
398 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
400 /* Allocate the new copy */
401 NewList
= ExAllocatePool(PagedPool
, NewSize
);
405 ExFreePool(PnpBusTypeGuidList
);
409 /* Now copy them, decrease the size too */
410 NewSize
-= sizeof(GUID
);
411 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
413 /* Free the old list */
414 ExFreePool(PnpBusTypeGuidList
);
416 /* Use the new buffer */
417 PnpBusTypeGuidList
= NewList
;
420 /* Copy the new GUID */
421 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
425 /* The new entry is the index */
426 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
427 PnpBusTypeGuidList
->GuidCount
++;
430 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
436 * Creates a device node
439 * ParentNode = Pointer to parent device node
440 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
441 * to have the root device node create one
442 * (eg. for legacy drivers)
443 * DeviceNode = Pointer to storage for created device node
449 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
450 PDEVICE_OBJECT PhysicalDeviceObject
,
451 PUNICODE_STRING ServiceName
,
452 PDEVICE_NODE
*DeviceNode
)
457 UNICODE_STRING FullServiceName
;
458 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
459 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
460 UNICODE_STRING KeyName
, ClassName
;
461 PUNICODE_STRING ServiceName1
;
464 UNICODE_STRING ClassGUID
;
466 HANDLE InstanceHandle
;
468 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
469 ParentNode
, PhysicalDeviceObject
, ServiceName
);
471 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
474 return STATUS_INSUFFICIENT_RESOURCES
;
477 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
480 ServiceName1
= &UnknownDeviceName
;
482 ServiceName1
= ServiceName
;
484 if (!PhysicalDeviceObject
)
486 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
487 FullServiceName
.Length
= 0;
488 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
489 if (!FullServiceName
.Buffer
)
492 return STATUS_INSUFFICIENT_RESOURCES
;
495 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
496 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
498 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
499 if (!NT_SUCCESS(Status
))
501 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
506 /* Create the device key for legacy drivers */
507 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
508 if (!NT_SUCCESS(Status
))
510 ZwClose(InstanceHandle
);
512 ExFreePool(FullServiceName
.Buffer
);
516 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
517 if (!Node
->ServiceName
.Buffer
)
519 ZwClose(InstanceHandle
);
521 ExFreePool(FullServiceName
.Buffer
);
525 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
526 Node
->ServiceName
.Length
= 0;
528 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
532 RtlInitUnicodeString(&KeyName
, L
"Service");
533 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
536 if (NT_SUCCESS(Status
))
538 RtlInitUnicodeString(&KeyName
, L
"Legacy");
541 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
542 if (NT_SUCCESS(Status
))
544 RtlInitUnicodeString(&KeyName
, L
"Class");
546 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
547 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
);
549 if (NT_SUCCESS(Status
))
551 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
553 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
554 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
);
560 ZwClose(InstanceHandle
);
561 ExFreePool(FullServiceName
.Buffer
);
563 if (!NT_SUCCESS(Status
))
569 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
570 IopDeviceNodeSetFlag(Node
, DNF_ADDED
);
571 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
574 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
576 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
580 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
581 Node
->Parent
= ParentNode
;
582 Node
->Sibling
= ParentNode
->Child
;
583 ParentNode
->Child
= Node
;
584 if (ParentNode
->LastChild
== NULL
)
585 ParentNode
->LastChild
= Node
;
586 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
587 Node
->Level
= ParentNode
->Level
+ 1;
590 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
594 return STATUS_SUCCESS
;
598 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
601 PDEVICE_NODE PrevSibling
= NULL
;
603 /* All children must be deleted before a parent is deleted */
604 ASSERT(!DeviceNode
->Child
);
606 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
608 ASSERT(DeviceNode
->PhysicalDeviceObject
);
610 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
612 /* Get previous sibling */
613 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
615 PrevSibling
= DeviceNode
->Parent
->Child
;
616 while (PrevSibling
->Sibling
!= DeviceNode
)
617 PrevSibling
= PrevSibling
->Sibling
;
620 /* Unlink from parent if it exists */
621 if (DeviceNode
->Parent
)
623 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
625 DeviceNode
->Parent
->LastChild
= PrevSibling
;
627 PrevSibling
->Sibling
= NULL
;
629 if (DeviceNode
->Parent
->Child
== DeviceNode
)
630 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
633 /* Unlink from sibling list */
635 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
637 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
639 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
641 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
643 if (DeviceNode
->ResourceList
)
645 ExFreePool(DeviceNode
->ResourceList
);
648 if (DeviceNode
->ResourceListTranslated
)
650 ExFreePool(DeviceNode
->ResourceListTranslated
);
653 if (DeviceNode
->ResourceRequirements
)
655 ExFreePool(DeviceNode
->ResourceRequirements
);
658 if (DeviceNode
->BootResources
)
660 ExFreePool(DeviceNode
->BootResources
);
663 ExFreePool(DeviceNode
);
665 return STATUS_SUCCESS
;
670 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
671 IN PIO_STACK_LOCATION IoStackLocation
,
672 OUT PVOID
*Information
)
675 PIO_STACK_LOCATION IrpStack
;
676 IO_STATUS_BLOCK IoStatusBlock
;
679 PDEVICE_OBJECT TopDeviceObject
;
682 /* Call the top of the device stack */
683 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
685 /* Allocate an IRP */
686 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
687 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
689 /* Initialize to failure */
690 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
691 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
693 /* Initialize the event */
694 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
697 Irp
->UserIosb
= &IoStatusBlock
;
698 Irp
->UserEvent
= &Event
;
701 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
702 IoQueueThreadIrp(Irp
);
704 /* Copy-in the stack */
705 IrpStack
= IoGetNextIrpStackLocation(Irp
);
706 *IrpStack
= *IoStackLocation
;
708 /* Call the driver */
709 Status
= IoCallDriver(TopDeviceObject
, Irp
);
710 if (Status
== STATUS_PENDING
)
713 KeWaitForSingleObject(&Event
,
718 Status
= IoStatusBlock
.Status
;
721 /* Return the information */
722 *Information
= (PVOID
)IoStatusBlock
.Information
;
728 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
729 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
730 IN ULONG MinorFunction
,
731 IN PIO_STACK_LOCATION Stack OPTIONAL
)
733 IO_STACK_LOCATION IoStackLocation
;
735 /* Fill out the stack information */
736 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
737 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
738 IoStackLocation
.MinorFunction
= MinorFunction
;
742 RtlCopyMemory(&IoStackLocation
.Parameters
,
744 sizeof(Stack
->Parameters
));
747 /* Do the PnP call */
748 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
750 (PVOID
)&IoStatusBlock
->Information
);
751 return IoStatusBlock
->Status
;
755 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
757 PDEVICE_NODE ParentDeviceNode
;
758 PDEVICE_NODE ChildDeviceNode
;
761 /* Copy context data so we don't overwrite it in subsequent calls to this function */
762 ParentDeviceNode
= Context
->DeviceNode
;
764 /* Call the action routine */
765 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
766 if (!NT_SUCCESS(Status
))
771 /* Traversal of all children nodes */
772 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
773 ChildDeviceNode
!= NULL
;
774 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
776 /* Pass the current device node to the action routine */
777 Context
->DeviceNode
= ChildDeviceNode
;
779 Status
= IopTraverseDeviceTreeNode(Context
);
780 if (!NT_SUCCESS(Status
))
791 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
795 DPRINT("Context 0x%p\n", Context
);
797 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
798 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
800 /* Start from the specified device node */
801 Context
->DeviceNode
= Context
->FirstDeviceNode
;
803 /* Recursively traverse the device tree */
804 Status
= IopTraverseDeviceTreeNode(Context
);
805 if (Status
== STATUS_UNSUCCESSFUL
)
807 /* The action routine just wanted to terminate the traversal with status
808 code STATUS_SUCCESS */
809 Status
= STATUS_SUCCESS
;
817 * IopCreateDeviceKeyPath
819 * Creates a registry key
823 * Name of the key to be created.
825 * Handle to the newly created key
828 * This method can create nested trees, so parent of RegistryPath can
829 * be not existant, and will be created if needed.
833 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
834 IN ULONG CreateOptions
,
837 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
838 HANDLE hParent
= NULL
, hKey
;
839 OBJECT_ATTRIBUTES ObjectAttributes
;
840 UNICODE_STRING KeyName
;
841 LPCWSTR Current
, Last
;
848 /* Open root key for device instances */
849 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
850 if (!NT_SUCCESS(Status
))
852 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
856 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
857 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
859 /* Go up to the end of the string */
860 while (Current
<= Last
)
862 if (Current
!= Last
&& *Current
!= '\\')
864 /* Not the end of the string and not a separator */
869 /* Prepare relative key name */
870 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
871 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
872 DPRINT("Create '%wZ'\n", &KeyName
);
875 InitializeObjectAttributes(&ObjectAttributes
,
877 OBJ_CASE_INSENSITIVE
,
880 Status
= ZwCreateKey(&hKey
,
881 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
888 /* Close parent key handle, we don't need it anymore */
892 /* Key opening/creating failed? */
893 if (!NT_SUCCESS(Status
))
895 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
899 /* Check if it is the end of the string */
902 /* Yes, return success */
904 return STATUS_SUCCESS
;
907 /* Start with this new parent key */
910 KeyName
.Buffer
= (LPWSTR
)Current
;
913 return STATUS_UNSUCCESSFUL
;
917 IopSetDeviceInstanceData(HANDLE InstanceKey
,
918 PDEVICE_NODE DeviceNode
)
920 OBJECT_ATTRIBUTES ObjectAttributes
;
921 UNICODE_STRING KeyName
;
926 HANDLE ControlHandle
;
928 DPRINT("IopSetDeviceInstanceData() called\n");
930 /* Create the 'LogConf' key */
931 RtlInitUnicodeString(&KeyName
, L
"LogConf");
932 InitializeObjectAttributes(&ObjectAttributes
,
934 OBJ_CASE_INSENSITIVE
,
937 Status
= ZwCreateKey(&LogConfKey
,
944 if (NT_SUCCESS(Status
))
946 /* Set 'BootConfig' value */
947 if (DeviceNode
->BootResources
!= NULL
)
949 ResCount
= DeviceNode
->BootResources
->Count
;
952 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
953 Status
= ZwSetValueKey(LogConfKey
,
957 DeviceNode
->BootResources
,
958 PnpDetermineResourceListSize(DeviceNode
->BootResources
));
962 /* Set 'BasicConfigVector' value */
963 if (DeviceNode
->ResourceRequirements
!= NULL
&&
964 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
966 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
967 Status
= ZwSetValueKey(LogConfKey
,
970 REG_RESOURCE_REQUIREMENTS_LIST
,
971 DeviceNode
->ResourceRequirements
,
972 DeviceNode
->ResourceRequirements
->ListSize
);
978 /* Set the 'ConfigFlags' value */
979 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
980 Status
= ZwQueryValueKey(InstanceKey
,
982 KeyValueBasicInformation
,
986 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
988 /* Write the default value */
989 ULONG DefaultConfigFlags
= 0;
990 Status
= ZwSetValueKey(InstanceKey
,
995 sizeof(DefaultConfigFlags
));
998 /* Create the 'Control' key */
999 RtlInitUnicodeString(&KeyName
, L
"Control");
1000 InitializeObjectAttributes(&ObjectAttributes
,
1002 OBJ_CASE_INSENSITIVE
,
1005 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1007 if (NT_SUCCESS(Status
))
1008 ZwClose(ControlHandle
);
1010 DPRINT("IopSetDeviceInstanceData() done\n");
1016 * IopGetParentIdPrefix
1018 * Retrieve (or create) a string which identifies a device.
1022 * Pointer to device node.
1024 * Pointer to the string where is returned the parent node identifier
1027 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1028 * valid and its Buffer field is NULL-terminated. The caller needs to
1029 * to free the string with RtlFreeUnicodeString when it is no longer
1034 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1035 PUNICODE_STRING ParentIdPrefix
)
1037 ULONG KeyNameBufferLength
;
1038 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1039 UNICODE_STRING KeyName
;
1040 UNICODE_STRING KeyValue
;
1041 UNICODE_STRING ValueName
;
1046 /* HACK: As long as some devices have a NULL device
1047 * instance path, the following test is required :(
1049 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1051 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1052 &DeviceNode
->InstancePath
);
1053 return STATUS_UNSUCCESSFUL
;
1056 /* 1. Try to retrieve ParentIdPrefix from registry */
1057 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1058 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1059 if (!ParentIdPrefixInformation
)
1061 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1066 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1067 if (!KeyName
.Buffer
)
1069 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1073 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1075 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1076 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1078 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1079 if (!NT_SUCCESS(Status
))
1081 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1082 Status
= ZwQueryValueKey(
1084 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1085 KeyNameBufferLength
, &KeyNameBufferLength
);
1086 if (NT_SUCCESS(Status
))
1088 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1089 Status
= STATUS_UNSUCCESSFUL
;
1092 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1093 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1097 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1099 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1100 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1104 /* 2. Create the ParentIdPrefix value */
1105 crc32
= RtlComputeCrc32(0,
1106 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1107 DeviceNode
->Parent
->InstancePath
.Length
);
1109 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1110 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1112 /* 3. Try to write the ParentIdPrefix to registry */
1113 Status
= ZwSetValueKey(hKey
,
1117 (PVOID
)KeyValue
.Buffer
,
1118 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1121 if (NT_SUCCESS(Status
))
1123 /* Duplicate the string to return it */
1124 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1126 ExFreePool(ParentIdPrefixInformation
);
1127 RtlFreeUnicodeString(&KeyName
);
1135 * IopActionInterrogateDeviceStack
1137 * Retrieve information for all (direct) child nodes of a parent node.
1141 * Pointer to device node.
1143 * Pointer to parent node to retrieve child node information for.
1146 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1147 * when we reach a device node which is not a direct child of the device
1148 * node for which we retrieve information of child nodes for. Any errors
1149 * that occur is logged instead so that all child services have a chance
1150 * of being interrogated.
1154 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1157 IO_STATUS_BLOCK IoStatusBlock
;
1158 PDEVICE_NODE ParentDeviceNode
;
1159 WCHAR InstancePath
[MAX_PATH
];
1160 IO_STACK_LOCATION Stack
;
1165 ULONG RequiredLength
;
1167 HANDLE InstanceKey
= NULL
;
1168 UNICODE_STRING ValueName
;
1169 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1170 DEVICE_CAPABILITIES DeviceCapabilities
;
1172 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1173 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1175 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1178 * We are called for the parent too, but we don't need to do special
1179 * handling for this node
1182 if (DeviceNode
== ParentDeviceNode
)
1184 DPRINT("Success\n");
1185 return STATUS_SUCCESS
;
1189 * Make sure this device node is a direct child of the parent device node
1190 * that is given as an argument
1193 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1195 /* Stop the traversal immediately and indicate successful operation */
1197 return STATUS_UNSUCCESSFUL
;
1201 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1202 if (!NT_SUCCESS(Status
))
1204 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1209 * FIXME: For critical errors, cleanup and disable device, but always
1210 * return STATUS_SUCCESS.
1213 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1215 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1216 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1220 if (NT_SUCCESS(Status
))
1222 /* Copy the device id string */
1223 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1226 * FIXME: Check for valid characters, if there is invalid characters
1232 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1235 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1237 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1238 if (!NT_SUCCESS(Status
))
1240 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1243 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1245 if (!DeviceCapabilities
.UniqueID
)
1247 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1248 DPRINT("Instance ID is not unique\n");
1249 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1250 if (!NT_SUCCESS(Status
))
1252 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1256 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1258 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1259 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1263 if (NT_SUCCESS(Status
))
1265 /* Append the instance id string */
1266 wcscat(InstancePath
, L
"\\");
1267 if (ParentIdPrefix
.Length
> 0)
1269 /* Add information from parent bus device to InstancePath */
1270 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1271 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1272 wcscat(InstancePath
, L
"&");
1274 if (IoStatusBlock
.Information
)
1275 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1278 * FIXME: Check for valid characters, if there is invalid characters
1284 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1286 RtlFreeUnicodeString(&ParentIdPrefix
);
1288 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1290 DPRINT("No resources\n");
1291 /* FIXME: Cleanup and disable device */
1294 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1297 * Create registry key for the instance id, if it doesn't exist yet
1299 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
1300 if (!NT_SUCCESS(Status
))
1302 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1306 /* Set 'Capabilities' value */
1307 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1308 Status
= ZwSetValueKey(InstanceKey
,
1312 (PVOID
)&DeviceNode
->CapabilityFlags
,
1315 /* Set 'UINumber' value */
1316 if (DeviceCapabilities
.UINumber
!= MAXULONG
)
1318 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1319 Status
= ZwSetValueKey(InstanceKey
,
1323 &DeviceCapabilities
.UINumber
,
1328 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1330 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1331 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1335 if (NT_SUCCESS(Status
))
1338 * FIXME: Check for valid characters, if there is invalid characters
1342 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1343 DPRINT("Hardware IDs:\n");
1346 DPRINT(" %S\n", Ptr
);
1347 Length
= wcslen(Ptr
) + 1;
1350 TotalLength
+= Length
;
1352 DPRINT("TotalLength: %hu\n", TotalLength
);
1355 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1356 Status
= ZwSetValueKey(InstanceKey
,
1360 (PVOID
)IoStatusBlock
.Information
,
1361 (TotalLength
+ 1) * sizeof(WCHAR
));
1362 if (!NT_SUCCESS(Status
))
1364 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1369 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1372 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1374 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1375 Status
= IopInitiatePnpIrp(
1376 DeviceNode
->PhysicalDeviceObject
,
1380 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1383 * FIXME: Check for valid characters, if there is invalid characters
1387 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1388 DPRINT("Compatible IDs:\n");
1391 DPRINT(" %S\n", Ptr
);
1392 Length
= wcslen(Ptr
) + 1;
1395 TotalLength
+= Length
;
1397 DPRINT("TotalLength: %hu\n", TotalLength
);
1400 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1401 Status
= ZwSetValueKey(InstanceKey
,
1405 (PVOID
)IoStatusBlock
.Information
,
1406 (TotalLength
+ 1) * sizeof(WCHAR
));
1407 if (!NT_SUCCESS(Status
))
1409 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1414 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1417 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1419 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1420 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1421 Status
= IopInitiatePnpIrp(
1422 DeviceNode
->PhysicalDeviceObject
,
1424 IRP_MN_QUERY_DEVICE_TEXT
,
1426 /* This key is mandatory, so even if the Irp fails, we still write it */
1427 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1428 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1430 if (NT_SUCCESS(Status
) &&
1431 IoStatusBlock
.Information
&&
1432 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1434 /* This key is overriden when a driver is installed. Don't write the
1435 * new description if another one already exists */
1436 Status
= ZwSetValueKey(InstanceKey
,
1440 (PVOID
)IoStatusBlock
.Information
,
1441 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1445 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1446 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1448 Status
= ZwSetValueKey(InstanceKey
,
1453 DeviceDesc
.MaximumLength
);
1455 if (!NT_SUCCESS(Status
))
1457 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1463 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1465 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1466 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1467 Status
= IopInitiatePnpIrp(
1468 DeviceNode
->PhysicalDeviceObject
,
1470 IRP_MN_QUERY_DEVICE_TEXT
,
1472 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1474 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1475 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1476 Status
= ZwSetValueKey(InstanceKey
,
1480 (PVOID
)IoStatusBlock
.Information
,
1481 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1482 if (!NT_SUCCESS(Status
))
1484 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1489 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1492 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1494 Status
= IopInitiatePnpIrp(
1495 DeviceNode
->PhysicalDeviceObject
,
1497 IRP_MN_QUERY_BUS_INFORMATION
,
1499 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1501 PPNP_BUS_INFORMATION BusInformation
=
1502 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1504 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1505 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1506 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1507 ExFreePool(BusInformation
);
1511 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1513 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1514 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1515 DeviceNode
->ChildBusTypeIndex
= -1;
1518 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1520 Status
= IopInitiatePnpIrp(
1521 DeviceNode
->PhysicalDeviceObject
,
1523 IRP_MN_QUERY_RESOURCES
,
1525 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1527 DeviceNode
->BootResources
=
1528 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1529 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
1533 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1534 DeviceNode
->BootResources
= NULL
;
1537 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1539 Status
= IopInitiatePnpIrp(
1540 DeviceNode
->PhysicalDeviceObject
,
1542 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1544 if (NT_SUCCESS(Status
))
1546 DeviceNode
->ResourceRequirements
=
1547 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1551 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1552 DeviceNode
->ResourceRequirements
= NULL
;
1555 if (InstanceKey
!= NULL
)
1557 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1560 ZwClose(InstanceKey
);
1562 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1564 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1566 /* Report the device to the user-mode pnp manager */
1567 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1568 &DeviceNode
->InstancePath
);
1571 return STATUS_SUCCESS
;
1577 IN PDEVICE_OBJECT DeviceObject
)
1579 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1580 DEVICETREE_TRAVERSE_CONTEXT Context
;
1581 PDEVICE_RELATIONS DeviceRelations
;
1582 PDEVICE_OBJECT ChildDeviceObject
;
1583 IO_STATUS_BLOCK IoStatusBlock
;
1584 PDEVICE_NODE ChildDeviceNode
;
1585 IO_STACK_LOCATION Stack
;
1589 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1591 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1593 /* Report the device to the user-mode pnp manager */
1594 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1595 &DeviceNode
->InstancePath
);
1597 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1599 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1601 Status
= IopInitiatePnpIrp(
1604 IRP_MN_QUERY_DEVICE_RELATIONS
,
1606 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1608 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1612 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1614 if (!DeviceRelations
)
1616 DPRINT("No PDOs\n");
1617 return STATUS_UNSUCCESSFUL
;
1620 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1623 * Create device nodes for all discovered devices
1625 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1627 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1628 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1630 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1631 if (!ChildDeviceNode
)
1633 /* One doesn't exist, create it */
1634 Status
= IopCreateDeviceNode(
1639 if (NT_SUCCESS(Status
))
1641 /* Mark the node as enumerated */
1642 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1644 /* Mark the DO as bus enumerated */
1645 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1649 /* Ignore this DO */
1650 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1651 ObDereferenceObject(ChildDeviceNode
);
1656 /* Mark it as enumerated */
1657 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1658 ObDereferenceObject(ChildDeviceObject
);
1661 ExFreePool(DeviceRelations
);
1664 * Retrieve information about all discovered children from the bus driver
1666 IopInitDeviceTreeTraverseContext(
1669 IopActionInterrogateDeviceStack
,
1672 Status
= IopTraverseDeviceTree(&Context
);
1673 if (!NT_SUCCESS(Status
))
1675 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1680 * Retrieve configuration from the registry for discovered children
1682 IopInitDeviceTreeTraverseContext(
1685 IopActionConfigureChildServices
,
1688 Status
= IopTraverseDeviceTree(&Context
);
1689 if (!NT_SUCCESS(Status
))
1691 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1696 * Initialize services for discovered children.
1698 Status
= IopInitializePnpServices(DeviceNode
);
1699 if (!NT_SUCCESS(Status
))
1701 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1705 DPRINT("IopEnumerateDevice() finished\n");
1706 return STATUS_SUCCESS
;
1711 * IopActionConfigureChildServices
1713 * Retrieve configuration for all (direct) child nodes of a parent node.
1717 * Pointer to device node.
1719 * Pointer to parent node to retrieve child node configuration for.
1722 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1723 * when we reach a device node which is not a direct child of the device
1724 * node for which we configure child services for. Any errors that occur is
1725 * logged instead so that all child services have a chance of beeing
1730 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1733 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1734 PDEVICE_NODE ParentDeviceNode
;
1735 PUNICODE_STRING Service
;
1736 UNICODE_STRING ClassGUID
;
1738 DEVICE_CAPABILITIES DeviceCaps
;
1740 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1742 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1745 * We are called for the parent too, but we don't need to do special
1746 * handling for this node
1748 if (DeviceNode
== ParentDeviceNode
)
1750 DPRINT("Success\n");
1751 return STATUS_SUCCESS
;
1755 * Make sure this device node is a direct child of the parent device node
1756 * that is given as an argument
1758 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1760 /* Stop the traversal immediately and indicate successful operation */
1762 return STATUS_UNSUCCESSFUL
;
1765 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1767 WCHAR RegKeyBuffer
[MAX_PATH
];
1768 UNICODE_STRING RegKey
;
1771 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1772 RegKey
.Buffer
= RegKeyBuffer
;
1775 * Retrieve configuration from Enum key
1778 Service
= &DeviceNode
->ServiceName
;
1780 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1781 RtlInitUnicodeString(Service
, NULL
);
1782 RtlInitUnicodeString(&ClassGUID
, NULL
);
1784 QueryTable
[0].Name
= L
"Service";
1785 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1786 QueryTable
[0].EntryContext
= Service
;
1788 QueryTable
[1].Name
= L
"ClassGUID";
1789 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1790 QueryTable
[1].EntryContext
= &ClassGUID
;
1791 QueryTable
[1].DefaultType
= REG_SZ
;
1792 QueryTable
[1].DefaultData
= L
"";
1793 QueryTable
[1].DefaultLength
= 0;
1795 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1796 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1798 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1799 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1801 if (!NT_SUCCESS(Status
))
1803 /* FIXME: Log the error */
1804 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
1805 &DeviceNode
->InstancePath
, Status
);
1806 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1807 return STATUS_SUCCESS
;
1810 if (Service
->Buffer
== NULL
)
1812 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
1813 DeviceCaps
.RawDeviceOK
)
1815 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
1817 DeviceNode
->ServiceName
.Length
= 0;
1818 DeviceNode
->ServiceName
.MaximumLength
= 0;
1819 DeviceNode
->ServiceName
.Buffer
= NULL
;
1821 else if (ClassGUID
.Length
!= 0)
1823 /* Device has a ClassGUID value, but no Service value.
1824 * Suppose it is using the NULL driver, so state the
1825 * device is started */
1826 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
1827 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1831 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1833 return STATUS_SUCCESS
;
1836 DPRINT("Got Service %S\n", Service
->Buffer
);
1839 return STATUS_SUCCESS
;
1843 * IopActionInitChildServices
1845 * Initialize the service for all (direct) child nodes of a parent node
1849 * Pointer to device node.
1851 * Pointer to parent node to initialize child node services for.
1854 * If the driver image for a service is not loaded and initialized
1855 * it is done here too. We only return a status code indicating an
1856 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1857 * not a direct child of the device node for which we initialize
1858 * child services for. Any errors that occur is logged instead so
1859 * that all child services have a chance of being initialized.
1863 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
1866 PDEVICE_NODE ParentDeviceNode
;
1868 BOOLEAN BootDrivers
= !PnpSystemInit
;
1870 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
1872 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1875 * We are called for the parent too, but we don't need to do special
1876 * handling for this node
1878 if (DeviceNode
== ParentDeviceNode
)
1880 DPRINT("Success\n");
1881 return STATUS_SUCCESS
;
1885 * Make sure this device node is a direct child of the parent device node
1886 * that is given as an argument
1889 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1892 * Stop the traversal immediately and indicate unsuccessful operation
1895 return STATUS_UNSUCCESSFUL
;
1898 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
1899 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
1900 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1901 return STATUS_SUCCESS
;
1903 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
1905 /* We don't need to worry about loading the driver because we're
1906 * being driven in raw mode so our parent must be loaded to get here */
1907 Status
= IopInitializeDevice(DeviceNode
, NULL
);
1908 if (NT_SUCCESS(Status
))
1910 Status
= IopStartDevice(DeviceNode
);
1911 if (!NT_SUCCESS(Status
))
1913 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
1914 &DeviceNode
->InstancePath
, Status
);
1920 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1921 PDRIVER_OBJECT DriverObject
;
1923 /* Get existing DriverObject pointer (in case the driver has
1924 already been loaded and initialized) */
1925 Status
= IopGetDriverObject(
1927 &DeviceNode
->ServiceName
,
1930 if (!NT_SUCCESS(Status
))
1932 /* Driver is not initialized, try to load it */
1933 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1935 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
1937 /* STATUS_IMAGE_ALREADY_LOADED means this driver
1938 was loaded by the bootloader */
1939 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
1940 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
1942 /* Initialize the driver */
1943 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
1944 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
1948 Status
= STATUS_SUCCESS
;
1953 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
1954 &DeviceNode
->ServiceName
, Status
);
1958 /* Driver is loaded and initialized at this point */
1959 if (NT_SUCCESS(Status
))
1961 /* Initialize the device, including all filters */
1962 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
1967 * Don't disable when trying to load only boot drivers
1971 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1972 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1973 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1974 DPRINT1("Initialization of service %S failed (Status %x)\n",
1975 DeviceNode
->ServiceName
.Buffer
, Status
);
1980 return STATUS_SUCCESS
;
1984 * IopInitializePnpServices
1986 * Initialize services for discovered children
1990 * Top device node to start initializing services.
1996 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
1998 DEVICETREE_TRAVERSE_CONTEXT Context
;
2000 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2002 IopInitDeviceTreeTraverseContext(
2005 IopActionInitChildServices
,
2008 return IopTraverseDeviceTree(&Context
);
2011 static NTSTATUS INIT_FUNCTION
2012 IopEnumerateDetectedDevices(
2014 IN PUNICODE_STRING RelativePath OPTIONAL
,
2016 IN BOOLEAN EnumerateSubKeys
,
2017 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2018 IN ULONG ParentBootResourcesLength
)
2020 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2021 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2022 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2023 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2024 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2025 OBJECT_ATTRIBUTES ObjectAttributes
;
2026 HANDLE hDevicesKey
= NULL
;
2027 HANDLE hDeviceKey
= NULL
;
2028 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2029 UNICODE_STRING Level2NameU
;
2030 WCHAR Level2Name
[5];
2031 ULONG IndexDevice
= 0;
2033 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2034 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2035 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2036 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2037 UNICODE_STRING DeviceName
, ValueName
;
2039 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2040 ULONG BootResourcesLength
;
2043 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2044 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2045 static ULONG DeviceIndexPci
= 0;
2046 const UNICODE_STRING IdentifierSW
= RTL_CONSTANT_STRING(L
"SWENUM");
2047 UNICODE_STRING HardwareIdSW
= RTL_CONSTANT_STRING(L
"SWENUM\0");
2048 static ULONG DeviceIndexSW
= 0;
2049 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2050 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2051 static ULONG DeviceIndexSerial
= 0;
2052 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2053 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2054 static ULONG DeviceIndexKeyboard
= 0;
2055 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2056 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2057 static ULONG DeviceIndexMouse
= 0;
2058 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2059 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2060 static ULONG DeviceIndexParallel
= 0;
2061 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2062 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2063 static ULONG DeviceIndexFloppy
= 0;
2064 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2065 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2066 static ULONG DeviceIndexIsa
= 0;
2067 UNICODE_STRING HardwareIdKey
;
2068 PUNICODE_STRING pHardwareId
;
2069 ULONG DeviceIndex
= 0;
2070 PUCHAR CmResourceList
;
2075 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2076 if (!NT_SUCCESS(Status
))
2078 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2083 hDevicesKey
= hBaseKey
;
2085 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2086 if (!pDeviceInformation
)
2088 DPRINT("ExAllocatePool() failed\n");
2089 Status
= STATUS_NO_MEMORY
;
2093 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2094 if (!pValueInformation
)
2096 DPRINT("ExAllocatePool() failed\n");
2097 Status
= STATUS_NO_MEMORY
;
2103 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2104 if (Status
== STATUS_NO_MORE_ENTRIES
)
2106 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2108 ExFreePool(pDeviceInformation
);
2109 DeviceInfoLength
= RequiredSize
;
2110 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2111 if (!pDeviceInformation
)
2113 DPRINT("ExAllocatePool() failed\n");
2114 Status
= STATUS_NO_MEMORY
;
2117 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2119 if (!NT_SUCCESS(Status
))
2121 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2126 /* Open device key */
2127 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2128 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2130 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2131 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2132 if (!NT_SUCCESS(Status
))
2134 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2138 /* Read boot resources, and add then to parent ones */
2139 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2140 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2142 ExFreePool(pValueInformation
);
2143 ValueInfoLength
= RequiredSize
;
2144 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2145 if (!pValueInformation
)
2147 DPRINT("ExAllocatePool() failed\n");
2148 ZwDeleteKey(hLevel2Key
);
2149 Status
= STATUS_NO_MEMORY
;
2152 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2154 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2156 BootResources
= ParentBootResources
;
2157 BootResourcesLength
= ParentBootResourcesLength
;
2159 else if (!NT_SUCCESS(Status
))
2161 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2164 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2166 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2171 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2173 /* Concatenate current resources and parent ones */
2174 if (ParentBootResourcesLength
== 0)
2175 BootResourcesLength
= pValueInformation
->DataLength
;
2177 BootResourcesLength
= ParentBootResourcesLength
2178 + pValueInformation
->DataLength
2180 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2183 DPRINT("ExAllocatePool() failed\n");
2186 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2188 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2190 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2192 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2194 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2195 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2196 ParentBootResourcesLength
- Header
);
2197 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2201 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2203 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2204 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2205 ParentBootResourcesLength
- Header
);
2207 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2208 pValueInformation
->Data
+ Header
,
2209 pValueInformation
->DataLength
- Header
);
2210 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2214 if (EnumerateSubKeys
)
2219 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2220 if (Status
== STATUS_NO_MORE_ENTRIES
)
2222 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2224 ExFreePool(pDeviceInformation
);
2225 DeviceInfoLength
= RequiredSize
;
2226 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2227 if (!pDeviceInformation
)
2229 DPRINT("ExAllocatePool() failed\n");
2230 Status
= STATUS_NO_MEMORY
;
2233 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2235 if (!NT_SUCCESS(Status
))
2237 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2241 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2242 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2244 Status
= IopEnumerateDetectedDevices(
2250 BootResourcesLength
);
2251 if (!NT_SUCCESS(Status
))
2256 /* Read identifier */
2257 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2258 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2260 ExFreePool(pValueInformation
);
2261 ValueInfoLength
= RequiredSize
;
2262 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2263 if (!pValueInformation
)
2265 DPRINT("ExAllocatePool() failed\n");
2266 Status
= STATUS_NO_MEMORY
;
2269 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2271 if (!NT_SUCCESS(Status
))
2273 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2275 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2278 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2280 else if (pValueInformation
->Type
!= REG_SZ
)
2282 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2287 /* Assign hardware id to this device */
2288 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2289 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2290 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2291 ValueName
.Length
-= sizeof(WCHAR
);
2293 DPRINT1("RelativePath %wZ\n", RelativePath
);
2294 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2296 pHardwareId
= &HardwareIdSerial
;
2297 DeviceIndex
= DeviceIndexSerial
++;
2299 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2301 pHardwareId
= &HardwareIdKeyboard
;
2302 DeviceIndex
= DeviceIndexKeyboard
++;
2304 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2306 pHardwareId
= &HardwareIdMouse
;
2307 DeviceIndex
= DeviceIndexMouse
++;
2309 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
2311 pHardwareId
= &HardwareIdParallel
;
2312 DeviceIndex
= DeviceIndexParallel
++;
2314 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
2316 pHardwareId
= &HardwareIdFloppy
;
2317 DeviceIndex
= DeviceIndexFloppy
++;
2319 else if (NT_SUCCESS(Status
))
2321 /* Try to also match the device identifier */
2322 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2324 pHardwareId
= &HardwareIdPci
;
2325 DeviceIndex
= DeviceIndexPci
++;
2327 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
2329 pHardwareId
= &HardwareIdIsa
;
2330 DeviceIndex
= DeviceIndexIsa
++;
2332 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierSW
, FALSE
) == 0)
2334 pHardwareId
= &HardwareIdSW
;
2335 DeviceIndex
= DeviceIndexSW
++;
2339 DPRINT1("Unknown device '%wZ'\n", &ValueName
);
2345 /* Unknown key path */
2346 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2350 /* Prepare hardware id key (hardware id value without final \0) */
2351 HardwareIdKey
= *pHardwareId
;
2352 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2354 /* Add the detected device to Root key */
2355 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2356 Status
= ZwCreateKey(
2362 REG_OPTION_NON_VOLATILE
,
2364 if (!NT_SUCCESS(Status
))
2366 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2369 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2370 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2371 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2372 Status
= ZwCreateKey(
2374 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2378 REG_OPTION_NON_VOLATILE
,
2380 ZwClose(hLevel1Key
);
2381 if (!NT_SUCCESS(Status
))
2383 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2386 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
2387 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2388 if (!NT_SUCCESS(Status
))
2390 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2391 ZwDeleteKey(hLevel2Key
);
2394 /* Create 'LogConf' subkey */
2395 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2396 Status
= ZwCreateKey(
2402 REG_OPTION_VOLATILE
,
2404 if (!NT_SUCCESS(Status
))
2406 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2407 ZwDeleteKey(hLevel2Key
);
2410 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2412 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
2413 if (!CmResourceList
)
2416 ZwDeleteKey(hLevel2Key
);
2420 /* Add the list count (1st member of CM_RESOURCE_LIST) */
2422 RtlCopyMemory(CmResourceList
,
2426 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
2427 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
2429 BootResourcesLength
);
2431 /* Save boot resources to 'LogConf\BootConfig' */
2432 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
2433 if (!NT_SUCCESS(Status
))
2435 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2437 ZwDeleteKey(hLevel2Key
);
2444 if (BootResources
&& BootResources
!= ParentBootResources
)
2446 ExFreePool(BootResources
);
2447 BootResources
= NULL
;
2451 ZwClose(hLevel2Key
);
2456 ZwClose(hDeviceKey
);
2461 Status
= STATUS_SUCCESS
;
2464 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2465 ZwClose(hDevicesKey
);
2467 ZwClose(hDeviceKey
);
2468 if (pDeviceInformation
)
2469 ExFreePool(pDeviceInformation
);
2470 if (pValueInformation
)
2471 ExFreePool(pValueInformation
);
2475 static BOOLEAN INIT_FUNCTION
2476 IopIsAcpiComputer(VOID
)
2481 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2482 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2483 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2484 OBJECT_ATTRIBUTES ObjectAttributes
;
2485 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2486 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2487 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2488 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2490 ULONG IndexDevice
= 0;
2491 UNICODE_STRING DeviceName
, ValueName
;
2492 HANDLE hDevicesKey
= NULL
;
2493 HANDLE hDeviceKey
= NULL
;
2495 BOOLEAN ret
= FALSE
;
2497 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2498 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2499 if (!NT_SUCCESS(Status
))
2501 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2505 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2506 if (!pDeviceInformation
)
2508 DPRINT("ExAllocatePool() failed\n");
2509 Status
= STATUS_NO_MEMORY
;
2513 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2514 if (!pDeviceInformation
)
2516 DPRINT("ExAllocatePool() failed\n");
2517 Status
= STATUS_NO_MEMORY
;
2523 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2524 if (Status
== STATUS_NO_MORE_ENTRIES
)
2526 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2528 ExFreePool(pDeviceInformation
);
2529 DeviceInfoLength
= RequiredSize
;
2530 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2531 if (!pDeviceInformation
)
2533 DPRINT("ExAllocatePool() failed\n");
2534 Status
= STATUS_NO_MEMORY
;
2537 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2539 if (!NT_SUCCESS(Status
))
2541 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2546 /* Open device key */
2547 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2548 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2549 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2554 if (!NT_SUCCESS(Status
))
2556 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2560 /* Read identifier */
2561 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2562 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2564 ExFreePool(pValueInformation
);
2565 ValueInfoLength
= RequiredSize
;
2566 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2567 if (!pValueInformation
)
2569 DPRINT("ExAllocatePool() failed\n");
2570 Status
= STATUS_NO_MEMORY
;
2573 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2575 if (!NT_SUCCESS(Status
))
2577 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2580 else if (pValueInformation
->Type
!= REG_SZ
)
2582 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2586 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2587 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2588 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2589 ValueName
.Length
-= sizeof(WCHAR
);
2590 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
2592 DPRINT("Found ACPI BIOS\n");
2598 ZwClose(hDeviceKey
);
2603 if (pDeviceInformation
)
2604 ExFreePool(pDeviceInformation
);
2605 if (pValueInformation
)
2606 ExFreePool(pValueInformation
);
2608 ZwClose(hDevicesKey
);
2610 ZwClose(hDeviceKey
);
2617 IopUpdateRootKey(VOID
)
2619 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2620 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2621 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2622 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2623 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2624 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2625 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
2626 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
2627 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
2628 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2629 OBJECT_ATTRIBUTES ObjectAttributes
;
2630 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
2634 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2635 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2636 if (!NT_SUCCESS(Status
))
2638 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2642 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2643 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2645 if (!NT_SUCCESS(Status
))
2647 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2651 if (IopIsAcpiComputer())
2653 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
2654 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2656 if (!NT_SUCCESS(Status
))
2658 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
2659 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, 0, &Disposition
);
2660 ZwClose(hHalAcpiDevice
);
2661 if (!NT_SUCCESS(Status
))
2663 if (Disposition
== REG_CREATED_NEW_KEY
)
2665 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
2666 if (NT_SUCCESS(Status
))
2667 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
2669 if (NT_SUCCESS(Status
))
2671 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
2672 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2673 if (NT_SUCCESS(Status
))
2676 ZwClose(hHalAcpiId
);
2681 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2682 if (!NT_SUCCESS(Status
))
2684 /* Nothing to do, don't return with an error status */
2685 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2687 return STATUS_SUCCESS
;
2689 Status
= IopEnumerateDetectedDevices(
2704 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2706 PUNICODE_STRING Name
,
2707 ACCESS_MASK DesiredAccess
)
2709 OBJECT_ATTRIBUTES ObjectAttributes
;
2716 InitializeObjectAttributes(&ObjectAttributes
,
2718 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2722 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2729 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
2730 IN HANDLE RootHandle OPTIONAL
,
2731 IN PUNICODE_STRING KeyName
,
2732 IN ACCESS_MASK DesiredAccess
,
2733 IN ULONG CreateOptions
,
2734 OUT PULONG Disposition OPTIONAL
)
2736 OBJECT_ATTRIBUTES ObjectAttributes
;
2737 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0, Length
;
2738 HANDLE HandleArray
[2];
2739 BOOLEAN Recursing
= TRUE
;
2741 UNICODE_STRING KeyString
;
2742 NTSTATUS Status
= STATUS_SUCCESS
;
2745 /* P1 is start, pp is end */
2746 p1
= KeyName
->Buffer
;
2747 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
2749 /* Create the target key */
2750 InitializeObjectAttributes(&ObjectAttributes
,
2752 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2755 Status
= ZwCreateKey(&HandleArray
[i
],
2763 /* Now we check if this failed */
2764 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
2766 /* Target key failed, so we'll need to create its parent. Setup array */
2767 HandleArray
[0] = NULL
;
2768 HandleArray
[1] = RootHandle
;
2770 /* Keep recursing for each missing parent */
2773 /* And if we're deep enough, close the last handle */
2774 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2776 /* We're setup to ping-pong between the two handle array entries */
2777 RootHandleIndex
= i
;
2780 /* Clear the one we're attempting to open now */
2781 HandleArray
[i
] = NULL
;
2783 /* Process the parent key name */
2784 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
2785 Length
= (p
- p1
) * sizeof(WCHAR
);
2787 /* Is there a parent name? */
2790 /* Build the unicode string for it */
2791 KeyString
.Buffer
= p1
;
2792 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
2794 /* Now try opening the parent */
2795 InitializeObjectAttributes(&ObjectAttributes
,
2797 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2798 HandleArray
[RootHandleIndex
],
2800 Status
= ZwCreateKey(&HandleArray
[i
],
2807 if (NT_SUCCESS(Status
))
2809 /* It worked, we have one more handle */
2814 /* Parent key creation failed, abandon loop */
2821 /* We don't have a parent name, probably corrupted key name */
2822 Status
= STATUS_INVALID_PARAMETER
;
2827 /* Now see if there's more parents to create */
2829 if ((p
== pp
) || (p1
== pp
))
2831 /* We're done, hopefully successfully, so stop */
2836 /* Outer loop check for handle nesting that requires closing the top handle */
2837 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2840 /* Check if we broke out of the loop due to success */
2841 if (NT_SUCCESS(Status
))
2843 /* Return the target handle (we closed all the parent ones) and disposition */
2844 *Handle
= HandleArray
[i
];
2845 if (Disposition
) *Disposition
= KeyDisposition
;
2848 /* Return the success state */
2854 IopGetRegistryValue(IN HANDLE Handle
,
2856 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
2858 UNICODE_STRING ValueString
;
2860 PKEY_VALUE_FULL_INFORMATION FullInformation
;
2864 RtlInitUnicodeString(&ValueString
, ValueName
);
2866 Status
= ZwQueryValueKey(Handle
,
2868 KeyValueFullInformation
,
2872 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
2873 (Status
!= STATUS_BUFFER_TOO_SMALL
))
2878 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
2879 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
2881 Status
= ZwQueryValueKey(Handle
,
2883 KeyValueFullInformation
,
2887 if (!NT_SUCCESS(Status
))
2889 ExFreePool(FullInformation
);
2893 *Information
= FullInformation
;
2894 return STATUS_SUCCESS
;
2897 RTL_GENERIC_COMPARE_RESULTS
2899 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
2900 IN PVOID FirstStruct
,
2901 IN PVOID SecondStruct
)
2909 // The allocation function is called by the generic table package whenever
2910 // it needs to allocate memory for the table.
2915 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
2925 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
2934 PpInitializeDeviceReferenceTable(VOID
)
2936 /* Setup the guarded mutex and AVL table */
2937 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
2938 RtlInitializeGenericTableAvl(
2939 &PpDeviceReferenceTable
,
2940 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
2941 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
2942 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
2950 /* Initialize the resource when accessing device registry data */
2951 ExInitializeResourceLite(&PpRegistryDeviceResource
);
2953 /* Setup the device reference AVL table */
2954 PpInitializeDeviceReferenceTable();
2962 /* Check the initialization phase */
2963 switch (ExpInitializationPhase
)
2968 return PiInitPhase0();
2974 //return PiInitPhase1();
2978 /* Don't know any other phase! Bugcheck! */
2979 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
2984 LONG IopNumberDeviceNodes
;
2988 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
2990 PDEVICE_NODE DeviceNode
;
2994 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), 'donD');
2995 if (!DeviceNode
) return DeviceNode
;
2998 InterlockedIncrement(&IopNumberDeviceNodes
);
3001 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
3002 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
3003 DeviceNode
->BusNumber
= -1;
3004 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
3005 DeviceNode
->ChildBusNumber
= -1;
3006 DeviceNode
->ChildBusTypeIndex
= -1;
3007 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
3008 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
3009 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
3010 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
3011 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
3012 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
3014 /* Check if there is a PDO */
3015 if (PhysicalDeviceObject
)
3017 /* Link it and remove the init flag */
3018 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
3019 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
3020 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3023 /* Return the node */
3027 /* PUBLIC FUNCTIONS **********************************************************/
3031 PnpBusTypeGuidGet(IN USHORT Index
,
3032 IN LPGUID BusTypeGuid
)
3034 NTSTATUS Status
= STATUS_SUCCESS
;
3036 /* Acquire the lock */
3037 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
3040 if (Index
< PnpBusTypeGuidList
->GuidCount
)
3043 RtlCopyMemory(BusTypeGuid
, &PnpBusTypeGuidList
->Guids
[Index
], sizeof(GUID
));
3048 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
3051 /* Release lock and return status */
3052 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
3058 PpIrpQueryCapabilities(IN PDEVICE_OBJECT DeviceObject
,
3059 OUT PDEVICE_CAPABILITIES DeviceCaps
)
3062 IO_STACK_LOCATION Stack
;
3066 /* Set up the Header */
3067 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
3068 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
3069 DeviceCaps
->Version
= 1;
3070 DeviceCaps
->Address
= -1;
3071 DeviceCaps
->UINumber
= -1;
3073 /* Set up the Stack */
3074 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
3075 Stack
.MajorFunction
= IRP_MJ_PNP
;
3076 Stack
.MinorFunction
= IRP_MN_QUERY_CAPABILITIES
;
3077 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
3080 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
3085 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject
,
3086 IN PHANDLE DeviceInstanceHandle
,
3087 IN ACCESS_MASK DesiredAccess
)
3091 PDEVICE_NODE DeviceNode
;
3092 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
3095 /* Open the enum key */
3096 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
3100 if (!NT_SUCCESS(Status
)) return Status
;
3102 /* Make sure we have an instance path */
3103 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3104 if ((DeviceNode
) && (DeviceNode
->InstancePath
.Length
))
3106 /* Get the instance key */
3107 Status
= IopOpenRegistryKeyEx(DeviceInstanceHandle
,
3109 &DeviceNode
->InstancePath
,
3115 Status
= STATUS_INVALID_DEVICE_REQUEST
;
3118 /* Close the handle and return status */
3125 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList
)
3127 ULONG FinalSize
, PartialSize
, EntrySize
, i
, j
;
3128 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
3129 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
3131 /* If we don't have one, that's easy */
3132 if (!ResourceList
) return 0;
3134 /* Start with the minimum size possible */
3135 FinalSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
3137 /* Loop each full descriptor */
3138 FullDescriptor
= ResourceList
->List
;
3139 for (i
= 0; i
< ResourceList
->Count
; i
++)
3141 /* Start with the minimum size possible */
3142 PartialSize
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
) +
3143 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
);
3145 /* Loop each partial descriptor */
3146 PartialDescriptor
= FullDescriptor
->PartialResourceList
.PartialDescriptors
;
3147 for (j
= 0; j
< FullDescriptor
->PartialResourceList
.Count
; j
++)
3149 /* Start with the minimum size possible */
3150 EntrySize
= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
3152 /* Check if there is extra data */
3153 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
3156 EntrySize
+= PartialDescriptor
->u
.DeviceSpecificData
.DataSize
;
3159 /* The size of partial descriptors is bigger */
3160 PartialSize
+= EntrySize
;
3162 /* Go to the next partial descriptor */
3163 PartialDescriptor
= (PVOID
)((ULONG_PTR
)PartialDescriptor
+ EntrySize
);
3166 /* The size of full descriptors is bigger */
3167 FinalSize
+= PartialSize
;
3169 /* Go to the next full descriptor */
3170 FullDescriptor
= (PVOID
)((ULONG_PTR
)FullDescriptor
+ PartialSize
);
3173 /* Return the final size */
3179 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject
,
3184 IN PULONG BufferLength
)
3187 HANDLE KeyHandle
, SubHandle
;
3188 UNICODE_STRING KeyString
;
3189 PKEY_VALUE_FULL_INFORMATION KeyValueInfo
= NULL
;
3193 /* Find the instance key */
3194 Status
= PnpDeviceObjectToDeviceInstance(DeviceObject
, &KeyHandle
, KEY_READ
);
3195 if (NT_SUCCESS(Status
))
3197 /* Check for name given by caller */
3201 RtlInitUnicodeString(&KeyString
, KeyName
);
3202 Status
= IopOpenRegistryKeyEx(&SubHandle
,
3206 if (NT_SUCCESS(Status
))
3208 /* And use this handle instead */
3210 KeyHandle
= SubHandle
;
3214 /* Check if sub-key handle succeeded (or no-op if no key name given) */
3215 if (NT_SUCCESS(Status
))
3217 /* Now get the size of the property */
3218 Status
= IopGetRegistryValue(KeyHandle
,
3227 /* Fail if any of the registry operations failed */
3228 if (!NT_SUCCESS(Status
)) return Status
;
3230 /* Check how much data we have to copy */
3231 Length
= KeyValueInfo
->DataLength
;
3232 if (*BufferLength
>= Length
)
3234 /* Check for a match in the value type */
3235 if (KeyValueInfo
->Type
== ValueType
)
3238 RtlCopyMemory(Buffer
,
3239 (PVOID
)((ULONG_PTR
)KeyValueInfo
+
3240 KeyValueInfo
->DataOffset
),
3245 /* Invalid registry property type, fail */
3246 Status
= STATUS_INVALID_PARAMETER_2
;
3251 /* Buffer is too small to hold data */
3252 Status
= STATUS_BUFFER_TOO_SMALL
;
3255 /* Return the required buffer length, free the buffer, and return status */
3256 *BufferLength
= Length
;
3257 ExFreePool(KeyValueInfo
);
3261 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
3262 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
3263 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED; while(TRUE); break;}
3270 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3271 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3272 IN ULONG BufferLength
,
3273 OUT PVOID PropertyBuffer
,
3274 OUT PULONG ResultLength
)
3276 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3277 DEVICE_CAPABILITIES DeviceCaps
;
3278 ULONG ReturnLength
= 0, Length
= 0, ValueType
;
3279 PWCHAR ValueName
= NULL
, EnumeratorNameEnd
, DeviceInstanceName
;
3281 NTSTATUS Status
= STATUS_BUFFER_TOO_SMALL
;
3283 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
3284 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3286 /* Assume failure */
3289 /* Only PDOs can call this */
3290 if (!DeviceNode
) return STATUS_INVALID_DEVICE_REQUEST
;
3292 /* Handle all properties */
3293 switch (DeviceProperty
)
3295 case DevicePropertyBusTypeGuid
:
3297 /* Get the GUID from the internal cache */
3298 Status
= PnpBusTypeGuidGet(DeviceNode
->ChildBusTypeIndex
, &BusTypeGuid
);
3299 if (!NT_SUCCESS(Status
)) return Status
;
3301 /* This is the format of the returned data */
3302 PIP_RETURN_DATA(sizeof(GUID
), &BusTypeGuid
);
3304 case DevicePropertyLegacyBusType
:
3306 /* Validate correct interface type */
3307 if (DeviceNode
->ChildInterfaceType
== InterfaceTypeUndefined
)
3308 return STATUS_OBJECT_NAME_NOT_FOUND
;
3310 /* This is the format of the returned data */
3311 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE
), &DeviceNode
->ChildInterfaceType
);
3313 case DevicePropertyBusNumber
:
3315 /* Validate correct bus number */
3316 if ((DeviceNode
->ChildBusNumber
& 0x80000000) == 0x80000000)
3317 return STATUS_OBJECT_NAME_NOT_FOUND
;
3319 /* This is the format of the returned data */
3320 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceNode
->ChildBusNumber
);
3322 case DevicePropertyEnumeratorName
:
3324 /* Get the instance path */
3325 DeviceInstanceName
= DeviceNode
->InstancePath
.Buffer
;
3328 ASSERT((BufferLength
& 1) == 0);
3329 ASSERT(DeviceInstanceName
!= NULL
);
3331 /* Get the name from the path */
3332 EnumeratorNameEnd
= wcschr(DeviceInstanceName
, OBJ_NAME_PATH_SEPARATOR
);
3333 ASSERT(EnumeratorNameEnd
);
3335 /* This is the format of the returned data */
3336 PIP_RETURN_DATA((EnumeratorNameEnd
- DeviceInstanceName
) * sizeof(WCHAR
),
3337 DeviceInstanceName
);
3339 case DevicePropertyAddress
:
3341 /* Query the device caps */
3342 Status
= PpIrpQueryCapabilities(DeviceObject
, &DeviceCaps
);
3343 if (!NT_SUCCESS(Status
) || (DeviceCaps
.Address
== MAXULONG
))
3344 return STATUS_OBJECT_NAME_NOT_FOUND
;
3346 /* This is the format of the returned data */
3347 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceCaps
.Address
);
3349 case DevicePropertyBootConfigurationTranslated
:
3351 /* Validate we have resources */
3352 if (!DeviceNode
->BootResources
)
3353 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
3355 /* No resources will still fake success, but with 0 bytes */
3357 return STATUS_SUCCESS
;
3360 /* This is the format of the returned data */
3361 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode
->BootResources
), // FIXFIX: Should use BootResourcesTranslated
3362 DeviceNode
->BootResources
); // FIXFIX: Should use BootResourcesTranslated
3364 case DevicePropertyPhysicalDeviceObjectName
:
3366 /* Sanity check for Unicode-sized string */
3367 ASSERT((BufferLength
& 1) == 0);
3369 /* Allocate name buffer */
3370 Length
= BufferLength
+ sizeof(OBJECT_NAME_INFORMATION
);
3371 ObjectNameInfo
= ExAllocatePool(PagedPool
, Length
);
3372 if (!ObjectNameInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
3374 /* Query the PDO name */
3375 Status
= ObQueryNameString(DeviceObject
,
3379 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
3381 /* It's up to the caller to try again */
3382 Status
= STATUS_BUFFER_TOO_SMALL
;
3385 /* Return if successful */
3386 if (NT_SUCCESS(Status
)) PIP_RETURN_DATA(ObjectNameInfo
->Name
.Length
,
3387 ObjectNameInfo
->Name
.Buffer
);
3389 /* Let the caller know how big the name is */
3390 *ResultLength
-= sizeof(OBJECT_NAME_INFORMATION
);
3393 /* Handle the registry-based properties */
3394 case DevicePropertyUINumber
:
3395 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER
, REG_DWORD
);
3396 case DevicePropertyLocationInformation
:
3397 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION
, REG_SZ
);
3398 case DevicePropertyDeviceDescription
:
3399 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC
, REG_SZ
);
3400 case DevicePropertyHardwareID
:
3401 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID
, REG_MULTI_SZ
);
3402 case DevicePropertyCompatibleIDs
:
3403 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS
, REG_MULTI_SZ
);
3404 case DevicePropertyBootConfiguration
:
3405 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG
, REG_RESOURCE_LIST
);
3406 case DevicePropertyClassName
:
3407 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS
, REG_SZ
);
3408 case DevicePropertyClassGuid
:
3409 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID
, REG_SZ
);
3410 case DevicePropertyDriverKeyName
:
3411 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER
, REG_SZ
);
3412 case DevicePropertyManufacturer
:
3413 PIP_REGISTRY_DATA(REGSTR_VAL_MFG
, REG_SZ
);
3414 case DevicePropertyFriendlyName
:
3415 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME
, REG_SZ
);
3416 case DevicePropertyContainerID
:
3417 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
3418 PIP_UNIMPLEMENTED();
3419 case DevicePropertyRemovalPolicy
:
3420 PIP_UNIMPLEMENTED();
3421 case DevicePropertyInstallState
:
3422 PIP_UNIMPLEMENTED();
3423 case DevicePropertyResourceRequirements
:
3424 PIP_UNIMPLEMENTED();
3425 case DevicePropertyAllocatedResources
:
3426 PIP_UNIMPLEMENTED();
3428 return STATUS_INVALID_PARAMETER_2
;
3431 /* Having a registry value name implies registry data */
3434 /* We know up-front how much data to expect */
3435 *ResultLength
= BufferLength
;
3437 /* Go get the data, use the LogConf subkey if necessary */
3438 Status
= PiGetDeviceRegistryProperty(DeviceObject
,
3442 DevicePropertyBootConfiguration
) ?
3447 else if (NT_SUCCESS(Status
))
3449 /* We know up-front how much data to expect, check the caller's buffer */
3450 *ResultLength
= ReturnLength
;
3451 if (ReturnLength
<= BufferLength
)
3453 /* Buffer is all good, copy the data */
3454 RtlCopyMemory(PropertyBuffer
, Data
, ReturnLength
);
3456 /* Check for properties that require a null-terminated string */
3457 if ((DeviceProperty
== DevicePropertyEnumeratorName
) ||
3458 (DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
))
3460 /* Terminate the string */
3461 ((PWCHAR
)PropertyBuffer
)[ReturnLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3464 /* This is the success path */
3465 Status
= STATUS_SUCCESS
;
3470 Status
= STATUS_BUFFER_TOO_SMALL
;
3474 /* Free any allocation we may have made, and return the status code */
3475 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
3484 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3490 * @name IoOpenDeviceRegistryKey
3492 * Open a registry key unique for a specified driver or device instance.
3494 * @param DeviceObject Device to get the registry key for.
3495 * @param DevInstKeyType Type of the key to return.
3496 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
3497 * @param DevInstRegKey Handle to the opened registry key on
3498 * successful return.
3506 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
3507 IN ULONG DevInstKeyType
,
3508 IN ACCESS_MASK DesiredAccess
,
3509 OUT PHANDLE DevInstRegKey
)
3511 static WCHAR RootKeyName
[] =
3512 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
3513 static WCHAR ProfileKeyName
[] =
3514 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
3515 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
3516 static WCHAR EnumKeyName
[] = L
"Enum\\";
3517 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
3518 ULONG KeyNameLength
;
3519 LPWSTR KeyNameBuffer
;
3520 UNICODE_STRING KeyName
;
3521 ULONG DriverKeyLength
;
3522 OBJECT_ATTRIBUTES ObjectAttributes
;
3523 PDEVICE_NODE DeviceNode
= NULL
;
3526 DPRINT("IoOpenDeviceRegistryKey() called\n");
3528 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
3530 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
3531 return STATUS_INVALID_PARAMETER
;
3534 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
3535 return STATUS_INVALID_DEVICE_REQUEST
;
3536 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3539 * Calculate the length of the base key name. This is the full
3540 * name for driver key or the name excluding "Device Parameters"
3541 * subkey for device key.
3544 KeyNameLength
= sizeof(RootKeyName
);
3545 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3546 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
3547 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3549 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
3550 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3551 0, NULL
, &DriverKeyLength
);
3552 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
3554 KeyNameLength
+= DriverKeyLength
;
3558 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
3559 DeviceNode
->InstancePath
.Length
;
3563 * Now allocate the buffer for the key name...
3566 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
3567 if (KeyNameBuffer
== NULL
)
3568 return STATUS_INSUFFICIENT_RESOURCES
;
3571 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
3572 KeyName
.Buffer
= KeyNameBuffer
;
3575 * ...and build the key name.
3578 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
3579 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
3581 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3582 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
3584 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3586 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
3587 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3588 DriverKeyLength
, KeyNameBuffer
+
3589 (KeyName
.Length
/ sizeof(WCHAR
)),
3591 if (!NT_SUCCESS(Status
))
3593 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
3594 ExFreePool(KeyNameBuffer
);
3597 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
3601 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
3602 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
3603 if (DeviceNode
->InstancePath
.Length
== 0)
3605 ExFreePool(KeyNameBuffer
);
3611 * Open the base key.
3613 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
3614 if (!NT_SUCCESS(Status
))
3616 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
3617 ExFreePool(KeyNameBuffer
);
3620 ExFreePool(KeyNameBuffer
);
3623 * For driver key we're done now.
3626 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3630 * Let's go further. For device key we must open "Device Parameters"
3631 * subkey and create it if it doesn't exist yet.
3634 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
3635 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
3636 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
3637 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
3638 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
3639 ZwClose(ObjectAttributes
.RootDirectory
);
3649 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3659 IoInvalidateDeviceRelations(
3660 IN PDEVICE_OBJECT DeviceObject
,
3661 IN DEVICE_RELATION_TYPE Type
)
3663 PIO_WORKITEM WorkItem
;
3664 PINVALIDATE_DEVICE_RELATION_DATA Data
;
3666 Data
= ExAllocatePool(NonPagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
3669 WorkItem
= IoAllocateWorkItem(DeviceObject
);
3676 ObReferenceObject(DeviceObject
);
3677 Data
->DeviceObject
= DeviceObject
;
3679 Data
->WorkItem
= WorkItem
;
3683 IopAsynchronousInvalidateDeviceRelations
,
3693 IoSynchronousInvalidateDeviceRelations(
3694 IN PDEVICE_OBJECT DeviceObject
,
3695 IN DEVICE_RELATION_TYPE Type
)
3702 /* Enumerate the device */
3703 return IopEnumerateDevice(DeviceObject
);
3704 case PowerRelations
:
3705 /* Not handled yet */
3706 return STATUS_NOT_IMPLEMENTED
;
3707 case TargetDeviceRelation
:
3709 return STATUS_SUCCESS
;
3711 /* Ejection relations are not supported */
3712 return STATUS_NOT_SUPPORTED
;
3721 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
3723 IN PHYSICAL_ADDRESS BusAddress
,
3724 IN OUT PULONG AddressSpace
,
3725 OUT PPHYSICAL_ADDRESS TranslatedAddress
)