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 ******************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS *******************************************************************/
20 PDEVICE_NODE IopRootDeviceNode
;
21 KSPIN_LOCK IopDeviceTreeLock
;
23 /* DATA **********************************************************************/
25 PDRIVER_OBJECT IopRootDriverObject
;
27 /* FUNCTIONS *****************************************************************/
34 IoInvalidateDeviceRelations(
35 IN PDEVICE_OBJECT DeviceObject
,
36 IN DEVICE_RELATION_TYPE Type
)
43 PDEVICE_OBJECT DeviceObject
)
45 return DeviceObject
->DeviceObjectExtension
->DeviceNode
;
54 IN PDEVICE_OBJECT DeviceObject
,
55 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
56 IN ULONG BufferLength
,
57 OUT PVOID PropertyBuffer
,
58 OUT PULONG ResultLength
)
60 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
65 DPRINT("IoGetDeviceProperty(%x %d)\n", DeviceObject
, DeviceProperty
);
67 if (DeviceNode
== NULL
)
68 return STATUS_INVALID_DEVICE_REQUEST
;
70 switch (DeviceProperty
)
72 case DevicePropertyBusNumber
:
73 Length
= sizeof(ULONG
);
74 Data
= &DeviceNode
->ChildBusNumber
;
77 /* Complete, untested */
78 case DevicePropertyBusTypeGuid
:
79 *ResultLength
= 39 * sizeof(WCHAR
);
80 if (BufferLength
< (39 * sizeof(WCHAR
)))
81 return STATUS_BUFFER_TOO_SMALL
;
82 swprintf((PWSTR
)PropertyBuffer
,
83 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
84 DeviceNode
->BusTypeGuid
.Data1
,
85 DeviceNode
->BusTypeGuid
.Data2
,
86 DeviceNode
->BusTypeGuid
.Data3
,
87 DeviceNode
->BusTypeGuid
.Data4
[0],
88 DeviceNode
->BusTypeGuid
.Data4
[1],
89 DeviceNode
->BusTypeGuid
.Data4
[2],
90 DeviceNode
->BusTypeGuid
.Data4
[3],
91 DeviceNode
->BusTypeGuid
.Data4
[4],
92 DeviceNode
->BusTypeGuid
.Data4
[5],
93 DeviceNode
->BusTypeGuid
.Data4
[6],
94 DeviceNode
->BusTypeGuid
.Data4
[7]);
95 return STATUS_SUCCESS
;
97 case DevicePropertyLegacyBusType
:
98 Length
= sizeof(INTERFACE_TYPE
);
99 Data
= &DeviceNode
->ChildInterfaceType
;
102 case DevicePropertyAddress
:
103 Length
= sizeof(ULONG
);
104 Data
= &DeviceNode
->Address
;
107 // case DevicePropertyUINumber:
108 // if (DeviceNode->CapabilityFlags == NULL)
109 // return STATUS_INVALID_DEVICE_REQUEST;
110 // Length = sizeof(ULONG);
111 // Data = &DeviceNode->CapabilityFlags->UINumber;
114 case DevicePropertyClassName
:
115 case DevicePropertyClassGuid
:
116 case DevicePropertyDriverKeyName
:
117 case DevicePropertyManufacturer
:
118 case DevicePropertyFriendlyName
:
119 case DevicePropertyHardwareID
:
120 case DevicePropertyCompatibleIDs
:
121 case DevicePropertyDeviceDescription
:
122 case DevicePropertyLocationInformation
:
123 case DevicePropertyUINumber
:
125 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
126 UNICODE_STRING KeyName
, ValueName
;
127 OBJECT_ATTRIBUTES ObjectAttributes
;
128 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
129 ULONG ValueInformationLength
;
133 switch (DeviceProperty
)
135 case DevicePropertyClassName
:
136 RegistryPropertyName
= L
"Class"; break;
137 case DevicePropertyClassGuid
:
138 RegistryPropertyName
= L
"ClassGuid"; break;
139 case DevicePropertyDriverKeyName
:
140 RegistryPropertyName
= L
"Driver"; break;
141 case DevicePropertyManufacturer
:
142 RegistryPropertyName
= L
"Mfg"; break;
143 case DevicePropertyFriendlyName
:
144 RegistryPropertyName
= L
"FriendlyName"; break;
145 case DevicePropertyHardwareID
:
146 RegistryPropertyName
= L
"HardwareID"; break;
147 case DevicePropertyCompatibleIDs
:
148 RegistryPropertyName
= L
"CompatibleIDs"; break;
149 case DevicePropertyDeviceDescription
:
150 RegistryPropertyName
= L
"DeviceDesc"; break;
151 case DevicePropertyLocationInformation
:
152 RegistryPropertyName
= L
"LocationInformation"; break;
153 case DevicePropertyUINumber
:
154 RegistryPropertyName
= L
"UINumber"; break;
156 RegistryPropertyName
= NULL
; break;
159 KeyNameBuffer
= ExAllocatePool(PagedPool
,
160 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
162 DPRINT("KeyNameBuffer: %x, value %S\n",
163 KeyNameBuffer
, RegistryPropertyName
);
165 if (KeyNameBuffer
== NULL
)
166 return STATUS_INSUFFICIENT_RESOURCES
;
168 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
169 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
170 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
171 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
172 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
174 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
175 ExFreePool(KeyNameBuffer
);
176 if (!NT_SUCCESS(Status
))
179 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
180 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
181 Data
[0]) + BufferLength
;
182 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
183 if (ValueInformation
== NULL
)
186 return STATUS_INSUFFICIENT_RESOURCES
;
189 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
190 KeyValuePartialInformation
, ValueInformation
,
191 ValueInformationLength
,
192 &ValueInformationLength
);
193 *ResultLength
= ValueInformation
->DataLength
;
196 if (ValueInformation
->DataLength
> BufferLength
)
197 Status
= STATUS_BUFFER_TOO_SMALL
;
199 if (!NT_SUCCESS(Status
))
201 ExFreePool(ValueInformation
);
205 /* FIXME: Verify the value (NULL-terminated, correct format). */
207 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
208 ValueInformation
->DataLength
);
209 ExFreePool(ValueInformation
);
211 return STATUS_SUCCESS
;
214 case DevicePropertyBootConfiguration
:
216 if (DeviceNode
->BootResources
->Count
!= 0)
218 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
220 Data
= &DeviceNode
->BootResources
;
223 /* FIXME: use a translated boot configuration instead */
224 case DevicePropertyBootConfigurationTranslated
:
226 if (DeviceNode
->BootResources
->Count
!= 0)
228 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
230 Data
= &DeviceNode
->BootResources
;
233 case DevicePropertyEnumeratorName
:
234 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
237 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
245 case DevicePropertyPhysicalDeviceObjectName
:
246 return STATUS_NOT_IMPLEMENTED
;
249 return STATUS_INVALID_PARAMETER_2
;
252 *ResultLength
= Length
;
253 if (BufferLength
< Length
)
254 return STATUS_BUFFER_TOO_SMALL
;
255 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
257 /* Terminate the string */
258 if (DeviceProperty
== DevicePropertyEnumeratorName
)
260 Ptr
= (PWSTR
)PropertyBuffer
;
261 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
264 return STATUS_SUCCESS
;
272 IoInvalidateDeviceState(
273 IN PDEVICE_OBJECT PhysicalDeviceObject
)
278 * @name IoOpenDeviceRegistryKey
280 * Open a registry key unique for a specified driver or device instance.
282 * @param DeviceObject Device to get the registry key for.
283 * @param DevInstKeyType Type of the key to return.
284 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
285 * @param DevInstRegKey Handle to the opened registry key on
294 IoOpenDeviceRegistryKey(
295 IN PDEVICE_OBJECT DeviceObject
,
296 IN ULONG DevInstKeyType
,
297 IN ACCESS_MASK DesiredAccess
,
298 OUT PHANDLE DevInstRegKey
)
300 static WCHAR RootKeyName
[] =
301 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
302 static WCHAR ProfileKeyName
[] =
303 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
304 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
305 static WCHAR EnumKeyName
[] = L
"Enum\\";
306 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters\\";
308 LPWSTR KeyNameBuffer
;
309 UNICODE_STRING KeyName
;
310 ULONG DriverKeyLength
;
311 OBJECT_ATTRIBUTES ObjectAttributes
;
312 PDEVICE_NODE DeviceNode
= NULL
;
315 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
316 return STATUS_INVALID_PARAMETER
;
319 * Calculate the length of the base key name. This is the full
320 * name for driver key or the name excluding "Device Parameters"
321 * subkey for device key.
324 KeyNameLength
= sizeof(RootKeyName
);
325 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
326 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
327 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
329 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
330 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
331 0, NULL
, &DriverKeyLength
);
332 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
334 KeyNameLength
+= DriverKeyLength
;
338 DeviceNode
= IopGetDeviceNode(DeviceObject
);
339 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
340 DeviceNode
->InstancePath
.Length
;
344 * Now allocate the buffer for the key name...
347 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
348 if (KeyNameBuffer
== NULL
)
349 return STATUS_INSUFFICIENT_RESOURCES
;
352 KeyName
.MaximumLength
= KeyNameLength
;
353 KeyName
.Buffer
= KeyNameBuffer
;
356 * ...and build the key name.
359 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
360 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
362 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
363 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
365 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
367 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
368 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
369 DriverKeyLength
, KeyNameBuffer
+
370 (KeyName
.Length
/ sizeof(WCHAR
)),
372 if (!NT_SUCCESS(Status
))
374 ExFreePool(KeyNameBuffer
);
377 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
381 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
382 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
383 if (DeviceNode
->InstancePath
.Length
== 0)
385 ExFreePool(KeyNameBuffer
);
394 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
395 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
396 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
397 ExFreePool(KeyNameBuffer
);
400 * For driver key we're done now. Also if the base key doesn't
401 * exist we can bail out with error...
404 if ((DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
) || !NT_SUCCESS(Status
))
408 * Let's go further. For device key we must open "Device Parameters"
409 * subkey and create it if it doesn't exist yet.
412 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
413 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
414 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
415 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
416 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
417 ZwClose(ObjectAttributes
.RootDirectory
);
427 IoRequestDeviceEject(
428 IN PDEVICE_OBJECT PhysicalDeviceObject
436 IopCreateUnicodeString(
437 PUNICODE_STRING Destination
,
445 RtlInitUnicodeString(Destination
, NULL
);
449 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
451 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
453 if (Destination
->Buffer
== NULL
)
458 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
460 Destination
->MaximumLength
= Length
;
462 Destination
->Length
= Length
- sizeof(WCHAR
);
468 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
472 if (PopSystemPowerDeviceNode
)
474 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
475 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
476 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
478 return STATUS_SUCCESS
;
481 return STATUS_UNSUCCESSFUL
;
484 /**********************************************************************
486 * Creates a device node
489 * ParentNode = Pointer to parent device node
490 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
491 * to have the root device node create one
492 * (eg. for legacy drivers)
493 * DeviceNode = Pointer to storage for created device node
499 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
500 PDEVICE_OBJECT PhysicalDeviceObject
,
501 PDEVICE_NODE
*DeviceNode
)
507 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
508 ParentNode
, PhysicalDeviceObject
);
510 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
513 return STATUS_INSUFFICIENT_RESOURCES
;
516 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
518 if (!PhysicalDeviceObject
)
520 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
521 if (!NT_SUCCESS(Status
))
527 /* This is for drivers passed on the command line to ntoskrnl.exe */
528 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
529 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
532 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
534 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
538 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
539 Node
->Parent
= ParentNode
;
540 Node
->NextSibling
= ParentNode
->Child
;
541 if (ParentNode
->Child
!= NULL
)
543 ParentNode
->Child
->PrevSibling
= Node
;
545 ParentNode
->Child
= Node
;
546 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
551 return STATUS_SUCCESS
;
555 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
559 /* All children must be deleted before a parent is deleted */
560 ASSERT(!DeviceNode
->Child
);
562 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
564 ASSERT(DeviceNode
->PhysicalDeviceObject
);
566 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
568 /* Unlink from parent if it exists */
570 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
572 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
575 /* Unlink from sibling list */
577 if (DeviceNode
->PrevSibling
)
579 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
582 if (DeviceNode
->NextSibling
)
584 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
587 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
589 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
591 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
593 if (DeviceNode
->ResourceList
)
595 ExFreePool(DeviceNode
->ResourceList
);
598 if (DeviceNode
->ResourceListTranslated
)
600 ExFreePool(DeviceNode
->ResourceListTranslated
);
603 if (DeviceNode
->ResourceRequirements
)
605 ExFreePool(DeviceNode
->ResourceRequirements
);
608 if (DeviceNode
->BootResources
)
610 ExFreePool(DeviceNode
->BootResources
);
613 ExFreePool(DeviceNode
);
615 return STATUS_SUCCESS
;
620 PDEVICE_OBJECT DeviceObject
,
621 PIO_STATUS_BLOCK IoStatusBlock
,
623 PIO_STACK_LOCATION Stack OPTIONAL
)
625 PDEVICE_OBJECT TopDeviceObject
;
626 PIO_STACK_LOCATION IrpSp
;
631 /* Always call the top of the device stack */
632 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
639 Irp
= IoBuildSynchronousFsdRequest(
648 /* PNP IRPs are always initialized with a status code of
649 STATUS_NOT_IMPLEMENTED */
650 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
651 Irp
->IoStatus
.Information
= 0;
653 IrpSp
= IoGetNextIrpStackLocation(Irp
);
654 IrpSp
->MinorFunction
= MinorFunction
;
661 sizeof(Stack
->Parameters
));
664 Status
= IoCallDriver(TopDeviceObject
, Irp
);
665 if (Status
== STATUS_PENDING
)
667 KeWaitForSingleObject(
673 Status
= IoStatusBlock
->Status
;
676 ObDereferenceObject(TopDeviceObject
);
683 IopTraverseDeviceTreeNode(
684 PDEVICETREE_TRAVERSE_CONTEXT Context
)
686 PDEVICE_NODE ParentDeviceNode
;
687 PDEVICE_NODE ChildDeviceNode
;
690 /* Copy context data so we don't overwrite it in subsequent calls to this function */
691 ParentDeviceNode
= Context
->DeviceNode
;
693 /* Call the action routine */
694 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
695 if (!NT_SUCCESS(Status
))
700 /* Traversal of all children nodes */
701 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
702 ChildDeviceNode
!= NULL
;
703 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
705 /* Pass the current device node to the action routine */
706 Context
->DeviceNode
= ChildDeviceNode
;
708 Status
= IopTraverseDeviceTreeNode(Context
);
709 if (!NT_SUCCESS(Status
))
720 IopTraverseDeviceTree(
721 PDEVICETREE_TRAVERSE_CONTEXT Context
)
725 DPRINT("Context %x\n", Context
);
727 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
728 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
730 /* Start from the specified device node */
731 Context
->DeviceNode
= Context
->FirstDeviceNode
;
733 /* Recursively traverse the device tree */
734 Status
= IopTraverseDeviceTreeNode(Context
);
735 if (Status
== STATUS_UNSUCCESSFUL
)
737 /* The action routine just wanted to terminate the traversal with status
738 code STATUS_SUCCESS */
739 Status
= STATUS_SUCCESS
;
747 IopCreateDeviceKeyPath(PWSTR Path
,
750 OBJECT_ATTRIBUTES ObjectAttributes
;
751 WCHAR KeyBuffer
[MAX_PATH
];
752 UNICODE_STRING KeyName
;
760 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
762 return STATUS_INVALID_PARAMETER
;
765 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
766 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
768 /* Skip \\Registry\\ */
769 Current
= KeyName
.Buffer
;
770 Current
= wcschr (Current
, '\\') + 1;
771 Current
= wcschr (Current
, '\\') + 1;
775 Next
= wcschr (Current
, '\\');
785 InitializeObjectAttributes (&ObjectAttributes
,
787 OBJ_CASE_INSENSITIVE
,
791 DPRINT("Create '%S'\n", KeyName
.Buffer
);
793 Status
= NtCreateKey (&KeyHandle
,
800 if (!NT_SUCCESS (Status
))
802 DPRINT ("NtCreateKey() failed with status %x\n", Status
);
809 return STATUS_SUCCESS
;
820 return STATUS_UNSUCCESSFUL
;
825 IopSetDeviceInstanceData(HANDLE InstanceKey
,
826 PDEVICE_NODE DeviceNode
)
828 OBJECT_ATTRIBUTES ObjectAttributes
;
829 UNICODE_STRING KeyName
;
835 DPRINT("IopSetDeviceInstanceData() called\n");
837 /* Create the 'LogConf' key */
838 RtlInitUnicodeString(&KeyName
,
840 InitializeObjectAttributes(&ObjectAttributes
,
842 OBJ_CASE_INSENSITIVE
,
845 Status
= NtCreateKey(&LogConfKey
,
852 if (NT_SUCCESS(Status
))
854 /* Set 'BootConfig' value */
855 if (DeviceNode
->BootResources
!= NULL
)
857 ResCount
= DeviceNode
->BootResources
->Count
;
860 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
862 RtlInitUnicodeString(&KeyName
,
864 Status
= NtSetValueKey(LogConfKey
,
868 &DeviceNode
->BootResources
,
873 /* Set 'BasicConfigVector' value */
874 if (DeviceNode
->ResourceRequirements
!= NULL
&&
875 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
877 RtlInitUnicodeString(&KeyName
,
878 L
"BasicConfigVector");
879 Status
= NtSetValueKey(LogConfKey
,
882 REG_RESOURCE_REQUIREMENTS_LIST
,
883 &DeviceNode
->ResourceRequirements
,
884 DeviceNode
->ResourceRequirements
->ListSize
);
890 DPRINT("IopSetDeviceInstanceData() done\n");
892 return STATUS_SUCCESS
;
897 * IopActionInterrogateDeviceStack
899 * Retrieve information for all (direct) child nodes of a parent node.
903 * Pointer to device node.
905 * Pointer to parent node to retrieve child node information for.
908 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
909 * when we reach a device node which is not a direct child of the device
910 * node for which we retrieve information of child nodes for. Any errors
911 * that occur is logged instead so that all child services have a chance
912 * of being interrogated.
916 IopActionInterrogateDeviceStack(
917 PDEVICE_NODE DeviceNode
,
920 IO_STATUS_BLOCK IoStatusBlock
;
921 PDEVICE_NODE ParentDeviceNode
;
922 WCHAR InstancePath
[MAX_PATH
];
923 IO_STACK_LOCATION Stack
;
929 HANDLE InstanceKey
= NULL
;
930 UNICODE_STRING ValueName
;
931 DEVICE_CAPABILITIES DeviceCapabilities
;
933 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
934 DPRINT("PDO %x\n", DeviceNode
->PhysicalDeviceObject
);
936 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
939 * We are called for the parent too, but we don't need to do special
940 * handling for this node
943 if (DeviceNode
== ParentDeviceNode
)
946 return STATUS_SUCCESS
;
950 * Make sure this device node is a direct child of the parent device node
951 * that is given as an argument
954 if (DeviceNode
->Parent
!= ParentDeviceNode
)
956 /* Stop the traversal immediately and indicate successful operation */
958 return STATUS_UNSUCCESSFUL
;
962 * FIXME: For critical errors, cleanup and disable device, but always
963 * return STATUS_SUCCESS.
966 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
968 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
969 Status
= IopInitiatePnpIrp(
970 DeviceNode
->PhysicalDeviceObject
,
974 if (NT_SUCCESS(Status
))
976 /* Copy the device id string */
977 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
980 * FIXME: Check for valid characters, if there is invalid characters
986 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
989 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
991 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
992 Status
= IopInitiatePnpIrp(
993 DeviceNode
->PhysicalDeviceObject
,
997 if (NT_SUCCESS(Status
))
999 /* Append the instance id string */
1000 wcscat(InstancePath
, L
"\\");
1001 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1004 * FIXME: Check for valid characters, if there is invalid characters
1010 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1013 RtlZeroMemory(&DeviceCapabilities
, sizeof(DEVICE_CAPABILITIES
));
1014 DeviceCapabilities
.Size
= sizeof(DEVICE_CAPABILITIES
);
1015 DeviceCapabilities
.Version
= 1;
1016 DeviceCapabilities
.Address
= -1;
1017 DeviceCapabilities
.UINumber
= -1;
1019 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= &DeviceCapabilities
;
1020 Status
= IopInitiatePnpIrp(
1021 DeviceNode
->PhysicalDeviceObject
,
1023 IRP_MN_QUERY_CAPABILITIES
,
1025 if (NT_SUCCESS(Status
))
1030 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1033 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1034 DeviceNode
->Address
= DeviceCapabilities
.Address
;
1036 if (!DeviceCapabilities
.UniqueID
)
1038 DPRINT("Instance ID is not unique\n");
1039 /* FIXME: Add information from parent bus driver to InstancePath */
1042 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
))
1044 DPRINT("No resources\n");
1045 /* FIXME: Cleanup and disable device */
1048 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1051 * Create registry key for the instance id, if it doesn't exist yet
1053 KeyBuffer
= ExAllocatePool(
1055 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1056 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1057 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1058 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1060 ExFreePool(KeyBuffer
);
1061 if (!NT_SUCCESS(Status
))
1063 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1068 /* Set 'Capabilities' value */
1069 RtlInitUnicodeString(&ValueName
,
1071 Status
= NtSetValueKey(InstanceKey
,
1075 (PVOID
)&DeviceNode
->CapabilityFlags
,
1078 /* Set 'UINumber' value */
1079 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1081 RtlInitUnicodeString(&ValueName
,
1083 Status
= NtSetValueKey(InstanceKey
,
1087 &DeviceCapabilities
.UINumber
,
1092 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1094 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1095 Status
= IopInitiatePnpIrp(
1096 DeviceNode
->PhysicalDeviceObject
,
1100 if (NT_SUCCESS(Status
))
1103 * FIXME: Check for valid characters, if there is invalid characters
1107 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1108 DPRINT("Hardware IDs:\n");
1111 DPRINT(" %S\n", Ptr
);
1112 Length
= wcslen(Ptr
) + 1;
1115 TotalLength
+= Length
;
1117 DPRINT("TotalLength: %hu\n", TotalLength
);
1120 RtlInitUnicodeString(&ValueName
,
1122 Status
= NtSetValueKey(InstanceKey
,
1126 (PVOID
)IoStatusBlock
.Information
,
1127 (TotalLength
+ 1) * sizeof(WCHAR
));
1128 if (!NT_SUCCESS(Status
))
1130 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1135 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1138 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1140 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1141 Status
= IopInitiatePnpIrp(
1142 DeviceNode
->PhysicalDeviceObject
,
1146 if (NT_SUCCESS(Status
))
1149 * FIXME: Check for valid characters, if there is invalid characters
1153 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1154 DPRINT("Compatible IDs:\n");
1157 DPRINT(" %S\n", Ptr
);
1158 Length
= wcslen(Ptr
) + 1;
1161 TotalLength
+= Length
;
1163 DPRINT("TotalLength: %hu\n", TotalLength
);
1166 RtlInitUnicodeString(&ValueName
,
1168 Status
= NtSetValueKey(InstanceKey
,
1172 (PVOID
)IoStatusBlock
.Information
,
1173 (TotalLength
+ 1) * sizeof(WCHAR
));
1174 if (!NT_SUCCESS(Status
))
1176 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1181 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1185 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1187 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1188 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
1189 Status
= IopInitiatePnpIrp(
1190 DeviceNode
->PhysicalDeviceObject
,
1192 IRP_MN_QUERY_DEVICE_TEXT
,
1194 if (NT_SUCCESS(Status
))
1196 RtlInitUnicodeString(&ValueName
,
1198 Status
= NtSetValueKey(InstanceKey
,
1202 (PVOID
)IoStatusBlock
.Information
,
1203 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1204 if (!NT_SUCCESS(Status
))
1206 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1211 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1214 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1216 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1217 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
1218 Status
= IopInitiatePnpIrp(
1219 DeviceNode
->PhysicalDeviceObject
,
1221 IRP_MN_QUERY_DEVICE_TEXT
,
1223 if (NT_SUCCESS(Status
))
1225 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1226 RtlInitUnicodeString(&ValueName
,
1227 L
"LocationInformation");
1228 Status
= NtSetValueKey(InstanceKey
,
1232 (PVOID
)IoStatusBlock
.Information
,
1233 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1234 if (!NT_SUCCESS(Status
))
1236 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1241 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1244 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1246 Status
= IopInitiatePnpIrp(
1247 DeviceNode
->PhysicalDeviceObject
,
1249 IRP_MN_QUERY_BUS_INFORMATION
,
1251 if (NT_SUCCESS(Status
))
1253 PPNP_BUS_INFORMATION BusInformation
=
1254 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1256 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1257 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1258 memcpy(&DeviceNode
->BusTypeGuid
,
1259 &BusInformation
->BusTypeGuid
,
1261 ExFreePool(BusInformation
);
1265 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1267 DeviceNode
->ChildBusNumber
= -1;
1268 DeviceNode
->ChildInterfaceType
= -1;
1269 memset(&DeviceNode
->BusTypeGuid
,
1274 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1276 Status
= IopInitiatePnpIrp(
1277 DeviceNode
->PhysicalDeviceObject
,
1279 IRP_MN_QUERY_RESOURCES
,
1281 if (NT_SUCCESS(Status
))
1283 DeviceNode
->BootResources
=
1284 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1285 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1289 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1290 DeviceNode
->BootResources
= NULL
;
1293 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1295 Status
= IopInitiatePnpIrp(
1296 DeviceNode
->PhysicalDeviceObject
,
1298 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1300 if (NT_SUCCESS(Status
))
1302 DeviceNode
->ResourceRequirements
=
1303 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1307 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1308 DeviceNode
->ResourceRequirements
= NULL
;
1312 if (InstanceKey
!= NULL
)
1314 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1317 NtClose(InstanceKey
);
1319 DeviceNode
->Flags
|= DNF_PROCESSED
;
1321 return STATUS_SUCCESS
;
1325 * IopActionConfigureChildServices
1327 * Retrieve configuration for all (direct) child nodes of a parent node.
1331 * Pointer to device node.
1333 * Pointer to parent node to retrieve child node configuration for.
1336 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1337 * when we reach a device node which is not a direct child of the device
1338 * node for which we configure child services for. Any errors that occur is
1339 * logged instead so that all child services have a chance of beeing
1344 IopActionConfigureChildServices(
1345 PDEVICE_NODE DeviceNode
,
1348 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1349 PDEVICE_NODE ParentDeviceNode
;
1350 PUNICODE_STRING Service
;
1353 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1355 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1358 * We are called for the parent too, but we don't need to do special
1359 * handling for this node
1361 if (DeviceNode
== ParentDeviceNode
)
1363 DPRINT("Success\n");
1364 return STATUS_SUCCESS
;
1368 * Make sure this device node is a direct child of the parent device node
1369 * that is given as an argument
1371 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1373 /* Stop the traversal immediately and indicate successful operation */
1375 return STATUS_UNSUCCESSFUL
;
1378 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1380 WCHAR RegKeyBuffer
[MAX_PATH
];
1381 UNICODE_STRING RegKey
;
1384 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1385 RegKey
.Buffer
= RegKeyBuffer
;
1388 * Retrieve configuration from Enum key
1391 Service
= &DeviceNode
->ServiceName
;
1393 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1394 RtlInitUnicodeString(Service
, NULL
);
1396 QueryTable
[0].Name
= L
"Service";
1397 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1398 QueryTable
[0].EntryContext
= Service
;
1400 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1401 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1403 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1404 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1406 if (!NT_SUCCESS(Status
))
1408 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1409 /* FIXME: Log the error */
1410 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1411 DeviceNode
->InstancePath
.Buffer
, Status
);
1412 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1413 return STATUS_SUCCESS
;
1416 if (Service
->Buffer
== NULL
)
1418 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1419 return STATUS_SUCCESS
;
1422 DPRINT("Got Service %S\n", Service
->Buffer
);
1425 return STATUS_SUCCESS
;
1429 * IopActionInitChildServices
1431 * Initialize the service for all (direct) child nodes of a parent node
1435 * Pointer to device node.
1437 * Pointer to parent node to initialize child node services for.
1439 * Load only driver marked as boot start.
1442 * If the driver image for a service is not loaded and initialized
1443 * it is done here too. We only return a status code indicating an
1444 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1445 * not a direct child of the device node for which we initialize
1446 * child services for. Any errors that occur is logged instead so
1447 * that all child services have a chance of being initialized.
1451 IopActionInitChildServices(
1452 PDEVICE_NODE DeviceNode
,
1454 BOOLEAN BootDrivers
)
1456 PDEVICE_NODE ParentDeviceNode
;
1459 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1462 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1465 * We are called for the parent too, but we don't need to do special
1466 * handling for this node
1468 if (DeviceNode
== ParentDeviceNode
)
1470 DPRINT("Success\n");
1471 return STATUS_SUCCESS
;
1475 * Make sure this device node is a direct child of the parent device node
1476 * that is given as an argument
1479 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1482 * Stop the traversal immediately and indicate unsuccessful operation
1485 return STATUS_UNSUCCESSFUL
;
1489 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1490 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1491 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1493 PMODULE_OBJECT ModuleObject
;
1494 PDRIVER_OBJECT DriverObject
;
1496 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1497 if (NT_SUCCESS(Status
))
1499 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
1500 if (NT_SUCCESS(Status
))
1502 /* Attach lower level filter drivers. */
1503 IopAttachFilterDrivers(DeviceNode
, TRUE
);
1504 /* Initialize the function driver for the device node */
1505 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1506 if (NT_SUCCESS(Status
))
1508 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1509 /* Attach upper level filter drivers. */
1510 IopAttachFilterDrivers(DeviceNode
, FALSE
);
1517 * Don't disable when trying to load only boot drivers
1521 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1522 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1524 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1525 CPRINT("Initialization of service %S failed (Status %x)\n",
1526 DeviceNode
->ServiceName
.Buffer
, Status
);
1530 DPRINT("Service %S is disabled or already initialized\n",
1531 DeviceNode
->ServiceName
.Buffer
);
1534 return STATUS_SUCCESS
;
1538 * IopActionInitAllServices
1540 * Initialize the service for all (direct) child nodes of a parent node. This
1541 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1545 IopActionInitAllServices(
1546 PDEVICE_NODE DeviceNode
,
1549 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1553 * IopActionInitBootServices
1555 * Initialize the boot start services for all (direct) child nodes of a
1556 * parent node. This function just calls IopActionInitChildServices with
1557 * BootDrivers = TRUE.
1561 IopActionInitBootServices(
1562 PDEVICE_NODE DeviceNode
,
1565 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1569 * IopInitializePnpServices
1571 * Initialize services for discovered children
1575 * Top device node to start initializing services.
1578 * When set to TRUE, only drivers marked as boot start will
1579 * be loaded. Otherwise, all drivers will be loaded.
1586 IopInitializePnpServices(
1587 IN PDEVICE_NODE DeviceNode
,
1588 IN BOOLEAN BootDrivers
)
1590 DEVICETREE_TRAVERSE_CONTEXT Context
;
1592 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1596 IopInitDeviceTreeTraverseContext(
1599 IopActionInitBootServices
,
1603 IopInitDeviceTreeTraverseContext(
1606 IopActionInitAllServices
,
1610 return IopTraverseDeviceTree(&Context
);
1615 IopInvalidateDeviceRelations(
1616 IN PDEVICE_NODE DeviceNode
,
1617 IN DEVICE_RELATION_TYPE Type
)
1619 DEVICETREE_TRAVERSE_CONTEXT Context
;
1620 PDEVICE_RELATIONS DeviceRelations
;
1621 IO_STATUS_BLOCK IoStatusBlock
;
1622 PDEVICE_NODE ChildDeviceNode
;
1623 IO_STACK_LOCATION Stack
;
1625 OBJECT_ATTRIBUTES ObjectAttributes
;
1626 UNICODE_STRING LinkName
;
1631 DPRINT("DeviceNode %x\n", DeviceNode
);
1633 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1635 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1637 Status
= IopInitiatePnpIrp(
1638 DeviceNode
->PhysicalDeviceObject
,
1640 IRP_MN_QUERY_DEVICE_RELATIONS
,
1642 if (!NT_SUCCESS(Status
))
1644 DPRINT("IopInitiatePnpIrp() failed\n");
1648 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1650 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1652 DPRINT("No PDOs\n");
1653 if (DeviceRelations
)
1655 ExFreePool(DeviceRelations
);
1657 return STATUS_SUCCESS
;
1660 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1663 * Create device nodes for all discovered devices
1666 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1668 Status
= IopCreateDeviceNode(
1670 DeviceRelations
->Objects
[i
],
1672 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1673 if (!NT_SUCCESS(Status
))
1675 DPRINT("No resources\n");
1676 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1677 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1678 ExFreePool(DeviceRelations
);
1679 return STATUS_INSUFFICIENT_RESOURCES
;
1682 ExFreePool(DeviceRelations
);
1685 * Retrieve information about all discovered children from the bus driver
1688 IopInitDeviceTreeTraverseContext(
1691 IopActionInterrogateDeviceStack
,
1694 Status
= IopTraverseDeviceTree(&Context
);
1695 if (!NT_SUCCESS(Status
))
1697 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1702 * Retrieve configuration from the registry for discovered children
1705 IopInitDeviceTreeTraverseContext(
1708 IopActionConfigureChildServices
,
1711 Status
= IopTraverseDeviceTree(&Context
);
1712 if (!NT_SUCCESS(Status
))
1714 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1719 * Get the state of the system boot. If the \\SystemRoot link isn't
1720 * created yet, we will assume that it's possible to load only boot
1724 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
1726 InitializeObjectAttributes(
1733 Status
= NtOpenFile(
1741 BootDrivers
= NT_SUCCESS(Status
) ? FALSE
: TRUE
;
1746 * Initialize services for discovered children. Only boot drivers will
1747 * be loaded from boot driver!
1750 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
1751 if (!NT_SUCCESS(Status
))
1753 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
1757 return STATUS_SUCCESS
;
1767 DPRINT("PnpInit()\n");
1769 KeInitializeSpinLock(&IopDeviceTreeLock
);
1772 * Create root device node
1775 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, FALSE
, NULL
, 0);
1776 if (!NT_SUCCESS(Status
))
1778 CPRINT("IoCreateDriverObject() failed\n");
1779 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1782 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
1784 if (!NT_SUCCESS(Status
))
1786 CPRINT("IoCreateDevice() failed\n");
1787 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1790 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
1791 if (!NT_SUCCESS(Status
))
1793 CPRINT("Insufficient resources\n");
1794 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1797 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1798 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1799 IopRootDriverObject
->DriverExtension
->AddDevice(
1800 IopRootDriverObject
,
1801 IopRootDeviceNode
->PhysicalDeviceObject
);