3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnpmgr.c
6 * PURPOSE: Initializes the PnP manager
8 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
11 /* INCLUDES ******************************************************************/
14 #include <ddk/wdmguid.h>
17 #include <internal/debug.h>
19 /* GLOBALS *******************************************************************/
21 PDEVICE_NODE IopRootDeviceNode
;
22 KSPIN_LOCK IopDeviceTreeLock
;
24 /* DATA **********************************************************************/
26 PDRIVER_OBJECT IopRootDriverObject
;
28 /* FUNCTIONS *****************************************************************/
32 PDEVICE_OBJECT DeviceObject
)
34 return DeviceObject
->DeviceObjectExtension
->DeviceNode
;
42 IoInvalidateDeviceRelations(
43 IN PDEVICE_OBJECT DeviceObject
,
44 IN DEVICE_RELATION_TYPE Type
)
46 IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject
), Type
);
55 IN PDEVICE_OBJECT DeviceObject
,
56 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
57 IN ULONG BufferLength
,
58 OUT PVOID PropertyBuffer
,
59 OUT PULONG ResultLength
)
61 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
66 DPRINT("IoGetDeviceProperty(%x %d)\n", DeviceObject
, DeviceProperty
);
68 if (DeviceNode
== NULL
)
69 return STATUS_INVALID_DEVICE_REQUEST
;
71 switch (DeviceProperty
)
73 case DevicePropertyBusNumber
:
74 Length
= sizeof(ULONG
);
75 Data
= &DeviceNode
->ChildBusNumber
;
78 /* Complete, untested */
79 case DevicePropertyBusTypeGuid
:
80 *ResultLength
= 39 * sizeof(WCHAR
);
81 if (BufferLength
< (39 * sizeof(WCHAR
)))
82 return STATUS_BUFFER_TOO_SMALL
;
83 swprintf((PWSTR
)PropertyBuffer
,
84 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
85 DeviceNode
->BusTypeGuid
.Data1
,
86 DeviceNode
->BusTypeGuid
.Data2
,
87 DeviceNode
->BusTypeGuid
.Data3
,
88 DeviceNode
->BusTypeGuid
.Data4
[0],
89 DeviceNode
->BusTypeGuid
.Data4
[1],
90 DeviceNode
->BusTypeGuid
.Data4
[2],
91 DeviceNode
->BusTypeGuid
.Data4
[3],
92 DeviceNode
->BusTypeGuid
.Data4
[4],
93 DeviceNode
->BusTypeGuid
.Data4
[5],
94 DeviceNode
->BusTypeGuid
.Data4
[6],
95 DeviceNode
->BusTypeGuid
.Data4
[7]);
96 return STATUS_SUCCESS
;
98 case DevicePropertyLegacyBusType
:
99 Length
= sizeof(INTERFACE_TYPE
);
100 Data
= &DeviceNode
->ChildInterfaceType
;
103 case DevicePropertyAddress
:
104 Length
= sizeof(ULONG
);
105 Data
= &DeviceNode
->Address
;
108 // case DevicePropertyUINumber:
109 // if (DeviceNode->CapabilityFlags == NULL)
110 // return STATUS_INVALID_DEVICE_REQUEST;
111 // Length = sizeof(ULONG);
112 // Data = &DeviceNode->CapabilityFlags->UINumber;
115 case DevicePropertyClassName
:
116 case DevicePropertyClassGuid
:
117 case DevicePropertyDriverKeyName
:
118 case DevicePropertyManufacturer
:
119 case DevicePropertyFriendlyName
:
120 case DevicePropertyHardwareID
:
121 case DevicePropertyCompatibleIDs
:
122 case DevicePropertyDeviceDescription
:
123 case DevicePropertyLocationInformation
:
124 case DevicePropertyUINumber
:
126 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
127 UNICODE_STRING KeyName
, ValueName
;
128 OBJECT_ATTRIBUTES ObjectAttributes
;
129 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
130 ULONG ValueInformationLength
;
134 switch (DeviceProperty
)
136 case DevicePropertyClassName
:
137 RegistryPropertyName
= L
"Class"; break;
138 case DevicePropertyClassGuid
:
139 RegistryPropertyName
= L
"ClassGuid"; break;
140 case DevicePropertyDriverKeyName
:
141 RegistryPropertyName
= L
"Driver"; break;
142 case DevicePropertyManufacturer
:
143 RegistryPropertyName
= L
"Mfg"; break;
144 case DevicePropertyFriendlyName
:
145 RegistryPropertyName
= L
"FriendlyName"; break;
146 case DevicePropertyHardwareID
:
147 RegistryPropertyName
= L
"HardwareID"; break;
148 case DevicePropertyCompatibleIDs
:
149 RegistryPropertyName
= L
"CompatibleIDs"; break;
150 case DevicePropertyDeviceDescription
:
151 RegistryPropertyName
= L
"DeviceDesc"; break;
152 case DevicePropertyLocationInformation
:
153 RegistryPropertyName
= L
"LocationInformation"; break;
154 case DevicePropertyUINumber
:
155 RegistryPropertyName
= L
"UINumber"; break;
157 RegistryPropertyName
= NULL
; break;
160 KeyNameBuffer
= ExAllocatePool(PagedPool
,
161 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
163 DPRINT("KeyNameBuffer: %x, value %S\n",
164 KeyNameBuffer
, RegistryPropertyName
);
166 if (KeyNameBuffer
== NULL
)
167 return STATUS_INSUFFICIENT_RESOURCES
;
169 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
170 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
171 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
172 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
173 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
175 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
176 ExFreePool(KeyNameBuffer
);
177 if (!NT_SUCCESS(Status
))
180 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
181 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
182 Data
[0]) + BufferLength
;
183 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
184 if (ValueInformation
== NULL
)
187 return STATUS_INSUFFICIENT_RESOURCES
;
190 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
191 KeyValuePartialInformation
, ValueInformation
,
192 ValueInformationLength
,
193 &ValueInformationLength
);
194 *ResultLength
= ValueInformation
->DataLength
;
197 if (ValueInformation
->DataLength
> BufferLength
)
198 Status
= STATUS_BUFFER_TOO_SMALL
;
200 if (!NT_SUCCESS(Status
))
202 ExFreePool(ValueInformation
);
206 /* FIXME: Verify the value (NULL-terminated, correct format). */
208 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
209 ValueInformation
->DataLength
);
210 ExFreePool(ValueInformation
);
212 return STATUS_SUCCESS
;
215 case DevicePropertyBootConfiguration
:
217 if (DeviceNode
->BootResources
->Count
!= 0)
219 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
221 Data
= &DeviceNode
->BootResources
;
224 /* FIXME: use a translated boot configuration instead */
225 case DevicePropertyBootConfigurationTranslated
:
227 if (DeviceNode
->BootResources
->Count
!= 0)
229 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
231 Data
= &DeviceNode
->BootResources
;
234 case DevicePropertyEnumeratorName
:
235 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
238 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
239 Data
= DeviceNode
->InstancePath
.Buffer
;
248 case DevicePropertyPhysicalDeviceObjectName
:
249 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
250 Data
= DeviceNode
->InstancePath
.Buffer
;
254 return STATUS_INVALID_PARAMETER_2
;
257 *ResultLength
= Length
;
258 if (BufferLength
< Length
)
259 return STATUS_BUFFER_TOO_SMALL
;
260 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
262 /* Terminate the string */
263 if (DeviceProperty
== DevicePropertyEnumeratorName
264 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
266 Ptr
= (PWSTR
)PropertyBuffer
;
267 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
270 return STATUS_SUCCESS
;
278 IoInvalidateDeviceState(
279 IN PDEVICE_OBJECT PhysicalDeviceObject
)
284 * @name IoOpenDeviceRegistryKey
286 * Open a registry key unique for a specified driver or device instance.
288 * @param DeviceObject Device to get the registry key for.
289 * @param DevInstKeyType Type of the key to return.
290 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
291 * @param DevInstRegKey Handle to the opened registry key on
300 IoOpenDeviceRegistryKey(
301 IN PDEVICE_OBJECT DeviceObject
,
302 IN ULONG DevInstKeyType
,
303 IN ACCESS_MASK DesiredAccess
,
304 OUT PHANDLE DevInstRegKey
)
306 static WCHAR RootKeyName
[] =
307 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
308 static WCHAR ProfileKeyName
[] =
309 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
310 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
311 static WCHAR EnumKeyName
[] = L
"Enum\\";
312 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters\\";
314 LPWSTR KeyNameBuffer
;
315 UNICODE_STRING KeyName
;
316 ULONG DriverKeyLength
;
317 OBJECT_ATTRIBUTES ObjectAttributes
;
318 PDEVICE_NODE DeviceNode
= NULL
;
321 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
322 return STATUS_INVALID_PARAMETER
;
325 * Calculate the length of the base key name. This is the full
326 * name for driver key or the name excluding "Device Parameters"
327 * subkey for device key.
330 KeyNameLength
= sizeof(RootKeyName
);
331 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
332 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
333 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
335 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
336 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
337 0, NULL
, &DriverKeyLength
);
338 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
340 KeyNameLength
+= DriverKeyLength
;
344 DeviceNode
= IopGetDeviceNode(DeviceObject
);
345 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
346 DeviceNode
->InstancePath
.Length
;
350 * Now allocate the buffer for the key name...
353 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
354 if (KeyNameBuffer
== NULL
)
355 return STATUS_INSUFFICIENT_RESOURCES
;
358 KeyName
.MaximumLength
= KeyNameLength
;
359 KeyName
.Buffer
= KeyNameBuffer
;
362 * ...and build the key name.
365 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
366 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
368 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
369 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
371 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
373 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
374 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
375 DriverKeyLength
, KeyNameBuffer
+
376 (KeyName
.Length
/ sizeof(WCHAR
)),
378 if (!NT_SUCCESS(Status
))
380 ExFreePool(KeyNameBuffer
);
383 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
387 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
388 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
389 if (DeviceNode
->InstancePath
.Length
== 0)
391 ExFreePool(KeyNameBuffer
);
400 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
401 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
402 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
403 ExFreePool(KeyNameBuffer
);
406 * For driver key we're done now. Also if the base key doesn't
407 * exist we can bail out with error...
410 if ((DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
) || !NT_SUCCESS(Status
))
414 * Let's go further. For device key we must open "Device Parameters"
415 * subkey and create it if it doesn't exist yet.
418 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
419 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
420 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
421 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
422 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
423 ZwClose(ObjectAttributes
.RootDirectory
);
433 IoRequestDeviceEject(
434 IN PDEVICE_OBJECT PhysicalDeviceObject
442 IopCreateUnicodeString(
443 PUNICODE_STRING Destination
,
451 RtlInitUnicodeString(Destination
, NULL
);
455 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
457 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
459 if (Destination
->Buffer
== NULL
)
464 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
466 Destination
->MaximumLength
= Length
;
468 Destination
->Length
= Length
- sizeof(WCHAR
);
474 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
478 if (PopSystemPowerDeviceNode
)
480 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
481 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
482 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
484 return STATUS_SUCCESS
;
487 return STATUS_UNSUCCESSFUL
;
492 * Creates a device node
495 * ParentNode = Pointer to parent device node
496 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
497 * to have the root device node create one
498 * (eg. for legacy drivers)
499 * DeviceNode = Pointer to storage for created device node
505 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
506 PDEVICE_OBJECT PhysicalDeviceObject
,
507 PDEVICE_NODE
*DeviceNode
)
513 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
514 ParentNode
, PhysicalDeviceObject
);
516 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
519 return STATUS_INSUFFICIENT_RESOURCES
;
522 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
524 if (!PhysicalDeviceObject
)
526 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
527 if (!NT_SUCCESS(Status
))
533 /* This is for drivers passed on the command line to ntoskrnl.exe */
534 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
535 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
538 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
540 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
544 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
545 Node
->Parent
= ParentNode
;
546 Node
->NextSibling
= ParentNode
->Child
;
547 if (ParentNode
->Child
!= NULL
)
549 ParentNode
->Child
->PrevSibling
= Node
;
551 ParentNode
->Child
= Node
;
552 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
557 return STATUS_SUCCESS
;
561 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
565 /* All children must be deleted before a parent is deleted */
566 ASSERT(!DeviceNode
->Child
);
568 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
570 ASSERT(DeviceNode
->PhysicalDeviceObject
);
572 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
574 /* Unlink from parent if it exists */
576 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
578 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
581 /* Unlink from sibling list */
583 if (DeviceNode
->PrevSibling
)
585 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
588 if (DeviceNode
->NextSibling
)
590 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
593 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
595 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
597 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
599 if (DeviceNode
->ResourceList
)
601 ExFreePool(DeviceNode
->ResourceList
);
604 if (DeviceNode
->ResourceListTranslated
)
606 ExFreePool(DeviceNode
->ResourceListTranslated
);
609 if (DeviceNode
->ResourceRequirements
)
611 ExFreePool(DeviceNode
->ResourceRequirements
);
614 if (DeviceNode
->BootResources
)
616 ExFreePool(DeviceNode
->BootResources
);
619 ExFreePool(DeviceNode
);
621 return STATUS_SUCCESS
;
626 PDEVICE_OBJECT DeviceObject
,
627 PIO_STATUS_BLOCK IoStatusBlock
,
629 PIO_STACK_LOCATION Stack OPTIONAL
)
631 PDEVICE_OBJECT TopDeviceObject
;
632 PIO_STACK_LOCATION IrpSp
;
637 /* Always call the top of the device stack */
638 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
645 Irp
= IoBuildSynchronousFsdRequest(
654 /* PNP IRPs are always initialized with a status code of
655 STATUS_NOT_IMPLEMENTED */
656 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
657 Irp
->IoStatus
.Information
= 0;
659 IrpSp
= IoGetNextIrpStackLocation(Irp
);
660 IrpSp
->MinorFunction
= MinorFunction
;
667 sizeof(Stack
->Parameters
));
670 Status
= IoCallDriver(TopDeviceObject
, Irp
);
671 if (Status
== STATUS_PENDING
)
673 KeWaitForSingleObject(
679 Status
= IoStatusBlock
->Status
;
682 ObDereferenceObject(TopDeviceObject
);
689 IopTraverseDeviceTreeNode(
690 PDEVICETREE_TRAVERSE_CONTEXT Context
)
692 PDEVICE_NODE ParentDeviceNode
;
693 PDEVICE_NODE ChildDeviceNode
;
696 /* Copy context data so we don't overwrite it in subsequent calls to this function */
697 ParentDeviceNode
= Context
->DeviceNode
;
699 /* Call the action routine */
700 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
701 if (!NT_SUCCESS(Status
))
706 /* Traversal of all children nodes */
707 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
708 ChildDeviceNode
!= NULL
;
709 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
711 /* Pass the current device node to the action routine */
712 Context
->DeviceNode
= ChildDeviceNode
;
714 Status
= IopTraverseDeviceTreeNode(Context
);
715 if (!NT_SUCCESS(Status
))
726 IopTraverseDeviceTree(
727 PDEVICETREE_TRAVERSE_CONTEXT Context
)
731 DPRINT("Context %x\n", Context
);
733 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
734 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
736 /* Start from the specified device node */
737 Context
->DeviceNode
= Context
->FirstDeviceNode
;
739 /* Recursively traverse the device tree */
740 Status
= IopTraverseDeviceTreeNode(Context
);
741 if (Status
== STATUS_UNSUCCESSFUL
)
743 /* The action routine just wanted to terminate the traversal with status
744 code STATUS_SUCCESS */
745 Status
= STATUS_SUCCESS
;
753 IopCreateDeviceKeyPath(PWSTR Path
,
756 OBJECT_ATTRIBUTES ObjectAttributes
;
757 WCHAR KeyBuffer
[MAX_PATH
];
758 UNICODE_STRING KeyName
;
766 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
768 return STATUS_INVALID_PARAMETER
;
771 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
773 /* Skip \\Registry\\ */
775 Current
= wcschr (Current
, L
'\\') + 1;
776 Current
= wcschr (Current
, L
'\\') + 1;
780 Next
= wcschr (Current
, L
'\\');
790 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
791 InitializeObjectAttributes (&ObjectAttributes
,
793 OBJ_CASE_INSENSITIVE
,
797 DPRINT("Create '%S'\n", KeyName
.Buffer
);
799 Status
= ZwCreateKey (&KeyHandle
,
806 if (!NT_SUCCESS (Status
))
808 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
815 return STATUS_SUCCESS
;
826 return STATUS_UNSUCCESSFUL
;
831 IopSetDeviceInstanceData(HANDLE InstanceKey
,
832 PDEVICE_NODE DeviceNode
)
834 OBJECT_ATTRIBUTES ObjectAttributes
;
835 UNICODE_STRING KeyName
;
841 DPRINT("IopSetDeviceInstanceData() called\n");
843 /* Create the 'LogConf' key */
844 RtlInitUnicodeString(&KeyName
,
846 InitializeObjectAttributes(&ObjectAttributes
,
848 OBJ_CASE_INSENSITIVE
,
851 Status
= ZwCreateKey(&LogConfKey
,
858 if (NT_SUCCESS(Status
))
860 /* Set 'BootConfig' value */
861 if (DeviceNode
->BootResources
!= NULL
)
863 ResCount
= DeviceNode
->BootResources
->Count
;
866 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
868 RtlInitUnicodeString(&KeyName
,
870 Status
= ZwSetValueKey(LogConfKey
,
874 &DeviceNode
->BootResources
,
879 /* Set 'BasicConfigVector' value */
880 if (DeviceNode
->ResourceRequirements
!= NULL
&&
881 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
883 RtlInitUnicodeString(&KeyName
,
884 L
"BasicConfigVector");
885 Status
= ZwSetValueKey(LogConfKey
,
888 REG_RESOURCE_REQUIREMENTS_LIST
,
889 &DeviceNode
->ResourceRequirements
,
890 DeviceNode
->ResourceRequirements
->ListSize
);
896 DPRINT("IopSetDeviceInstanceData() done\n");
898 return STATUS_SUCCESS
;
903 IopAssignDeviceResources(
904 PDEVICE_NODE DeviceNode
)
906 PIO_RESOURCE_LIST ResourceList
;
907 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
908 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
909 ULONG NumberOfResources
= 0;
912 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
913 * by using DeviceNode->ResourceRequirements */
915 if (!DeviceNode
->ResourceRequirements
916 || DeviceNode
->ResourceRequirements
->AlternativeLists
== 0)
918 DeviceNode
->ResourceList
= DeviceNode
->ResourceListTranslated
= NULL
;
919 return STATUS_SUCCESS
;
922 /* FIXME: that's here that PnP arbiter should go */
923 /* Actually, simply use resource list #0 as assigned resource list */
924 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
925 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
926 return STATUS_REVISION_MISMATCH
;
928 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
,
929 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
930 if (!DeviceNode
->ResourceList
)
931 return STATUS_INSUFFICIENT_RESOURCES
;
933 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
,
934 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
935 if (!DeviceNode
->ResourceListTranslated
)
937 ExFreePool(DeviceNode
->ResourceList
);
938 return STATUS_INSUFFICIENT_RESOURCES
;
941 DeviceNode
->ResourceList
->Count
= 1;
942 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
943 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
944 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
945 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
947 DeviceNode
->ResourceListTranslated
->Count
= 1;
948 DeviceNode
->ResourceListTranslated
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
949 DeviceNode
->ResourceListTranslated
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
950 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Version
= 1;
951 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Revision
= 1;
953 for (i
= 0; i
< ResourceList
->Count
; i
++)
955 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
957 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
959 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
960 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
963 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
964 DescriptorRaw
->Type
= DescriptorTranslated
->Type
= ResourceDescriptor
->Type
;
965 DescriptorRaw
->ShareDisposition
= DescriptorTranslated
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
966 DescriptorRaw
->Flags
= DescriptorTranslated
->Flags
= ResourceDescriptor
->Flags
;
967 switch (ResourceDescriptor
->Type
)
969 case CmResourceTypePort
:
971 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
972 DescriptorRaw
->u
.Port
.Length
= DescriptorTranslated
->u
.Port
.Length
973 = ResourceDescriptor
->u
.Port
.Length
;
974 /*FIXME: DescriptorTranslated->u.Port.Start? */
977 case CmResourceTypeInterrupt
:
979 DescriptorRaw
->u
.Interrupt
.Vector
= 0;
980 /* FIXME: if IRQ 9 is in the possible range, use it.
981 * This should be a PCI device */
982 if (ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= 9
983 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= 9)
984 DescriptorRaw
->u
.Interrupt
.Level
= 9;
986 DescriptorRaw
->u
.Interrupt
.Level
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
988 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
989 DeviceNode
->ResourceRequirements
->InterfaceType
,
990 DeviceNode
->ResourceRequirements
->BusNumber
,
991 DescriptorRaw
->u
.Interrupt
.Level
,
992 DescriptorRaw
->u
.Interrupt
.Vector
,
993 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
994 &DescriptorRaw
->u
.Interrupt
.Affinity
);
995 DescriptorTranslated
->u
.Interrupt
.Affinity
= DescriptorRaw
->u
.Interrupt
.Affinity
;
998 case CmResourceTypeMemory
:
1000 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1001 DescriptorRaw
->u
.Memory
.Length
= DescriptorTranslated
->u
.Memory
.Length
1002 = ResourceDescriptor
->u
.Port
.Length
;
1003 /*FIXME: DescriptorTranslated->u.Memory.Start? */
1006 case CmResourceTypeDma
:
1008 DPRINT1("IopAssignDeviceResources(): CmResourceTypeDma case not implemented\n");
1009 DescriptorRaw
->u
.Dma
.Channel
= DescriptorTranslated
->u
.Dma
.Channel
1010 = ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1011 DescriptorRaw
->u
.Dma
.Port
= DescriptorTranslated
->u
.Dma
.Port
1013 DescriptorRaw
->u
.Dma
.Reserved1
= DescriptorTranslated
->u
.Dma
.Reserved1
1017 /*case CmResourceTypeBusNumber:
1019 DescriptorRaw->u.BusNumber.Start = DescriptorTranslated->u.BusNumber.Start
1020 = ResourceDescriptor->u.BusNumber.MinBusNumber;
1021 DescriptorRaw->u.BusNumber.Length = DescriptorTranslated->u.BusNumber.Length
1022 = ResourceDescriptor->u.BusNumber.Length;
1023 DescriptorRaw->u.BusNumber.Reserved = DescriptorTranslated->u.BusNumber.Reserved
1024 = ResourceDescriptor->u.BusNumber.Reserved;
1027 /*CmResourceTypeDevicePrivate:
1028 case CmResourceTypePcCardConfig:
1029 case CmResourceTypeMfCardConfig:
1032 &DescriptorRaw->u.DevicePrivate,
1033 &ResourceDescriptor->u.DevicePrivate,
1034 sizeof(ResourceDescriptor->u.DevicePrivate));
1036 &DescriptorTranslated->u.DevicePrivate,
1037 &ResourceDescriptor->u.DevicePrivate,
1038 sizeof(ResourceDescriptor->u.DevicePrivate));
1042 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1043 NumberOfResources
--;
1049 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1050 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1052 return STATUS_SUCCESS
;
1057 * IopActionInterrogateDeviceStack
1059 * Retrieve information for all (direct) child nodes of a parent node.
1063 * Pointer to device node.
1065 * Pointer to parent node to retrieve child node information for.
1068 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1069 * when we reach a device node which is not a direct child of the device
1070 * node for which we retrieve information of child nodes for. Any errors
1071 * that occur is logged instead so that all child services have a chance
1072 * of being interrogated.
1076 IopActionInterrogateDeviceStack(
1077 PDEVICE_NODE DeviceNode
,
1080 IO_STATUS_BLOCK IoStatusBlock
;
1081 PDEVICE_NODE ParentDeviceNode
;
1082 WCHAR InstancePath
[MAX_PATH
];
1083 IO_STACK_LOCATION Stack
;
1089 HANDLE InstanceKey
= NULL
;
1090 UNICODE_STRING ValueName
;
1091 DEVICE_CAPABILITIES DeviceCapabilities
;
1093 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1094 DPRINT("PDO %x\n", DeviceNode
->PhysicalDeviceObject
);
1096 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1099 * We are called for the parent too, but we don't need to do special
1100 * handling for this node
1103 if (DeviceNode
== ParentDeviceNode
)
1105 DPRINT("Success\n");
1106 return STATUS_SUCCESS
;
1110 * Make sure this device node is a direct child of the parent device node
1111 * that is given as an argument
1114 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1116 /* Stop the traversal immediately and indicate successful operation */
1118 return STATUS_UNSUCCESSFUL
;
1122 * FIXME: For critical errors, cleanup and disable device, but always
1123 * return STATUS_SUCCESS.
1126 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1128 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1129 Status
= IopInitiatePnpIrp(
1130 DeviceNode
->PhysicalDeviceObject
,
1134 if (NT_SUCCESS(Status
))
1136 /* Copy the device id string */
1137 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1140 * FIXME: Check for valid characters, if there is invalid characters
1146 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1149 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1151 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1152 Status
= IopInitiatePnpIrp(
1153 DeviceNode
->PhysicalDeviceObject
,
1157 if (NT_SUCCESS(Status
))
1159 /* Append the instance id string */
1160 wcscat(InstancePath
, L
"\\");
1161 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1164 * FIXME: Check for valid characters, if there is invalid characters
1170 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1173 RtlZeroMemory(&DeviceCapabilities
, sizeof(DEVICE_CAPABILITIES
));
1174 DeviceCapabilities
.Size
= sizeof(DEVICE_CAPABILITIES
);
1175 DeviceCapabilities
.Version
= 1;
1176 DeviceCapabilities
.Address
= -1;
1177 DeviceCapabilities
.UINumber
= -1;
1179 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= &DeviceCapabilities
;
1180 Status
= IopInitiatePnpIrp(
1181 DeviceNode
->PhysicalDeviceObject
,
1183 IRP_MN_QUERY_CAPABILITIES
,
1185 if (NT_SUCCESS(Status
))
1190 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1193 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1194 DeviceNode
->Address
= DeviceCapabilities
.Address
;
1196 if (!DeviceCapabilities
.UniqueID
)
1198 DPRINT("Instance ID is not unique\n");
1199 /* FIXME: Add information from parent bus driver to InstancePath */
1202 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
))
1204 DPRINT("No resources\n");
1205 /* FIXME: Cleanup and disable device */
1208 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1211 * Create registry key for the instance id, if it doesn't exist yet
1213 KeyBuffer
= ExAllocatePool(
1215 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1216 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1217 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1218 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1220 ExFreePool(KeyBuffer
);
1221 if (!NT_SUCCESS(Status
))
1223 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1228 /* Set 'Capabilities' value */
1229 RtlInitUnicodeString(&ValueName
,
1231 Status
= ZwSetValueKey(InstanceKey
,
1235 (PVOID
)&DeviceNode
->CapabilityFlags
,
1238 /* Set 'UINumber' value */
1239 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1241 RtlInitUnicodeString(&ValueName
,
1243 Status
= ZwSetValueKey(InstanceKey
,
1247 &DeviceCapabilities
.UINumber
,
1252 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1254 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1255 Status
= IopInitiatePnpIrp(
1256 DeviceNode
->PhysicalDeviceObject
,
1260 if (NT_SUCCESS(Status
))
1263 * FIXME: Check for valid characters, if there is invalid characters
1267 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1268 DPRINT("Hardware IDs:\n");
1271 DPRINT(" %S\n", Ptr
);
1272 Length
= wcslen(Ptr
) + 1;
1275 TotalLength
+= Length
;
1277 DPRINT("TotalLength: %hu\n", TotalLength
);
1280 RtlInitUnicodeString(&ValueName
,
1282 Status
= ZwSetValueKey(InstanceKey
,
1286 (PVOID
)IoStatusBlock
.Information
,
1287 (TotalLength
+ 1) * sizeof(WCHAR
));
1288 if (!NT_SUCCESS(Status
))
1290 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1295 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1298 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1300 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1301 Status
= IopInitiatePnpIrp(
1302 DeviceNode
->PhysicalDeviceObject
,
1306 if (NT_SUCCESS(Status
))
1309 * FIXME: Check for valid characters, if there is invalid characters
1313 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1314 DPRINT("Compatible IDs:\n");
1317 DPRINT(" %S\n", Ptr
);
1318 Length
= wcslen(Ptr
) + 1;
1321 TotalLength
+= Length
;
1323 DPRINT("TotalLength: %hu\n", TotalLength
);
1326 RtlInitUnicodeString(&ValueName
,
1328 Status
= ZwSetValueKey(InstanceKey
,
1332 (PVOID
)IoStatusBlock
.Information
,
1333 (TotalLength
+ 1) * sizeof(WCHAR
));
1334 if (!NT_SUCCESS(Status
))
1336 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1341 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1345 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1347 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1348 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
1349 Status
= IopInitiatePnpIrp(
1350 DeviceNode
->PhysicalDeviceObject
,
1352 IRP_MN_QUERY_DEVICE_TEXT
,
1354 if (NT_SUCCESS(Status
))
1356 RtlInitUnicodeString(&ValueName
,
1358 Status
= ZwSetValueKey(InstanceKey
,
1362 (PVOID
)IoStatusBlock
.Information
,
1363 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1364 if (!NT_SUCCESS(Status
))
1366 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1371 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1374 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1376 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1377 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
1378 Status
= IopInitiatePnpIrp(
1379 DeviceNode
->PhysicalDeviceObject
,
1381 IRP_MN_QUERY_DEVICE_TEXT
,
1383 if (NT_SUCCESS(Status
))
1385 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1386 RtlInitUnicodeString(&ValueName
,
1387 L
"LocationInformation");
1388 Status
= ZwSetValueKey(InstanceKey
,
1392 (PVOID
)IoStatusBlock
.Information
,
1393 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1394 if (!NT_SUCCESS(Status
))
1396 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1401 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1404 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1406 Status
= IopInitiatePnpIrp(
1407 DeviceNode
->PhysicalDeviceObject
,
1409 IRP_MN_QUERY_BUS_INFORMATION
,
1411 if (NT_SUCCESS(Status
))
1413 PPNP_BUS_INFORMATION BusInformation
=
1414 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1416 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1417 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1418 memcpy(&DeviceNode
->BusTypeGuid
,
1419 &BusInformation
->BusTypeGuid
,
1421 ExFreePool(BusInformation
);
1425 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1427 DeviceNode
->ChildBusNumber
= -1;
1428 DeviceNode
->ChildInterfaceType
= -1;
1429 memset(&DeviceNode
->BusTypeGuid
,
1434 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1436 Status
= IopInitiatePnpIrp(
1437 DeviceNode
->PhysicalDeviceObject
,
1439 IRP_MN_QUERY_RESOURCES
,
1441 if (NT_SUCCESS(Status
))
1443 DeviceNode
->BootResources
=
1444 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1445 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1449 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1450 DeviceNode
->BootResources
= NULL
;
1453 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1455 Status
= IopInitiatePnpIrp(
1456 DeviceNode
->PhysicalDeviceObject
,
1458 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1460 if (NT_SUCCESS(Status
))
1462 DeviceNode
->ResourceRequirements
=
1463 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1467 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1468 DeviceNode
->ResourceRequirements
= NULL
;
1472 if (InstanceKey
!= NULL
)
1474 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1477 ZwClose(InstanceKey
);
1479 Status
= IopAssignDeviceResources(DeviceNode
);
1480 if (!NT_SUCCESS(Status
))
1482 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status
);
1485 DeviceNode
->Flags
|= DNF_PROCESSED
;
1487 /* Report the device to the user-mode pnp manager */
1488 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1489 &DeviceNode
->InstancePath
);
1491 return STATUS_SUCCESS
;
1495 * IopActionConfigureChildServices
1497 * Retrieve configuration for all (direct) child nodes of a parent node.
1501 * Pointer to device node.
1503 * Pointer to parent node to retrieve child node configuration for.
1506 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1507 * when we reach a device node which is not a direct child of the device
1508 * node for which we configure child services for. Any errors that occur is
1509 * logged instead so that all child services have a chance of beeing
1514 IopActionConfigureChildServices(
1515 PDEVICE_NODE DeviceNode
,
1518 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1519 PDEVICE_NODE ParentDeviceNode
;
1520 PUNICODE_STRING Service
;
1523 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1525 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1528 * We are called for the parent too, but we don't need to do special
1529 * handling for this node
1531 if (DeviceNode
== ParentDeviceNode
)
1533 DPRINT("Success\n");
1534 return STATUS_SUCCESS
;
1538 * Make sure this device node is a direct child of the parent device node
1539 * that is given as an argument
1541 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1543 /* Stop the traversal immediately and indicate successful operation */
1545 return STATUS_UNSUCCESSFUL
;
1548 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1550 WCHAR RegKeyBuffer
[MAX_PATH
];
1551 UNICODE_STRING RegKey
;
1554 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1555 RegKey
.Buffer
= RegKeyBuffer
;
1558 * Retrieve configuration from Enum key
1561 Service
= &DeviceNode
->ServiceName
;
1563 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1564 RtlInitUnicodeString(Service
, NULL
);
1566 QueryTable
[0].Name
= L
"Service";
1567 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1568 QueryTable
[0].EntryContext
= Service
;
1570 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1571 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1573 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1574 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1576 if (!NT_SUCCESS(Status
))
1578 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1579 /* FIXME: Log the error */
1580 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1581 DeviceNode
->InstancePath
.Buffer
, Status
);
1582 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1583 return STATUS_SUCCESS
;
1586 if (Service
->Buffer
== NULL
)
1588 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1589 return STATUS_SUCCESS
;
1592 DPRINT("Got Service %S\n", Service
->Buffer
);
1595 return STATUS_SUCCESS
;
1599 * IopActionInitChildServices
1601 * Initialize the service for all (direct) child nodes of a parent node
1605 * Pointer to device node.
1607 * Pointer to parent node to initialize child node services for.
1609 * Load only driver marked as boot start.
1612 * If the driver image for a service is not loaded and initialized
1613 * it is done here too. We only return a status code indicating an
1614 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1615 * not a direct child of the device node for which we initialize
1616 * child services for. Any errors that occur is logged instead so
1617 * that all child services have a chance of being initialized.
1621 IopActionInitChildServices(
1622 PDEVICE_NODE DeviceNode
,
1624 BOOLEAN BootDrivers
)
1626 PDEVICE_NODE ParentDeviceNode
;
1629 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1632 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1635 * We are called for the parent too, but we don't need to do special
1636 * handling for this node
1638 if (DeviceNode
== ParentDeviceNode
)
1640 DPRINT("Success\n");
1641 return STATUS_SUCCESS
;
1645 * Make sure this device node is a direct child of the parent device node
1646 * that is given as an argument
1649 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1652 * Stop the traversal immediately and indicate unsuccessful operation
1655 return STATUS_UNSUCCESSFUL
;
1659 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1660 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1661 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1663 PMODULE_OBJECT ModuleObject
;
1664 PDRIVER_OBJECT DriverObject
;
1666 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1667 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
1669 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
1670 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
1671 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
1674 /* get existing DriverObject pointer */
1675 Status
= IopGetDriverObject(
1677 &DeviceNode
->ServiceName
,
1680 if (NT_SUCCESS(Status
))
1682 /* Attach lower level filter drivers. */
1683 IopAttachFilterDrivers(DeviceNode
, TRUE
);
1684 /* Initialize the function driver for the device node */
1685 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1686 if (NT_SUCCESS(Status
))
1688 /* Attach upper level filter drivers. */
1689 IopAttachFilterDrivers(DeviceNode
, FALSE
);
1690 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1692 Status
= IopStartDevice(DeviceNode
);
1699 * Don't disable when trying to load only boot drivers
1703 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1704 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1706 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1707 CPRINT("Initialization of service %S failed (Status %x)\n",
1708 DeviceNode
->ServiceName
.Buffer
, Status
);
1712 DPRINT("Service %S is disabled or already initialized\n",
1713 DeviceNode
->ServiceName
.Buffer
);
1716 return STATUS_SUCCESS
;
1720 * IopActionInitAllServices
1722 * Initialize the service for all (direct) child nodes of a parent node. This
1723 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1727 IopActionInitAllServices(
1728 PDEVICE_NODE DeviceNode
,
1731 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1735 * IopActionInitBootServices
1737 * Initialize the boot start services for all (direct) child nodes of a
1738 * parent node. This function just calls IopActionInitChildServices with
1739 * BootDrivers = TRUE.
1742 IopActionInitBootServices(
1743 PDEVICE_NODE DeviceNode
,
1746 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1750 * IopInitializePnpServices
1752 * Initialize services for discovered children
1756 * Top device node to start initializing services.
1759 * When set to TRUE, only drivers marked as boot start will
1760 * be loaded. Otherwise, all drivers will be loaded.
1766 IopInitializePnpServices(
1767 IN PDEVICE_NODE DeviceNode
,
1768 IN BOOLEAN BootDrivers
)
1770 DEVICETREE_TRAVERSE_CONTEXT Context
;
1772 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1776 IopInitDeviceTreeTraverseContext(
1779 IopActionInitBootServices
,
1783 IopInitDeviceTreeTraverseContext(
1786 IopActionInitAllServices
,
1790 return IopTraverseDeviceTree(&Context
);
1795 IopInvalidateDeviceRelations(
1796 IN PDEVICE_NODE DeviceNode
,
1797 IN DEVICE_RELATION_TYPE Type
)
1799 DEVICETREE_TRAVERSE_CONTEXT Context
;
1800 PDEVICE_RELATIONS DeviceRelations
;
1801 IO_STATUS_BLOCK IoStatusBlock
;
1802 PDEVICE_NODE ChildDeviceNode
;
1803 IO_STACK_LOCATION Stack
;
1805 OBJECT_ATTRIBUTES ObjectAttributes
;
1806 UNICODE_STRING LinkName
;
1811 DPRINT("DeviceNode %x\n", DeviceNode
);
1813 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1815 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1817 Status
= IopInitiatePnpIrp(
1818 DeviceNode
->PhysicalDeviceObject
,
1820 IRP_MN_QUERY_DEVICE_RELATIONS
,
1822 if (!NT_SUCCESS(Status
))
1824 DPRINT("IopInitiatePnpIrp() failed\n");
1828 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1830 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1832 DPRINT("No PDOs\n");
1833 if (DeviceRelations
)
1835 ExFreePool(DeviceRelations
);
1837 return STATUS_SUCCESS
;
1840 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1843 * Create device nodes for all discovered devices
1846 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1848 Status
= IopCreateDeviceNode(
1850 DeviceRelations
->Objects
[i
],
1852 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1853 if (!NT_SUCCESS(Status
))
1855 DPRINT("No resources\n");
1856 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1857 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1858 ExFreePool(DeviceRelations
);
1859 return STATUS_INSUFFICIENT_RESOURCES
;
1862 ExFreePool(DeviceRelations
);
1865 * Retrieve information about all discovered children from the bus driver
1868 IopInitDeviceTreeTraverseContext(
1871 IopActionInterrogateDeviceStack
,
1874 Status
= IopTraverseDeviceTree(&Context
);
1875 if (!NT_SUCCESS(Status
))
1877 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1882 * Retrieve configuration from the registry for discovered children
1885 IopInitDeviceTreeTraverseContext(
1888 IopActionConfigureChildServices
,
1891 Status
= IopTraverseDeviceTree(&Context
);
1892 if (!NT_SUCCESS(Status
))
1894 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1899 * Get the state of the system boot. If the \\SystemRoot link isn't
1900 * created yet, we will assume that it's possible to load only boot
1904 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
1906 InitializeObjectAttributes(
1913 Status
= ZwOpenFile(
1920 if(NT_SUCCESS(Status
))
1922 BootDrivers
= FALSE
;
1929 * Initialize services for discovered children. Only boot drivers will
1930 * be loaded from boot driver!
1933 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
1934 if (!NT_SUCCESS(Status
))
1936 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
1940 return STATUS_SUCCESS
;
1950 DPRINT("PnpInit()\n");
1952 KeInitializeSpinLock(&IopDeviceTreeLock
);
1954 /* Initialize PnP-Event notification support */
1955 Status
= IopInitPlugPlayEvents();
1956 if (!NT_SUCCESS(Status
))
1958 CPRINT("IopInitPlugPlayEvents() failed\n");
1959 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1963 * Create root device node
1966 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
1967 if (!NT_SUCCESS(Status
))
1969 CPRINT("IoCreateDriverObject() failed\n");
1970 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1973 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
1975 if (!NT_SUCCESS(Status
))
1977 CPRINT("IoCreateDevice() failed\n");
1978 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1981 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
1982 if (!NT_SUCCESS(Status
))
1984 CPRINT("Insufficient resources\n");
1985 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1988 if (!IopCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
1992 CPRINT("Failed to create the instance path!\n");
1993 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_UNSUCCESSFUL
, 0, 0, 0);
1996 /* Report the device to the user-mode pnp manager */
1997 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1998 &IopRootDeviceNode
->InstancePath
);
2000 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2001 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2002 IopRootDriverObject
->DriverExtension
->AddDevice(
2003 IopRootDriverObject
,
2004 IopRootDeviceNode
->PhysicalDeviceObject
);