1 /* $Id: pnpmgr.c,v 1.45 2004/10/23 14:48:16 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnpmgr/pnpmgr.c
6 * PURPOSE: Initializes the PnP manager
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 16/04/2001 CSH Created
12 /* INCLUDES ******************************************************************/
15 #include <ole32/guiddef.h>
17 DEFINE_GUID(GUID_CLASS_COMPORT
, 0x86e0d1e0L
, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73);
18 DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR
, 0x4D36E978L
, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
22 #include <internal/debug.h>
25 /* GLOBALS *******************************************************************/
27 PDEVICE_NODE IopRootDeviceNode
;
28 KSPIN_LOCK IopDeviceTreeLock
;
30 /* DATA **********************************************************************/
32 PDRIVER_OBJECT IopRootDriverObject
;
34 /* FUNCTIONS *****************************************************************/
41 IoInvalidateDeviceRelations(
42 IN PDEVICE_OBJECT DeviceObject
,
43 IN DEVICE_RELATION_TYPE Type
)
49 PDEVICE_OBJECT DeviceObject
)
51 return DeviceObject
->DeviceObjectExtension
->DeviceNode
;
60 IN PDEVICE_OBJECT DeviceObject
,
61 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
62 IN ULONG BufferLength
,
63 OUT PVOID PropertyBuffer
,
64 OUT PULONG ResultLength
)
66 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
71 DPRINT("IoGetDeviceProperty(%x %d)\n", DeviceObject
, DeviceProperty
);
73 if (DeviceNode
== NULL
)
74 return STATUS_INVALID_DEVICE_REQUEST
;
76 switch (DeviceProperty
)
78 case DevicePropertyBusNumber
:
79 Length
= sizeof(ULONG
);
80 Data
= &DeviceNode
->BusNumber
;
83 /* Complete, untested */
84 case DevicePropertyBusTypeGuid
:
85 *ResultLength
= 39 * sizeof(WCHAR
);
86 if (BufferLength
< (39 * sizeof(WCHAR
)))
87 return STATUS_BUFFER_TOO_SMALL
;
88 swprintf((PWSTR
)PropertyBuffer
,
89 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
90 DeviceNode
->BusTypeGuid
.Data1
,
91 DeviceNode
->BusTypeGuid
.Data2
,
92 DeviceNode
->BusTypeGuid
.Data3
,
93 DeviceNode
->BusTypeGuid
.Data4
[0],
94 DeviceNode
->BusTypeGuid
.Data4
[1],
95 DeviceNode
->BusTypeGuid
.Data4
[2],
96 DeviceNode
->BusTypeGuid
.Data4
[3],
97 DeviceNode
->BusTypeGuid
.Data4
[4],
98 DeviceNode
->BusTypeGuid
.Data4
[5],
99 DeviceNode
->BusTypeGuid
.Data4
[6],
100 DeviceNode
->BusTypeGuid
.Data4
[7]);
101 return STATUS_SUCCESS
;
103 case DevicePropertyLegacyBusType
:
104 Length
= sizeof(INTERFACE_TYPE
);
105 Data
= &DeviceNode
->InterfaceType
;
108 case DevicePropertyAddress
:
109 Length
= sizeof(ULONG
);
110 Data
= &DeviceNode
->Address
;
113 // case DevicePropertyUINumber:
114 // if (DeviceNode->CapabilityFlags == NULL)
115 // return STATUS_INVALID_DEVICE_REQUEST;
116 // Length = sizeof(ULONG);
117 // Data = &DeviceNode->CapabilityFlags->UINumber;
120 case DevicePropertyClassName
:
121 case DevicePropertyClassGuid
:
122 case DevicePropertyDriverKeyName
:
123 case DevicePropertyManufacturer
:
124 case DevicePropertyFriendlyName
:
125 case DevicePropertyHardwareID
:
126 case DevicePropertyCompatibleIDs
:
127 case DevicePropertyDeviceDescription
:
128 case DevicePropertyLocationInformation
:
129 case DevicePropertyUINumber
:
131 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
132 UNICODE_STRING KeyName
, ValueName
;
133 OBJECT_ATTRIBUTES ObjectAttributes
;
134 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
135 ULONG ValueInformationLength
;
139 switch (DeviceProperty
)
141 case DevicePropertyClassName
:
142 RegistryPropertyName
= L
"Class"; break;
143 case DevicePropertyClassGuid
:
144 RegistryPropertyName
= L
"ClassGuid"; break;
145 case DevicePropertyDriverKeyName
:
146 RegistryPropertyName
= L
"Driver"; break;
147 case DevicePropertyManufacturer
:
148 RegistryPropertyName
= L
"Mfg"; break;
149 case DevicePropertyFriendlyName
:
150 RegistryPropertyName
= L
"FriendlyName"; break;
151 case DevicePropertyHardwareID
:
152 RegistryPropertyName
= L
"HardwareID"; break;
153 case DevicePropertyCompatibleIDs
:
154 RegistryPropertyName
= L
"CompatibleIDs"; break;
155 case DevicePropertyDeviceDescription
:
156 RegistryPropertyName
= L
"DeviceDesc"; break;
157 case DevicePropertyLocationInformation
:
158 RegistryPropertyName
= L
"LocationInformation"; break;
159 case DevicePropertyUINumber
:
160 RegistryPropertyName
= L
"UINumber"; break;
162 RegistryPropertyName
= NULL
; break;
165 KeyNameBuffer
= ExAllocatePool(PagedPool
,
166 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
168 DPRINT1("KeyNameBuffer: %x, value %S\n",
169 KeyNameBuffer
, RegistryPropertyName
);
171 if (KeyNameBuffer
== NULL
)
172 return STATUS_INSUFFICIENT_RESOURCES
;
174 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
175 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
176 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
177 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
178 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
180 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
181 ExFreePool(KeyNameBuffer
);
182 if (!NT_SUCCESS(Status
))
185 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
186 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
187 Data
[0]) + BufferLength
;
188 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
189 if (ValueInformation
== NULL
)
192 return STATUS_INSUFFICIENT_RESOURCES
;
195 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
196 KeyValuePartialInformation
, ValueInformation
,
197 ValueInformationLength
,
198 &ValueInformationLength
);
199 *ResultLength
= ValueInformation
->DataLength
;
202 if (ValueInformation
->DataLength
> BufferLength
)
203 Status
= STATUS_BUFFER_TOO_SMALL
;
205 if (!NT_SUCCESS(Status
))
207 ExFreePool(ValueInformation
);
211 /* FIXME: Verify the value (NULL-terminated, correct format). */
213 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
214 ValueInformation
->DataLength
);
215 ExFreePool(ValueInformation
);
217 return STATUS_SUCCESS
;
220 case DevicePropertyBootConfiguration
:
222 if (DeviceNode
->BootResources
->Count
!= 0)
224 Length
= sizeof(CM_RESOURCE_LIST
) +
225 ((DeviceNode
->BootResources
->Count
- 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
227 Data
= &DeviceNode
->BootResources
;
230 /* FIXME: use a translated boot configuration instead */
231 case DevicePropertyBootConfigurationTranslated
:
233 if (DeviceNode
->BootResources
->Count
!= 0)
235 Length
= sizeof(CM_RESOURCE_LIST
) +
236 ((DeviceNode
->BootResources
->Count
- 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
238 Data
= &DeviceNode
->BootResources
;
241 case DevicePropertyEnumeratorName
:
242 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
245 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
253 case DevicePropertyPhysicalDeviceObjectName
:
254 return STATUS_NOT_IMPLEMENTED
;
257 return STATUS_INVALID_PARAMETER_2
;
260 *ResultLength
= Length
;
261 if (BufferLength
< Length
)
262 return STATUS_BUFFER_TOO_SMALL
;
263 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
265 /* Terminate the string */
266 if (DeviceProperty
== DevicePropertyEnumeratorName
)
268 Ptr
= (PWSTR
)PropertyBuffer
;
269 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
272 return STATUS_SUCCESS
;
280 IoInvalidateDeviceState(
281 IN PDEVICE_OBJECT PhysicalDeviceObject
)
290 IoOpenDeviceRegistryKey(
291 IN PDEVICE_OBJECT DeviceObject
,
292 IN ULONG DevInstKeyType
,
293 IN ACCESS_MASK DesiredAccess
,
294 OUT PHANDLE DevInstRegKey
)
296 static const WCHAR ClassKeyName
[] = {
297 '\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
298 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t',
299 'r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\',
300 'C','l','a','s','s','\\'};
301 LPWSTR KeyNameBuffer
;
302 UNICODE_STRING KeyName
;
303 ULONG DriverKeyLength
;
304 OBJECT_ATTRIBUTES ObjectAttributes
;
307 if (DevInstKeyType
== PLUGPLAY_REGKEY_DRIVER
)
309 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
310 0, NULL
, &DriverKeyLength
);
311 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
314 KeyNameBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+ sizeof(ClassKeyName
));
315 if (KeyNameBuffer
== NULL
)
316 return STATUS_INSUFFICIENT_RESOURCES
;
318 RtlCopyMemory(KeyNameBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
319 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
320 DriverKeyLength
, KeyNameBuffer
+
321 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
323 if (!NT_SUCCESS(Status
))
325 ExFreePool(KeyNameBuffer
);
329 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
330 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
331 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
332 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
333 ExFreePool(KeyNameBuffer
);
337 return STATUS_NOT_IMPLEMENTED
;
345 IoRequestDeviceEject(
346 IN PDEVICE_OBJECT PhysicalDeviceObject
354 IopCreateUnicodeString(
355 PUNICODE_STRING Destination
,
363 RtlInitUnicodeString(Destination
, NULL
);
367 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
369 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
371 if (Destination
->Buffer
== NULL
)
376 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
378 Destination
->MaximumLength
= Length
;
380 Destination
->Length
= Length
- sizeof(WCHAR
);
386 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
390 if (PopSystemPowerDeviceNode
)
392 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
393 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
394 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
396 return STATUS_SUCCESS
;
399 return STATUS_UNSUCCESSFUL
;
402 /**********************************************************************
404 * Creates a device node
407 * ParentNode = Pointer to parent device node
408 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
409 * to have the root device node create one
410 * (eg. for legacy drivers)
411 * DeviceNode = Pointer to storage for created device node
417 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
418 PDEVICE_OBJECT PhysicalDeviceObject
,
419 PDEVICE_NODE
*DeviceNode
)
425 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
426 ParentNode
, PhysicalDeviceObject
);
428 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
431 return STATUS_INSUFFICIENT_RESOURCES
;
434 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
436 if (!PhysicalDeviceObject
)
438 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
439 if (!NT_SUCCESS(Status
))
445 /* This is for drivers passed on the command line to ntoskrnl.exe */
446 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
447 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
450 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
452 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
456 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
457 Node
->Parent
= ParentNode
;
458 Node
->NextSibling
= ParentNode
->Child
;
459 if (ParentNode
->Child
!= NULL
)
461 ParentNode
->Child
->PrevSibling
= Node
;
463 ParentNode
->Child
= Node
;
464 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
469 return STATUS_SUCCESS
;
473 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
477 /* All children must be deleted before a parent is deleted */
478 ASSERT(!DeviceNode
->Child
);
480 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
482 ASSERT(DeviceNode
->PhysicalDeviceObject
);
484 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
486 /* Unlink from parent if it exists */
488 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
490 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
493 /* Unlink from sibling list */
495 if (DeviceNode
->PrevSibling
)
497 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
500 if (DeviceNode
->NextSibling
)
502 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
505 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
507 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
509 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
511 if (DeviceNode
->ResourceList
)
513 ExFreePool(DeviceNode
->ResourceList
);
516 if (DeviceNode
->ResourceListTranslated
)
518 ExFreePool(DeviceNode
->ResourceListTranslated
);
521 if (DeviceNode
->ResourceRequirements
)
523 ExFreePool(DeviceNode
->ResourceRequirements
);
526 if (DeviceNode
->BootResources
)
528 ExFreePool(DeviceNode
->BootResources
);
531 ExFreePool(DeviceNode
);
533 return STATUS_SUCCESS
;
538 PDEVICE_OBJECT DeviceObject
,
539 PIO_STATUS_BLOCK IoStatusBlock
,
541 PIO_STACK_LOCATION Stack OPTIONAL
)
543 PDEVICE_OBJECT TopDeviceObject
;
544 PIO_STACK_LOCATION IrpSp
;
549 /* Always call the top of the device stack */
550 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
557 Irp
= IoBuildSynchronousFsdRequest(
566 /* PNP IRPs are always initialized with a status code of
567 STATUS_NOT_IMPLEMENTED */
568 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
569 Irp
->IoStatus
.Information
= 0;
571 IrpSp
= IoGetNextIrpStackLocation(Irp
);
572 IrpSp
->MinorFunction
= MinorFunction
;
579 sizeof(Stack
->Parameters
));
582 Status
= IoCallDriver(TopDeviceObject
, Irp
);
583 if (Status
== STATUS_PENDING
)
585 KeWaitForSingleObject(
591 Status
= IoStatusBlock
->Status
;
594 ObDereferenceObject(TopDeviceObject
);
601 IopTraverseDeviceTreeNode(
602 PDEVICETREE_TRAVERSE_CONTEXT Context
)
604 PDEVICE_NODE ParentDeviceNode
;
605 PDEVICE_NODE ChildDeviceNode
;
608 /* Copy context data so we don't overwrite it in subsequent calls to this function */
609 ParentDeviceNode
= Context
->DeviceNode
;
611 /* Call the action routine */
612 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
613 if (!NT_SUCCESS(Status
))
618 /* Traversal of all children nodes */
619 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
620 ChildDeviceNode
!= NULL
;
621 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
623 /* Pass the current device node to the action routine */
624 Context
->DeviceNode
= ChildDeviceNode
;
626 Status
= IopTraverseDeviceTreeNode(Context
);
627 if (!NT_SUCCESS(Status
))
638 IopTraverseDeviceTree(
639 PDEVICETREE_TRAVERSE_CONTEXT Context
)
643 DPRINT("Context %x\n", Context
);
645 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
646 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
648 /* Start from the specified device node */
649 Context
->DeviceNode
= Context
->FirstDeviceNode
;
651 /* Recursively traverse the device tree */
652 Status
= IopTraverseDeviceTreeNode(Context
);
653 if (Status
== STATUS_UNSUCCESSFUL
)
655 /* The action routine just wanted to terminate the traversal with status
656 code STATUS_SUCCESS */
657 Status
= STATUS_SUCCESS
;
665 IopCreateDeviceKeyPath(PWSTR Path
,
668 OBJECT_ATTRIBUTES ObjectAttributes
;
669 WCHAR KeyBuffer
[MAX_PATH
];
670 UNICODE_STRING KeyName
;
678 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
680 return STATUS_INVALID_PARAMETER
;
683 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
684 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
686 /* Skip \\Registry\\ */
687 Current
= KeyName
.Buffer
;
688 Current
= wcschr (Current
, '\\') + 1;
689 Current
= wcschr (Current
, '\\') + 1;
693 Next
= wcschr (Current
, '\\');
703 InitializeObjectAttributes (&ObjectAttributes
,
705 OBJ_CASE_INSENSITIVE
,
709 DPRINT("Create '%S'\n", KeyName
.Buffer
);
711 Status
= NtCreateKey (&KeyHandle
,
718 if (!NT_SUCCESS (Status
))
720 DPRINT ("NtCreateKey() failed with status %x\n", Status
);
727 return STATUS_SUCCESS
;
738 return STATUS_UNSUCCESSFUL
;
743 IopSetDeviceInstanceData(HANDLE InstanceKey
,
744 PDEVICE_NODE DeviceNode
)
746 OBJECT_ATTRIBUTES ObjectAttributes
;
747 UNICODE_STRING KeyName
;
753 DPRINT("IopSetDeviceInstanceData() called\n");
755 /* Create the 'LogConf' key */
756 RtlInitUnicodeString(&KeyName
,
758 InitializeObjectAttributes(&ObjectAttributes
,
760 OBJ_CASE_INSENSITIVE
,
763 Status
= NtCreateKey(&LogConfKey
,
770 if (NT_SUCCESS(Status
))
772 /* Set 'BootConfig' value */
773 if (DeviceNode
->BootResources
!= NULL
)
775 ResCount
= DeviceNode
->BootResources
->Count
;
778 ListSize
= sizeof(CM_RESOURCE_LIST
) +
779 ((ResCount
- 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
781 RtlInitUnicodeString(&KeyName
,
783 Status
= NtSetValueKey(LogConfKey
,
787 &DeviceNode
->BootResources
,
792 /* Set 'BasicConfigVector' value */
793 if (DeviceNode
->ResourceRequirements
!= NULL
&&
794 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
796 RtlInitUnicodeString(&KeyName
,
797 L
"BasicConfigVector");
798 Status
= NtSetValueKey(LogConfKey
,
801 REG_RESOURCE_REQUIREMENTS_LIST
,
802 &DeviceNode
->ResourceRequirements
,
803 DeviceNode
->ResourceRequirements
->ListSize
);
809 DPRINT("IopSetDeviceInstanceData() done\n");
811 return STATUS_SUCCESS
;
816 * IopActionInterrogateDeviceStack
818 * Retrieve information for all (direct) child nodes of a parent node.
822 * Pointer to device node.
824 * Pointer to parent node to retrieve child node information for.
827 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
828 * when we reach a device node which is not a direct child of the device
829 * node for which we retrieve information of child nodes for. Any errors
830 * that occur is logged instead so that all child services have a chance
831 * of being interrogated.
835 IopActionInterrogateDeviceStack(
836 PDEVICE_NODE DeviceNode
,
839 IO_STATUS_BLOCK IoStatusBlock
;
840 PDEVICE_NODE ParentDeviceNode
;
841 WCHAR InstancePath
[MAX_PATH
];
842 IO_STACK_LOCATION Stack
;
848 HANDLE InstanceKey
= NULL
;
849 UNICODE_STRING ValueName
;
850 DEVICE_CAPABILITIES DeviceCapabilities
;
852 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
853 DPRINT("PDO %x\n", DeviceNode
->PhysicalDeviceObject
);
855 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
858 * We are called for the parent too, but we don't need to do special
859 * handling for this node
862 if (DeviceNode
== ParentDeviceNode
)
865 return STATUS_SUCCESS
;
869 * Make sure this device node is a direct child of the parent device node
870 * that is given as an argument
873 if (DeviceNode
->Parent
!= ParentDeviceNode
)
875 /* Stop the traversal immediately and indicate successful operation */
877 return STATUS_UNSUCCESSFUL
;
881 * FIXME: For critical errors, cleanup and disable device, but always
882 * return STATUS_SUCCESS.
885 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
887 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
888 Status
= IopInitiatePnpIrp(
889 DeviceNode
->PhysicalDeviceObject
,
893 if (NT_SUCCESS(Status
))
895 /* Copy the device id string */
896 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
899 * FIXME: Check for valid characters, if there is invalid characters
905 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
908 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
910 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
911 Status
= IopInitiatePnpIrp(
912 DeviceNode
->PhysicalDeviceObject
,
916 if (NT_SUCCESS(Status
))
918 /* Append the instance id string */
919 wcscat(InstancePath
, L
"\\");
920 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
923 * FIXME: Check for valid characters, if there is invalid characters
929 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
932 RtlZeroMemory(&DeviceCapabilities
, sizeof(DEVICE_CAPABILITIES
));
933 DeviceCapabilities
.Size
= sizeof(DEVICE_CAPABILITIES
);
934 DeviceCapabilities
.Version
= 1;
935 DeviceCapabilities
.Address
= -1;
936 DeviceCapabilities
.UINumber
= -1;
938 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= &DeviceCapabilities
;
939 Status
= IopInitiatePnpIrp(
940 DeviceNode
->PhysicalDeviceObject
,
942 IRP_MN_QUERY_CAPABILITIES
,
944 if (NT_SUCCESS(Status
))
949 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
952 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
953 DeviceNode
->Address
= DeviceCapabilities
.Address
;
955 if (!DeviceCapabilities
.UniqueID
)
957 DPRINT("Instance ID is not unique\n");
958 /* FIXME: Add information from parent bus driver to InstancePath */
961 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
))
963 DPRINT("No resources\n");
964 /* FIXME: Cleanup and disable device */
967 DPRINT1("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
970 * Create registry key for the instance id, if it doesn't exist yet
972 KeyBuffer
= ExAllocatePool(
974 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
975 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
976 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
977 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
979 ExFreePool(KeyBuffer
);
980 if (!NT_SUCCESS(Status
))
982 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
987 /* Set 'Capabilities' value */
988 RtlInitUnicodeString(&ValueName
,
990 Status
= NtSetValueKey(InstanceKey
,
994 (PVOID
)&DeviceNode
->CapabilityFlags
,
997 /* Set 'UINumber' value */
998 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1000 RtlInitUnicodeString(&ValueName
,
1002 Status
= NtSetValueKey(InstanceKey
,
1006 &DeviceCapabilities
.UINumber
,
1011 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1013 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1014 Status
= IopInitiatePnpIrp(
1015 DeviceNode
->PhysicalDeviceObject
,
1019 if (NT_SUCCESS(Status
))
1022 * FIXME: Check for valid characters, if there is invalid characters
1026 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1027 DPRINT("Hardware IDs:\n");
1030 DPRINT(" %S\n", Ptr
);
1031 Length
= wcslen(Ptr
) + 1;
1034 TotalLength
+= Length
;
1036 DPRINT("TotalLength: %hu\n", TotalLength
);
1039 RtlInitUnicodeString(&ValueName
,
1041 Status
= NtSetValueKey(InstanceKey
,
1045 (PVOID
)IoStatusBlock
.Information
,
1046 (TotalLength
+ 1) * sizeof(WCHAR
));
1047 if (!NT_SUCCESS(Status
))
1049 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1054 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1057 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1059 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1060 Status
= IopInitiatePnpIrp(
1061 DeviceNode
->PhysicalDeviceObject
,
1065 if (NT_SUCCESS(Status
))
1068 * FIXME: Check for valid characters, if there is invalid characters
1072 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1073 DPRINT("Compatible IDs:\n");
1076 DPRINT(" %S\n", Ptr
);
1077 Length
= wcslen(Ptr
) + 1;
1080 TotalLength
+= Length
;
1082 DPRINT("TotalLength: %hu\n", TotalLength
);
1085 RtlInitUnicodeString(&ValueName
,
1087 Status
= NtSetValueKey(InstanceKey
,
1091 (PVOID
)IoStatusBlock
.Information
,
1092 (TotalLength
+ 1) * sizeof(WCHAR
));
1093 if (!NT_SUCCESS(Status
))
1095 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1100 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1104 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1106 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1107 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
1108 Status
= IopInitiatePnpIrp(
1109 DeviceNode
->PhysicalDeviceObject
,
1111 IRP_MN_QUERY_DEVICE_TEXT
,
1113 if (NT_SUCCESS(Status
))
1115 RtlInitUnicodeString(&ValueName
,
1117 Status
= NtSetValueKey(InstanceKey
,
1121 (PVOID
)IoStatusBlock
.Information
,
1122 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1123 if (!NT_SUCCESS(Status
))
1125 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1130 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1133 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1135 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1136 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
1137 Status
= IopInitiatePnpIrp(
1138 DeviceNode
->PhysicalDeviceObject
,
1140 IRP_MN_QUERY_DEVICE_TEXT
,
1142 if (NT_SUCCESS(Status
))
1144 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1145 RtlInitUnicodeString(&ValueName
,
1146 L
"LocationInformation");
1147 Status
= NtSetValueKey(InstanceKey
,
1151 (PVOID
)IoStatusBlock
.Information
,
1152 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1153 if (!NT_SUCCESS(Status
))
1155 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1160 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1163 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1165 Status
= IopInitiatePnpIrp(
1166 DeviceNode
->PhysicalDeviceObject
,
1168 IRP_MN_QUERY_BUS_INFORMATION
,
1170 if (NT_SUCCESS(Status
))
1172 PPNP_BUS_INFORMATION BusInformation
=
1173 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1175 DeviceNode
->BusNumber
= BusInformation
->BusNumber
;
1176 DeviceNode
->InterfaceType
= BusInformation
->LegacyBusType
;
1177 memcpy(&DeviceNode
->BusTypeGuid
,
1178 &BusInformation
->BusTypeGuid
,
1180 ExFreePool(BusInformation
);
1184 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1186 DeviceNode
->BusNumber
= -1;
1187 DeviceNode
->InterfaceType
= -1;
1188 memset(&DeviceNode
->BusTypeGuid
,
1193 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1195 Status
= IopInitiatePnpIrp(
1196 DeviceNode
->PhysicalDeviceObject
,
1198 IRP_MN_QUERY_RESOURCES
,
1200 if (NT_SUCCESS(Status
))
1202 DeviceNode
->BootResources
=
1203 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1204 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1208 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1209 DeviceNode
->BootResources
= NULL
;
1212 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1214 Status
= IopInitiatePnpIrp(
1215 DeviceNode
->PhysicalDeviceObject
,
1217 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1219 if (NT_SUCCESS(Status
))
1221 DeviceNode
->ResourceRequirements
=
1222 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1226 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1227 DeviceNode
->ResourceRequirements
= NULL
;
1231 if (InstanceKey
!= NULL
)
1233 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1236 NtClose(InstanceKey
);
1238 DeviceNode
->Flags
|= DNF_PROCESSED
;
1240 return STATUS_SUCCESS
;
1244 * IopActionConfigureChildServices
1246 * Retrieve configuration for all (direct) child nodes of a parent node.
1250 * Pointer to device node.
1252 * Pointer to parent node to retrieve child node configuration for.
1255 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1256 * when we reach a device node which is not a direct child of the device
1257 * node for which we configure child services for. Any errors that occur is
1258 * logged instead so that all child services have a chance of beeing
1263 IopActionConfigureChildServices(
1264 PDEVICE_NODE DeviceNode
,
1267 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1268 PDEVICE_NODE ParentDeviceNode
;
1269 PUNICODE_STRING Service
;
1272 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1274 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1277 * We are called for the parent too, but we don't need to do special
1278 * handling for this node
1280 if (DeviceNode
== ParentDeviceNode
)
1282 DPRINT("Success\n");
1283 return STATUS_SUCCESS
;
1287 * Make sure this device node is a direct child of the parent device node
1288 * that is given as an argument
1290 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1292 /* Stop the traversal immediately and indicate successful operation */
1294 return STATUS_UNSUCCESSFUL
;
1297 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1300 * Retrieve configuration from Enum key
1303 Service
= &DeviceNode
->ServiceName
;
1305 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1306 RtlInitUnicodeString(Service
, NULL
);
1308 QueryTable
[0].Name
= L
"Service";
1309 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1310 QueryTable
[0].EntryContext
= Service
;
1312 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ENUM
,
1313 DeviceNode
->InstancePath
.Buffer
, QueryTable
, NULL
, NULL
);
1315 if (!NT_SUCCESS(Status
))
1317 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1318 /* FIXME: Log the error */
1319 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1320 DeviceNode
->InstancePath
.Buffer
, Status
);
1321 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1322 return STATUS_SUCCESS
;
1325 if (Service
->Buffer
== NULL
)
1327 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1328 return STATUS_SUCCESS
;
1331 DPRINT("Got Service %S\n", Service
->Buffer
);
1334 return STATUS_SUCCESS
;
1338 * IopActionInitChildServices
1340 * Initialize the service for all (direct) child nodes of a parent node
1344 * Pointer to device node.
1346 * Pointer to parent node to initialize child node services for.
1348 * Load only driver marked as boot start.
1351 * If the driver image for a service is not loaded and initialized
1352 * it is done here too. We only return a status code indicating an
1353 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1354 * not a direct child of the device node for which we initialize
1355 * child services for. Any errors that occur is logged instead so
1356 * that all child services have a chance of being initialized.
1360 IopActionInitChildServices(
1361 PDEVICE_NODE DeviceNode
,
1363 BOOLEAN BootDrivers
)
1365 PDEVICE_NODE ParentDeviceNode
;
1368 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1371 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1374 * We are called for the parent too, but we don't need to do special
1375 * handling for this node
1377 if (DeviceNode
== ParentDeviceNode
)
1379 DPRINT("Success\n");
1380 return STATUS_SUCCESS
;
1384 * Make sure this device node is a direct child of the parent device node
1385 * that is given as an argument
1388 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1391 * Stop the traversal immediately and indicate unsuccessful operation
1394 return STATUS_UNSUCCESSFUL
;
1398 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1399 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1400 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1402 PMODULE_OBJECT ModuleObject
;
1403 PDRIVER_OBJECT DriverObject
;
1405 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1406 if (NT_SUCCESS(Status
))
1408 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
1409 if (NT_SUCCESS(Status
))
1411 /* Attach lower level filter drivers. */
1412 IopAttachFilterDrivers(DeviceNode
, TRUE
);
1413 /* Initialize the function driver for the device node */
1414 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1415 if (NT_SUCCESS(Status
))
1417 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1418 /* Attach upper level filter drivers. */
1419 IopAttachFilterDrivers(DeviceNode
, FALSE
);
1426 * Don't disable when trying to load only boot drivers
1430 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1431 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1433 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1434 CPRINT("Initialization of service %S failed (Status %x)\n",
1435 DeviceNode
->ServiceName
.Buffer
, Status
);
1439 DPRINT("Service %S is disabled or already initialized\n",
1440 DeviceNode
->ServiceName
.Buffer
);
1443 return STATUS_SUCCESS
;
1447 * IopActionInitAllServices
1449 * Initialize the service for all (direct) child nodes of a parent node. This
1450 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1454 IopActionInitAllServices(
1455 PDEVICE_NODE DeviceNode
,
1458 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1462 * IopActionInitBootServices
1464 * Initialize the boot start services for all (direct) child nodes of a
1465 * parent node. This function just calls IopActionInitChildServices with
1466 * BootDrivers = TRUE.
1470 IopActionInitBootServices(
1471 PDEVICE_NODE DeviceNode
,
1474 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1478 * IopInitializePnpServices
1480 * Initialize services for discovered children
1484 * Top device node to start initializing services.
1487 * When set to TRUE, only drivers marked as boot start will
1488 * be loaded. Otherwise, all drivers will be loaded.
1495 IopInitializePnpServices(
1496 IN PDEVICE_NODE DeviceNode
,
1497 IN BOOLEAN BootDrivers
)
1499 DEVICETREE_TRAVERSE_CONTEXT Context
;
1501 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1505 IopInitDeviceTreeTraverseContext(
1508 IopActionInitBootServices
,
1512 IopInitDeviceTreeTraverseContext(
1515 IopActionInitAllServices
,
1519 return IopTraverseDeviceTree(&Context
);
1524 IopInvalidateDeviceRelations(
1525 IN PDEVICE_NODE DeviceNode
,
1526 IN DEVICE_RELATION_TYPE Type
)
1528 DEVICETREE_TRAVERSE_CONTEXT Context
;
1529 PDEVICE_RELATIONS DeviceRelations
;
1530 IO_STATUS_BLOCK IoStatusBlock
;
1531 PDEVICE_NODE ChildDeviceNode
;
1532 IO_STACK_LOCATION Stack
;
1534 OBJECT_ATTRIBUTES ObjectAttributes
;
1535 UNICODE_STRING LinkName
;
1540 DPRINT("DeviceNode %x\n", DeviceNode
);
1542 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1544 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1546 Status
= IopInitiatePnpIrp(
1547 DeviceNode
->PhysicalDeviceObject
,
1549 IRP_MN_QUERY_DEVICE_RELATIONS
,
1551 if (!NT_SUCCESS(Status
))
1553 DPRINT("IopInitiatePnpIrp() failed\n");
1557 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1559 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1561 DPRINT("No PDOs\n");
1562 if (DeviceRelations
)
1564 ExFreePool(DeviceRelations
);
1566 return STATUS_SUCCESS
;
1569 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1572 * Create device nodes for all discovered devices
1575 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1577 Status
= IopCreateDeviceNode(
1579 DeviceRelations
->Objects
[i
],
1581 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1582 if (!NT_SUCCESS(Status
))
1584 DPRINT("No resources\n");
1585 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1586 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1587 ExFreePool(DeviceRelations
);
1588 return STATUS_INSUFFICIENT_RESOURCES
;
1591 ExFreePool(DeviceRelations
);
1594 * Retrieve information about all discovered children from the bus driver
1597 IopInitDeviceTreeTraverseContext(
1600 IopActionInterrogateDeviceStack
,
1603 Status
= IopTraverseDeviceTree(&Context
);
1604 if (!NT_SUCCESS(Status
))
1606 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1611 * Retrieve configuration from the registry for discovered children
1614 IopInitDeviceTreeTraverseContext(
1617 IopActionConfigureChildServices
,
1620 Status
= IopTraverseDeviceTree(&Context
);
1621 if (!NT_SUCCESS(Status
))
1623 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1628 * Get the state of the system boot. If the \\SystemRoot link isn't
1629 * created yet, we will assume that it's possible to load only boot
1633 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
1635 InitializeObjectAttributes(
1642 Status
= NtOpenFile(
1650 BootDrivers
= NT_SUCCESS(Status
) ? FALSE
: TRUE
;
1655 * Initialize services for discovered children. Only boot drivers will
1656 * be loaded from boot driver!
1659 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
1660 if (!NT_SUCCESS(Status
))
1662 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
1666 return STATUS_SUCCESS
;
1676 DPRINT("PnpInit()\n");
1678 KeInitializeSpinLock(&IopDeviceTreeLock
);
1681 * Create root device node
1684 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, FALSE
, NULL
, 0);
1685 if (!NT_SUCCESS(Status
))
1687 CPRINT("IoCreateDriverObject() failed\n");
1688 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1691 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
1693 if (!NT_SUCCESS(Status
))
1695 CPRINT("IoCreateDevice() failed\n");
1696 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1699 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
1700 if (!NT_SUCCESS(Status
))
1702 CPRINT("Insufficient resources\n");
1703 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1706 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1707 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1708 IopRootDriverObject
->DriverExtension
->AddDevice(
1709 IopRootDriverObject
,
1710 IopRootDeviceNode
->PhysicalDeviceObject
);