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
)
68 if (!DriverObject
->DriverExtension
->AddDevice
)
70 DeviceNode
->Flags
|= DNF_LEGACY_DRIVER
;
73 if (DeviceNode
->Flags
& DNF_LEGACY_DRIVER
)
75 DeviceNode
->Flags
|= DNF_ADDED
+ DNF_STARTED
;
76 return STATUS_SUCCESS
;
79 /* This is a Plug and Play driver */
80 DPRINT("Plug and Play driver found\n");
81 ASSERT(DeviceNode
->PhysicalDeviceObject
);
83 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
84 &DriverObject
->DriverName
,
85 &DeviceNode
->InstancePath
);
86 Status
= DriverObject
->DriverExtension
->AddDevice(
87 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
88 if (!NT_SUCCESS(Status
))
90 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
94 /* Check if driver added a FDO above the PDO */
95 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
96 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
98 /* FIXME: What do we do? Unload the driver or just disable the device? */
99 DPRINT1("An FDO was not attached\n");
100 ObDereferenceObject(Fdo
);
101 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
102 return STATUS_UNSUCCESSFUL
;
105 /* Check if we have a ACPI device (needed for power management) */
106 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
108 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
110 /* There can be only one system power device */
111 if (!SystemPowerDeviceNodeCreated
)
113 PopSystemPowerDeviceNode
= DeviceNode
;
114 ObReferenceObject(PopSystemPowerDeviceNode
);
115 SystemPowerDeviceNodeCreated
= TRUE
;
119 ObDereferenceObject(Fdo
);
121 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
123 return STATUS_SUCCESS
;
128 IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
130 IO_STACK_LOCATION Stack
;
133 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
134 Stack
.MajorFunction
= IRP_MJ_PNP
;
135 Stack
.MinorFunction
= IRP_MN_REMOVE_DEVICE
;
137 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
138 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
143 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject
)
145 IO_STACK_LOCATION Stack
;
146 PDEVICE_NODE DeviceNode
;
150 /* Get the device node */
151 DeviceNode
= IopGetDeviceNode(DeviceObject
);
153 /* Build the I/O stack locaiton */
154 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
155 Stack
.MajorFunction
= IRP_MJ_PNP
;
156 Stack
.MinorFunction
= IRP_MN_START_DEVICE
;
158 /* Check if we didn't already report the resources */
159 if (!(DeviceNode
->Flags
& DNF_RESOURCE_REPORTED
))
162 Stack
.Parameters
.StartDevice
.AllocatedResources
=
163 DeviceNode
->ResourceList
;
164 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
=
165 DeviceNode
->ResourceListTranslated
;
168 /* I don't think we set this flag yet */
169 ASSERT(!(DeviceNode
->Flags
& DNF_STOPPED
));
172 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
173 if (!NT_SUCCESS(Status
))
175 /* Send an IRP_MN_REMOVE_DEVICE request */
176 IopSendRemoveDevice(DeviceObject
);
178 /* Set the appropriate flag */
179 DeviceNode
->Flags
|= DNF_START_FAILED
;
181 DPRINT1("Warning: PnP Start failed (%wZ)\n", &DeviceNode
->InstancePath
);
185 /* Otherwise, mark us as started */
186 DeviceNode
->Flags
|= DNF_STARTED
;
188 /* We now need enumeration */
189 DeviceNode
->Flags
|= DNF_NEED_ENUMERATION_ONLY
;
194 IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode
)
196 PDEVICE_OBJECT DeviceObject
;
201 ASSERT((DeviceNode
->Flags
& DNF_ADDED
));
202 ASSERT((DeviceNode
->Flags
& (DNF_RESOURCE_ASSIGNED
|
203 DNF_RESOURCE_REPORTED
|
204 DNF_NO_RESOURCE_REQUIRED
)));
205 ASSERT((!(DeviceNode
->Flags
& (DNF_HAS_PROBLEM
|
207 DNF_START_REQUEST_PENDING
))));
209 /* Get the device object */
210 DeviceObject
= DeviceNode
->PhysicalDeviceObject
;
212 /* Check if we're not started yet */
213 if (!(DeviceNode
->Flags
& DNF_STARTED
))
216 IopStartDevice2(DeviceObject
);
219 /* Do we need to query IDs? This happens in the case of manual reporting */
221 if (DeviceNode
->Flags
& DNF_NEED_QUERY_IDS
)
223 DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
224 /* And that case shouldn't happen yet */
229 /* Make sure we're started, and check if we need enumeration */
230 if ((DeviceNode
->Flags
& DNF_STARTED
) &&
231 (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
))
234 IoSynchronousInvalidateDeviceRelations(DeviceObject
, BusRelations
);
235 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
236 Status
= STATUS_SUCCESS
;
241 Status
= STATUS_SUCCESS
;
250 PDEVICE_NODE DeviceNode
)
253 HANDLE InstanceHandle
= INVALID_HANDLE_VALUE
, ControlHandle
= INVALID_HANDLE_VALUE
;
254 UNICODE_STRING KeyName
;
255 OBJECT_ATTRIBUTES ObjectAttributes
;
257 if (DeviceNode
->Flags
& (DNF_STARTED
| DNF_START_REQUEST_PENDING
))
259 /* Nothing to do here */
260 return STATUS_SUCCESS
;
263 Status
= IopAssignDeviceResources(DeviceNode
);
264 if (!NT_SUCCESS(Status
))
268 IopStartAndEnumerateDevice(DeviceNode
);
270 /* FIX: Should be done in new device instance code */
271 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceHandle
);
272 if (!NT_SUCCESS(Status
))
275 /* FIX: Should be done in IoXxxPrepareDriverLoading */
277 RtlInitUnicodeString(&KeyName
, L
"Control");
278 InitializeObjectAttributes(&ObjectAttributes
,
280 OBJ_CASE_INSENSITIVE
,
283 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
284 if (!NT_SUCCESS(Status
))
287 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
288 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
292 if (ControlHandle
!= INVALID_HANDLE_VALUE
)
293 ZwClose(ControlHandle
);
295 if (InstanceHandle
!= INVALID_HANDLE_VALUE
)
296 ZwClose(InstanceHandle
);
303 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
304 PDEVICE_CAPABILITIES DeviceCaps
)
306 IO_STATUS_BLOCK StatusBlock
;
307 IO_STACK_LOCATION Stack
;
309 /* Set up the Header */
310 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
311 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
312 DeviceCaps
->Version
= 1;
313 DeviceCaps
->Address
= -1;
314 DeviceCaps
->UINumber
= -1;
316 /* Set up the Stack */
317 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
318 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
321 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
323 IRP_MN_QUERY_CAPABILITIES
,
328 IopAsynchronousInvalidateDeviceRelations(
329 IN PDEVICE_OBJECT DeviceObject
,
330 IN PVOID InvalidateContext
)
332 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
334 IoSynchronousInvalidateDeviceRelations(
338 ObDereferenceObject(Data
->DeviceObject
);
339 IoFreeWorkItem(Data
->WorkItem
);
344 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
348 if (PopSystemPowerDeviceNode
)
350 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
351 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
352 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
354 return STATUS_SUCCESS
;
357 return STATUS_UNSUCCESSFUL
;
362 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
364 USHORT i
= 0, FoundIndex
= 0xFFFF;
368 /* Acquire the lock */
369 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
371 /* Loop all entries */
372 while (i
< PnpBusTypeGuidList
->GuidCount
)
374 /* Try to find a match */
375 if (RtlCompareMemory(BusTypeGuid
,
376 &PnpBusTypeGuidList
->Guids
[i
],
377 sizeof(GUID
)) == sizeof(GUID
))
386 /* Check if we have to grow the list */
387 if (PnpBusTypeGuidList
->GuidCount
)
389 /* Calculate the new size */
390 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
391 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
393 /* Allocate the new copy */
394 NewList
= ExAllocatePool(PagedPool
, NewSize
);
398 ExFreePool(PnpBusTypeGuidList
);
402 /* Now copy them, decrease the size too */
403 NewSize
-= sizeof(GUID
);
404 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
406 /* Free the old list */
407 ExFreePool(PnpBusTypeGuidList
);
409 /* Use the new buffer */
410 PnpBusTypeGuidList
= NewList
;
413 /* Copy the new GUID */
414 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
418 /* The new entry is the index */
419 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
420 PnpBusTypeGuidList
->GuidCount
++;
423 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
429 * Creates a device node
432 * ParentNode = Pointer to parent device node
433 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
434 * to have the root device node create one
435 * (eg. for legacy drivers)
436 * DeviceNode = Pointer to storage for created device node
442 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
443 PDEVICE_OBJECT PhysicalDeviceObject
,
444 PUNICODE_STRING ServiceName
,
445 PDEVICE_NODE
*DeviceNode
)
450 UNICODE_STRING FullServiceName
;
451 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
452 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
453 UNICODE_STRING KeyName
, ClassName
;
454 PUNICODE_STRING ServiceName1
;
457 UNICODE_STRING ClassGUID
;
459 HANDLE InstanceHandle
;
461 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
462 ParentNode
, PhysicalDeviceObject
, ServiceName
);
464 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
467 return STATUS_INSUFFICIENT_RESOURCES
;
470 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
473 ServiceName1
= &UnknownDeviceName
;
475 ServiceName1
= ServiceName
;
477 if (!PhysicalDeviceObject
)
479 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
480 FullServiceName
.Length
= 0;
481 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
482 if (!FullServiceName
.Buffer
)
485 return STATUS_INSUFFICIENT_RESOURCES
;
488 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
489 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
491 Status
= PnpRootCreateDevice(&FullServiceName
, &PhysicalDeviceObject
, &Node
->InstancePath
);
492 if (!NT_SUCCESS(Status
))
494 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
499 /* Create the device key for legacy drivers */
500 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
501 if (!NT_SUCCESS(Status
))
503 ZwClose(InstanceHandle
);
505 ExFreePool(FullServiceName
.Buffer
);
509 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
510 if (!Node
->ServiceName
.Buffer
)
512 ZwClose(InstanceHandle
);
514 ExFreePool(FullServiceName
.Buffer
);
518 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
519 Node
->ServiceName
.Length
= 0;
521 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
525 RtlInitUnicodeString(&KeyName
, L
"Service");
526 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
529 if (NT_SUCCESS(Status
))
531 RtlInitUnicodeString(&KeyName
, L
"Legacy");
534 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
535 if (NT_SUCCESS(Status
))
537 RtlInitUnicodeString(&KeyName
, L
"Class");
539 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
540 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
);
542 if (NT_SUCCESS(Status
))
544 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
546 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
547 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
);
553 ZwClose(InstanceHandle
);
554 ExFreePool(FullServiceName
.Buffer
);
556 if (!NT_SUCCESS(Status
))
562 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
563 IopDeviceNodeSetFlag(Node
, DNF_ADDED
);
564 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
567 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
569 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
573 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
574 Node
->Parent
= ParentNode
;
575 Node
->Sibling
= ParentNode
->Child
;
576 ParentNode
->Child
= Node
;
577 if (ParentNode
->LastChild
== NULL
)
578 ParentNode
->LastChild
= Node
;
579 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
580 Node
->Level
= ParentNode
->Level
+ 1;
583 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
587 return STATUS_SUCCESS
;
591 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
594 PDEVICE_NODE PrevSibling
= NULL
;
596 /* All children must be deleted before a parent is deleted */
597 ASSERT(!DeviceNode
->Child
);
599 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
601 ASSERT(DeviceNode
->PhysicalDeviceObject
);
603 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
605 /* Get previous sibling */
606 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
608 PrevSibling
= DeviceNode
->Parent
->Child
;
609 while (PrevSibling
->Sibling
!= DeviceNode
)
610 PrevSibling
= PrevSibling
->Sibling
;
613 /* Unlink from parent if it exists */
614 if (DeviceNode
->Parent
)
616 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
618 DeviceNode
->Parent
->LastChild
= PrevSibling
;
620 PrevSibling
->Sibling
= NULL
;
622 if (DeviceNode
->Parent
->Child
== DeviceNode
)
623 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
626 /* Unlink from sibling list */
628 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
630 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
632 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
634 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
636 if (DeviceNode
->ResourceList
)
638 ExFreePool(DeviceNode
->ResourceList
);
641 if (DeviceNode
->ResourceListTranslated
)
643 ExFreePool(DeviceNode
->ResourceListTranslated
);
646 if (DeviceNode
->ResourceRequirements
)
648 ExFreePool(DeviceNode
->ResourceRequirements
);
651 if (DeviceNode
->BootResources
)
653 ExFreePool(DeviceNode
->BootResources
);
656 ExFreePool(DeviceNode
);
658 return STATUS_SUCCESS
;
663 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
664 IN PIO_STACK_LOCATION IoStackLocation
,
665 OUT PVOID
*Information
)
668 PIO_STACK_LOCATION IrpStack
;
669 IO_STATUS_BLOCK IoStatusBlock
;
672 PDEVICE_OBJECT TopDeviceObject
;
675 /* Call the top of the device stack */
676 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
678 /* Allocate an IRP */
679 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
680 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
682 /* Initialize to failure */
683 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
684 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
686 /* Initialize the event */
687 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
690 Irp
->UserIosb
= &IoStatusBlock
;
691 Irp
->UserEvent
= &Event
;
694 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
695 IoQueueThreadIrp(Irp
);
697 /* Copy-in the stack */
698 IrpStack
= IoGetNextIrpStackLocation(Irp
);
699 *IrpStack
= *IoStackLocation
;
701 /* Call the driver */
702 Status
= IoCallDriver(TopDeviceObject
, Irp
);
703 if (Status
== STATUS_PENDING
)
706 KeWaitForSingleObject(&Event
,
711 Status
= IoStatusBlock
.Status
;
714 /* Return the information */
715 *Information
= (PVOID
)IoStatusBlock
.Information
;
721 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
722 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
723 IN ULONG MinorFunction
,
724 IN PIO_STACK_LOCATION Stack OPTIONAL
)
726 IO_STACK_LOCATION IoStackLocation
;
728 /* Fill out the stack information */
729 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
730 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
731 IoStackLocation
.MinorFunction
= MinorFunction
;
735 RtlCopyMemory(&IoStackLocation
.Parameters
,
737 sizeof(Stack
->Parameters
));
740 /* Do the PnP call */
741 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
743 (PVOID
)&IoStatusBlock
->Information
);
744 return IoStatusBlock
->Status
;
748 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
750 PDEVICE_NODE ParentDeviceNode
;
751 PDEVICE_NODE ChildDeviceNode
;
754 /* Copy context data so we don't overwrite it in subsequent calls to this function */
755 ParentDeviceNode
= Context
->DeviceNode
;
757 /* Call the action routine */
758 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
759 if (!NT_SUCCESS(Status
))
764 /* Traversal of all children nodes */
765 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
766 ChildDeviceNode
!= NULL
;
767 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
769 /* Pass the current device node to the action routine */
770 Context
->DeviceNode
= ChildDeviceNode
;
772 Status
= IopTraverseDeviceTreeNode(Context
);
773 if (!NT_SUCCESS(Status
))
784 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
788 DPRINT("Context 0x%p\n", Context
);
790 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
791 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
793 /* Start from the specified device node */
794 Context
->DeviceNode
= Context
->FirstDeviceNode
;
796 /* Recursively traverse the device tree */
797 Status
= IopTraverseDeviceTreeNode(Context
);
798 if (Status
== STATUS_UNSUCCESSFUL
)
800 /* The action routine just wanted to terminate the traversal with status
801 code STATUS_SUCCESS */
802 Status
= STATUS_SUCCESS
;
810 * IopCreateDeviceKeyPath
812 * Creates a registry key
816 * Name of the key to be created.
818 * Handle to the newly created key
821 * This method can create nested trees, so parent of RegistryPath can
822 * be not existant, and will be created if needed.
826 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
827 IN ULONG CreateOptions
,
830 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
831 HANDLE hParent
= NULL
, hKey
;
832 OBJECT_ATTRIBUTES ObjectAttributes
;
833 UNICODE_STRING KeyName
;
834 LPCWSTR Current
, Last
;
841 /* Open root key for device instances */
842 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
843 if (!NT_SUCCESS(Status
))
845 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
849 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
850 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
852 /* Go up to the end of the string */
853 while (Current
<= Last
)
855 if (Current
!= Last
&& *Current
!= '\\')
857 /* Not the end of the string and not a separator */
862 /* Prepare relative key name */
863 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
864 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
865 DPRINT("Create '%wZ'\n", &KeyName
);
868 InitializeObjectAttributes(&ObjectAttributes
,
870 OBJ_CASE_INSENSITIVE
,
873 Status
= ZwCreateKey(&hKey
,
874 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
881 /* Close parent key handle, we don't need it anymore */
885 /* Key opening/creating failed? */
886 if (!NT_SUCCESS(Status
))
888 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
892 /* Check if it is the end of the string */
895 /* Yes, return success */
897 return STATUS_SUCCESS
;
900 /* Start with this new parent key */
903 KeyName
.Buffer
= (LPWSTR
)Current
;
906 return STATUS_UNSUCCESSFUL
;
910 IopSetDeviceInstanceData(HANDLE InstanceKey
,
911 PDEVICE_NODE DeviceNode
)
913 OBJECT_ATTRIBUTES ObjectAttributes
;
914 UNICODE_STRING KeyName
;
919 HANDLE ControlHandle
;
921 DPRINT("IopSetDeviceInstanceData() called\n");
923 /* Create the 'LogConf' key */
924 RtlInitUnicodeString(&KeyName
, L
"LogConf");
925 InitializeObjectAttributes(&ObjectAttributes
,
927 OBJ_CASE_INSENSITIVE
,
930 Status
= ZwCreateKey(&LogConfKey
,
937 if (NT_SUCCESS(Status
))
939 /* Set 'BootConfig' value */
940 if (DeviceNode
->BootResources
!= NULL
)
942 ResCount
= DeviceNode
->BootResources
->Count
;
945 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
946 Status
= ZwSetValueKey(LogConfKey
,
950 DeviceNode
->BootResources
,
951 PnpDetermineResourceListSize(DeviceNode
->BootResources
));
955 /* Set 'BasicConfigVector' value */
956 if (DeviceNode
->ResourceRequirements
!= NULL
&&
957 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
959 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
960 Status
= ZwSetValueKey(LogConfKey
,
963 REG_RESOURCE_REQUIREMENTS_LIST
,
964 DeviceNode
->ResourceRequirements
,
965 DeviceNode
->ResourceRequirements
->ListSize
);
971 /* Set the 'ConfigFlags' value */
972 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
973 Status
= ZwQueryValueKey(InstanceKey
,
975 KeyValueBasicInformation
,
979 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
981 /* Write the default value */
982 ULONG DefaultConfigFlags
= 0;
983 Status
= ZwSetValueKey(InstanceKey
,
988 sizeof(DefaultConfigFlags
));
991 /* Create the 'Control' key */
992 RtlInitUnicodeString(&KeyName
, L
"Control");
993 InitializeObjectAttributes(&ObjectAttributes
,
995 OBJ_CASE_INSENSITIVE
,
998 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1000 if (NT_SUCCESS(Status
))
1001 ZwClose(ControlHandle
);
1003 DPRINT("IopSetDeviceInstanceData() done\n");
1009 * IopGetParentIdPrefix
1011 * Retrieve (or create) a string which identifies a device.
1015 * Pointer to device node.
1017 * Pointer to the string where is returned the parent node identifier
1020 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1021 * valid and its Buffer field is NULL-terminated. The caller needs to
1022 * to free the string with RtlFreeUnicodeString when it is no longer
1027 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1028 PUNICODE_STRING ParentIdPrefix
)
1030 ULONG KeyNameBufferLength
;
1031 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1032 UNICODE_STRING KeyName
;
1033 UNICODE_STRING KeyValue
;
1034 UNICODE_STRING ValueName
;
1039 /* HACK: As long as some devices have a NULL device
1040 * instance path, the following test is required :(
1042 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1044 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1045 &DeviceNode
->InstancePath
);
1046 return STATUS_UNSUCCESSFUL
;
1049 /* 1. Try to retrieve ParentIdPrefix from registry */
1050 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1051 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1052 if (!ParentIdPrefixInformation
)
1054 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1059 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1060 if (!KeyName
.Buffer
)
1062 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1066 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1068 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1069 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1071 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1072 if (!NT_SUCCESS(Status
))
1074 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1075 Status
= ZwQueryValueKey(
1077 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1078 KeyNameBufferLength
, &KeyNameBufferLength
);
1079 if (NT_SUCCESS(Status
))
1081 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1082 Status
= STATUS_UNSUCCESSFUL
;
1085 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1086 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1090 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1092 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1093 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1097 /* 2. Create the ParentIdPrefix value */
1098 crc32
= RtlComputeCrc32(0,
1099 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1100 DeviceNode
->Parent
->InstancePath
.Length
);
1102 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1103 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1105 /* 3. Try to write the ParentIdPrefix to registry */
1106 Status
= ZwSetValueKey(hKey
,
1110 (PVOID
)KeyValue
.Buffer
,
1111 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1114 if (NT_SUCCESS(Status
))
1116 /* Duplicate the string to return it */
1117 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1119 ExFreePool(ParentIdPrefixInformation
);
1120 RtlFreeUnicodeString(&KeyName
);
1128 * IopActionInterrogateDeviceStack
1130 * Retrieve information for all (direct) child nodes of a parent node.
1134 * Pointer to device node.
1136 * Pointer to parent node to retrieve child node information for.
1139 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1140 * when we reach a device node which is not a direct child of the device
1141 * node for which we retrieve information of child nodes for. Any errors
1142 * that occur is logged instead so that all child services have a chance
1143 * of being interrogated.
1147 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1150 IO_STATUS_BLOCK IoStatusBlock
;
1151 PDEVICE_NODE ParentDeviceNode
;
1152 WCHAR InstancePath
[MAX_PATH
];
1153 IO_STACK_LOCATION Stack
;
1158 ULONG RequiredLength
;
1160 HANDLE InstanceKey
= NULL
;
1161 UNICODE_STRING ValueName
;
1162 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1163 DEVICE_CAPABILITIES DeviceCapabilities
;
1165 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1166 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1168 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1171 * We are called for the parent too, but we don't need to do special
1172 * handling for this node
1175 if (DeviceNode
== ParentDeviceNode
)
1177 DPRINT("Success\n");
1178 return STATUS_SUCCESS
;
1182 * Make sure this device node is a direct child of the parent device node
1183 * that is given as an argument
1186 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1188 /* Stop the traversal immediately and indicate successful operation */
1190 return STATUS_UNSUCCESSFUL
;
1194 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1195 if (!NT_SUCCESS(Status
))
1197 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1202 * FIXME: For critical errors, cleanup and disable device, but always
1203 * return STATUS_SUCCESS.
1206 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1208 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1209 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1213 if (NT_SUCCESS(Status
))
1215 /* Copy the device id string */
1216 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1219 * FIXME: Check for valid characters, if there is invalid characters
1225 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1228 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1230 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1231 if (!NT_SUCCESS(Status
))
1233 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1236 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1238 if (!DeviceCapabilities
.UniqueID
)
1240 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1241 DPRINT("Instance ID is not unique\n");
1242 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1243 if (!NT_SUCCESS(Status
))
1245 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1249 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1251 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1252 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1256 if (NT_SUCCESS(Status
))
1258 /* Append the instance id string */
1259 wcscat(InstancePath
, L
"\\");
1260 if (ParentIdPrefix
.Length
> 0)
1262 /* Add information from parent bus device to InstancePath */
1263 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1264 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1265 wcscat(InstancePath
, L
"&");
1267 if (IoStatusBlock
.Information
)
1268 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1271 * FIXME: Check for valid characters, if there is invalid characters
1277 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1279 RtlFreeUnicodeString(&ParentIdPrefix
);
1281 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1283 DPRINT("No resources\n");
1284 /* FIXME: Cleanup and disable device */
1287 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1290 * Create registry key for the instance id, if it doesn't exist yet
1292 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
1293 if (!NT_SUCCESS(Status
))
1295 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1299 /* Set 'Capabilities' value */
1300 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1301 Status
= ZwSetValueKey(InstanceKey
,
1305 (PVOID
)&DeviceNode
->CapabilityFlags
,
1308 /* Set 'UINumber' value */
1309 if (DeviceCapabilities
.UINumber
!= MAXULONG
)
1311 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1312 Status
= ZwSetValueKey(InstanceKey
,
1316 &DeviceCapabilities
.UINumber
,
1321 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1323 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1324 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1328 if (NT_SUCCESS(Status
))
1331 * FIXME: Check for valid characters, if there is invalid characters
1335 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1336 DPRINT("Hardware IDs:\n");
1339 DPRINT(" %S\n", Ptr
);
1340 Length
= wcslen(Ptr
) + 1;
1343 TotalLength
+= Length
;
1345 DPRINT("TotalLength: %hu\n", TotalLength
);
1348 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1349 Status
= ZwSetValueKey(InstanceKey
,
1353 (PVOID
)IoStatusBlock
.Information
,
1354 (TotalLength
+ 1) * sizeof(WCHAR
));
1355 if (!NT_SUCCESS(Status
))
1357 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1362 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1365 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1367 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1368 Status
= IopInitiatePnpIrp(
1369 DeviceNode
->PhysicalDeviceObject
,
1373 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1376 * FIXME: Check for valid characters, if there is invalid characters
1380 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1381 DPRINT("Compatible IDs:\n");
1384 DPRINT(" %S\n", Ptr
);
1385 Length
= wcslen(Ptr
) + 1;
1388 TotalLength
+= Length
;
1390 DPRINT("TotalLength: %hu\n", TotalLength
);
1393 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1394 Status
= ZwSetValueKey(InstanceKey
,
1398 (PVOID
)IoStatusBlock
.Information
,
1399 (TotalLength
+ 1) * sizeof(WCHAR
));
1400 if (!NT_SUCCESS(Status
))
1402 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1407 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1410 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1412 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1413 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1414 Status
= IopInitiatePnpIrp(
1415 DeviceNode
->PhysicalDeviceObject
,
1417 IRP_MN_QUERY_DEVICE_TEXT
,
1419 /* This key is mandatory, so even if the Irp fails, we still write it */
1420 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1421 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1423 if (NT_SUCCESS(Status
) &&
1424 IoStatusBlock
.Information
&&
1425 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1427 /* This key is overriden when a driver is installed. Don't write the
1428 * new description if another one already exists */
1429 Status
= ZwSetValueKey(InstanceKey
,
1433 (PVOID
)IoStatusBlock
.Information
,
1434 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1438 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1439 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1441 Status
= ZwSetValueKey(InstanceKey
,
1446 DeviceDesc
.MaximumLength
);
1448 if (!NT_SUCCESS(Status
))
1450 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1456 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1458 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1459 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1460 Status
= IopInitiatePnpIrp(
1461 DeviceNode
->PhysicalDeviceObject
,
1463 IRP_MN_QUERY_DEVICE_TEXT
,
1465 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1467 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1468 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1469 Status
= ZwSetValueKey(InstanceKey
,
1473 (PVOID
)IoStatusBlock
.Information
,
1474 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1475 if (!NT_SUCCESS(Status
))
1477 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1482 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1485 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1487 Status
= IopInitiatePnpIrp(
1488 DeviceNode
->PhysicalDeviceObject
,
1490 IRP_MN_QUERY_BUS_INFORMATION
,
1492 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1494 PPNP_BUS_INFORMATION BusInformation
=
1495 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1497 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1498 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1499 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1500 ExFreePool(BusInformation
);
1504 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1506 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1507 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1508 DeviceNode
->ChildBusTypeIndex
= -1;
1511 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1513 Status
= IopInitiatePnpIrp(
1514 DeviceNode
->PhysicalDeviceObject
,
1516 IRP_MN_QUERY_RESOURCES
,
1518 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1520 DeviceNode
->BootResources
=
1521 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1522 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
1526 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1527 DeviceNode
->BootResources
= NULL
;
1530 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1532 Status
= IopInitiatePnpIrp(
1533 DeviceNode
->PhysicalDeviceObject
,
1535 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1537 if (NT_SUCCESS(Status
))
1539 DeviceNode
->ResourceRequirements
=
1540 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1544 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1545 DeviceNode
->ResourceRequirements
= NULL
;
1548 if (InstanceKey
!= NULL
)
1550 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1553 ZwClose(InstanceKey
);
1555 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
1557 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
1559 /* Report the device to the user-mode pnp manager */
1560 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
1561 &DeviceNode
->InstancePath
);
1564 return STATUS_SUCCESS
;
1570 IN PDEVICE_OBJECT DeviceObject
)
1572 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1573 DEVICETREE_TRAVERSE_CONTEXT Context
;
1574 PDEVICE_RELATIONS DeviceRelations
;
1575 PDEVICE_OBJECT ChildDeviceObject
;
1576 IO_STATUS_BLOCK IoStatusBlock
;
1577 PDEVICE_NODE ChildDeviceNode
;
1578 IO_STACK_LOCATION Stack
;
1582 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
1584 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
1586 /* Report the device to the user-mode pnp manager */
1587 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1588 &DeviceNode
->InstancePath
);
1590 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1592 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1594 Status
= IopInitiatePnpIrp(
1597 IRP_MN_QUERY_DEVICE_RELATIONS
,
1599 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
1601 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
1605 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1607 if (!DeviceRelations
)
1609 DPRINT("No PDOs\n");
1610 return STATUS_UNSUCCESSFUL
;
1613 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
1616 * Create device nodes for all discovered devices
1618 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1620 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
1621 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
1623 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
1624 if (!ChildDeviceNode
)
1626 /* One doesn't exist, create it */
1627 Status
= IopCreateDeviceNode(
1632 if (NT_SUCCESS(Status
))
1634 /* Mark the node as enumerated */
1635 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1637 /* Mark the DO as bus enumerated */
1638 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1642 /* Ignore this DO */
1643 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
1644 ObDereferenceObject(ChildDeviceNode
);
1649 /* Mark it as enumerated */
1650 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
1651 ObDereferenceObject(ChildDeviceObject
);
1654 ExFreePool(DeviceRelations
);
1657 * Retrieve information about all discovered children from the bus driver
1659 IopInitDeviceTreeTraverseContext(
1662 IopActionInterrogateDeviceStack
,
1665 Status
= IopTraverseDeviceTree(&Context
);
1666 if (!NT_SUCCESS(Status
))
1668 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1673 * Retrieve configuration from the registry for discovered children
1675 IopInitDeviceTreeTraverseContext(
1678 IopActionConfigureChildServices
,
1681 Status
= IopTraverseDeviceTree(&Context
);
1682 if (!NT_SUCCESS(Status
))
1684 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
1689 * Initialize services for discovered children.
1691 Status
= IopInitializePnpServices(DeviceNode
);
1692 if (!NT_SUCCESS(Status
))
1694 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
1698 DPRINT("IopEnumerateDevice() finished\n");
1699 return STATUS_SUCCESS
;
1704 * IopActionConfigureChildServices
1706 * Retrieve configuration for all (direct) child nodes of a parent node.
1710 * Pointer to device node.
1712 * Pointer to parent node to retrieve child node configuration for.
1715 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1716 * when we reach a device node which is not a direct child of the device
1717 * node for which we configure child services for. Any errors that occur is
1718 * logged instead so that all child services have a chance of beeing
1723 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
1726 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
1727 PDEVICE_NODE ParentDeviceNode
;
1728 PUNICODE_STRING Service
;
1729 UNICODE_STRING ClassGUID
;
1731 DEVICE_CAPABILITIES DeviceCaps
;
1733 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1735 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1738 * We are called for the parent too, but we don't need to do special
1739 * handling for this node
1741 if (DeviceNode
== ParentDeviceNode
)
1743 DPRINT("Success\n");
1744 return STATUS_SUCCESS
;
1748 * Make sure this device node is a direct child of the parent device node
1749 * that is given as an argument
1751 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1753 /* Stop the traversal immediately and indicate successful operation */
1755 return STATUS_UNSUCCESSFUL
;
1758 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1760 WCHAR RegKeyBuffer
[MAX_PATH
];
1761 UNICODE_STRING RegKey
;
1764 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1765 RegKey
.Buffer
= RegKeyBuffer
;
1768 * Retrieve configuration from Enum key
1771 Service
= &DeviceNode
->ServiceName
;
1773 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1774 RtlInitUnicodeString(Service
, NULL
);
1775 RtlInitUnicodeString(&ClassGUID
, NULL
);
1777 QueryTable
[0].Name
= L
"Service";
1778 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1779 QueryTable
[0].EntryContext
= Service
;
1781 QueryTable
[1].Name
= L
"ClassGUID";
1782 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1783 QueryTable
[1].EntryContext
= &ClassGUID
;
1784 QueryTable
[1].DefaultType
= REG_SZ
;
1785 QueryTable
[1].DefaultData
= L
"";
1786 QueryTable
[1].DefaultLength
= 0;
1788 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1789 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1791 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1792 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1794 if (!NT_SUCCESS(Status
))
1796 /* FIXME: Log the error */
1797 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
1798 &DeviceNode
->InstancePath
, Status
);
1799 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1800 return STATUS_SUCCESS
;
1803 if (Service
->Buffer
== NULL
)
1805 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
1806 DeviceCaps
.RawDeviceOK
)
1808 DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
1810 DeviceNode
->ServiceName
.Length
= 0;
1811 DeviceNode
->ServiceName
.MaximumLength
= 0;
1812 DeviceNode
->ServiceName
.Buffer
= NULL
;
1814 else if (ClassGUID
.Length
!= 0)
1816 /* Device has a ClassGUID value, but no Service value.
1817 * Suppose it is using the NULL driver, so state the
1818 * device is started */
1819 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
1820 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1824 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1826 return STATUS_SUCCESS
;
1829 DPRINT("Got Service %S\n", Service
->Buffer
);
1832 return STATUS_SUCCESS
;
1836 * IopActionInitChildServices
1838 * Initialize the service for all (direct) child nodes of a parent node
1842 * Pointer to device node.
1844 * Pointer to parent node to initialize child node services for.
1847 * If the driver image for a service is not loaded and initialized
1848 * it is done here too. We only return a status code indicating an
1849 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1850 * not a direct child of the device node for which we initialize
1851 * child services for. Any errors that occur is logged instead so
1852 * that all child services have a chance of being initialized.
1856 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
1859 PDEVICE_NODE ParentDeviceNode
;
1861 BOOLEAN BootDrivers
= !PnpSystemInit
;
1863 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
1865 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1868 * We are called for the parent too, but we don't need to do special
1869 * handling for this node
1871 if (DeviceNode
== ParentDeviceNode
)
1873 DPRINT("Success\n");
1874 return STATUS_SUCCESS
;
1878 * Make sure this device node is a direct child of the parent device node
1879 * that is given as an argument
1882 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1885 * Stop the traversal immediately and indicate unsuccessful operation
1888 return STATUS_UNSUCCESSFUL
;
1891 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
1892 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
1893 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1894 return STATUS_SUCCESS
;
1896 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
1898 /* We don't need to worry about loading the driver because we're
1899 * being driven in raw mode so our parent must be loaded to get here */
1900 Status
= IopStartDevice(DeviceNode
);
1901 if (!NT_SUCCESS(Status
))
1903 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
1904 &DeviceNode
->InstancePath
, Status
);
1909 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1910 PDRIVER_OBJECT DriverObject
;
1912 /* Get existing DriverObject pointer (in case the driver has
1913 already been loaded and initialized) */
1914 Status
= IopGetDriverObject(
1916 &DeviceNode
->ServiceName
,
1919 if (!NT_SUCCESS(Status
))
1921 /* Driver is not initialized, try to load it */
1922 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1924 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
1926 /* STATUS_IMAGE_ALREADY_LOADED means this driver
1927 was loaded by the bootloader */
1928 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
1929 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
1931 /* Initialize the driver */
1932 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
1933 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
1937 Status
= STATUS_SUCCESS
;
1942 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
1943 &DeviceNode
->ServiceName
, Status
);
1947 /* Driver is loaded and initialized at this point */
1948 if (NT_SUCCESS(Status
))
1950 /* Initialize the device, including all filters */
1951 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
1956 * Don't disable when trying to load only boot drivers
1960 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1961 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1962 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1963 DPRINT1("Initialization of service %S failed (Status %x)\n",
1964 DeviceNode
->ServiceName
.Buffer
, Status
);
1969 return STATUS_SUCCESS
;
1973 * IopInitializePnpServices
1975 * Initialize services for discovered children
1979 * Top device node to start initializing services.
1985 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
1987 DEVICETREE_TRAVERSE_CONTEXT Context
;
1989 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
1991 IopInitDeviceTreeTraverseContext(
1994 IopActionInitChildServices
,
1997 return IopTraverseDeviceTree(&Context
);
2000 static NTSTATUS INIT_FUNCTION
2001 IopEnumerateDetectedDevices(
2003 IN PUNICODE_STRING RelativePath OPTIONAL
,
2005 IN BOOLEAN EnumerateSubKeys
,
2006 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2007 IN ULONG ParentBootResourcesLength
)
2009 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2010 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2011 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2012 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2013 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2014 OBJECT_ATTRIBUTES ObjectAttributes
;
2015 HANDLE hDevicesKey
= NULL
;
2016 HANDLE hDeviceKey
= NULL
;
2017 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2018 UNICODE_STRING Level2NameU
;
2019 WCHAR Level2Name
[5];
2020 ULONG IndexDevice
= 0;
2022 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2023 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2024 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2025 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2026 UNICODE_STRING DeviceName
, ValueName
;
2028 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2029 ULONG BootResourcesLength
;
2032 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2033 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2034 static ULONG DeviceIndexPci
= 0;
2035 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2036 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2037 static ULONG DeviceIndexSerial
= 0;
2038 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2039 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2040 static ULONG DeviceIndexKeyboard
= 0;
2041 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2042 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2043 static ULONG DeviceIndexMouse
= 0;
2044 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2045 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2046 static ULONG DeviceIndexParallel
= 0;
2047 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2048 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2049 static ULONG DeviceIndexFloppy
= 0;
2050 const UNICODE_STRING IdentifierIsa
= RTL_CONSTANT_STRING(L
"ISA");
2051 UNICODE_STRING HardwareIdIsa
= RTL_CONSTANT_STRING(L
"*PNP0A00\0");
2052 static ULONG DeviceIndexIsa
= 0;
2053 UNICODE_STRING HardwareIdKey
;
2054 PUNICODE_STRING pHardwareId
;
2055 ULONG DeviceIndex
= 0;
2056 PUCHAR CmResourceList
;
2061 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2062 if (!NT_SUCCESS(Status
))
2064 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2069 hDevicesKey
= hBaseKey
;
2071 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2072 if (!pDeviceInformation
)
2074 DPRINT("ExAllocatePool() failed\n");
2075 Status
= STATUS_NO_MEMORY
;
2079 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2080 if (!pValueInformation
)
2082 DPRINT("ExAllocatePool() failed\n");
2083 Status
= STATUS_NO_MEMORY
;
2089 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2090 if (Status
== STATUS_NO_MORE_ENTRIES
)
2092 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2094 ExFreePool(pDeviceInformation
);
2095 DeviceInfoLength
= RequiredSize
;
2096 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2097 if (!pDeviceInformation
)
2099 DPRINT("ExAllocatePool() failed\n");
2100 Status
= STATUS_NO_MEMORY
;
2103 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2105 if (!NT_SUCCESS(Status
))
2107 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2112 /* Open device key */
2113 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2114 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2116 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2117 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2118 if (!NT_SUCCESS(Status
))
2120 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2124 /* Read boot resources, and add then to parent ones */
2125 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2126 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2128 ExFreePool(pValueInformation
);
2129 ValueInfoLength
= RequiredSize
;
2130 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2131 if (!pValueInformation
)
2133 DPRINT("ExAllocatePool() failed\n");
2134 ZwDeleteKey(hLevel2Key
);
2135 Status
= STATUS_NO_MEMORY
;
2138 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2140 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2142 BootResources
= ParentBootResources
;
2143 BootResourcesLength
= ParentBootResourcesLength
;
2145 else if (!NT_SUCCESS(Status
))
2147 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2150 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2152 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2157 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2159 /* Concatenate current resources and parent ones */
2160 if (ParentBootResourcesLength
== 0)
2161 BootResourcesLength
= pValueInformation
->DataLength
;
2163 BootResourcesLength
= ParentBootResourcesLength
2164 + pValueInformation
->DataLength
2166 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2169 DPRINT("ExAllocatePool() failed\n");
2172 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2174 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2176 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2178 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2180 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2181 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2182 ParentBootResourcesLength
- Header
);
2183 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2187 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2189 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2190 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2191 ParentBootResourcesLength
- Header
);
2193 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2194 pValueInformation
->Data
+ Header
,
2195 pValueInformation
->DataLength
- Header
);
2196 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2200 if (EnumerateSubKeys
)
2205 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2206 if (Status
== STATUS_NO_MORE_ENTRIES
)
2208 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2210 ExFreePool(pDeviceInformation
);
2211 DeviceInfoLength
= RequiredSize
;
2212 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2213 if (!pDeviceInformation
)
2215 DPRINT("ExAllocatePool() failed\n");
2216 Status
= STATUS_NO_MEMORY
;
2219 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2221 if (!NT_SUCCESS(Status
))
2223 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2227 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2228 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2230 Status
= IopEnumerateDetectedDevices(
2236 BootResourcesLength
);
2237 if (!NT_SUCCESS(Status
))
2242 /* Read identifier */
2243 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2244 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2246 ExFreePool(pValueInformation
);
2247 ValueInfoLength
= RequiredSize
;
2248 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2249 if (!pValueInformation
)
2251 DPRINT("ExAllocatePool() failed\n");
2252 Status
= STATUS_NO_MEMORY
;
2255 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2257 if (!NT_SUCCESS(Status
))
2259 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2261 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2264 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2266 else if (pValueInformation
->Type
!= REG_SZ
)
2268 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2273 /* Assign hardware id to this device */
2274 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2275 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2276 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2277 ValueName
.Length
-= sizeof(WCHAR
);
2280 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2282 pHardwareId
= &HardwareIdSerial
;
2283 DeviceIndex
= DeviceIndexSerial
++;
2285 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2287 pHardwareId
= &HardwareIdKeyboard
;
2288 DeviceIndex
= DeviceIndexKeyboard
++;
2290 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2292 pHardwareId
= &HardwareIdMouse
;
2293 DeviceIndex
= DeviceIndexMouse
++;
2295 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
2297 pHardwareId
= &HardwareIdParallel
;
2298 DeviceIndex
= DeviceIndexParallel
++;
2300 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
2302 pHardwareId
= &HardwareIdFloppy
;
2303 DeviceIndex
= DeviceIndexFloppy
++;
2305 else if (NT_SUCCESS(Status
))
2307 /* Try to also match the device identifier */
2308 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2310 pHardwareId
= &HardwareIdPci
;
2311 DeviceIndex
= DeviceIndexPci
++;
2313 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierIsa
, FALSE
) == 0)
2315 pHardwareId
= &HardwareIdIsa
;
2316 DeviceIndex
= DeviceIndexIsa
++;
2320 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2326 /* Unknown key path */
2327 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2331 /* Prepare hardware id key (hardware id value without final \0) */
2332 HardwareIdKey
= *pHardwareId
;
2333 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2335 /* Add the detected device to Root key */
2336 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2337 Status
= ZwCreateKey(
2343 REG_OPTION_NON_VOLATILE
,
2345 if (!NT_SUCCESS(Status
))
2347 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2350 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2351 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2352 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2353 Status
= ZwCreateKey(
2355 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2359 REG_OPTION_NON_VOLATILE
,
2361 ZwClose(hLevel1Key
);
2362 if (!NT_SUCCESS(Status
))
2364 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2367 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
2368 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2369 if (!NT_SUCCESS(Status
))
2371 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2372 ZwDeleteKey(hLevel2Key
);
2375 /* Create 'LogConf' subkey */
2376 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2377 Status
= ZwCreateKey(
2383 REG_OPTION_VOLATILE
,
2385 if (!NT_SUCCESS(Status
))
2387 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2388 ZwDeleteKey(hLevel2Key
);
2391 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2393 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
2394 if (!CmResourceList
)
2397 ZwDeleteKey(hLevel2Key
);
2401 /* Add the list count (1st member of CM_RESOURCE_LIST) */
2403 RtlCopyMemory(CmResourceList
,
2407 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
2408 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
2410 BootResourcesLength
);
2412 /* Save boot resources to 'LogConf\BootConfig' */
2413 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
2414 if (!NT_SUCCESS(Status
))
2416 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2418 ZwDeleteKey(hLevel2Key
);
2425 if (BootResources
&& BootResources
!= ParentBootResources
)
2427 ExFreePool(BootResources
);
2428 BootResources
= NULL
;
2432 ZwClose(hLevel2Key
);
2437 ZwClose(hDeviceKey
);
2442 Status
= STATUS_SUCCESS
;
2445 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
2446 ZwClose(hDevicesKey
);
2448 ZwClose(hDeviceKey
);
2449 if (pDeviceInformation
)
2450 ExFreePool(pDeviceInformation
);
2451 if (pValueInformation
)
2452 ExFreePool(pValueInformation
);
2456 static BOOLEAN INIT_FUNCTION
2457 IopIsAcpiComputer(VOID
)
2462 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2463 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2464 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2465 OBJECT_ATTRIBUTES ObjectAttributes
;
2466 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2467 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2468 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2469 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2471 ULONG IndexDevice
= 0;
2472 UNICODE_STRING DeviceName
, ValueName
;
2473 HANDLE hDevicesKey
= NULL
;
2474 HANDLE hDeviceKey
= NULL
;
2476 BOOLEAN ret
= FALSE
;
2478 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2479 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2480 if (!NT_SUCCESS(Status
))
2482 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2486 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2487 if (!pDeviceInformation
)
2489 DPRINT("ExAllocatePool() failed\n");
2490 Status
= STATUS_NO_MEMORY
;
2494 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2495 if (!pDeviceInformation
)
2497 DPRINT("ExAllocatePool() failed\n");
2498 Status
= STATUS_NO_MEMORY
;
2504 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2505 if (Status
== STATUS_NO_MORE_ENTRIES
)
2507 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2509 ExFreePool(pDeviceInformation
);
2510 DeviceInfoLength
= RequiredSize
;
2511 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2512 if (!pDeviceInformation
)
2514 DPRINT("ExAllocatePool() failed\n");
2515 Status
= STATUS_NO_MEMORY
;
2518 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2520 if (!NT_SUCCESS(Status
))
2522 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2527 /* Open device key */
2528 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2529 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2530 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2535 if (!NT_SUCCESS(Status
))
2537 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2541 /* Read identifier */
2542 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2543 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2545 ExFreePool(pValueInformation
);
2546 ValueInfoLength
= RequiredSize
;
2547 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2548 if (!pValueInformation
)
2550 DPRINT("ExAllocatePool() failed\n");
2551 Status
= STATUS_NO_MEMORY
;
2554 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2556 if (!NT_SUCCESS(Status
))
2558 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2561 else if (pValueInformation
->Type
!= REG_SZ
)
2563 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2567 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2568 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2569 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2570 ValueName
.Length
-= sizeof(WCHAR
);
2571 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
2573 DPRINT("Found ACPI BIOS\n");
2579 ZwClose(hDeviceKey
);
2584 if (pDeviceInformation
)
2585 ExFreePool(pDeviceInformation
);
2586 if (pValueInformation
)
2587 ExFreePool(pValueInformation
);
2589 ZwClose(hDevicesKey
);
2591 ZwClose(hDeviceKey
);
2598 IopUpdateRootKey(VOID
)
2600 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
2601 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
2602 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2603 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2604 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2605 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2606 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
2607 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
2608 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
2609 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2610 OBJECT_ATTRIBUTES ObjectAttributes
;
2611 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
2614 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
2615 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2616 if (!NT_SUCCESS(Status
))
2618 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2622 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
2623 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2625 if (!NT_SUCCESS(Status
))
2627 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2631 if (IopIsAcpiComputer())
2633 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hRoot
, NULL
);
2634 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2636 if (!NT_SUCCESS(Status
))
2638 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiDevice
, NULL
);
2639 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
2640 ZwClose(hHalAcpiDevice
);
2641 if (!NT_SUCCESS(Status
))
2643 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
2644 if (NT_SUCCESS(Status
))
2645 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
2646 if (NT_SUCCESS(Status
))
2648 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hHalAcpiId
, NULL
);
2649 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
2650 if (NT_SUCCESS(Status
))
2653 ZwClose(hHalAcpiId
);
2658 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
2659 if (!NT_SUCCESS(Status
))
2661 /* Nothing to do, don't return with an error status */
2662 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2664 return STATUS_SUCCESS
;
2666 Status
= IopEnumerateDetectedDevices(
2681 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
2683 PUNICODE_STRING Name
,
2684 ACCESS_MASK DesiredAccess
)
2686 OBJECT_ATTRIBUTES ObjectAttributes
;
2693 InitializeObjectAttributes(&ObjectAttributes
,
2695 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2699 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
2706 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
2707 IN HANDLE RootHandle OPTIONAL
,
2708 IN PUNICODE_STRING KeyName
,
2709 IN ACCESS_MASK DesiredAccess
,
2710 IN ULONG CreateOptions
,
2711 OUT PULONG Disposition OPTIONAL
)
2713 OBJECT_ATTRIBUTES ObjectAttributes
;
2714 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0, Length
;
2715 HANDLE HandleArray
[2];
2716 BOOLEAN Recursing
= TRUE
;
2718 UNICODE_STRING KeyString
;
2719 NTSTATUS Status
= STATUS_SUCCESS
;
2722 /* P1 is start, pp is end */
2723 p1
= KeyName
->Buffer
;
2724 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
2726 /* Create the target key */
2727 InitializeObjectAttributes(&ObjectAttributes
,
2729 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2732 Status
= ZwCreateKey(&HandleArray
[i
],
2740 /* Now we check if this failed */
2741 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
2743 /* Target key failed, so we'll need to create its parent. Setup array */
2744 HandleArray
[0] = NULL
;
2745 HandleArray
[1] = RootHandle
;
2747 /* Keep recursing for each missing parent */
2750 /* And if we're deep enough, close the last handle */
2751 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2753 /* We're setup to ping-pong between the two handle array entries */
2754 RootHandleIndex
= i
;
2757 /* Clear the one we're attempting to open now */
2758 HandleArray
[i
] = NULL
;
2760 /* Process the parent key name */
2761 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
2762 Length
= (p
- p1
) * sizeof(WCHAR
);
2764 /* Is there a parent name? */
2767 /* Build the unicode string for it */
2768 KeyString
.Buffer
= p1
;
2769 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
2771 /* Now try opening the parent */
2772 InitializeObjectAttributes(&ObjectAttributes
,
2774 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2775 HandleArray
[RootHandleIndex
],
2777 Status
= ZwCreateKey(&HandleArray
[i
],
2784 if (NT_SUCCESS(Status
))
2786 /* It worked, we have one more handle */
2791 /* Parent key creation failed, abandon loop */
2798 /* We don't have a parent name, probably corrupted key name */
2799 Status
= STATUS_INVALID_PARAMETER
;
2804 /* Now see if there's more parents to create */
2806 if ((p
== pp
) || (p1
== pp
))
2808 /* We're done, hopefully successfully, so stop */
2813 /* Outer loop check for handle nesting that requires closing the top handle */
2814 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
2817 /* Check if we broke out of the loop due to success */
2818 if (NT_SUCCESS(Status
))
2820 /* Return the target handle (we closed all the parent ones) and disposition */
2821 *Handle
= HandleArray
[i
];
2822 if (Disposition
) *Disposition
= KeyDisposition
;
2825 /* Return the success state */
2831 IopGetRegistryValue(IN HANDLE Handle
,
2833 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
2835 UNICODE_STRING ValueString
;
2837 PKEY_VALUE_FULL_INFORMATION FullInformation
;
2841 RtlInitUnicodeString(&ValueString
, ValueName
);
2843 Status
= ZwQueryValueKey(Handle
,
2845 KeyValueFullInformation
,
2849 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
2850 (Status
!= STATUS_BUFFER_TOO_SMALL
))
2855 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
2856 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
2858 Status
= ZwQueryValueKey(Handle
,
2860 KeyValueFullInformation
,
2864 if (!NT_SUCCESS(Status
))
2866 ExFreePool(FullInformation
);
2870 *Information
= FullInformation
;
2871 return STATUS_SUCCESS
;
2874 RTL_GENERIC_COMPARE_RESULTS
2876 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
2877 IN PVOID FirstStruct
,
2878 IN PVOID SecondStruct
)
2886 // The allocation function is called by the generic table package whenever
2887 // it needs to allocate memory for the table.
2892 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
2902 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
2911 PpInitializeDeviceReferenceTable(VOID
)
2913 /* Setup the guarded mutex and AVL table */
2914 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
2915 RtlInitializeGenericTableAvl(
2916 &PpDeviceReferenceTable
,
2917 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
2918 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
2919 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
2927 /* Initialize the resource when accessing device registry data */
2928 ExInitializeResourceLite(&PpRegistryDeviceResource
);
2930 /* Setup the device reference AVL table */
2931 PpInitializeDeviceReferenceTable();
2939 /* Check the initialization phase */
2940 switch (ExpInitializationPhase
)
2945 return PiInitPhase0();
2951 //return PiInitPhase1();
2955 /* Don't know any other phase! Bugcheck! */
2956 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
2961 LONG IopNumberDeviceNodes
;
2965 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
2967 PDEVICE_NODE DeviceNode
;
2971 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), 'donD');
2972 if (!DeviceNode
) return DeviceNode
;
2975 InterlockedIncrement(&IopNumberDeviceNodes
);
2978 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
2979 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
2980 DeviceNode
->BusNumber
= -1;
2981 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2982 DeviceNode
->ChildBusNumber
= -1;
2983 DeviceNode
->ChildBusTypeIndex
= -1;
2984 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
2985 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
2986 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
2987 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
2988 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
2989 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
2991 /* Check if there is a PDO */
2992 if (PhysicalDeviceObject
)
2994 /* Link it and remove the init flag */
2995 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
2996 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
2997 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3000 /* Return the node */
3004 /* PUBLIC FUNCTIONS **********************************************************/
3008 PnpBusTypeGuidGet(IN USHORT Index
,
3009 IN LPGUID BusTypeGuid
)
3011 NTSTATUS Status
= STATUS_SUCCESS
;
3013 /* Acquire the lock */
3014 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
3017 if (Index
< PnpBusTypeGuidList
->GuidCount
)
3020 RtlCopyMemory(BusTypeGuid
, &PnpBusTypeGuidList
->Guids
[Index
], sizeof(GUID
));
3025 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
3028 /* Release lock and return status */
3029 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
3035 PpIrpQueryCapabilities(IN PDEVICE_OBJECT DeviceObject
,
3036 OUT PDEVICE_CAPABILITIES DeviceCaps
)
3039 IO_STACK_LOCATION Stack
;
3043 /* Set up the Header */
3044 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
3045 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
3046 DeviceCaps
->Version
= 1;
3047 DeviceCaps
->Address
= -1;
3048 DeviceCaps
->UINumber
= -1;
3050 /* Set up the Stack */
3051 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
3052 Stack
.MajorFunction
= IRP_MJ_PNP
;
3053 Stack
.MinorFunction
= IRP_MN_QUERY_CAPABILITIES
;
3054 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
3057 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
3062 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject
,
3063 IN PHANDLE DeviceInstanceHandle
,
3064 IN ACCESS_MASK DesiredAccess
)
3068 PDEVICE_NODE DeviceNode
;
3069 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
3072 /* Open the enum key */
3073 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
3077 if (!NT_SUCCESS(Status
)) return Status
;
3079 /* Make sure we have an instance path */
3080 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3081 if ((DeviceNode
) && (DeviceNode
->InstancePath
.Length
))
3083 /* Get the instance key */
3084 Status
= IopOpenRegistryKeyEx(DeviceInstanceHandle
,
3086 &DeviceNode
->InstancePath
,
3092 Status
= STATUS_INVALID_DEVICE_REQUEST
;
3095 /* Close the handle and return status */
3102 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList
)
3104 ULONG FinalSize
, PartialSize
, EntrySize
, i
, j
;
3105 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
3106 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
3108 /* If we don't have one, that's easy */
3109 if (!ResourceList
) return 0;
3111 /* Start with the minimum size possible */
3112 FinalSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
3114 /* Loop each full descriptor */
3115 FullDescriptor
= ResourceList
->List
;
3116 for (i
= 0; i
< ResourceList
->Count
; i
++)
3118 /* Start with the minimum size possible */
3119 PartialSize
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
) +
3120 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
);
3122 /* Loop each partial descriptor */
3123 PartialDescriptor
= FullDescriptor
->PartialResourceList
.PartialDescriptors
;
3124 for (j
= 0; j
< FullDescriptor
->PartialResourceList
.Count
; j
++)
3126 /* Start with the minimum size possible */
3127 EntrySize
= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
3129 /* Check if there is extra data */
3130 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
3133 EntrySize
+= PartialDescriptor
->u
.DeviceSpecificData
.DataSize
;
3136 /* The size of partial descriptors is bigger */
3137 PartialSize
+= EntrySize
;
3139 /* Go to the next partial descriptor */
3140 PartialDescriptor
= (PVOID
)((ULONG_PTR
)PartialDescriptor
+ EntrySize
);
3143 /* The size of full descriptors is bigger */
3144 FinalSize
+= PartialSize
;
3146 /* Go to the next full descriptor */
3147 FullDescriptor
= (PVOID
)((ULONG_PTR
)FullDescriptor
+ PartialSize
);
3150 /* Return the final size */
3156 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject
,
3161 IN PULONG BufferLength
)
3164 HANDLE KeyHandle
, SubHandle
;
3165 UNICODE_STRING KeyString
;
3166 PKEY_VALUE_FULL_INFORMATION KeyValueInfo
= NULL
;
3170 /* Find the instance key */
3171 Status
= PnpDeviceObjectToDeviceInstance(DeviceObject
, &KeyHandle
, KEY_READ
);
3172 if (NT_SUCCESS(Status
))
3174 /* Check for name given by caller */
3178 RtlInitUnicodeString(&KeyString
, KeyName
);
3179 Status
= IopOpenRegistryKeyEx(&SubHandle
,
3183 if (NT_SUCCESS(Status
))
3185 /* And use this handle instead */
3187 KeyHandle
= SubHandle
;
3191 /* Check if sub-key handle succeeded (or no-op if no key name given) */
3192 if (NT_SUCCESS(Status
))
3194 /* Now get the size of the property */
3195 Status
= IopGetRegistryValue(KeyHandle
,
3204 /* Fail if any of the registry operations failed */
3205 if (!NT_SUCCESS(Status
)) return Status
;
3207 /* Check how much data we have to copy */
3208 Length
= KeyValueInfo
->DataLength
;
3209 if (*BufferLength
>= Length
)
3211 /* Check for a match in the value type */
3212 if (KeyValueInfo
->Type
== ValueType
)
3215 RtlCopyMemory(Buffer
,
3216 (PVOID
)((ULONG_PTR
)KeyValueInfo
+
3217 KeyValueInfo
->DataOffset
),
3222 /* Invalid registry property type, fail */
3223 Status
= STATUS_INVALID_PARAMETER_2
;
3228 /* Buffer is too small to hold data */
3229 Status
= STATUS_BUFFER_TOO_SMALL
;
3232 /* Return the required buffer length, free the buffer, and return status */
3233 *BufferLength
= Length
;
3234 ExFreePool(KeyValueInfo
);
3238 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
3239 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
3240 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED; while(TRUE); break;}
3247 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3248 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3249 IN ULONG BufferLength
,
3250 OUT PVOID PropertyBuffer
,
3251 OUT PULONG ResultLength
)
3253 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3254 DEVICE_CAPABILITIES DeviceCaps
;
3255 ULONG ReturnLength
= 0, Length
= 0, ValueType
;
3256 PWCHAR ValueName
= NULL
, EnumeratorNameEnd
, DeviceInstanceName
;
3258 NTSTATUS Status
= STATUS_BUFFER_TOO_SMALL
;
3260 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
3261 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3263 /* Assume failure */
3266 /* Only PDOs can call this */
3267 if (!DeviceNode
) return STATUS_INVALID_DEVICE_REQUEST
;
3269 /* Handle all properties */
3270 switch (DeviceProperty
)
3272 case DevicePropertyBusTypeGuid
:
3274 /* Get the GUID from the internal cache */
3275 Status
= PnpBusTypeGuidGet(DeviceNode
->ChildBusTypeIndex
, &BusTypeGuid
);
3276 if (!NT_SUCCESS(Status
)) return Status
;
3278 /* This is the format of the returned data */
3279 PIP_RETURN_DATA(sizeof(GUID
), &BusTypeGuid
);
3281 case DevicePropertyLegacyBusType
:
3283 /* Validate correct interface type */
3284 if (DeviceNode
->ChildInterfaceType
== InterfaceTypeUndefined
)
3285 return STATUS_OBJECT_NAME_NOT_FOUND
;
3287 /* This is the format of the returned data */
3288 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE
), &DeviceNode
->ChildInterfaceType
);
3290 case DevicePropertyBusNumber
:
3292 /* Validate correct bus number */
3293 if ((DeviceNode
->ChildBusNumber
& 0x80000000) == 0x80000000)
3294 return STATUS_OBJECT_NAME_NOT_FOUND
;
3296 /* This is the format of the returned data */
3297 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceNode
->ChildBusNumber
);
3299 case DevicePropertyEnumeratorName
:
3301 /* Get the instance path */
3302 DeviceInstanceName
= DeviceNode
->InstancePath
.Buffer
;
3305 ASSERT((BufferLength
& 1) == 0);
3306 ASSERT(DeviceInstanceName
!= NULL
);
3308 /* Get the name from the path */
3309 EnumeratorNameEnd
= wcschr(DeviceInstanceName
, OBJ_NAME_PATH_SEPARATOR
);
3310 ASSERT(EnumeratorNameEnd
);
3312 /* This is the format of the returned data */
3313 PIP_RETURN_DATA((EnumeratorNameEnd
- DeviceInstanceName
) * 2,
3314 &DeviceNode
->ChildBusNumber
);
3316 case DevicePropertyAddress
:
3318 /* Query the device caps */
3319 Status
= PpIrpQueryCapabilities(DeviceObject
, &DeviceCaps
);
3320 if (!NT_SUCCESS(Status
) || (DeviceCaps
.Address
== MAXULONG
))
3321 return STATUS_OBJECT_NAME_NOT_FOUND
;
3323 /* This is the format of the returned data */
3324 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceCaps
.Address
);
3326 case DevicePropertyBootConfigurationTranslated
:
3328 /* Validate we have resources */
3329 if (!DeviceNode
->BootResources
)
3330 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
3332 /* No resources will still fake success, but with 0 bytes */
3334 return STATUS_SUCCESS
;
3337 /* This is the format of the returned data */
3338 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode
->BootResources
), // FIXFIX: Should use BootResourcesTranslated
3339 DeviceNode
->BootResources
); // FIXFIX: Should use BootResourcesTranslated
3341 case DevicePropertyPhysicalDeviceObjectName
:
3343 /* Sanity check for Unicode-sized string */
3344 ASSERT((BufferLength
& 1) == 0);
3346 /* Allocate name buffer */
3347 Length
= BufferLength
+ sizeof(OBJECT_NAME_INFORMATION
);
3348 ObjectNameInfo
= ExAllocatePool(PagedPool
, Length
);
3349 if (!ObjectNameInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
3351 /* Query the PDO name */
3352 Status
= ObQueryNameString(DeviceObject
,
3356 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
3358 /* It's up to the caller to try again */
3359 Status
= STATUS_BUFFER_TOO_SMALL
;
3362 /* Return if successful */
3363 if (NT_SUCCESS(Status
)) PIP_RETURN_DATA(ObjectNameInfo
->Name
.Length
,
3364 ObjectNameInfo
->Name
.Buffer
);
3366 /* Let the caller know how big the name is */
3367 *ResultLength
-= sizeof(OBJECT_NAME_INFORMATION
);
3370 /* Handle the registry-based properties */
3371 case DevicePropertyUINumber
:
3372 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER
, REG_DWORD
);
3373 case DevicePropertyLocationInformation
:
3374 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION
, REG_SZ
);
3375 case DevicePropertyDeviceDescription
:
3376 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC
, REG_SZ
);
3377 case DevicePropertyHardwareID
:
3378 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID
, REG_MULTI_SZ
);
3379 case DevicePropertyCompatibleIDs
:
3380 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS
, REG_MULTI_SZ
);
3381 case DevicePropertyBootConfiguration
:
3382 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG
, REG_RESOURCE_LIST
);
3383 case DevicePropertyClassName
:
3384 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS
, REG_SZ
);
3385 case DevicePropertyClassGuid
:
3386 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID
, REG_SZ
);
3387 case DevicePropertyDriverKeyName
:
3388 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER
, REG_SZ
);
3389 case DevicePropertyManufacturer
:
3390 PIP_REGISTRY_DATA(REGSTR_VAL_MFG
, REG_SZ
);
3391 case DevicePropertyFriendlyName
:
3392 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME
, REG_SZ
);
3393 case DevicePropertyContainerID
:
3394 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
3395 PIP_UNIMPLEMENTED();
3396 case DevicePropertyRemovalPolicy
:
3397 PIP_UNIMPLEMENTED();
3398 case DevicePropertyInstallState
:
3399 PIP_UNIMPLEMENTED();
3400 case DevicePropertyResourceRequirements
:
3401 PIP_UNIMPLEMENTED();
3402 case DevicePropertyAllocatedResources
:
3403 PIP_UNIMPLEMENTED();
3405 return STATUS_INVALID_PARAMETER_2
;
3408 /* Having a registry value name implies registry data */
3411 /* We know up-front how much data to expect */
3412 *ResultLength
= BufferLength
;
3414 /* Go get the data, use the LogConf subkey if necessary */
3415 Status
= PiGetDeviceRegistryProperty(DeviceObject
,
3419 DevicePropertyBootConfiguration
) ?
3424 else if (NT_SUCCESS(Status
))
3426 /* We know up-front how much data to expect, check the caller's buffer */
3427 *ResultLength
= ReturnLength
;
3428 if (ReturnLength
<= BufferLength
)
3430 /* Buffer is all good, copy the data */
3431 RtlCopyMemory(PropertyBuffer
, Data
, ReturnLength
);
3433 /* Check for properties that require a null-terminated string */
3434 if ((DeviceProperty
== DevicePropertyEnumeratorName
) ||
3435 (DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
))
3437 /* Terminate the string */
3438 ((PWCHAR
)PropertyBuffer
)[ReturnLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3441 /* This is the success path */
3442 Status
= STATUS_SUCCESS
;
3447 Status
= STATUS_BUFFER_TOO_SMALL
;
3451 /* Free any allocation we may have made, and return the status code */
3452 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
3461 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3467 * @name IoOpenDeviceRegistryKey
3469 * Open a registry key unique for a specified driver or device instance.
3471 * @param DeviceObject Device to get the registry key for.
3472 * @param DevInstKeyType Type of the key to return.
3473 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
3474 * @param DevInstRegKey Handle to the opened registry key on
3475 * successful return.
3483 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
3484 IN ULONG DevInstKeyType
,
3485 IN ACCESS_MASK DesiredAccess
,
3486 OUT PHANDLE DevInstRegKey
)
3488 static WCHAR RootKeyName
[] =
3489 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
3490 static WCHAR ProfileKeyName
[] =
3491 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
3492 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
3493 static WCHAR EnumKeyName
[] = L
"Enum\\";
3494 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
3495 ULONG KeyNameLength
;
3496 LPWSTR KeyNameBuffer
;
3497 UNICODE_STRING KeyName
;
3498 ULONG DriverKeyLength
;
3499 OBJECT_ATTRIBUTES ObjectAttributes
;
3500 PDEVICE_NODE DeviceNode
= NULL
;
3503 DPRINT("IoOpenDeviceRegistryKey() called\n");
3505 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
3507 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
3508 return STATUS_INVALID_PARAMETER
;
3511 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
3512 return STATUS_INVALID_DEVICE_REQUEST
;
3513 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3516 * Calculate the length of the base key name. This is the full
3517 * name for driver key or the name excluding "Device Parameters"
3518 * subkey for device key.
3521 KeyNameLength
= sizeof(RootKeyName
);
3522 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3523 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
3524 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3526 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
3527 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3528 0, NULL
, &DriverKeyLength
);
3529 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
3531 KeyNameLength
+= DriverKeyLength
;
3535 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
3536 DeviceNode
->InstancePath
.Length
;
3540 * Now allocate the buffer for the key name...
3543 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
3544 if (KeyNameBuffer
== NULL
)
3545 return STATUS_INSUFFICIENT_RESOURCES
;
3548 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
3549 KeyName
.Buffer
= KeyNameBuffer
;
3552 * ...and build the key name.
3555 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
3556 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
3558 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
3559 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
3561 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3563 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
3564 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
3565 DriverKeyLength
, KeyNameBuffer
+
3566 (KeyName
.Length
/ sizeof(WCHAR
)),
3568 if (!NT_SUCCESS(Status
))
3570 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
3571 ExFreePool(KeyNameBuffer
);
3574 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
3578 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
3579 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
3580 if (DeviceNode
->InstancePath
.Length
== 0)
3582 ExFreePool(KeyNameBuffer
);
3588 * Open the base key.
3590 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
3591 if (!NT_SUCCESS(Status
))
3593 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
3594 ExFreePool(KeyNameBuffer
);
3597 ExFreePool(KeyNameBuffer
);
3600 * For driver key we're done now.
3603 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
3607 * Let's go further. For device key we must open "Device Parameters"
3608 * subkey and create it if it doesn't exist yet.
3611 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
3612 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
3613 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
3614 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
3615 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
3616 ZwClose(ObjectAttributes
.RootDirectory
);
3626 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3636 IoInvalidateDeviceRelations(
3637 IN PDEVICE_OBJECT DeviceObject
,
3638 IN DEVICE_RELATION_TYPE Type
)
3640 PIO_WORKITEM WorkItem
;
3641 PINVALIDATE_DEVICE_RELATION_DATA Data
;
3643 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
3646 WorkItem
= IoAllocateWorkItem(DeviceObject
);
3653 ObReferenceObject(DeviceObject
);
3654 Data
->DeviceObject
= DeviceObject
;
3656 Data
->WorkItem
= WorkItem
;
3660 IopAsynchronousInvalidateDeviceRelations
,
3670 IoSynchronousInvalidateDeviceRelations(
3671 IN PDEVICE_OBJECT DeviceObject
,
3672 IN DEVICE_RELATION_TYPE Type
)
3679 /* Enumerate the device */
3680 return IopEnumerateDevice(DeviceObject
);
3681 case PowerRelations
:
3682 /* Not handled yet */
3683 return STATUS_NOT_IMPLEMENTED
;
3684 case TargetDeviceRelation
:
3686 return STATUS_SUCCESS
;
3688 /* Ejection relations are not supported */
3689 return STATUS_NOT_SUPPORTED
;
3698 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
3700 IN PHYSICAL_ADDRESS BusAddress
,
3701 IN OUT PULONG AddressSpace
,
3702 OUT PPHYSICAL_ADDRESS TranslatedAddress
)