2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/pnpmgr.c
5 * PURPOSE: Initializes the PnP manager
7 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 /* INCLUDES ******************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS *******************************************************************/
19 PDEVICE_NODE IopRootDeviceNode
;
20 KSPIN_LOCK IopDeviceTreeLock
;
22 /* DATA **********************************************************************/
24 PDRIVER_OBJECT IopRootDriverObject
;
26 /* FUNCTIONS *****************************************************************/
30 PDEVICE_OBJECT DeviceObject
)
32 return DeviceObject
->DeviceObjectExtension
->DeviceNode
;
40 IoInvalidateDeviceRelations(
41 IN PDEVICE_OBJECT DeviceObject
,
42 IN DEVICE_RELATION_TYPE Type
)
44 IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject
), Type
);
53 IN PDEVICE_OBJECT DeviceObject
,
54 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
55 IN ULONG BufferLength
,
56 OUT PVOID PropertyBuffer
,
57 OUT PULONG ResultLength
)
59 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
64 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
66 if (DeviceNode
== NULL
)
67 return STATUS_INVALID_DEVICE_REQUEST
;
69 switch (DeviceProperty
)
71 case DevicePropertyBusNumber
:
72 Length
= sizeof(ULONG
);
73 Data
= &DeviceNode
->ChildBusNumber
;
76 /* Complete, untested */
77 case DevicePropertyBusTypeGuid
:
78 *ResultLength
= 39 * sizeof(WCHAR
);
79 if (BufferLength
< (39 * sizeof(WCHAR
)))
80 return STATUS_BUFFER_TOO_SMALL
;
81 swprintf((PWSTR
)PropertyBuffer
,
82 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
83 DeviceNode
->BusTypeGuid
.Data1
,
84 DeviceNode
->BusTypeGuid
.Data2
,
85 DeviceNode
->BusTypeGuid
.Data3
,
86 DeviceNode
->BusTypeGuid
.Data4
[0],
87 DeviceNode
->BusTypeGuid
.Data4
[1],
88 DeviceNode
->BusTypeGuid
.Data4
[2],
89 DeviceNode
->BusTypeGuid
.Data4
[3],
90 DeviceNode
->BusTypeGuid
.Data4
[4],
91 DeviceNode
->BusTypeGuid
.Data4
[5],
92 DeviceNode
->BusTypeGuid
.Data4
[6],
93 DeviceNode
->BusTypeGuid
.Data4
[7]);
94 return STATUS_SUCCESS
;
96 case DevicePropertyLegacyBusType
:
97 Length
= sizeof(INTERFACE_TYPE
);
98 Data
= &DeviceNode
->ChildInterfaceType
;
101 case DevicePropertyAddress
:
102 Length
= sizeof(ULONG
);
103 Data
= &DeviceNode
->Address
;
106 // case DevicePropertyUINumber:
107 // if (DeviceNode->CapabilityFlags == NULL)
108 // return STATUS_INVALID_DEVICE_REQUEST;
109 // Length = sizeof(ULONG);
110 // Data = &DeviceNode->CapabilityFlags->UINumber;
113 case DevicePropertyClassName
:
114 case DevicePropertyClassGuid
:
115 case DevicePropertyDriverKeyName
:
116 case DevicePropertyManufacturer
:
117 case DevicePropertyFriendlyName
:
118 case DevicePropertyHardwareID
:
119 case DevicePropertyCompatibleIDs
:
120 case DevicePropertyDeviceDescription
:
121 case DevicePropertyLocationInformation
:
122 case DevicePropertyUINumber
:
124 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
125 UNICODE_STRING KeyName
, ValueName
;
126 OBJECT_ATTRIBUTES ObjectAttributes
;
127 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
128 ULONG ValueInformationLength
;
132 switch (DeviceProperty
)
134 case DevicePropertyClassName
:
135 RegistryPropertyName
= L
"Class"; break;
136 case DevicePropertyClassGuid
:
137 RegistryPropertyName
= L
"ClassGuid"; break;
138 case DevicePropertyDriverKeyName
:
139 RegistryPropertyName
= L
"Driver"; break;
140 case DevicePropertyManufacturer
:
141 RegistryPropertyName
= L
"Mfg"; break;
142 case DevicePropertyFriendlyName
:
143 RegistryPropertyName
= L
"FriendlyName"; break;
144 case DevicePropertyHardwareID
:
145 RegistryPropertyName
= L
"HardwareID"; break;
146 case DevicePropertyCompatibleIDs
:
147 RegistryPropertyName
= L
"CompatibleIDs"; break;
148 case DevicePropertyDeviceDescription
:
149 RegistryPropertyName
= L
"DeviceDesc"; break;
150 case DevicePropertyLocationInformation
:
151 RegistryPropertyName
= L
"LocationInformation"; break;
152 case DevicePropertyUINumber
:
153 RegistryPropertyName
= L
"UINumber"; break;
155 RegistryPropertyName
= NULL
; break;
158 KeyNameBuffer
= ExAllocatePool(PagedPool
,
159 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
161 DPRINT("KeyNameBuffer: 0x%p, value %S\n",
162 KeyNameBuffer
, RegistryPropertyName
);
164 if (KeyNameBuffer
== NULL
)
165 return STATUS_INSUFFICIENT_RESOURCES
;
167 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
168 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
169 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
170 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
171 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
173 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
174 ExFreePool(KeyNameBuffer
);
175 if (!NT_SUCCESS(Status
))
178 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
179 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
180 Data
[0]) + BufferLength
;
181 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
182 if (ValueInformation
== NULL
)
185 return STATUS_INSUFFICIENT_RESOURCES
;
188 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
189 KeyValuePartialInformation
, ValueInformation
,
190 ValueInformationLength
,
191 &ValueInformationLength
);
192 *ResultLength
= ValueInformation
->DataLength
;
195 if (ValueInformation
->DataLength
> BufferLength
)
196 Status
= STATUS_BUFFER_TOO_SMALL
;
198 if (!NT_SUCCESS(Status
))
200 ExFreePool(ValueInformation
);
204 /* FIXME: Verify the value (NULL-terminated, correct format). */
206 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
207 ValueInformation
->DataLength
);
208 ExFreePool(ValueInformation
);
210 return STATUS_SUCCESS
;
213 case DevicePropertyBootConfiguration
:
215 if (DeviceNode
->BootResources
->Count
!= 0)
217 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
219 Data
= &DeviceNode
->BootResources
;
222 /* FIXME: use a translated boot configuration instead */
223 case DevicePropertyBootConfigurationTranslated
:
225 if (DeviceNode
->BootResources
->Count
!= 0)
227 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
229 Data
= &DeviceNode
->BootResources
;
232 case DevicePropertyEnumeratorName
:
233 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
236 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
237 Data
= DeviceNode
->InstancePath
.Buffer
;
246 case DevicePropertyPhysicalDeviceObjectName
:
247 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
248 Data
= DeviceNode
->InstancePath
.Buffer
;
252 return STATUS_INVALID_PARAMETER_2
;
255 *ResultLength
= Length
;
256 if (BufferLength
< Length
)
257 return STATUS_BUFFER_TOO_SMALL
;
258 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
260 /* Terminate the string */
261 if (DeviceProperty
== DevicePropertyEnumeratorName
262 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
264 Ptr
= (PWSTR
)PropertyBuffer
;
265 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
268 return STATUS_SUCCESS
;
276 IoInvalidateDeviceState(
277 IN PDEVICE_OBJECT PhysicalDeviceObject
)
282 * @name IoOpenDeviceRegistryKey
284 * Open a registry key unique for a specified driver or device instance.
286 * @param DeviceObject Device to get the registry key for.
287 * @param DevInstKeyType Type of the key to return.
288 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
289 * @param DevInstRegKey Handle to the opened registry key on
298 IoOpenDeviceRegistryKey(
299 IN PDEVICE_OBJECT DeviceObject
,
300 IN ULONG DevInstKeyType
,
301 IN ACCESS_MASK DesiredAccess
,
302 OUT PHANDLE DevInstRegKey
)
304 static WCHAR RootKeyName
[] =
305 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
306 static WCHAR ProfileKeyName
[] =
307 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
308 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
309 static WCHAR EnumKeyName
[] = L
"Enum\\";
310 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters\\";
312 LPWSTR KeyNameBuffer
;
313 UNICODE_STRING KeyName
;
314 ULONG DriverKeyLength
;
315 OBJECT_ATTRIBUTES ObjectAttributes
;
316 PDEVICE_NODE DeviceNode
= NULL
;
319 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
320 return STATUS_INVALID_PARAMETER
;
323 * Calculate the length of the base key name. This is the full
324 * name for driver key or the name excluding "Device Parameters"
325 * subkey for device key.
328 KeyNameLength
= sizeof(RootKeyName
);
329 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
330 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
331 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
333 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
334 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
335 0, NULL
, &DriverKeyLength
);
336 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
338 KeyNameLength
+= DriverKeyLength
;
342 DeviceNode
= IopGetDeviceNode(DeviceObject
);
343 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
344 DeviceNode
->InstancePath
.Length
;
348 * Now allocate the buffer for the key name...
351 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
352 if (KeyNameBuffer
== NULL
)
353 return STATUS_INSUFFICIENT_RESOURCES
;
356 KeyName
.MaximumLength
= KeyNameLength
;
357 KeyName
.Buffer
= KeyNameBuffer
;
360 * ...and build the key name.
363 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
364 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
366 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
367 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
369 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
371 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
372 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
373 DriverKeyLength
, KeyNameBuffer
+
374 (KeyName
.Length
/ sizeof(WCHAR
)),
376 if (!NT_SUCCESS(Status
))
378 ExFreePool(KeyNameBuffer
);
381 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
385 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
386 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
387 if (DeviceNode
->InstancePath
.Length
== 0)
389 ExFreePool(KeyNameBuffer
);
398 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
399 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
400 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
401 ExFreePool(KeyNameBuffer
);
404 * For driver key we're done now. Also if the base key doesn't
405 * exist we can bail out with error...
408 if ((DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
) || !NT_SUCCESS(Status
))
412 * Let's go further. For device key we must open "Device Parameters"
413 * subkey and create it if it doesn't exist yet.
416 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
417 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
418 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
419 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
420 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
421 ZwClose(ObjectAttributes
.RootDirectory
);
431 IoRequestDeviceEject(
432 IN PDEVICE_OBJECT PhysicalDeviceObject
440 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
444 if (PopSystemPowerDeviceNode
)
446 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
447 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
448 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
450 return STATUS_SUCCESS
;
453 return STATUS_UNSUCCESSFUL
;
458 * Creates a device node
461 * ParentNode = Pointer to parent device node
462 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
463 * to have the root device node create one
464 * (eg. for legacy drivers)
465 * DeviceNode = Pointer to storage for created device node
471 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
472 PDEVICE_OBJECT PhysicalDeviceObject
,
473 PDEVICE_NODE
*DeviceNode
)
479 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
480 ParentNode
, PhysicalDeviceObject
);
482 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
485 return STATUS_INSUFFICIENT_RESOURCES
;
488 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
490 if (!PhysicalDeviceObject
)
492 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
493 if (!NT_SUCCESS(Status
))
499 /* This is for drivers passed on the command line to ntoskrnl.exe */
500 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
501 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
504 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
506 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
510 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
511 Node
->Parent
= ParentNode
;
512 Node
->NextSibling
= ParentNode
->Child
;
513 if (ParentNode
->Child
!= NULL
)
515 ParentNode
->Child
->PrevSibling
= Node
;
517 ParentNode
->Child
= Node
;
518 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
523 return STATUS_SUCCESS
;
527 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
531 /* All children must be deleted before a parent is deleted */
532 ASSERT(!DeviceNode
->Child
);
534 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
536 ASSERT(DeviceNode
->PhysicalDeviceObject
);
538 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
540 /* Unlink from parent if it exists */
542 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
544 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
547 /* Unlink from sibling list */
549 if (DeviceNode
->PrevSibling
)
551 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
554 if (DeviceNode
->NextSibling
)
556 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
559 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
561 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
563 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
565 if (DeviceNode
->ResourceList
)
567 ExFreePool(DeviceNode
->ResourceList
);
570 if (DeviceNode
->ResourceListTranslated
)
572 ExFreePool(DeviceNode
->ResourceListTranslated
);
575 if (DeviceNode
->ResourceRequirements
)
577 ExFreePool(DeviceNode
->ResourceRequirements
);
580 if (DeviceNode
->BootResources
)
582 ExFreePool(DeviceNode
->BootResources
);
585 ExFreePool(DeviceNode
);
587 return STATUS_SUCCESS
;
592 PDEVICE_OBJECT DeviceObject
,
593 PIO_STATUS_BLOCK IoStatusBlock
,
595 PIO_STACK_LOCATION Stack OPTIONAL
)
597 PDEVICE_OBJECT TopDeviceObject
;
598 PIO_STACK_LOCATION IrpSp
;
603 /* Always call the top of the device stack */
604 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
611 Irp
= IoBuildSynchronousFsdRequest(
620 /* PNP IRPs are always initialized with a status code of
621 STATUS_NOT_IMPLEMENTED */
622 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
623 Irp
->IoStatus
.Information
= 0;
625 IrpSp
= IoGetNextIrpStackLocation(Irp
);
626 IrpSp
->MinorFunction
= MinorFunction
;
633 sizeof(Stack
->Parameters
));
636 Status
= IoCallDriver(TopDeviceObject
, Irp
);
637 if (Status
== STATUS_PENDING
)
639 KeWaitForSingleObject(
645 Status
= IoStatusBlock
->Status
;
648 ObDereferenceObject(TopDeviceObject
);
655 IopTraverseDeviceTreeNode(
656 PDEVICETREE_TRAVERSE_CONTEXT Context
)
658 PDEVICE_NODE ParentDeviceNode
;
659 PDEVICE_NODE ChildDeviceNode
;
662 /* Copy context data so we don't overwrite it in subsequent calls to this function */
663 ParentDeviceNode
= Context
->DeviceNode
;
665 /* Call the action routine */
666 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
667 if (!NT_SUCCESS(Status
))
672 /* Traversal of all children nodes */
673 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
674 ChildDeviceNode
!= NULL
;
675 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
677 /* Pass the current device node to the action routine */
678 Context
->DeviceNode
= ChildDeviceNode
;
680 Status
= IopTraverseDeviceTreeNode(Context
);
681 if (!NT_SUCCESS(Status
))
692 IopTraverseDeviceTree(
693 PDEVICETREE_TRAVERSE_CONTEXT Context
)
697 DPRINT("Context 0x%p\n", Context
);
699 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
700 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
702 /* Start from the specified device node */
703 Context
->DeviceNode
= Context
->FirstDeviceNode
;
705 /* Recursively traverse the device tree */
706 Status
= IopTraverseDeviceTreeNode(Context
);
707 if (Status
== STATUS_UNSUCCESSFUL
)
709 /* The action routine just wanted to terminate the traversal with status
710 code STATUS_SUCCESS */
711 Status
= STATUS_SUCCESS
;
719 IopCreateDeviceKeyPath(PWSTR Path
,
722 OBJECT_ATTRIBUTES ObjectAttributes
;
723 WCHAR KeyBuffer
[MAX_PATH
];
724 UNICODE_STRING KeyName
;
732 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
734 return STATUS_INVALID_PARAMETER
;
737 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
739 /* Skip \\Registry\\ */
741 Current
= wcschr (Current
, L
'\\') + 1;
742 Current
= wcschr (Current
, L
'\\') + 1;
746 Next
= wcschr (Current
, L
'\\');
756 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
757 InitializeObjectAttributes (&ObjectAttributes
,
759 OBJ_CASE_INSENSITIVE
,
763 DPRINT("Create '%S'\n", KeyName
.Buffer
);
765 Status
= ZwCreateKey (&KeyHandle
,
772 if (!NT_SUCCESS (Status
))
774 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
781 return STATUS_SUCCESS
;
792 return STATUS_UNSUCCESSFUL
;
797 IopSetDeviceInstanceData(HANDLE InstanceKey
,
798 PDEVICE_NODE DeviceNode
)
800 OBJECT_ATTRIBUTES ObjectAttributes
;
801 UNICODE_STRING KeyName
;
807 DPRINT("IopSetDeviceInstanceData() called\n");
809 /* Create the 'LogConf' key */
810 RtlInitUnicodeString(&KeyName
,
812 InitializeObjectAttributes(&ObjectAttributes
,
814 OBJ_CASE_INSENSITIVE
,
817 Status
= ZwCreateKey(&LogConfKey
,
824 if (NT_SUCCESS(Status
))
826 /* Set 'BootConfig' value */
827 if (DeviceNode
->BootResources
!= NULL
)
829 ResCount
= DeviceNode
->BootResources
->Count
;
832 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
834 RtlInitUnicodeString(&KeyName
,
836 Status
= ZwSetValueKey(LogConfKey
,
840 &DeviceNode
->BootResources
,
845 /* Set 'BasicConfigVector' value */
846 if (DeviceNode
->ResourceRequirements
!= NULL
&&
847 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
849 RtlInitUnicodeString(&KeyName
,
850 L
"BasicConfigVector");
851 Status
= ZwSetValueKey(LogConfKey
,
854 REG_RESOURCE_REQUIREMENTS_LIST
,
855 DeviceNode
->ResourceRequirements
,
856 DeviceNode
->ResourceRequirements
->ListSize
);
863 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
865 /* Create the 'Control' key */
866 RtlInitUnicodeString(&KeyName
,
868 InitializeObjectAttributes(&ObjectAttributes
,
870 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
873 Status
= ZwCreateKey(&LogConfKey
,
880 if (NT_SUCCESS(Status
))
882 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
883 RtlInitUnicodeString(&KeyName
,
885 Status
= ZwSetValueKey(LogConfKey
,
897 DPRINT("IopSetDeviceInstanceData() done\n");
899 return STATUS_SUCCESS
;
904 IopAssignDeviceResources(
905 PDEVICE_NODE DeviceNode
)
907 PIO_RESOURCE_LIST ResourceList
;
908 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
909 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
910 ULONG NumberOfResources
= 0;
914 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
915 * by using DeviceNode->ResourceRequirements */
917 if (!DeviceNode
->ResourceRequirements
918 || DeviceNode
->ResourceRequirements
->AlternativeLists
== 0)
920 DeviceNode
->ResourceList
= DeviceNode
->ResourceListTranslated
= NULL
;
921 return STATUS_SUCCESS
;
924 /* FIXME: that's here that PnP arbiter should go */
925 /* Actually, simply use resource list #0 as assigned resource list */
926 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
927 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
929 Status
= STATUS_REVISION_MISMATCH
;
933 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
,
934 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
935 if (!DeviceNode
->ResourceList
)
937 Status
= STATUS_INSUFFICIENT_RESOURCES
;
941 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
,
942 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
943 if (!DeviceNode
->ResourceListTranslated
)
945 Status
= STATUS_INSUFFICIENT_RESOURCES
;
949 DeviceNode
->ResourceList
->Count
= 1;
950 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
951 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
952 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
953 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
955 DeviceNode
->ResourceListTranslated
->Count
= 1;
956 DeviceNode
->ResourceListTranslated
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
957 DeviceNode
->ResourceListTranslated
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
958 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Version
= 1;
959 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Revision
= 1;
961 for (i
= 0; i
< ResourceList
->Count
; i
++)
963 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
965 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
967 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
968 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
971 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
972 DescriptorRaw
->Type
= DescriptorTranslated
->Type
= ResourceDescriptor
->Type
;
973 DescriptorRaw
->ShareDisposition
= DescriptorTranslated
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
974 DescriptorRaw
->Flags
= DescriptorTranslated
->Flags
= ResourceDescriptor
->Flags
;
975 switch (ResourceDescriptor
->Type
)
977 case CmResourceTypePort
:
979 ULONG AddressSpace
= 0; /* IO space */
980 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
981 DescriptorRaw
->u
.Port
.Length
= DescriptorTranslated
->u
.Port
.Length
982 = ResourceDescriptor
->u
.Port
.Length
;
983 if (!HalTranslateBusAddress(
984 DeviceNode
->ResourceRequirements
->InterfaceType
,
985 DeviceNode
->ResourceRequirements
->BusNumber
,
986 DescriptorRaw
->u
.Port
.Start
,
988 &DescriptorTranslated
->u
.Port
.Start
))
990 Status
= STATUS_UNSUCCESSFUL
;
995 case CmResourceTypeInterrupt
:
997 DescriptorRaw
->u
.Interrupt
.Level
= 0;
998 /* FIXME: if IRQ 9 is in the possible range, use it.
999 * This should be a PCI device */
1000 if (ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= 9
1001 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= 9)
1002 DescriptorRaw
->u
.Interrupt
.Vector
= 9;
1004 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1006 DescriptorTranslated
->u
.Interrupt
.Level
= 0;
1007 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1008 DeviceNode
->ResourceRequirements
->InterfaceType
,
1009 DeviceNode
->ResourceRequirements
->BusNumber
,
1010 DescriptorRaw
->u
.Interrupt
.Level
,
1011 DescriptorRaw
->u
.Interrupt
.Vector
,
1012 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1013 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1014 DescriptorTranslated
->u
.Interrupt
.Affinity
= DescriptorRaw
->u
.Interrupt
.Affinity
;
1017 case CmResourceTypeMemory
:
1019 ULONG AddressSpace
= 1; /* Memory space */
1020 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1021 DescriptorRaw
->u
.Memory
.Length
= DescriptorTranslated
->u
.Memory
.Length
1022 = ResourceDescriptor
->u
.Memory
.Length
;
1023 if (!HalTranslateBusAddress(
1024 DeviceNode
->ResourceRequirements
->InterfaceType
,
1025 DeviceNode
->ResourceRequirements
->BusNumber
,
1026 DescriptorRaw
->u
.Memory
.Start
,
1028 &DescriptorTranslated
->u
.Memory
.Start
))
1030 Status
= STATUS_UNSUCCESSFUL
;
1035 case CmResourceTypeDma
:
1037 DescriptorRaw
->u
.Dma
.Channel
= DescriptorTranslated
->u
.Dma
.Channel
1038 = ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1039 DescriptorRaw
->u
.Dma
.Port
= DescriptorTranslated
->u
.Dma
.Port
1041 DescriptorRaw
->u
.Dma
.Reserved1
= DescriptorTranslated
->u
.Dma
.Reserved1
1045 /*case CmResourceTypeBusNumber:
1047 DescriptorRaw->u.BusNumber.Start = DescriptorTranslated->u.BusNumber.Start
1048 = ResourceDescriptor->u.BusNumber.MinBusNumber;
1049 DescriptorRaw->u.BusNumber.Length = DescriptorTranslated->u.BusNumber.Length
1050 = ResourceDescriptor->u.BusNumber.Length;
1051 DescriptorRaw->u.BusNumber.Reserved = DescriptorTranslated->u.BusNumber.Reserved
1052 = ResourceDescriptor->u.BusNumber.Reserved;
1055 /*CmResourceTypeDevicePrivate:
1056 case CmResourceTypePcCardConfig:
1057 case CmResourceTypeMfCardConfig:
1060 &DescriptorRaw->u.DevicePrivate,
1061 &ResourceDescriptor->u.DevicePrivate,
1062 sizeof(ResourceDescriptor->u.DevicePrivate));
1064 &DescriptorTranslated->u.DevicePrivate,
1065 &ResourceDescriptor->u.DevicePrivate,
1066 sizeof(ResourceDescriptor->u.DevicePrivate));
1070 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1071 NumberOfResources
--;
1077 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1078 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1080 return STATUS_SUCCESS
;
1083 if (DeviceNode
->ResourceList
)
1085 ExFreePool(DeviceNode
->ResourceList
);
1086 DeviceNode
->ResourceList
= NULL
;
1088 if (DeviceNode
->ResourceListTranslated
)
1090 ExFreePool(DeviceNode
->ResourceListTranslated
);
1091 DeviceNode
->ResourceListTranslated
= NULL
;
1099 * IopActionInterrogateDeviceStack
1101 * Retrieve information for all (direct) child nodes of a parent node.
1105 * Pointer to device node.
1107 * Pointer to parent node to retrieve child node information for.
1110 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1111 * when we reach a device node which is not a direct child of the device
1112 * node for which we retrieve information of child nodes for. Any errors
1113 * that occur is logged instead so that all child services have a chance
1114 * of being interrogated.
1118 IopActionInterrogateDeviceStack(
1119 PDEVICE_NODE DeviceNode
,
1122 IO_STATUS_BLOCK IoStatusBlock
;
1123 PDEVICE_NODE ParentDeviceNode
;
1124 WCHAR InstancePath
[MAX_PATH
];
1125 IO_STACK_LOCATION Stack
;
1131 HANDLE InstanceKey
= NULL
;
1132 UNICODE_STRING ValueName
;
1133 DEVICE_CAPABILITIES DeviceCapabilities
;
1135 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1136 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1138 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1141 * We are called for the parent too, but we don't need to do special
1142 * handling for this node
1145 if (DeviceNode
== ParentDeviceNode
)
1147 DPRINT("Success\n");
1148 return STATUS_SUCCESS
;
1152 * Make sure this device node is a direct child of the parent device node
1153 * that is given as an argument
1156 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1158 /* Stop the traversal immediately and indicate successful operation */
1160 return STATUS_UNSUCCESSFUL
;
1164 * FIXME: For critical errors, cleanup and disable device, but always
1165 * return STATUS_SUCCESS.
1168 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1170 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1171 Status
= IopInitiatePnpIrp(
1172 DeviceNode
->PhysicalDeviceObject
,
1176 if (NT_SUCCESS(Status
))
1178 /* Copy the device id string */
1179 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1182 * FIXME: Check for valid characters, if there is invalid characters
1188 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1191 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1193 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1194 Status
= IopInitiatePnpIrp(
1195 DeviceNode
->PhysicalDeviceObject
,
1199 if (NT_SUCCESS(Status
))
1201 /* Append the instance id string */
1202 wcscat(InstancePath
, L
"\\");
1203 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1206 * FIXME: Check for valid characters, if there is invalid characters
1212 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1215 RtlZeroMemory(&DeviceCapabilities
, sizeof(DEVICE_CAPABILITIES
));
1216 DeviceCapabilities
.Size
= sizeof(DEVICE_CAPABILITIES
);
1217 DeviceCapabilities
.Version
= 1;
1218 DeviceCapabilities
.Address
= -1;
1219 DeviceCapabilities
.UINumber
= -1;
1221 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= &DeviceCapabilities
;
1222 Status
= IopInitiatePnpIrp(
1223 DeviceNode
->PhysicalDeviceObject
,
1225 IRP_MN_QUERY_CAPABILITIES
,
1227 if (NT_SUCCESS(Status
))
1232 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1235 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1236 DeviceNode
->Address
= DeviceCapabilities
.Address
;
1238 if (!DeviceCapabilities
.UniqueID
)
1240 DPRINT("Instance ID is not unique\n");
1241 /* FIXME: Add information from parent bus driver to InstancePath */
1244 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1246 DPRINT("No resources\n");
1247 /* FIXME: Cleanup and disable device */
1250 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1253 * Create registry key for the instance id, if it doesn't exist yet
1255 KeyBuffer
= ExAllocatePool(
1257 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1258 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1259 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1260 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1262 ExFreePool(KeyBuffer
);
1263 if (!NT_SUCCESS(Status
))
1265 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1270 /* Set 'Capabilities' value */
1271 RtlInitUnicodeString(&ValueName
,
1273 Status
= ZwSetValueKey(InstanceKey
,
1277 (PVOID
)&DeviceNode
->CapabilityFlags
,
1280 /* Set 'UINumber' value */
1281 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1283 RtlInitUnicodeString(&ValueName
,
1285 Status
= ZwSetValueKey(InstanceKey
,
1289 &DeviceCapabilities
.UINumber
,
1294 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1296 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1297 Status
= IopInitiatePnpIrp(
1298 DeviceNode
->PhysicalDeviceObject
,
1302 if (NT_SUCCESS(Status
))
1305 * FIXME: Check for valid characters, if there is invalid characters
1309 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1310 DPRINT("Hardware IDs:\n");
1313 DPRINT(" %S\n", Ptr
);
1314 Length
= wcslen(Ptr
) + 1;
1317 TotalLength
+= Length
;
1319 DPRINT("TotalLength: %hu\n", TotalLength
);
1322 RtlInitUnicodeString(&ValueName
,
1324 Status
= ZwSetValueKey(InstanceKey
,
1328 (PVOID
)IoStatusBlock
.Information
,
1329 (TotalLength
+ 1) * sizeof(WCHAR
));
1330 if (!NT_SUCCESS(Status
))
1332 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1337 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1340 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1342 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1343 Status
= IopInitiatePnpIrp(
1344 DeviceNode
->PhysicalDeviceObject
,
1348 if (NT_SUCCESS(Status
))
1351 * FIXME: Check for valid characters, if there is invalid characters
1355 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1356 DPRINT("Compatible IDs:\n");
1359 DPRINT(" %S\n", Ptr
);
1360 Length
= wcslen(Ptr
) + 1;
1363 TotalLength
+= Length
;
1365 DPRINT("TotalLength: %hu\n", TotalLength
);
1368 RtlInitUnicodeString(&ValueName
,
1370 Status
= ZwSetValueKey(InstanceKey
,
1374 (PVOID
)IoStatusBlock
.Information
,
1375 (TotalLength
+ 1) * sizeof(WCHAR
));
1376 if (!NT_SUCCESS(Status
))
1378 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1383 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1387 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1389 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1390 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
1391 Status
= IopInitiatePnpIrp(
1392 DeviceNode
->PhysicalDeviceObject
,
1394 IRP_MN_QUERY_DEVICE_TEXT
,
1396 if (NT_SUCCESS(Status
))
1398 RtlInitUnicodeString(&ValueName
,
1400 Status
= ZwSetValueKey(InstanceKey
,
1404 (PVOID
)IoStatusBlock
.Information
,
1405 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1406 if (!NT_SUCCESS(Status
))
1408 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1413 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1416 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1418 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1419 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
1420 Status
= IopInitiatePnpIrp(
1421 DeviceNode
->PhysicalDeviceObject
,
1423 IRP_MN_QUERY_DEVICE_TEXT
,
1425 if (NT_SUCCESS(Status
))
1427 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1428 RtlInitUnicodeString(&ValueName
,
1429 L
"LocationInformation");
1430 Status
= ZwSetValueKey(InstanceKey
,
1434 (PVOID
)IoStatusBlock
.Information
,
1435 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1436 if (!NT_SUCCESS(Status
))
1438 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1443 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1446 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1448 Status
= IopInitiatePnpIrp(
1449 DeviceNode
->PhysicalDeviceObject
,
1451 IRP_MN_QUERY_BUS_INFORMATION
,
1453 if (NT_SUCCESS(Status
))
1455 PPNP_BUS_INFORMATION BusInformation
=
1456 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1458 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1459 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1460 memcpy(&DeviceNode
->BusTypeGuid
,
1461 &BusInformation
->BusTypeGuid
,
1463 ExFreePool(BusInformation
);
1467 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1469 DeviceNode
->ChildBusNumber
= -1;
1470 DeviceNode
->ChildInterfaceType
= -1;
1471 memset(&DeviceNode
->BusTypeGuid
,
1476 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1478 Status
= IopInitiatePnpIrp(
1479 DeviceNode
->PhysicalDeviceObject
,
1481 IRP_MN_QUERY_RESOURCES
,
1483 if (NT_SUCCESS(Status
))
1485 DeviceNode
->BootResources
=
1486 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1487 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1491 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1492 DeviceNode
->BootResources
= NULL
;
1495 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1497 Status
= IopInitiatePnpIrp(
1498 DeviceNode
->PhysicalDeviceObject
,
1500 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1502 if (NT_SUCCESS(Status
))
1504 DeviceNode
->ResourceRequirements
=
1505 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1509 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1510 DeviceNode
->ResourceRequirements
= NULL
;
1514 if (InstanceKey
!= NULL
)
1516 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1519 ZwClose(InstanceKey
);
1521 Status
= IopAssignDeviceResources(DeviceNode
);
1522 if (!NT_SUCCESS(Status
))
1524 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status
);
1527 DeviceNode
->Flags
|= DNF_PROCESSED
;
1529 /* Report the device to the user-mode pnp manager */
1530 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1531 &DeviceNode
->InstancePath
);
1533 return STATUS_SUCCESS
;
1537 * IopActionConfigureChildServices
1539 * Retrieve configuration for all (direct) child nodes of a parent node.
1543 * Pointer to device node.
1545 * Pointer to parent node to retrieve child node configuration for.
1548 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1549 * when we reach a device node which is not a direct child of the device
1550 * node for which we configure child services for. Any errors that occur is
1551 * logged instead so that all child services have a chance of beeing
1556 IopActionConfigureChildServices(
1557 PDEVICE_NODE DeviceNode
,
1560 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1561 PDEVICE_NODE ParentDeviceNode
;
1562 PUNICODE_STRING Service
;
1565 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1567 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1570 * We are called for the parent too, but we don't need to do special
1571 * handling for this node
1573 if (DeviceNode
== ParentDeviceNode
)
1575 DPRINT("Success\n");
1576 return STATUS_SUCCESS
;
1580 * Make sure this device node is a direct child of the parent device node
1581 * that is given as an argument
1583 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1585 /* Stop the traversal immediately and indicate successful operation */
1587 return STATUS_UNSUCCESSFUL
;
1590 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1592 WCHAR RegKeyBuffer
[MAX_PATH
];
1593 UNICODE_STRING RegKey
;
1596 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1597 RegKey
.Buffer
= RegKeyBuffer
;
1600 * Retrieve configuration from Enum key
1603 Service
= &DeviceNode
->ServiceName
;
1605 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1606 RtlInitUnicodeString(Service
, NULL
);
1608 QueryTable
[0].Name
= L
"Service";
1609 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1610 QueryTable
[0].EntryContext
= Service
;
1612 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1613 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1615 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1616 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1618 if (!NT_SUCCESS(Status
))
1620 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1621 /* FIXME: Log the error */
1622 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1623 DeviceNode
->InstancePath
.Buffer
, Status
);
1624 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1625 return STATUS_SUCCESS
;
1628 if (Service
->Buffer
== NULL
)
1630 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1631 return STATUS_SUCCESS
;
1634 DPRINT("Got Service %S\n", Service
->Buffer
);
1637 return STATUS_SUCCESS
;
1641 * IopActionInitChildServices
1643 * Initialize the service for all (direct) child nodes of a parent node
1647 * Pointer to device node.
1649 * Pointer to parent node to initialize child node services for.
1651 * Load only driver marked as boot start.
1654 * If the driver image for a service is not loaded and initialized
1655 * it is done here too. We only return a status code indicating an
1656 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1657 * not a direct child of the device node for which we initialize
1658 * child services for. Any errors that occur is logged instead so
1659 * that all child services have a chance of being initialized.
1663 IopActionInitChildServices(
1664 PDEVICE_NODE DeviceNode
,
1666 BOOLEAN BootDrivers
)
1668 PDEVICE_NODE ParentDeviceNode
;
1671 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1674 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1677 * We are called for the parent too, but we don't need to do special
1678 * handling for this node
1680 if (DeviceNode
== ParentDeviceNode
)
1682 DPRINT("Success\n");
1683 return STATUS_SUCCESS
;
1687 * Make sure this device node is a direct child of the parent device node
1688 * that is given as an argument
1691 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1694 * Stop the traversal immediately and indicate unsuccessful operation
1697 return STATUS_UNSUCCESSFUL
;
1701 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1702 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1703 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1705 PLDR_DATA_TABLE_ENTRY ModuleObject
;
1706 PDRIVER_OBJECT DriverObject
;
1708 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1709 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
1711 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
1712 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
1713 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
1716 /* get existing DriverObject pointer */
1717 Status
= IopGetDriverObject(
1719 &DeviceNode
->ServiceName
,
1722 if (NT_SUCCESS(Status
))
1724 /* Attach lower level filter drivers. */
1725 IopAttachFilterDrivers(DeviceNode
, TRUE
);
1726 /* Initialize the function driver for the device node */
1727 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1728 if (NT_SUCCESS(Status
))
1730 /* Attach upper level filter drivers. */
1731 IopAttachFilterDrivers(DeviceNode
, FALSE
);
1732 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1734 Status
= IopStartDevice(DeviceNode
);
1741 * Don't disable when trying to load only boot drivers
1745 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1746 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1748 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1749 CPRINT("Initialization of service %S failed (Status %x)\n",
1750 DeviceNode
->ServiceName
.Buffer
, Status
);
1754 DPRINT("Service %S is disabled or already initialized\n",
1755 DeviceNode
->ServiceName
.Buffer
);
1758 return STATUS_SUCCESS
;
1762 * IopActionInitAllServices
1764 * Initialize the service for all (direct) child nodes of a parent node. This
1765 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1769 IopActionInitAllServices(
1770 PDEVICE_NODE DeviceNode
,
1773 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1777 * IopActionInitBootServices
1779 * Initialize the boot start services for all (direct) child nodes of a
1780 * parent node. This function just calls IopActionInitChildServices with
1781 * BootDrivers = TRUE.
1784 IopActionInitBootServices(
1785 PDEVICE_NODE DeviceNode
,
1788 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1792 * IopInitializePnpServices
1794 * Initialize services for discovered children
1798 * Top device node to start initializing services.
1801 * When set to TRUE, only drivers marked as boot start will
1802 * be loaded. Otherwise, all drivers will be loaded.
1808 IopInitializePnpServices(
1809 IN PDEVICE_NODE DeviceNode
,
1810 IN BOOLEAN BootDrivers
)
1812 DEVICETREE_TRAVERSE_CONTEXT Context
;
1814 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1818 IopInitDeviceTreeTraverseContext(
1821 IopActionInitBootServices
,
1826 IopInitDeviceTreeTraverseContext(
1829 IopActionInitAllServices
,
1833 return IopTraverseDeviceTree(&Context
);
1838 IopInvalidateDeviceRelations(
1839 IN PDEVICE_NODE DeviceNode
,
1840 IN DEVICE_RELATION_TYPE Type
)
1842 DEVICETREE_TRAVERSE_CONTEXT Context
;
1843 PDEVICE_RELATIONS DeviceRelations
;
1844 IO_STATUS_BLOCK IoStatusBlock
;
1845 PDEVICE_NODE ChildDeviceNode
;
1846 IO_STACK_LOCATION Stack
;
1848 OBJECT_ATTRIBUTES ObjectAttributes
;
1849 UNICODE_STRING LinkName
;
1854 DPRINT("DeviceNode 0x%p\n", DeviceNode
);
1856 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1858 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1860 Status
= IopInitiatePnpIrp(
1861 DeviceNode
->PhysicalDeviceObject
,
1863 IRP_MN_QUERY_DEVICE_RELATIONS
,
1865 if (!NT_SUCCESS(Status
))
1867 DPRINT("IopInitiatePnpIrp() failed\n");
1871 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1873 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1875 DPRINT("No PDOs\n");
1876 if (DeviceRelations
)
1878 ExFreePool(DeviceRelations
);
1880 return STATUS_SUCCESS
;
1883 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1886 * Create device nodes for all discovered devices
1889 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1891 Status
= IopCreateDeviceNode(
1893 DeviceRelations
->Objects
[i
],
1895 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1896 if (!NT_SUCCESS(Status
))
1898 DPRINT("No resources\n");
1899 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1900 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1901 ExFreePool(DeviceRelations
);
1902 return STATUS_INSUFFICIENT_RESOURCES
;
1905 ExFreePool(DeviceRelations
);
1908 * Retrieve information about all discovered children from the bus driver
1911 IopInitDeviceTreeTraverseContext(
1914 IopActionInterrogateDeviceStack
,
1917 Status
= IopTraverseDeviceTree(&Context
);
1918 if (!NT_SUCCESS(Status
))
1920 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1925 * Retrieve configuration from the registry for discovered children
1928 IopInitDeviceTreeTraverseContext(
1931 IopActionConfigureChildServices
,
1934 Status
= IopTraverseDeviceTree(&Context
);
1935 if (!NT_SUCCESS(Status
))
1937 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1942 * Get the state of the system boot. If the \\SystemRoot link isn't
1943 * created yet, we will assume that it's possible to load only boot
1947 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
1949 InitializeObjectAttributes(
1956 Status
= ZwOpenFile(
1963 if(NT_SUCCESS(Status
))
1965 BootDrivers
= FALSE
;
1972 * Initialize services for discovered children. Only boot drivers will
1973 * be loaded from boot driver!
1976 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
1977 if (!NT_SUCCESS(Status
))
1979 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
1983 return STATUS_SUCCESS
;
1987 static NTSTATUS INIT_FUNCTION
1988 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
)
1992 HANDLE InstanceKey
= NULL
;
1995 /* Create registry key for the instance id, if it doesn't exist yet */
1996 KeyBuffer
= ExAllocatePool(PagedPool
,
1997 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1998 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1999 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
2000 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
2002 ExFreePool(KeyBuffer
);
2003 if (!NT_SUCCESS(Status
))
2005 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2009 /* FIXME: Set 'ConfigFlags' value */
2011 ZwClose(InstanceKey
);
2015 return STATUS_SUCCESS
;
2025 DPRINT("PnpInit()\n");
2027 KeInitializeSpinLock(&IopDeviceTreeLock
);
2029 /* Initialize PnP-Event notification support */
2030 Status
= IopInitPlugPlayEvents();
2031 if (!NT_SUCCESS(Status
))
2033 CPRINT("IopInitPlugPlayEvents() failed\n");
2034 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2038 * Create root device node
2041 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
2042 if (!NT_SUCCESS(Status
))
2044 CPRINT("IoCreateDriverObject() failed\n");
2045 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2048 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2050 if (!NT_SUCCESS(Status
))
2052 CPRINT("IoCreateDevice() failed\n");
2053 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2056 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
2057 if (!NT_SUCCESS(Status
))
2059 CPRINT("Insufficient resources\n");
2060 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2063 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2066 CPRINT("Failed to create the instance path!\n");
2067 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_UNSUCCESSFUL
, 0, 0, 0);
2070 /* Report the device to the user-mode pnp manager */
2071 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2072 &IopRootDeviceNode
->InstancePath
);
2074 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2075 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2076 IopRootDriverObject
->DriverExtension
->AddDevice(
2077 IopRootDriverObject
,
2078 IopRootDeviceNode
->PhysicalDeviceObject
);
2087 /* Set root device instance data */
2088 Status
= IopSetRootDeviceInstanceData(IopRootDeviceNode
);
2089 if (!NT_SUCCESS(Status
))
2091 CPRINT("Failed to set instance data\n");
2092 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);