1 /* $Id: pnpmgr.c,v 1.41 2004/10/22 11:00:41 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 IoAdjustPagingPathCount(
52 IoInvalidateDeviceRelations(
53 IN PDEVICE_OBJECT DeviceObject
,
54 IN DEVICE_RELATION_TYPE Type
)
60 PDEVICE_OBJECT DeviceObject
)
62 return DeviceObject
->DeviceObjectExtension
->DeviceNode
;
71 IN PDEVICE_OBJECT DeviceObject
,
72 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
73 IN ULONG BufferLength
,
74 OUT PVOID PropertyBuffer
,
75 OUT PULONG ResultLength
)
77 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
82 DPRINT("IoGetDeviceProperty(%x %d)\n", DeviceObject
, DeviceProperty
);
84 if (DeviceNode
== NULL
)
85 return STATUS_INVALID_DEVICE_REQUEST
;
87 switch (DeviceProperty
)
89 case DevicePropertyBusNumber
:
90 if (DeviceNode
->BusInformation
== NULL
)
91 return STATUS_INVALID_DEVICE_REQUEST
;
92 Length
= sizeof(ULONG
);
93 Data
= &DeviceNode
->BusInformation
->BusNumber
;
96 /* Complete, untested */
97 case DevicePropertyBusTypeGuid
:
98 if (DeviceNode
->BusInformation
== NULL
)
99 return STATUS_INVALID_DEVICE_REQUEST
;
100 *ResultLength
= 39 * sizeof(WCHAR
);
101 if (BufferLength
< (39 * sizeof(WCHAR
)))
102 return STATUS_BUFFER_TOO_SMALL
;
103 swprintf((PWSTR
)PropertyBuffer
,
104 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
105 DeviceNode
->BusInformation
->BusTypeGuid
.Data1
,
106 DeviceNode
->BusInformation
->BusTypeGuid
.Data2
,
107 DeviceNode
->BusInformation
->BusTypeGuid
.Data3
,
108 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[0],
109 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[1],
110 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[2],
111 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[3],
112 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[4],
113 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[5],
114 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[6],
115 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[7]);
116 return STATUS_SUCCESS
;
118 case DevicePropertyLegacyBusType
:
119 if (DeviceNode
->BusInformation
== NULL
)
120 return STATUS_INVALID_DEVICE_REQUEST
;
121 Length
= sizeof(INTERFACE_TYPE
);
122 Data
= &DeviceNode
->BusInformation
->LegacyBusType
;
125 case DevicePropertyAddress
:
126 if (DeviceNode
->CapabilityFlags
== NULL
)
127 return STATUS_INVALID_DEVICE_REQUEST
;
128 Length
= sizeof(ULONG
);
129 Data
= &DeviceNode
->CapabilityFlags
->Address
;
132 case DevicePropertyUINumber
:
133 if (DeviceNode
->CapabilityFlags
== NULL
)
134 return STATUS_INVALID_DEVICE_REQUEST
;
135 Length
= sizeof(ULONG
);
136 Data
= &DeviceNode
->CapabilityFlags
->UINumber
;
139 case DevicePropertyClassName
:
140 case DevicePropertyClassGuid
:
141 case DevicePropertyDriverKeyName
:
142 case DevicePropertyManufacturer
:
143 case DevicePropertyFriendlyName
:
144 case DevicePropertyHardwareID
:
145 case DevicePropertyCompatibleIDs
:
146 case DevicePropertyDeviceDescription
:
147 case DevicePropertyLocationInformation
:
149 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
150 UNICODE_STRING KeyName
, ValueName
;
151 OBJECT_ATTRIBUTES ObjectAttributes
;
152 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
153 ULONG ValueInformationLength
;
157 switch (DeviceProperty
)
159 case DevicePropertyClassName
:
160 RegistryPropertyName
= L
"Class"; break;
161 case DevicePropertyClassGuid
:
162 RegistryPropertyName
= L
"ClassGuid"; break;
163 case DevicePropertyDriverKeyName
:
164 RegistryPropertyName
= L
"Driver"; break;
165 case DevicePropertyManufacturer
:
166 RegistryPropertyName
= L
"Mfg"; break;
167 case DevicePropertyFriendlyName
:
168 RegistryPropertyName
= L
"FriendlyName"; break;
169 case DevicePropertyHardwareID
:
170 RegistryPropertyName
= L
"HardwareID"; break;
171 case DevicePropertyCompatibleIDs
:
172 RegistryPropertyName
= L
"CompatibleIDs"; break;
173 case DevicePropertyDeviceDescription
:
174 RegistryPropertyName
= L
"DeviceDesc"; break;
175 case DevicePropertyLocationInformation
:
176 RegistryPropertyName
= L
"LocationInformation"; break;
178 RegistryPropertyName
= NULL
; break;
181 KeyNameBuffer
= ExAllocatePool(PagedPool
,
182 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
184 DPRINT1("KeyNameBuffer: %x, value %S\n",
185 KeyNameBuffer
, RegistryPropertyName
);
187 if (KeyNameBuffer
== NULL
)
188 return STATUS_INSUFFICIENT_RESOURCES
;
190 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
191 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
192 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
193 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
194 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
196 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
197 ExFreePool(KeyNameBuffer
);
198 if (!NT_SUCCESS(Status
))
201 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
202 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
203 Data
[0]) + BufferLength
;
204 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
205 if (ValueInformation
== NULL
)
208 return STATUS_INSUFFICIENT_RESOURCES
;
211 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
212 KeyValuePartialInformation
, ValueInformation
,
213 ValueInformationLength
,
214 &ValueInformationLength
);
215 *ResultLength
= ValueInformation
->DataLength
;
218 if (ValueInformation
->DataLength
> BufferLength
)
219 Status
= STATUS_BUFFER_TOO_SMALL
;
221 if (!NT_SUCCESS(Status
))
223 ExFreePool(ValueInformation
);
227 /* FIXME: Verify the value (NULL-terminated, correct format). */
229 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
230 ValueInformation
->DataLength
);
231 ExFreePool(ValueInformation
);
233 return STATUS_SUCCESS
;
236 case DevicePropertyBootConfiguration
:
238 if (DeviceNode
->BootResourceList
->Count
!= 0)
240 Length
= sizeof(CM_RESOURCE_LIST
) +
241 ((DeviceNode
->BootResourceList
->Count
- 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
243 Data
= &DeviceNode
->BootResourceList
;
246 /* FIXME: use a translated boot configuration instead */
247 case DevicePropertyBootConfigurationTranslated
:
249 if (DeviceNode
->BootResourceList
->Count
!= 0)
251 Length
= sizeof(CM_RESOURCE_LIST
) +
252 ((DeviceNode
->BootResourceList
->Count
- 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
254 Data
= &DeviceNode
->BootResourceList
;
257 case DevicePropertyEnumeratorName
:
258 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
261 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
269 case DevicePropertyPhysicalDeviceObjectName
:
270 return STATUS_NOT_IMPLEMENTED
;
273 return STATUS_INVALID_PARAMETER_2
;
276 *ResultLength
= Length
;
277 if (BufferLength
< Length
)
278 return STATUS_BUFFER_TOO_SMALL
;
279 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
281 /* Terminate the string */
282 if (DeviceProperty
== DevicePropertyEnumeratorName
)
284 Ptr
= (PWSTR
)PropertyBuffer
;
285 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
288 return STATUS_SUCCESS
;
296 IoInvalidateDeviceState(
297 IN PDEVICE_OBJECT PhysicalDeviceObject
)
306 IoOpenDeviceRegistryKey(
307 IN PDEVICE_OBJECT DeviceObject
,
308 IN ULONG DevInstKeyType
,
309 IN ACCESS_MASK DesiredAccess
,
310 OUT PHANDLE DevInstRegKey
)
312 static const WCHAR ClassKeyName
[] = {
313 '\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
314 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t',
315 'r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\',
316 'C','l','a','s','s','\\'};
317 LPWSTR KeyNameBuffer
;
318 UNICODE_STRING KeyName
;
319 ULONG DriverKeyLength
;
320 OBJECT_ATTRIBUTES ObjectAttributes
;
323 if (DevInstKeyType
== PLUGPLAY_REGKEY_DRIVER
)
325 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
326 0, NULL
, &DriverKeyLength
);
327 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
330 KeyNameBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+ sizeof(ClassKeyName
));
331 if (KeyNameBuffer
== NULL
)
332 return STATUS_INSUFFICIENT_RESOURCES
;
334 RtlCopyMemory(KeyNameBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
335 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
336 DriverKeyLength
, KeyNameBuffer
+
337 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
339 if (!NT_SUCCESS(Status
))
341 ExFreePool(KeyNameBuffer
);
345 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
346 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
347 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
348 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
349 ExFreePool(KeyNameBuffer
);
353 return STATUS_NOT_IMPLEMENTED
;
361 IoRequestDeviceEject(
362 IN PDEVICE_OBJECT PhysicalDeviceObject
370 IopCreateUnicodeString(
371 PUNICODE_STRING Destination
,
379 RtlInitUnicodeString(Destination
, NULL
);
383 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
385 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
387 if (Destination
->Buffer
== NULL
)
392 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
394 Destination
->MaximumLength
= Length
;
396 Destination
->Length
= Length
- sizeof(WCHAR
);
402 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
406 if (PopSystemPowerDeviceNode
)
408 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
409 *DeviceObject
= PopSystemPowerDeviceNode
->Pdo
;
410 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
412 return STATUS_SUCCESS
;
415 return STATUS_UNSUCCESSFUL
;
418 /**********************************************************************
420 * Creates a device node
423 * ParentNode = Pointer to parent device node
424 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
425 * to have the root device node create one
426 * (eg. for legacy drivers)
427 * DeviceNode = Pointer to storage for created device node
433 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
434 PDEVICE_OBJECT PhysicalDeviceObject
,
435 PDEVICE_NODE
*DeviceNode
)
441 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
442 ParentNode
, PhysicalDeviceObject
);
444 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
447 return STATUS_INSUFFICIENT_RESOURCES
;
450 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
452 if (!PhysicalDeviceObject
)
454 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
455 if (!NT_SUCCESS(Status
))
461 /* This is for drivers passed on the command line to ntoskrnl.exe */
462 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
463 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
466 Node
->Pdo
= PhysicalDeviceObject
;
468 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
472 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
473 Node
->Parent
= ParentNode
;
474 Node
->NextSibling
= ParentNode
->Child
;
475 if (ParentNode
->Child
!= NULL
)
477 ParentNode
->Child
->PrevSibling
= Node
;
479 ParentNode
->Child
= Node
;
480 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
485 return STATUS_SUCCESS
;
489 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
493 /* All children must be deleted before a parent is deleted */
494 assert(!DeviceNode
->Child
);
496 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
498 assert(DeviceNode
->Pdo
);
500 ObDereferenceObject(DeviceNode
->Pdo
);
502 /* Unlink from parent if it exists */
504 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
506 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
509 /* Unlink from sibling list */
511 if (DeviceNode
->PrevSibling
)
513 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
516 if (DeviceNode
->NextSibling
)
518 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
521 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
523 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
525 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
527 if (DeviceNode
->CapabilityFlags
)
529 ExFreePool(DeviceNode
->CapabilityFlags
);
532 if (DeviceNode
->CmResourceList
)
534 ExFreePool(DeviceNode
->CmResourceList
);
537 if (DeviceNode
->BootResourceList
)
539 ExFreePool(DeviceNode
->BootResourceList
);
542 if (DeviceNode
->ResourceRequirementsList
)
544 ExFreePool(DeviceNode
->ResourceRequirementsList
);
547 if (DeviceNode
->BusInformation
)
549 ExFreePool(DeviceNode
->BusInformation
);
552 ExFreePool(DeviceNode
);
554 return STATUS_SUCCESS
;
559 PDEVICE_OBJECT DeviceObject
,
560 PIO_STATUS_BLOCK IoStatusBlock
,
562 PIO_STACK_LOCATION Stack OPTIONAL
)
564 PDEVICE_OBJECT TopDeviceObject
;
565 PIO_STACK_LOCATION IrpSp
;
570 /* Always call the top of the device stack */
571 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
578 Irp
= IoBuildSynchronousFsdRequest(
587 /* PNP IRPs are always initialized with a status code of
588 STATUS_NOT_IMPLEMENTED */
589 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
590 Irp
->IoStatus
.Information
= 0;
592 IrpSp
= IoGetNextIrpStackLocation(Irp
);
593 IrpSp
->MinorFunction
= MinorFunction
;
600 sizeof(Stack
->Parameters
));
603 Status
= IoCallDriver(TopDeviceObject
, Irp
);
604 if (Status
== STATUS_PENDING
)
606 KeWaitForSingleObject(
612 Status
= IoStatusBlock
->Status
;
615 ObDereferenceObject(TopDeviceObject
);
622 IopQueryCapabilities(
624 PDEVICE_CAPABILITIES
*Capabilities
)
626 IO_STATUS_BLOCK IoStatusBlock
;
627 PDEVICE_CAPABILITIES Caps
;
628 IO_STACK_LOCATION Stack
;
631 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
633 *Capabilities
= NULL
;
635 Caps
= ExAllocatePool(PagedPool
, sizeof(DEVICE_CAPABILITIES
));
638 return STATUS_INSUFFICIENT_RESOURCES
;
641 RtlZeroMemory(Caps
, sizeof(DEVICE_CAPABILITIES
));
642 Caps
->Size
= sizeof(DEVICE_CAPABILITIES
);
647 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= Caps
;
649 Status
= IopInitiatePnpIrp(
652 IRP_MN_QUERY_CAPABILITIES
,
654 if (NT_SUCCESS(Status
))
656 *Capabilities
= Caps
;
660 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
668 IopTraverseDeviceTreeNode(
669 PDEVICETREE_TRAVERSE_CONTEXT Context
)
671 PDEVICE_NODE ParentDeviceNode
;
672 PDEVICE_NODE ChildDeviceNode
;
675 /* Copy context data so we don't overwrite it in subsequent calls to this function */
676 ParentDeviceNode
= Context
->DeviceNode
;
678 /* Call the action routine */
679 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
680 if (!NT_SUCCESS(Status
))
685 /* Traversal of all children nodes */
686 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
687 ChildDeviceNode
!= NULL
;
688 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
690 /* Pass the current device node to the action routine */
691 Context
->DeviceNode
= ChildDeviceNode
;
693 Status
= IopTraverseDeviceTreeNode(Context
);
694 if (!NT_SUCCESS(Status
))
705 IopTraverseDeviceTree(
706 PDEVICETREE_TRAVERSE_CONTEXT Context
)
710 DPRINT("Context %x\n", Context
);
712 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
713 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
715 /* Start from the specified device node */
716 Context
->DeviceNode
= Context
->FirstDeviceNode
;
718 /* Recursively traverse the device tree */
719 Status
= IopTraverseDeviceTreeNode(Context
);
720 if (Status
== STATUS_UNSUCCESSFUL
)
722 /* The action routine just wanted to terminate the traversal with status
723 code STATUS_SUCCESS */
724 Status
= STATUS_SUCCESS
;
732 IopCreateDeviceKeyPath(PWSTR Path
,
735 OBJECT_ATTRIBUTES ObjectAttributes
;
736 WCHAR KeyBuffer
[MAX_PATH
];
737 UNICODE_STRING KeyName
;
745 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
747 return STATUS_INVALID_PARAMETER
;
750 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
751 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
753 /* Skip \\Registry\\ */
754 Current
= KeyName
.Buffer
;
755 Current
= wcschr (Current
, '\\') + 1;
756 Current
= wcschr (Current
, '\\') + 1;
760 Next
= wcschr (Current
, '\\');
770 InitializeObjectAttributes (&ObjectAttributes
,
772 OBJ_CASE_INSENSITIVE
,
776 DPRINT("Create '%S'\n", KeyName
.Buffer
);
778 Status
= NtCreateKey (&KeyHandle
,
785 if (!NT_SUCCESS (Status
))
787 DPRINT ("NtCreateKey() failed with status %x\n", Status
);
794 return STATUS_SUCCESS
;
805 return STATUS_UNSUCCESSFUL
;
810 IopSetDeviceInstanceData(HANDLE InstanceKey
,
811 PDEVICE_NODE DeviceNode
)
813 OBJECT_ATTRIBUTES ObjectAttributes
;
814 UNICODE_STRING KeyName
;
820 DPRINT("IopSetDeviceInstanceData() called\n");
822 /* Create the 'LogConf' key */
823 RtlInitUnicodeString(&KeyName
,
825 InitializeObjectAttributes(&ObjectAttributes
,
827 OBJ_CASE_INSENSITIVE
,
830 Status
= NtCreateKey(&LogConfKey
,
837 if (NT_SUCCESS(Status
))
839 /* Set 'BootConfig' value */
840 if (DeviceNode
->BootResourceList
!= NULL
)
842 ResCount
= DeviceNode
->BootResourceList
->Count
;
845 ListSize
= sizeof(CM_RESOURCE_LIST
) +
846 ((ResCount
- 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
848 RtlInitUnicodeString(&KeyName
,
850 Status
= NtSetValueKey(LogConfKey
,
854 &DeviceNode
->BootResourceList
,
859 /* Set 'BasicConfigVector' value */
860 if (DeviceNode
->ResourceRequirementsList
!= NULL
&&
861 DeviceNode
->ResourceRequirementsList
->ListSize
!= 0)
863 RtlInitUnicodeString(&KeyName
,
864 L
"BasicConfigVector");
865 Status
= NtSetValueKey(LogConfKey
,
868 REG_RESOURCE_REQUIREMENTS_LIST
,
869 &DeviceNode
->ResourceRequirementsList
,
870 DeviceNode
->ResourceRequirementsList
->ListSize
);
876 DPRINT("IopSetDeviceInstanceData() done\n");
878 return STATUS_SUCCESS
;
883 * IopActionInterrogateDeviceStack
885 * Retrieve information for all (direct) child nodes of a parent node.
889 * Pointer to device node.
891 * Pointer to parent node to retrieve child node information for.
894 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
895 * when we reach a device node which is not a direct child of the device
896 * node for which we retrieve information of child nodes for. Any errors
897 * that occur is logged instead so that all child services have a chance
898 * of being interrogated.
902 IopActionInterrogateDeviceStack(
903 PDEVICE_NODE DeviceNode
,
906 IO_STATUS_BLOCK IoStatusBlock
;
907 PDEVICE_NODE ParentDeviceNode
;
908 WCHAR InstancePath
[MAX_PATH
];
909 IO_STACK_LOCATION Stack
;
915 HANDLE InstanceKey
= NULL
;
916 UNICODE_STRING ValueName
;
918 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
919 DPRINT("PDO %x\n", DeviceNode
->Pdo
);
921 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
924 * We are called for the parent too, but we don't need to do special
925 * handling for this node
928 if (DeviceNode
== ParentDeviceNode
)
931 return STATUS_SUCCESS
;
935 * Make sure this device node is a direct child of the parent device node
936 * that is given as an argument
939 if (DeviceNode
->Parent
!= ParentDeviceNode
)
941 /* Stop the traversal immediately and indicate successful operation */
943 return STATUS_UNSUCCESSFUL
;
947 * FIXME: For critical errors, cleanup and disable device, but always
948 * return STATUS_SUCCESS.
951 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
953 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
954 Status
= IopInitiatePnpIrp(
959 if (NT_SUCCESS(Status
))
961 /* Copy the device id string */
962 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
965 * FIXME: Check for valid characters, if there is invalid characters
971 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
974 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
976 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
977 Status
= IopInitiatePnpIrp(
982 if (NT_SUCCESS(Status
))
984 /* Append the instance id string */
985 wcscat(InstancePath
, L
"\\");
986 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
989 * FIXME: Check for valid characters, if there is invalid characters
995 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
998 Status
= IopQueryCapabilities(DeviceNode
->Pdo
, &DeviceNode
->CapabilityFlags
);
999 if (NT_SUCCESS(Status
))
1006 if (!DeviceNode
->CapabilityFlags
->UniqueID
)
1008 DPRINT("Instance ID is not unique\n");
1009 /* FIXME: Add information from parent bus driver to InstancePath */
1012 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
))
1014 DPRINT("No resources\n");
1015 /* FIXME: Cleanup and disable device */
1018 DPRINT1("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1021 * Create registry key for the instance id, if it doesn't exist yet
1023 KeyBuffer
= ExAllocatePool(
1025 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1026 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1027 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1028 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1030 ExFreePool(KeyBuffer
);
1031 if (!NT_SUCCESS(Status
))
1033 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1037 if (DeviceNode
->CapabilityFlags
!= NULL
)
1039 /* Set 'Capabilities' value */
1040 RtlInitUnicodeString(&ValueName
,
1042 Status
= NtSetValueKey(InstanceKey
,
1046 (PVOID
)((ULONG_PTR
)&DeviceNode
->CapabilityFlags
+ 4),
1049 /* Set 'UINumber' value */
1050 if (DeviceNode
->CapabilityFlags
->UINumber
!= (ULONG
)-1)
1052 RtlInitUnicodeString(&ValueName
,
1054 Status
= NtSetValueKey(InstanceKey
,
1058 &DeviceNode
->CapabilityFlags
->UINumber
,
1063 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1065 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1066 Status
= IopInitiatePnpIrp(
1071 if (NT_SUCCESS(Status
))
1074 * FIXME: Check for valid characters, if there is invalid characters
1078 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1079 DPRINT("Hardware IDs:\n");
1082 DPRINT(" %S\n", Ptr
);
1083 Length
= wcslen(Ptr
) + 1;
1086 TotalLength
+= Length
;
1088 DPRINT("TotalLength: %hu\n", TotalLength
);
1091 RtlInitUnicodeString(&ValueName
,
1093 Status
= NtSetValueKey(InstanceKey
,
1097 (PVOID
)IoStatusBlock
.Information
,
1098 (TotalLength
+ 1) * sizeof(WCHAR
));
1099 if (!NT_SUCCESS(Status
))
1101 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1106 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1109 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1111 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1112 Status
= IopInitiatePnpIrp(
1117 if (NT_SUCCESS(Status
))
1120 * FIXME: Check for valid characters, if there is invalid characters
1124 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1125 DPRINT("Compatible IDs:\n");
1128 DPRINT(" %S\n", Ptr
);
1129 Length
= wcslen(Ptr
) + 1;
1132 TotalLength
+= Length
;
1134 DPRINT("TotalLength: %hu\n", TotalLength
);
1137 RtlInitUnicodeString(&ValueName
,
1139 Status
= NtSetValueKey(InstanceKey
,
1143 (PVOID
)IoStatusBlock
.Information
,
1144 (TotalLength
+ 1) * sizeof(WCHAR
));
1145 if (!NT_SUCCESS(Status
))
1147 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1152 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1156 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1158 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1159 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
1160 Status
= IopInitiatePnpIrp(
1163 IRP_MN_QUERY_DEVICE_TEXT
,
1165 if (NT_SUCCESS(Status
))
1167 RtlInitUnicodeString(&ValueName
,
1169 Status
= NtSetValueKey(InstanceKey
,
1173 (PVOID
)IoStatusBlock
.Information
,
1174 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1175 if (!NT_SUCCESS(Status
))
1177 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1182 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1185 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1187 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1188 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
1189 Status
= IopInitiatePnpIrp(
1192 IRP_MN_QUERY_DEVICE_TEXT
,
1194 if (NT_SUCCESS(Status
))
1196 DPRINT("LocationInformation: %wZ\n", &DeviceNode
->DeviceTextLocation
);
1197 RtlInitUnicodeString(&ValueName
,
1198 L
"LocationInformation");
1199 Status
= NtSetValueKey(InstanceKey
,
1203 (PVOID
)IoStatusBlock
.Information
,
1204 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1205 if (!NT_SUCCESS(Status
))
1207 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1212 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1215 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1217 Status
= IopInitiatePnpIrp(
1220 IRP_MN_QUERY_BUS_INFORMATION
,
1222 if (NT_SUCCESS(Status
))
1224 DeviceNode
->BusInformation
=
1225 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1229 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1230 DeviceNode
->BusInformation
= NULL
;
1233 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1235 Status
= IopInitiatePnpIrp(
1238 IRP_MN_QUERY_RESOURCES
,
1240 if (NT_SUCCESS(Status
))
1242 DeviceNode
->BootResourceList
=
1243 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1244 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1248 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1249 DeviceNode
->BootResourceList
= NULL
;
1252 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1254 Status
= IopInitiatePnpIrp(
1257 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1259 if (NT_SUCCESS(Status
))
1261 DeviceNode
->ResourceRequirementsList
=
1262 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1266 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1267 DeviceNode
->ResourceRequirementsList
= NULL
;
1271 if (InstanceKey
!= NULL
)
1273 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1276 NtClose(InstanceKey
);
1278 DeviceNode
->Flags
|= DNF_PROCESSED
;
1280 return STATUS_SUCCESS
;
1284 * IopActionConfigureChildServices
1286 * Retrieve configuration for all (direct) child nodes of a parent node.
1290 * Pointer to device node.
1292 * Pointer to parent node to retrieve child node configuration for.
1295 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1296 * when we reach a device node which is not a direct child of the device
1297 * node for which we configure child services for. Any errors that occur is
1298 * logged instead so that all child services have a chance of beeing
1303 IopActionConfigureChildServices(
1304 PDEVICE_NODE DeviceNode
,
1307 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1308 PDEVICE_NODE ParentDeviceNode
;
1309 PUNICODE_STRING Service
;
1312 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1314 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1317 * We are called for the parent too, but we don't need to do special
1318 * handling for this node
1320 if (DeviceNode
== ParentDeviceNode
)
1322 DPRINT("Success\n");
1323 return STATUS_SUCCESS
;
1327 * Make sure this device node is a direct child of the parent device node
1328 * that is given as an argument
1330 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1332 /* Stop the traversal immediately and indicate successful operation */
1334 return STATUS_UNSUCCESSFUL
;
1337 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1340 * Retrieve configuration from Enum key
1343 Service
= &DeviceNode
->ServiceName
;
1345 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1346 RtlInitUnicodeString(Service
, NULL
);
1348 QueryTable
[0].Name
= L
"Service";
1349 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1350 QueryTable
[0].EntryContext
= Service
;
1352 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ENUM
,
1353 DeviceNode
->InstancePath
.Buffer
, QueryTable
, NULL
, NULL
);
1355 if (!NT_SUCCESS(Status
))
1357 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1358 /* FIXME: Log the error */
1359 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1360 DeviceNode
->InstancePath
.Buffer
, Status
);
1361 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1362 return STATUS_SUCCESS
;
1365 if (Service
->Buffer
== NULL
)
1367 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1368 return STATUS_SUCCESS
;
1371 DPRINT("Got Service %S\n", Service
->Buffer
);
1374 return STATUS_SUCCESS
;
1378 * IopActionInitChildServices
1380 * Initialize the service for all (direct) child nodes of a parent node
1384 * Pointer to device node.
1386 * Pointer to parent node to initialize child node services for.
1388 * Load only driver marked as boot start.
1391 * If the driver image for a service is not loaded and initialized
1392 * it is done here too. We only return a status code indicating an
1393 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1394 * not a direct child of the device node for which we initialize
1395 * child services for. Any errors that occur is logged instead so
1396 * that all child services have a chance of being initialized.
1400 IopActionInitChildServices(
1401 PDEVICE_NODE DeviceNode
,
1403 BOOLEAN BootDrivers
)
1405 PDEVICE_NODE ParentDeviceNode
;
1408 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1411 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1414 * We are called for the parent too, but we don't need to do special
1415 * handling for this node
1417 if (DeviceNode
== ParentDeviceNode
)
1419 DPRINT("Success\n");
1420 return STATUS_SUCCESS
;
1424 * Make sure this device node is a direct child of the parent device node
1425 * that is given as an argument
1428 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1431 * Stop the traversal immediately and indicate unsuccessful operation
1434 return STATUS_UNSUCCESSFUL
;
1438 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1439 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1440 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1442 PMODULE_OBJECT ModuleObject
;
1443 PDRIVER_OBJECT DriverObject
;
1445 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1446 if (NT_SUCCESS(Status
))
1448 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
1449 if (NT_SUCCESS(Status
))
1451 /* Attach lower level filter drivers. */
1452 IopAttachFilterDrivers(DeviceNode
, TRUE
);
1453 /* Initialize the function driver for the device node */
1454 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1455 if (NT_SUCCESS(Status
))
1457 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1458 /* Attach upper level filter drivers. */
1459 IopAttachFilterDrivers(DeviceNode
, FALSE
);
1466 * Don't disable when trying to load only boot drivers
1470 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1471 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1473 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1474 CPRINT("Initialization of service %S failed (Status %x)\n",
1475 DeviceNode
->ServiceName
.Buffer
, Status
);
1479 DPRINT("Service %S is disabled or already initialized\n",
1480 DeviceNode
->ServiceName
.Buffer
);
1483 return STATUS_SUCCESS
;
1487 * IopActionInitAllServices
1489 * Initialize the service for all (direct) child nodes of a parent node. This
1490 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1494 IopActionInitAllServices(
1495 PDEVICE_NODE DeviceNode
,
1498 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1502 * IopActionInitBootServices
1504 * Initialize the boot start services for all (direct) child nodes of a
1505 * parent node. This function just calls IopActionInitChildServices with
1506 * BootDrivers = TRUE.
1510 IopActionInitBootServices(
1511 PDEVICE_NODE DeviceNode
,
1514 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1518 * IopInitializePnpServices
1520 * Initialize services for discovered children
1524 * Top device node to start initializing services.
1527 * When set to TRUE, only drivers marked as boot start will
1528 * be loaded. Otherwise, all drivers will be loaded.
1535 IopInitializePnpServices(
1536 IN PDEVICE_NODE DeviceNode
,
1537 IN BOOLEAN BootDrivers
)
1539 DEVICETREE_TRAVERSE_CONTEXT Context
;
1541 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1545 IopInitDeviceTreeTraverseContext(
1548 IopActionInitBootServices
,
1552 IopInitDeviceTreeTraverseContext(
1555 IopActionInitAllServices
,
1559 return IopTraverseDeviceTree(&Context
);
1564 IopInvalidateDeviceRelations(
1565 IN PDEVICE_NODE DeviceNode
,
1566 IN DEVICE_RELATION_TYPE Type
)
1568 DEVICETREE_TRAVERSE_CONTEXT Context
;
1569 PDEVICE_RELATIONS DeviceRelations
;
1570 IO_STATUS_BLOCK IoStatusBlock
;
1571 PDEVICE_NODE ChildDeviceNode
;
1572 IO_STACK_LOCATION Stack
;
1574 OBJECT_ATTRIBUTES ObjectAttributes
;
1575 UNICODE_STRING LinkName
;
1580 DPRINT("DeviceNode %x\n", DeviceNode
);
1582 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1584 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1586 Status
= IopInitiatePnpIrp(
1589 IRP_MN_QUERY_DEVICE_RELATIONS
,
1591 if (!NT_SUCCESS(Status
))
1593 DPRINT("IopInitiatePnpIrp() failed\n");
1597 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1599 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1601 DPRINT("No PDOs\n");
1602 if (DeviceRelations
)
1604 ExFreePool(DeviceRelations
);
1606 return STATUS_SUCCESS
;
1609 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1612 * Create device nodes for all discovered devices
1615 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1617 Status
= IopCreateDeviceNode(
1619 DeviceRelations
->Objects
[i
],
1621 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1622 if (!NT_SUCCESS(Status
))
1624 DPRINT("No resources\n");
1625 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1626 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1627 ExFreePool(DeviceRelations
);
1628 return STATUS_INSUFFICIENT_RESOURCES
;
1631 ExFreePool(DeviceRelations
);
1634 * Retrieve information about all discovered children from the bus driver
1637 IopInitDeviceTreeTraverseContext(
1640 IopActionInterrogateDeviceStack
,
1643 Status
= IopTraverseDeviceTree(&Context
);
1644 if (!NT_SUCCESS(Status
))
1646 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1651 * Retrieve configuration from the registry for discovered children
1654 IopInitDeviceTreeTraverseContext(
1657 IopActionConfigureChildServices
,
1660 Status
= IopTraverseDeviceTree(&Context
);
1661 if (!NT_SUCCESS(Status
))
1663 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1668 * Get the state of the system boot. If the \\SystemRoot link isn't
1669 * created yet, we will assume that it's possible to load only boot
1673 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
1675 InitializeObjectAttributes(
1682 Status
= NtOpenFile(
1690 BootDrivers
= NT_SUCCESS(Status
) ? FALSE
: TRUE
;
1695 * Initialize services for discovered children. Only boot drivers will
1696 * be loaded from boot driver!
1699 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
1700 if (!NT_SUCCESS(Status
))
1702 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
1706 return STATUS_SUCCESS
;
1716 DPRINT("PnpInit()\n");
1718 KeInitializeSpinLock(&IopDeviceTreeLock
);
1721 * Create root device node
1724 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, FALSE
, NULL
, 0);
1725 if (!NT_SUCCESS(Status
))
1727 CPRINT("IoCreateDriverObject() failed\n");
1728 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1731 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
1733 if (!NT_SUCCESS(Status
))
1735 CPRINT("IoCreateDevice() failed\n");
1736 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1739 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
1740 if (!NT_SUCCESS(Status
))
1742 CPRINT("Insufficient resources\n");
1743 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1746 IopRootDeviceNode
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1747 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1748 IopRootDriverObject
->DriverExtension
->AddDevice(
1749 IopRootDriverObject
,
1750 IopRootDeviceNode
->Pdo
);