1 /* $Id: pnpmgr.c,v 1.43 2004/10/22 20:25:54 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 if (DeviceNode
->BusInformation
== NULL
)
80 return STATUS_INVALID_DEVICE_REQUEST
;
81 Length
= sizeof(ULONG
);
82 Data
= &DeviceNode
->BusInformation
->BusNumber
;
85 /* Complete, untested */
86 case DevicePropertyBusTypeGuid
:
87 if (DeviceNode
->BusInformation
== NULL
)
88 return STATUS_INVALID_DEVICE_REQUEST
;
89 *ResultLength
= 39 * sizeof(WCHAR
);
90 if (BufferLength
< (39 * sizeof(WCHAR
)))
91 return STATUS_BUFFER_TOO_SMALL
;
92 swprintf((PWSTR
)PropertyBuffer
,
93 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
94 DeviceNode
->BusInformation
->BusTypeGuid
.Data1
,
95 DeviceNode
->BusInformation
->BusTypeGuid
.Data2
,
96 DeviceNode
->BusInformation
->BusTypeGuid
.Data3
,
97 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[0],
98 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[1],
99 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[2],
100 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[3],
101 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[4],
102 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[5],
103 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[6],
104 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[7]);
105 return STATUS_SUCCESS
;
107 case DevicePropertyLegacyBusType
:
108 if (DeviceNode
->BusInformation
== NULL
)
109 return STATUS_INVALID_DEVICE_REQUEST
;
110 Length
= sizeof(INTERFACE_TYPE
);
111 Data
= &DeviceNode
->BusInformation
->LegacyBusType
;
114 case DevicePropertyAddress
:
115 if (DeviceNode
->CapabilityFlags
== NULL
)
116 return STATUS_INVALID_DEVICE_REQUEST
;
117 Length
= sizeof(ULONG
);
118 Data
= &DeviceNode
->CapabilityFlags
->Address
;
121 case DevicePropertyUINumber
:
122 if (DeviceNode
->CapabilityFlags
== NULL
)
123 return STATUS_INVALID_DEVICE_REQUEST
;
124 Length
= sizeof(ULONG
);
125 Data
= &DeviceNode
->CapabilityFlags
->UINumber
;
128 case DevicePropertyClassName
:
129 case DevicePropertyClassGuid
:
130 case DevicePropertyDriverKeyName
:
131 case DevicePropertyManufacturer
:
132 case DevicePropertyFriendlyName
:
133 case DevicePropertyHardwareID
:
134 case DevicePropertyCompatibleIDs
:
135 case DevicePropertyDeviceDescription
:
136 case DevicePropertyLocationInformation
:
138 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
139 UNICODE_STRING KeyName
, ValueName
;
140 OBJECT_ATTRIBUTES ObjectAttributes
;
141 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
142 ULONG ValueInformationLength
;
146 switch (DeviceProperty
)
148 case DevicePropertyClassName
:
149 RegistryPropertyName
= L
"Class"; break;
150 case DevicePropertyClassGuid
:
151 RegistryPropertyName
= L
"ClassGuid"; break;
152 case DevicePropertyDriverKeyName
:
153 RegistryPropertyName
= L
"Driver"; break;
154 case DevicePropertyManufacturer
:
155 RegistryPropertyName
= L
"Mfg"; break;
156 case DevicePropertyFriendlyName
:
157 RegistryPropertyName
= L
"FriendlyName"; break;
158 case DevicePropertyHardwareID
:
159 RegistryPropertyName
= L
"HardwareID"; break;
160 case DevicePropertyCompatibleIDs
:
161 RegistryPropertyName
= L
"CompatibleIDs"; break;
162 case DevicePropertyDeviceDescription
:
163 RegistryPropertyName
= L
"DeviceDesc"; break;
164 case DevicePropertyLocationInformation
:
165 RegistryPropertyName
= L
"LocationInformation"; break;
167 RegistryPropertyName
= NULL
; break;
170 KeyNameBuffer
= ExAllocatePool(PagedPool
,
171 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
173 DPRINT1("KeyNameBuffer: %x, value %S\n",
174 KeyNameBuffer
, RegistryPropertyName
);
176 if (KeyNameBuffer
== NULL
)
177 return STATUS_INSUFFICIENT_RESOURCES
;
179 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
180 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
181 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
182 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
183 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
185 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
186 ExFreePool(KeyNameBuffer
);
187 if (!NT_SUCCESS(Status
))
190 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
191 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
192 Data
[0]) + BufferLength
;
193 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
194 if (ValueInformation
== NULL
)
197 return STATUS_INSUFFICIENT_RESOURCES
;
200 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
201 KeyValuePartialInformation
, ValueInformation
,
202 ValueInformationLength
,
203 &ValueInformationLength
);
204 *ResultLength
= ValueInformation
->DataLength
;
207 if (ValueInformation
->DataLength
> BufferLength
)
208 Status
= STATUS_BUFFER_TOO_SMALL
;
210 if (!NT_SUCCESS(Status
))
212 ExFreePool(ValueInformation
);
216 /* FIXME: Verify the value (NULL-terminated, correct format). */
218 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
219 ValueInformation
->DataLength
);
220 ExFreePool(ValueInformation
);
222 return STATUS_SUCCESS
;
225 case DevicePropertyBootConfiguration
:
227 if (DeviceNode
->BootResourceList
->Count
!= 0)
229 Length
= sizeof(CM_RESOURCE_LIST
) +
230 ((DeviceNode
->BootResourceList
->Count
- 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
232 Data
= &DeviceNode
->BootResourceList
;
235 /* FIXME: use a translated boot configuration instead */
236 case DevicePropertyBootConfigurationTranslated
:
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 case DevicePropertyEnumeratorName
:
247 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
250 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
258 case DevicePropertyPhysicalDeviceObjectName
:
259 return STATUS_NOT_IMPLEMENTED
;
262 return STATUS_INVALID_PARAMETER_2
;
265 *ResultLength
= Length
;
266 if (BufferLength
< Length
)
267 return STATUS_BUFFER_TOO_SMALL
;
268 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
270 /* Terminate the string */
271 if (DeviceProperty
== DevicePropertyEnumeratorName
)
273 Ptr
= (PWSTR
)PropertyBuffer
;
274 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
277 return STATUS_SUCCESS
;
285 IoInvalidateDeviceState(
286 IN PDEVICE_OBJECT PhysicalDeviceObject
)
295 IoOpenDeviceRegistryKey(
296 IN PDEVICE_OBJECT DeviceObject
,
297 IN ULONG DevInstKeyType
,
298 IN ACCESS_MASK DesiredAccess
,
299 OUT PHANDLE DevInstRegKey
)
301 static const WCHAR ClassKeyName
[] = {
302 '\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
303 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t',
304 'r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\',
305 'C','l','a','s','s','\\'};
306 LPWSTR KeyNameBuffer
;
307 UNICODE_STRING KeyName
;
308 ULONG DriverKeyLength
;
309 OBJECT_ATTRIBUTES ObjectAttributes
;
312 if (DevInstKeyType
== PLUGPLAY_REGKEY_DRIVER
)
314 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
315 0, NULL
, &DriverKeyLength
);
316 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
319 KeyNameBuffer
= ExAllocatePool(PagedPool
, DriverKeyLength
+ sizeof(ClassKeyName
));
320 if (KeyNameBuffer
== NULL
)
321 return STATUS_INSUFFICIENT_RESOURCES
;
323 RtlCopyMemory(KeyNameBuffer
, ClassKeyName
, sizeof(ClassKeyName
));
324 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
325 DriverKeyLength
, KeyNameBuffer
+
326 (sizeof(ClassKeyName
) / sizeof(WCHAR
)),
328 if (!NT_SUCCESS(Status
))
330 ExFreePool(KeyNameBuffer
);
334 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
335 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
336 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
337 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
338 ExFreePool(KeyNameBuffer
);
342 return STATUS_NOT_IMPLEMENTED
;
350 IoRequestDeviceEject(
351 IN PDEVICE_OBJECT PhysicalDeviceObject
359 IopCreateUnicodeString(
360 PUNICODE_STRING Destination
,
368 RtlInitUnicodeString(Destination
, NULL
);
372 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
374 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
376 if (Destination
->Buffer
== NULL
)
381 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
383 Destination
->MaximumLength
= Length
;
385 Destination
->Length
= Length
- sizeof(WCHAR
);
391 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
395 if (PopSystemPowerDeviceNode
)
397 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
398 *DeviceObject
= PopSystemPowerDeviceNode
->Pdo
;
399 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
401 return STATUS_SUCCESS
;
404 return STATUS_UNSUCCESSFUL
;
407 /**********************************************************************
409 * Creates a device node
412 * ParentNode = Pointer to parent device node
413 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
414 * to have the root device node create one
415 * (eg. for legacy drivers)
416 * DeviceNode = Pointer to storage for created device node
422 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
423 PDEVICE_OBJECT PhysicalDeviceObject
,
424 PDEVICE_NODE
*DeviceNode
)
430 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
431 ParentNode
, PhysicalDeviceObject
);
433 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
436 return STATUS_INSUFFICIENT_RESOURCES
;
439 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
441 if (!PhysicalDeviceObject
)
443 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
444 if (!NT_SUCCESS(Status
))
450 /* This is for drivers passed on the command line to ntoskrnl.exe */
451 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
452 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
455 Node
->Pdo
= PhysicalDeviceObject
;
457 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
461 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
462 Node
->Parent
= ParentNode
;
463 Node
->NextSibling
= ParentNode
->Child
;
464 if (ParentNode
->Child
!= NULL
)
466 ParentNode
->Child
->PrevSibling
= Node
;
468 ParentNode
->Child
= Node
;
469 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
474 return STATUS_SUCCESS
;
478 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
482 /* All children must be deleted before a parent is deleted */
483 ASSERT(!DeviceNode
->Child
);
485 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
487 ASSERT(DeviceNode
->Pdo
);
489 ObDereferenceObject(DeviceNode
->Pdo
);
491 /* Unlink from parent if it exists */
493 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
495 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
498 /* Unlink from sibling list */
500 if (DeviceNode
->PrevSibling
)
502 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
505 if (DeviceNode
->NextSibling
)
507 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
510 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
512 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
514 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
516 if (DeviceNode
->CapabilityFlags
)
518 ExFreePool(DeviceNode
->CapabilityFlags
);
521 if (DeviceNode
->CmResourceList
)
523 ExFreePool(DeviceNode
->CmResourceList
);
526 if (DeviceNode
->BootResourceList
)
528 ExFreePool(DeviceNode
->BootResourceList
);
531 if (DeviceNode
->ResourceRequirementsList
)
533 ExFreePool(DeviceNode
->ResourceRequirementsList
);
536 if (DeviceNode
->BusInformation
)
538 ExFreePool(DeviceNode
->BusInformation
);
541 ExFreePool(DeviceNode
);
543 return STATUS_SUCCESS
;
548 PDEVICE_OBJECT DeviceObject
,
549 PIO_STATUS_BLOCK IoStatusBlock
,
551 PIO_STACK_LOCATION Stack OPTIONAL
)
553 PDEVICE_OBJECT TopDeviceObject
;
554 PIO_STACK_LOCATION IrpSp
;
559 /* Always call the top of the device stack */
560 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
567 Irp
= IoBuildSynchronousFsdRequest(
576 /* PNP IRPs are always initialized with a status code of
577 STATUS_NOT_IMPLEMENTED */
578 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
579 Irp
->IoStatus
.Information
= 0;
581 IrpSp
= IoGetNextIrpStackLocation(Irp
);
582 IrpSp
->MinorFunction
= MinorFunction
;
589 sizeof(Stack
->Parameters
));
592 Status
= IoCallDriver(TopDeviceObject
, Irp
);
593 if (Status
== STATUS_PENDING
)
595 KeWaitForSingleObject(
601 Status
= IoStatusBlock
->Status
;
604 ObDereferenceObject(TopDeviceObject
);
611 IopQueryCapabilities(
613 PDEVICE_CAPABILITIES
*Capabilities
)
615 IO_STATUS_BLOCK IoStatusBlock
;
616 PDEVICE_CAPABILITIES Caps
;
617 IO_STACK_LOCATION Stack
;
620 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
622 *Capabilities
= NULL
;
624 Caps
= ExAllocatePool(PagedPool
, sizeof(DEVICE_CAPABILITIES
));
627 return STATUS_INSUFFICIENT_RESOURCES
;
630 RtlZeroMemory(Caps
, sizeof(DEVICE_CAPABILITIES
));
631 Caps
->Size
= sizeof(DEVICE_CAPABILITIES
);
636 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= Caps
;
638 Status
= IopInitiatePnpIrp(
641 IRP_MN_QUERY_CAPABILITIES
,
643 if (NT_SUCCESS(Status
))
645 *Capabilities
= Caps
;
649 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
657 IopTraverseDeviceTreeNode(
658 PDEVICETREE_TRAVERSE_CONTEXT Context
)
660 PDEVICE_NODE ParentDeviceNode
;
661 PDEVICE_NODE ChildDeviceNode
;
664 /* Copy context data so we don't overwrite it in subsequent calls to this function */
665 ParentDeviceNode
= Context
->DeviceNode
;
667 /* Call the action routine */
668 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
669 if (!NT_SUCCESS(Status
))
674 /* Traversal of all children nodes */
675 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
676 ChildDeviceNode
!= NULL
;
677 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
679 /* Pass the current device node to the action routine */
680 Context
->DeviceNode
= ChildDeviceNode
;
682 Status
= IopTraverseDeviceTreeNode(Context
);
683 if (!NT_SUCCESS(Status
))
694 IopTraverseDeviceTree(
695 PDEVICETREE_TRAVERSE_CONTEXT Context
)
699 DPRINT("Context %x\n", Context
);
701 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
702 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
704 /* Start from the specified device node */
705 Context
->DeviceNode
= Context
->FirstDeviceNode
;
707 /* Recursively traverse the device tree */
708 Status
= IopTraverseDeviceTreeNode(Context
);
709 if (Status
== STATUS_UNSUCCESSFUL
)
711 /* The action routine just wanted to terminate the traversal with status
712 code STATUS_SUCCESS */
713 Status
= STATUS_SUCCESS
;
721 IopCreateDeviceKeyPath(PWSTR Path
,
724 OBJECT_ATTRIBUTES ObjectAttributes
;
725 WCHAR KeyBuffer
[MAX_PATH
];
726 UNICODE_STRING KeyName
;
734 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
736 return STATUS_INVALID_PARAMETER
;
739 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
740 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
742 /* Skip \\Registry\\ */
743 Current
= KeyName
.Buffer
;
744 Current
= wcschr (Current
, '\\') + 1;
745 Current
= wcschr (Current
, '\\') + 1;
749 Next
= wcschr (Current
, '\\');
759 InitializeObjectAttributes (&ObjectAttributes
,
761 OBJ_CASE_INSENSITIVE
,
765 DPRINT("Create '%S'\n", KeyName
.Buffer
);
767 Status
= NtCreateKey (&KeyHandle
,
774 if (!NT_SUCCESS (Status
))
776 DPRINT ("NtCreateKey() failed with status %x\n", Status
);
783 return STATUS_SUCCESS
;
794 return STATUS_UNSUCCESSFUL
;
799 IopSetDeviceInstanceData(HANDLE InstanceKey
,
800 PDEVICE_NODE DeviceNode
)
802 OBJECT_ATTRIBUTES ObjectAttributes
;
803 UNICODE_STRING KeyName
;
809 DPRINT("IopSetDeviceInstanceData() called\n");
811 /* Create the 'LogConf' key */
812 RtlInitUnicodeString(&KeyName
,
814 InitializeObjectAttributes(&ObjectAttributes
,
816 OBJ_CASE_INSENSITIVE
,
819 Status
= NtCreateKey(&LogConfKey
,
826 if (NT_SUCCESS(Status
))
828 /* Set 'BootConfig' value */
829 if (DeviceNode
->BootResourceList
!= NULL
)
831 ResCount
= DeviceNode
->BootResourceList
->Count
;
834 ListSize
= sizeof(CM_RESOURCE_LIST
) +
835 ((ResCount
- 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
837 RtlInitUnicodeString(&KeyName
,
839 Status
= NtSetValueKey(LogConfKey
,
843 &DeviceNode
->BootResourceList
,
848 /* Set 'BasicConfigVector' value */
849 if (DeviceNode
->ResourceRequirementsList
!= NULL
&&
850 DeviceNode
->ResourceRequirementsList
->ListSize
!= 0)
852 RtlInitUnicodeString(&KeyName
,
853 L
"BasicConfigVector");
854 Status
= NtSetValueKey(LogConfKey
,
857 REG_RESOURCE_REQUIREMENTS_LIST
,
858 &DeviceNode
->ResourceRequirementsList
,
859 DeviceNode
->ResourceRequirementsList
->ListSize
);
865 DPRINT("IopSetDeviceInstanceData() done\n");
867 return STATUS_SUCCESS
;
872 * IopActionInterrogateDeviceStack
874 * Retrieve information for all (direct) child nodes of a parent node.
878 * Pointer to device node.
880 * Pointer to parent node to retrieve child node information for.
883 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
884 * when we reach a device node which is not a direct child of the device
885 * node for which we retrieve information of child nodes for. Any errors
886 * that occur is logged instead so that all child services have a chance
887 * of being interrogated.
891 IopActionInterrogateDeviceStack(
892 PDEVICE_NODE DeviceNode
,
895 IO_STATUS_BLOCK IoStatusBlock
;
896 PDEVICE_NODE ParentDeviceNode
;
897 WCHAR InstancePath
[MAX_PATH
];
898 IO_STACK_LOCATION Stack
;
904 HANDLE InstanceKey
= NULL
;
905 UNICODE_STRING ValueName
;
907 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
908 DPRINT("PDO %x\n", DeviceNode
->Pdo
);
910 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
913 * We are called for the parent too, but we don't need to do special
914 * handling for this node
917 if (DeviceNode
== ParentDeviceNode
)
920 return STATUS_SUCCESS
;
924 * Make sure this device node is a direct child of the parent device node
925 * that is given as an argument
928 if (DeviceNode
->Parent
!= ParentDeviceNode
)
930 /* Stop the traversal immediately and indicate successful operation */
932 return STATUS_UNSUCCESSFUL
;
936 * FIXME: For critical errors, cleanup and disable device, but always
937 * return STATUS_SUCCESS.
940 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
942 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
943 Status
= IopInitiatePnpIrp(
948 if (NT_SUCCESS(Status
))
950 /* Copy the device id string */
951 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
954 * FIXME: Check for valid characters, if there is invalid characters
960 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
963 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
965 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
966 Status
= IopInitiatePnpIrp(
971 if (NT_SUCCESS(Status
))
973 /* Append the instance id string */
974 wcscat(InstancePath
, L
"\\");
975 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
978 * FIXME: Check for valid characters, if there is invalid characters
984 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
987 Status
= IopQueryCapabilities(DeviceNode
->Pdo
, &DeviceNode
->CapabilityFlags
);
988 if (NT_SUCCESS(Status
))
995 if (!DeviceNode
->CapabilityFlags
->UniqueID
)
997 DPRINT("Instance ID is not unique\n");
998 /* FIXME: Add information from parent bus driver to InstancePath */
1001 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
))
1003 DPRINT("No resources\n");
1004 /* FIXME: Cleanup and disable device */
1007 DPRINT1("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1010 * Create registry key for the instance id, if it doesn't exist yet
1012 KeyBuffer
= ExAllocatePool(
1014 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1015 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1016 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1017 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1019 ExFreePool(KeyBuffer
);
1020 if (!NT_SUCCESS(Status
))
1022 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1026 if (DeviceNode
->CapabilityFlags
!= NULL
)
1028 /* Set 'Capabilities' value */
1029 RtlInitUnicodeString(&ValueName
,
1031 Status
= NtSetValueKey(InstanceKey
,
1035 (PVOID
)((ULONG_PTR
)&DeviceNode
->CapabilityFlags
+ 4),
1038 /* Set 'UINumber' value */
1039 if (DeviceNode
->CapabilityFlags
->UINumber
!= (ULONG
)-1)
1041 RtlInitUnicodeString(&ValueName
,
1043 Status
= NtSetValueKey(InstanceKey
,
1047 &DeviceNode
->CapabilityFlags
->UINumber
,
1052 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1054 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1055 Status
= IopInitiatePnpIrp(
1060 if (NT_SUCCESS(Status
))
1063 * FIXME: Check for valid characters, if there is invalid characters
1067 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1068 DPRINT("Hardware IDs:\n");
1071 DPRINT(" %S\n", Ptr
);
1072 Length
= wcslen(Ptr
) + 1;
1075 TotalLength
+= Length
;
1077 DPRINT("TotalLength: %hu\n", TotalLength
);
1080 RtlInitUnicodeString(&ValueName
,
1082 Status
= NtSetValueKey(InstanceKey
,
1086 (PVOID
)IoStatusBlock
.Information
,
1087 (TotalLength
+ 1) * sizeof(WCHAR
));
1088 if (!NT_SUCCESS(Status
))
1090 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1095 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1098 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1100 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1101 Status
= IopInitiatePnpIrp(
1106 if (NT_SUCCESS(Status
))
1109 * FIXME: Check for valid characters, if there is invalid characters
1113 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1114 DPRINT("Compatible IDs:\n");
1117 DPRINT(" %S\n", Ptr
);
1118 Length
= wcslen(Ptr
) + 1;
1121 TotalLength
+= Length
;
1123 DPRINT("TotalLength: %hu\n", TotalLength
);
1126 RtlInitUnicodeString(&ValueName
,
1128 Status
= NtSetValueKey(InstanceKey
,
1132 (PVOID
)IoStatusBlock
.Information
,
1133 (TotalLength
+ 1) * sizeof(WCHAR
));
1134 if (!NT_SUCCESS(Status
))
1136 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1141 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1145 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1147 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1148 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
1149 Status
= IopInitiatePnpIrp(
1152 IRP_MN_QUERY_DEVICE_TEXT
,
1154 if (NT_SUCCESS(Status
))
1156 RtlInitUnicodeString(&ValueName
,
1158 Status
= NtSetValueKey(InstanceKey
,
1162 (PVOID
)IoStatusBlock
.Information
,
1163 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1164 if (!NT_SUCCESS(Status
))
1166 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1171 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1174 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1176 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1177 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
1178 Status
= IopInitiatePnpIrp(
1181 IRP_MN_QUERY_DEVICE_TEXT
,
1183 if (NT_SUCCESS(Status
))
1185 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1186 RtlInitUnicodeString(&ValueName
,
1187 L
"LocationInformation");
1188 Status
= NtSetValueKey(InstanceKey
,
1192 (PVOID
)IoStatusBlock
.Information
,
1193 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1194 if (!NT_SUCCESS(Status
))
1196 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
1201 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1204 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1206 Status
= IopInitiatePnpIrp(
1209 IRP_MN_QUERY_BUS_INFORMATION
,
1211 if (NT_SUCCESS(Status
))
1213 DeviceNode
->BusInformation
=
1214 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1218 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1219 DeviceNode
->BusInformation
= NULL
;
1222 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1224 Status
= IopInitiatePnpIrp(
1227 IRP_MN_QUERY_RESOURCES
,
1229 if (NT_SUCCESS(Status
))
1231 DeviceNode
->BootResourceList
=
1232 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1233 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1237 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1238 DeviceNode
->BootResourceList
= NULL
;
1241 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1243 Status
= IopInitiatePnpIrp(
1246 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1248 if (NT_SUCCESS(Status
))
1250 DeviceNode
->ResourceRequirementsList
=
1251 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1255 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1256 DeviceNode
->ResourceRequirementsList
= NULL
;
1260 if (InstanceKey
!= NULL
)
1262 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1265 NtClose(InstanceKey
);
1267 DeviceNode
->Flags
|= DNF_PROCESSED
;
1269 return STATUS_SUCCESS
;
1273 * IopActionConfigureChildServices
1275 * Retrieve configuration for all (direct) child nodes of a parent node.
1279 * Pointer to device node.
1281 * Pointer to parent node to retrieve child node configuration for.
1284 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1285 * when we reach a device node which is not a direct child of the device
1286 * node for which we configure child services for. Any errors that occur is
1287 * logged instead so that all child services have a chance of beeing
1292 IopActionConfigureChildServices(
1293 PDEVICE_NODE DeviceNode
,
1296 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1297 PDEVICE_NODE ParentDeviceNode
;
1298 PUNICODE_STRING Service
;
1301 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1303 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1306 * We are called for the parent too, but we don't need to do special
1307 * handling for this node
1309 if (DeviceNode
== ParentDeviceNode
)
1311 DPRINT("Success\n");
1312 return STATUS_SUCCESS
;
1316 * Make sure this device node is a direct child of the parent device node
1317 * that is given as an argument
1319 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1321 /* Stop the traversal immediately and indicate successful operation */
1323 return STATUS_UNSUCCESSFUL
;
1326 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1329 * Retrieve configuration from Enum key
1332 Service
= &DeviceNode
->ServiceName
;
1334 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1335 RtlInitUnicodeString(Service
, NULL
);
1337 QueryTable
[0].Name
= L
"Service";
1338 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1339 QueryTable
[0].EntryContext
= Service
;
1341 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ENUM
,
1342 DeviceNode
->InstancePath
.Buffer
, QueryTable
, NULL
, NULL
);
1344 if (!NT_SUCCESS(Status
))
1346 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1347 /* FIXME: Log the error */
1348 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1349 DeviceNode
->InstancePath
.Buffer
, Status
);
1350 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1351 return STATUS_SUCCESS
;
1354 if (Service
->Buffer
== NULL
)
1356 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1357 return STATUS_SUCCESS
;
1360 DPRINT("Got Service %S\n", Service
->Buffer
);
1363 return STATUS_SUCCESS
;
1367 * IopActionInitChildServices
1369 * Initialize the service for all (direct) child nodes of a parent node
1373 * Pointer to device node.
1375 * Pointer to parent node to initialize child node services for.
1377 * Load only driver marked as boot start.
1380 * If the driver image for a service is not loaded and initialized
1381 * it is done here too. We only return a status code indicating an
1382 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1383 * not a direct child of the device node for which we initialize
1384 * child services for. Any errors that occur is logged instead so
1385 * that all child services have a chance of being initialized.
1389 IopActionInitChildServices(
1390 PDEVICE_NODE DeviceNode
,
1392 BOOLEAN BootDrivers
)
1394 PDEVICE_NODE ParentDeviceNode
;
1397 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1400 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1403 * We are called for the parent too, but we don't need to do special
1404 * handling for this node
1406 if (DeviceNode
== ParentDeviceNode
)
1408 DPRINT("Success\n");
1409 return STATUS_SUCCESS
;
1413 * Make sure this device node is a direct child of the parent device node
1414 * that is given as an argument
1417 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1420 * Stop the traversal immediately and indicate unsuccessful operation
1423 return STATUS_UNSUCCESSFUL
;
1427 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1428 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1429 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1431 PMODULE_OBJECT ModuleObject
;
1432 PDRIVER_OBJECT DriverObject
;
1434 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1435 if (NT_SUCCESS(Status
))
1437 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
1438 if (NT_SUCCESS(Status
))
1440 /* Attach lower level filter drivers. */
1441 IopAttachFilterDrivers(DeviceNode
, TRUE
);
1442 /* Initialize the function driver for the device node */
1443 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1444 if (NT_SUCCESS(Status
))
1446 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1447 /* Attach upper level filter drivers. */
1448 IopAttachFilterDrivers(DeviceNode
, FALSE
);
1455 * Don't disable when trying to load only boot drivers
1459 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1460 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1462 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1463 CPRINT("Initialization of service %S failed (Status %x)\n",
1464 DeviceNode
->ServiceName
.Buffer
, Status
);
1468 DPRINT("Service %S is disabled or already initialized\n",
1469 DeviceNode
->ServiceName
.Buffer
);
1472 return STATUS_SUCCESS
;
1476 * IopActionInitAllServices
1478 * Initialize the service for all (direct) child nodes of a parent node. This
1479 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1483 IopActionInitAllServices(
1484 PDEVICE_NODE DeviceNode
,
1487 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1491 * IopActionInitBootServices
1493 * Initialize the boot start services for all (direct) child nodes of a
1494 * parent node. This function just calls IopActionInitChildServices with
1495 * BootDrivers = TRUE.
1499 IopActionInitBootServices(
1500 PDEVICE_NODE DeviceNode
,
1503 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1507 * IopInitializePnpServices
1509 * Initialize services for discovered children
1513 * Top device node to start initializing services.
1516 * When set to TRUE, only drivers marked as boot start will
1517 * be loaded. Otherwise, all drivers will be loaded.
1524 IopInitializePnpServices(
1525 IN PDEVICE_NODE DeviceNode
,
1526 IN BOOLEAN BootDrivers
)
1528 DEVICETREE_TRAVERSE_CONTEXT Context
;
1530 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1534 IopInitDeviceTreeTraverseContext(
1537 IopActionInitBootServices
,
1541 IopInitDeviceTreeTraverseContext(
1544 IopActionInitAllServices
,
1548 return IopTraverseDeviceTree(&Context
);
1553 IopInvalidateDeviceRelations(
1554 IN PDEVICE_NODE DeviceNode
,
1555 IN DEVICE_RELATION_TYPE Type
)
1557 DEVICETREE_TRAVERSE_CONTEXT Context
;
1558 PDEVICE_RELATIONS DeviceRelations
;
1559 IO_STATUS_BLOCK IoStatusBlock
;
1560 PDEVICE_NODE ChildDeviceNode
;
1561 IO_STACK_LOCATION Stack
;
1563 OBJECT_ATTRIBUTES ObjectAttributes
;
1564 UNICODE_STRING LinkName
;
1569 DPRINT("DeviceNode %x\n", DeviceNode
);
1571 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1573 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1575 Status
= IopInitiatePnpIrp(
1578 IRP_MN_QUERY_DEVICE_RELATIONS
,
1580 if (!NT_SUCCESS(Status
))
1582 DPRINT("IopInitiatePnpIrp() failed\n");
1586 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1588 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1590 DPRINT("No PDOs\n");
1591 if (DeviceRelations
)
1593 ExFreePool(DeviceRelations
);
1595 return STATUS_SUCCESS
;
1598 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1601 * Create device nodes for all discovered devices
1604 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1606 Status
= IopCreateDeviceNode(
1608 DeviceRelations
->Objects
[i
],
1610 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1611 if (!NT_SUCCESS(Status
))
1613 DPRINT("No resources\n");
1614 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1615 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1616 ExFreePool(DeviceRelations
);
1617 return STATUS_INSUFFICIENT_RESOURCES
;
1620 ExFreePool(DeviceRelations
);
1623 * Retrieve information about all discovered children from the bus driver
1626 IopInitDeviceTreeTraverseContext(
1629 IopActionInterrogateDeviceStack
,
1632 Status
= IopTraverseDeviceTree(&Context
);
1633 if (!NT_SUCCESS(Status
))
1635 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1640 * Retrieve configuration from the registry for discovered children
1643 IopInitDeviceTreeTraverseContext(
1646 IopActionConfigureChildServices
,
1649 Status
= IopTraverseDeviceTree(&Context
);
1650 if (!NT_SUCCESS(Status
))
1652 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1657 * Get the state of the system boot. If the \\SystemRoot link isn't
1658 * created yet, we will assume that it's possible to load only boot
1662 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
1664 InitializeObjectAttributes(
1671 Status
= NtOpenFile(
1679 BootDrivers
= NT_SUCCESS(Status
) ? FALSE
: TRUE
;
1684 * Initialize services for discovered children. Only boot drivers will
1685 * be loaded from boot driver!
1688 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
1689 if (!NT_SUCCESS(Status
))
1691 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
1695 return STATUS_SUCCESS
;
1705 DPRINT("PnpInit()\n");
1707 KeInitializeSpinLock(&IopDeviceTreeLock
);
1710 * Create root device node
1713 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, FALSE
, NULL
, 0);
1714 if (!NT_SUCCESS(Status
))
1716 CPRINT("IoCreateDriverObject() failed\n");
1717 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1720 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
1722 if (!NT_SUCCESS(Status
))
1724 CPRINT("IoCreateDevice() failed\n");
1725 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1728 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
1729 if (!NT_SUCCESS(Status
))
1731 CPRINT("Insufficient resources\n");
1732 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1735 IopRootDeviceNode
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1736 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1737 IopRootDriverObject
->DriverExtension
->AddDevice(
1738 IopRootDriverObject
,
1739 IopRootDeviceNode
->Pdo
);