3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnpmgr.c
6 * PURPOSE: Initializes the PnP manager
8 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
11 /* INCLUDES ******************************************************************/
14 #include <ddk/wdmguid.h>
17 #include <internal/debug.h>
19 /* GLOBALS *******************************************************************/
21 PDEVICE_NODE IopRootDeviceNode
;
22 KSPIN_LOCK IopDeviceTreeLock
;
24 /* DATA **********************************************************************/
26 PDRIVER_OBJECT IopRootDriverObject
;
28 /* FUNCTIONS *****************************************************************/
35 IoInvalidateDeviceRelations(
36 IN PDEVICE_OBJECT DeviceObject
,
37 IN DEVICE_RELATION_TYPE Type
)
44 PDEVICE_OBJECT DeviceObject
)
46 return DeviceObject
->DeviceObjectExtension
->DeviceNode
;
55 IN PDEVICE_OBJECT DeviceObject
,
56 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
57 IN ULONG BufferLength
,
58 OUT PVOID PropertyBuffer
,
59 OUT PULONG ResultLength
)
61 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
66 DPRINT("IoGetDeviceProperty(%x %d)\n", DeviceObject
, DeviceProperty
);
68 if (DeviceNode
== NULL
)
69 return STATUS_INVALID_DEVICE_REQUEST
;
71 switch (DeviceProperty
)
73 case DevicePropertyBusNumber
:
74 Length
= sizeof(ULONG
);
75 Data
= &DeviceNode
->ChildBusNumber
;
78 /* Complete, untested */
79 case DevicePropertyBusTypeGuid
:
80 *ResultLength
= 39 * sizeof(WCHAR
);
81 if (BufferLength
< (39 * sizeof(WCHAR
)))
82 return STATUS_BUFFER_TOO_SMALL
;
83 swprintf((PWSTR
)PropertyBuffer
,
84 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
85 DeviceNode
->BusTypeGuid
.Data1
,
86 DeviceNode
->BusTypeGuid
.Data2
,
87 DeviceNode
->BusTypeGuid
.Data3
,
88 DeviceNode
->BusTypeGuid
.Data4
[0],
89 DeviceNode
->BusTypeGuid
.Data4
[1],
90 DeviceNode
->BusTypeGuid
.Data4
[2],
91 DeviceNode
->BusTypeGuid
.Data4
[3],
92 DeviceNode
->BusTypeGuid
.Data4
[4],
93 DeviceNode
->BusTypeGuid
.Data4
[5],
94 DeviceNode
->BusTypeGuid
.Data4
[6],
95 DeviceNode
->BusTypeGuid
.Data4
[7]);
96 return STATUS_SUCCESS
;
98 case DevicePropertyLegacyBusType
:
99 Length
= sizeof(INTERFACE_TYPE
);
100 Data
= &DeviceNode
->ChildInterfaceType
;
103 case DevicePropertyAddress
:
104 Length
= sizeof(ULONG
);
105 Data
= &DeviceNode
->Address
;
108 // case DevicePropertyUINumber:
109 // if (DeviceNode->CapabilityFlags == NULL)
110 // return STATUS_INVALID_DEVICE_REQUEST;
111 // Length = sizeof(ULONG);
112 // Data = &DeviceNode->CapabilityFlags->UINumber;
115 case DevicePropertyClassName
:
116 case DevicePropertyClassGuid
:
117 case DevicePropertyDriverKeyName
:
118 case DevicePropertyManufacturer
:
119 case DevicePropertyFriendlyName
:
120 case DevicePropertyHardwareID
:
121 case DevicePropertyCompatibleIDs
:
122 case DevicePropertyDeviceDescription
:
123 case DevicePropertyLocationInformation
:
124 case DevicePropertyUINumber
:
126 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
127 UNICODE_STRING KeyName
, ValueName
;
128 OBJECT_ATTRIBUTES ObjectAttributes
;
129 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
130 ULONG ValueInformationLength
;
134 switch (DeviceProperty
)
136 case DevicePropertyClassName
:
137 RegistryPropertyName
= L
"Class"; break;
138 case DevicePropertyClassGuid
:
139 RegistryPropertyName
= L
"ClassGuid"; break;
140 case DevicePropertyDriverKeyName
:
141 RegistryPropertyName
= L
"Driver"; break;
142 case DevicePropertyManufacturer
:
143 RegistryPropertyName
= L
"Mfg"; break;
144 case DevicePropertyFriendlyName
:
145 RegistryPropertyName
= L
"FriendlyName"; break;
146 case DevicePropertyHardwareID
:
147 RegistryPropertyName
= L
"HardwareID"; break;
148 case DevicePropertyCompatibleIDs
:
149 RegistryPropertyName
= L
"CompatibleIDs"; break;
150 case DevicePropertyDeviceDescription
:
151 RegistryPropertyName
= L
"DeviceDesc"; break;
152 case DevicePropertyLocationInformation
:
153 RegistryPropertyName
= L
"LocationInformation"; break;
154 case DevicePropertyUINumber
:
155 RegistryPropertyName
= L
"UINumber"; break;
157 RegistryPropertyName
= NULL
; break;
160 KeyNameBuffer
= ExAllocatePool(PagedPool
,
161 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
163 DPRINT("KeyNameBuffer: %x, value %S\n",
164 KeyNameBuffer
, RegistryPropertyName
);
166 if (KeyNameBuffer
== NULL
)
167 return STATUS_INSUFFICIENT_RESOURCES
;
169 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
170 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
171 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
172 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
173 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
175 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
176 ExFreePool(KeyNameBuffer
);
177 if (!NT_SUCCESS(Status
))
180 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
181 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
182 Data
[0]) + BufferLength
;
183 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
184 if (ValueInformation
== NULL
)
187 return STATUS_INSUFFICIENT_RESOURCES
;
190 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
191 KeyValuePartialInformation
, ValueInformation
,
192 ValueInformationLength
,
193 &ValueInformationLength
);
194 *ResultLength
= ValueInformation
->DataLength
;
197 if (ValueInformation
->DataLength
> BufferLength
)
198 Status
= STATUS_BUFFER_TOO_SMALL
;
200 if (!NT_SUCCESS(Status
))
202 ExFreePool(ValueInformation
);
206 /* FIXME: Verify the value (NULL-terminated, correct format). */
208 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
209 ValueInformation
->DataLength
);
210 ExFreePool(ValueInformation
);
212 return STATUS_SUCCESS
;
215 case DevicePropertyBootConfiguration
:
217 if (DeviceNode
->BootResources
->Count
!= 0)
219 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
221 Data
= &DeviceNode
->BootResources
;
224 /* FIXME: use a translated boot configuration instead */
225 case DevicePropertyBootConfigurationTranslated
:
227 if (DeviceNode
->BootResources
->Count
!= 0)
229 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
231 Data
= &DeviceNode
->BootResources
;
234 case DevicePropertyEnumeratorName
:
235 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
238 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
246 case DevicePropertyPhysicalDeviceObjectName
:
247 return STATUS_NOT_IMPLEMENTED
;
250 return STATUS_INVALID_PARAMETER_2
;
253 *ResultLength
= Length
;
254 if (BufferLength
< Length
)
255 return STATUS_BUFFER_TOO_SMALL
;
256 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
258 /* Terminate the string */
259 if (DeviceProperty
== DevicePropertyEnumeratorName
)
261 Ptr
= (PWSTR
)PropertyBuffer
;
262 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
265 return STATUS_SUCCESS
;
273 IoInvalidateDeviceState(
274 IN PDEVICE_OBJECT PhysicalDeviceObject
)
279 * @name IoOpenDeviceRegistryKey
281 * Open a registry key unique for a specified driver or device instance.
283 * @param DeviceObject Device to get the registry key for.
284 * @param DevInstKeyType Type of the key to return.
285 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
286 * @param DevInstRegKey Handle to the opened registry key on
295 IoOpenDeviceRegistryKey(
296 IN PDEVICE_OBJECT DeviceObject
,
297 IN ULONG DevInstKeyType
,
298 IN ACCESS_MASK DesiredAccess
,
299 OUT PHANDLE DevInstRegKey
)
301 static WCHAR RootKeyName
[] =
302 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
303 static WCHAR ProfileKeyName
[] =
304 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
305 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
306 static WCHAR EnumKeyName
[] = L
"Enum\\";
307 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters\\";
309 LPWSTR KeyNameBuffer
;
310 UNICODE_STRING KeyName
;
311 ULONG DriverKeyLength
;
312 OBJECT_ATTRIBUTES ObjectAttributes
;
313 PDEVICE_NODE DeviceNode
= NULL
;
316 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
317 return STATUS_INVALID_PARAMETER
;
320 * Calculate the length of the base key name. This is the full
321 * name for driver key or the name excluding "Device Parameters"
322 * subkey for device key.
325 KeyNameLength
= sizeof(RootKeyName
);
326 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
327 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
328 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
330 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
331 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
332 0, NULL
, &DriverKeyLength
);
333 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
335 KeyNameLength
+= DriverKeyLength
;
339 DeviceNode
= IopGetDeviceNode(DeviceObject
);
340 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
341 DeviceNode
->InstancePath
.Length
;
345 * Now allocate the buffer for the key name...
348 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
349 if (KeyNameBuffer
== NULL
)
350 return STATUS_INSUFFICIENT_RESOURCES
;
353 KeyName
.MaximumLength
= KeyNameLength
;
354 KeyName
.Buffer
= KeyNameBuffer
;
357 * ...and build the key name.
360 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
361 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
363 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
364 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
366 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
368 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
369 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
370 DriverKeyLength
, KeyNameBuffer
+
371 (KeyName
.Length
/ sizeof(WCHAR
)),
373 if (!NT_SUCCESS(Status
))
375 ExFreePool(KeyNameBuffer
);
378 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
382 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
383 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
384 if (DeviceNode
->InstancePath
.Length
== 0)
386 ExFreePool(KeyNameBuffer
);
395 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
396 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
397 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
398 ExFreePool(KeyNameBuffer
);
401 * For driver key we're done now. Also if the base key doesn't
402 * exist we can bail out with error...
405 if ((DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
) || !NT_SUCCESS(Status
))
409 * Let's go further. For device key we must open "Device Parameters"
410 * subkey and create it if it doesn't exist yet.
413 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
414 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
415 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
416 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
417 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
418 ZwClose(ObjectAttributes
.RootDirectory
);
428 IoRequestDeviceEject(
429 IN PDEVICE_OBJECT PhysicalDeviceObject
437 IopCreateUnicodeString(
438 PUNICODE_STRING Destination
,
446 RtlInitUnicodeString(Destination
, NULL
);
450 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
452 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
454 if (Destination
->Buffer
== NULL
)
459 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
461 Destination
->MaximumLength
= Length
;
463 Destination
->Length
= Length
- sizeof(WCHAR
);
469 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
473 if (PopSystemPowerDeviceNode
)
475 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
476 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
477 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
479 return STATUS_SUCCESS
;
482 return STATUS_UNSUCCESSFUL
;
487 * Creates a device node
490 * ParentNode = Pointer to parent device node
491 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
492 * to have the root device node create one
493 * (eg. for legacy drivers)
494 * DeviceNode = Pointer to storage for created device node
500 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
501 PDEVICE_OBJECT PhysicalDeviceObject
,
502 PDEVICE_NODE
*DeviceNode
)
508 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
509 ParentNode
, PhysicalDeviceObject
);
511 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
514 return STATUS_INSUFFICIENT_RESOURCES
;
517 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
519 if (!PhysicalDeviceObject
)
521 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
522 if (!NT_SUCCESS(Status
))
528 /* This is for drivers passed on the command line to ntoskrnl.exe */
529 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
530 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
533 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
535 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
539 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
540 Node
->Parent
= ParentNode
;
541 Node
->NextSibling
= ParentNode
->Child
;
542 if (ParentNode
->Child
!= NULL
)
544 ParentNode
->Child
->PrevSibling
= Node
;
546 ParentNode
->Child
= Node
;
547 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
552 return STATUS_SUCCESS
;
556 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
560 /* All children must be deleted before a parent is deleted */
561 ASSERT(!DeviceNode
->Child
);
563 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
565 ASSERT(DeviceNode
->PhysicalDeviceObject
);
567 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
569 /* Unlink from parent if it exists */
571 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
573 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
576 /* Unlink from sibling list */
578 if (DeviceNode
->PrevSibling
)
580 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
583 if (DeviceNode
->NextSibling
)
585 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
588 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
590 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
592 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
594 if (DeviceNode
->ResourceList
)
596 ExFreePool(DeviceNode
->ResourceList
);
599 if (DeviceNode
->ResourceListTranslated
)
601 ExFreePool(DeviceNode
->ResourceListTranslated
);
604 if (DeviceNode
->ResourceRequirements
)
606 ExFreePool(DeviceNode
->ResourceRequirements
);
609 if (DeviceNode
->BootResources
)
611 ExFreePool(DeviceNode
->BootResources
);
614 ExFreePool(DeviceNode
);
616 return STATUS_SUCCESS
;
621 PDEVICE_OBJECT DeviceObject
,
622 PIO_STATUS_BLOCK IoStatusBlock
,
624 PIO_STACK_LOCATION Stack OPTIONAL
)
626 PDEVICE_OBJECT TopDeviceObject
;
627 PIO_STACK_LOCATION IrpSp
;
632 /* Always call the top of the device stack */
633 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
640 Irp
= IoBuildSynchronousFsdRequest(
649 /* PNP IRPs are always initialized with a status code of
650 STATUS_NOT_IMPLEMENTED */
651 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
652 Irp
->IoStatus
.Information
= 0;
654 IrpSp
= IoGetNextIrpStackLocation(Irp
);
655 IrpSp
->MinorFunction
= MinorFunction
;
662 sizeof(Stack
->Parameters
));
665 Status
= IoCallDriver(TopDeviceObject
, Irp
);
666 if (Status
== STATUS_PENDING
)
668 KeWaitForSingleObject(
674 Status
= IoStatusBlock
->Status
;
677 ObDereferenceObject(TopDeviceObject
);
684 IopTraverseDeviceTreeNode(
685 PDEVICETREE_TRAVERSE_CONTEXT Context
)
687 PDEVICE_NODE ParentDeviceNode
;
688 PDEVICE_NODE ChildDeviceNode
;
691 /* Copy context data so we don't overwrite it in subsequent calls to this function */
692 ParentDeviceNode
= Context
->DeviceNode
;
694 /* Call the action routine */
695 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
696 if (!NT_SUCCESS(Status
))
701 /* Traversal of all children nodes */
702 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
703 ChildDeviceNode
!= NULL
;
704 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
706 /* Pass the current device node to the action routine */
707 Context
->DeviceNode
= ChildDeviceNode
;
709 Status
= IopTraverseDeviceTreeNode(Context
);
710 if (!NT_SUCCESS(Status
))
721 IopTraverseDeviceTree(
722 PDEVICETREE_TRAVERSE_CONTEXT Context
)
726 DPRINT("Context %x\n", Context
);
728 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
729 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
731 /* Start from the specified device node */
732 Context
->DeviceNode
= Context
->FirstDeviceNode
;
734 /* Recursively traverse the device tree */
735 Status
= IopTraverseDeviceTreeNode(Context
);
736 if (Status
== STATUS_UNSUCCESSFUL
)
738 /* The action routine just wanted to terminate the traversal with status
739 code STATUS_SUCCESS */
740 Status
= STATUS_SUCCESS
;
748 IopCreateDeviceKeyPath(PWSTR Path
,
751 OBJECT_ATTRIBUTES ObjectAttributes
;
752 WCHAR KeyBuffer
[MAX_PATH
];
753 UNICODE_STRING KeyName
;
761 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
763 return STATUS_INVALID_PARAMETER
;
766 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
768 /* Skip \\Registry\\ */
770 Current
= wcschr (Current
, L
'\\') + 1;
771 Current
= wcschr (Current
, L
'\\') + 1;
775 Next
= wcschr (Current
, L
'\\');
785 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
786 InitializeObjectAttributes (&ObjectAttributes
,
788 OBJ_CASE_INSENSITIVE
,
792 DPRINT("Create '%S'\n", KeyName
.Buffer
);
794 Status
= ZwCreateKey (&KeyHandle
,
801 if (!NT_SUCCESS (Status
))
803 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
810 return STATUS_SUCCESS
;
821 return STATUS_UNSUCCESSFUL
;
826 IopSetDeviceInstanceData(HANDLE InstanceKey
,
827 PDEVICE_NODE DeviceNode
)
829 OBJECT_ATTRIBUTES ObjectAttributes
;
830 UNICODE_STRING KeyName
;
836 DPRINT("IopSetDeviceInstanceData() called\n");
838 /* Create the 'LogConf' key */
839 RtlInitUnicodeString(&KeyName
,
841 InitializeObjectAttributes(&ObjectAttributes
,
843 OBJ_CASE_INSENSITIVE
,
846 Status
= ZwCreateKey(&LogConfKey
,
853 if (NT_SUCCESS(Status
))
855 /* Set 'BootConfig' value */
856 if (DeviceNode
->BootResources
!= NULL
)
858 ResCount
= DeviceNode
->BootResources
->Count
;
861 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
863 RtlInitUnicodeString(&KeyName
,
865 Status
= ZwSetValueKey(LogConfKey
,
869 &DeviceNode
->BootResources
,
874 /* Set 'BasicConfigVector' value */
875 if (DeviceNode
->ResourceRequirements
!= NULL
&&
876 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
878 RtlInitUnicodeString(&KeyName
,
879 L
"BasicConfigVector");
880 Status
= ZwSetValueKey(LogConfKey
,
883 REG_RESOURCE_REQUIREMENTS_LIST
,
884 &DeviceNode
->ResourceRequirements
,
885 DeviceNode
->ResourceRequirements
->ListSize
);
891 DPRINT("IopSetDeviceInstanceData() done\n");
893 return STATUS_SUCCESS
;
898 * IopActionInterrogateDeviceStack
900 * Retrieve information for all (direct) child nodes of a parent node.
904 * Pointer to device node.
906 * Pointer to parent node to retrieve child node information for.
909 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
910 * when we reach a device node which is not a direct child of the device
911 * node for which we retrieve information of child nodes for. Any errors
912 * that occur is logged instead so that all child services have a chance
913 * of being interrogated.
917 IopActionInterrogateDeviceStack(
918 PDEVICE_NODE DeviceNode
,
921 IO_STATUS_BLOCK IoStatusBlock
;
922 PDEVICE_NODE ParentDeviceNode
;
923 WCHAR InstancePath
[MAX_PATH
];
924 IO_STACK_LOCATION Stack
;
930 HANDLE InstanceKey
= NULL
;
931 UNICODE_STRING ValueName
;
932 DEVICE_CAPABILITIES DeviceCapabilities
;
934 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
935 DPRINT("PDO %x\n", DeviceNode
->PhysicalDeviceObject
);
937 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
940 * We are called for the parent too, but we don't need to do special
941 * handling for this node
944 if (DeviceNode
== ParentDeviceNode
)
947 return STATUS_SUCCESS
;
951 * Make sure this device node is a direct child of the parent device node
952 * that is given as an argument
955 if (DeviceNode
->Parent
!= ParentDeviceNode
)
957 /* Stop the traversal immediately and indicate successful operation */
959 return STATUS_UNSUCCESSFUL
;
963 * FIXME: For critical errors, cleanup and disable device, but always
964 * return STATUS_SUCCESS.
967 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
969 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
970 Status
= IopInitiatePnpIrp(
971 DeviceNode
->PhysicalDeviceObject
,
975 if (NT_SUCCESS(Status
))
977 /* Copy the device id string */
978 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
981 * FIXME: Check for valid characters, if there is invalid characters
987 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
990 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
992 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
993 Status
= IopInitiatePnpIrp(
994 DeviceNode
->PhysicalDeviceObject
,
998 if (NT_SUCCESS(Status
))
1000 /* Append the instance id string */
1001 wcscat(InstancePath
, L
"\\");
1002 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1005 * FIXME: Check for valid characters, if there is invalid characters
1011 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1014 RtlZeroMemory(&DeviceCapabilities
, sizeof(DEVICE_CAPABILITIES
));
1015 DeviceCapabilities
.Size
= sizeof(DEVICE_CAPABILITIES
);
1016 DeviceCapabilities
.Version
= 1;
1017 DeviceCapabilities
.Address
= -1;
1018 DeviceCapabilities
.UINumber
= -1;
1020 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= &DeviceCapabilities
;
1021 Status
= IopInitiatePnpIrp(
1022 DeviceNode
->PhysicalDeviceObject
,
1024 IRP_MN_QUERY_CAPABILITIES
,
1026 if (NT_SUCCESS(Status
))
1031 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1034 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1035 DeviceNode
->Address
= DeviceCapabilities
.Address
;
1037 if (!DeviceCapabilities
.UniqueID
)
1039 DPRINT("Instance ID is not unique\n");
1040 /* FIXME: Add information from parent bus driver to InstancePath */
1043 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
))
1045 DPRINT("No resources\n");
1046 /* FIXME: Cleanup and disable device */
1049 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1052 * Create registry key for the instance id, if it doesn't exist yet
1054 KeyBuffer
= ExAllocatePool(
1056 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1057 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1058 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1059 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1061 ExFreePool(KeyBuffer
);
1062 if (!NT_SUCCESS(Status
))
1064 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1069 /* Set 'Capabilities' value */
1070 RtlInitUnicodeString(&ValueName
,
1072 Status
= ZwSetValueKey(InstanceKey
,
1076 (PVOID
)&DeviceNode
->CapabilityFlags
,
1079 /* Set 'UINumber' value */
1080 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1082 RtlInitUnicodeString(&ValueName
,
1084 Status
= ZwSetValueKey(InstanceKey
,
1088 &DeviceCapabilities
.UINumber
,
1093 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1095 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1096 Status
= IopInitiatePnpIrp(
1097 DeviceNode
->PhysicalDeviceObject
,
1101 if (NT_SUCCESS(Status
))
1104 * FIXME: Check for valid characters, if there is invalid characters
1108 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1109 DPRINT("Hardware IDs:\n");
1112 DPRINT(" %S\n", Ptr
);
1113 Length
= wcslen(Ptr
) + 1;
1116 TotalLength
+= Length
;
1118 DPRINT("TotalLength: %hu\n", TotalLength
);
1121 RtlInitUnicodeString(&ValueName
,
1123 Status
= ZwSetValueKey(InstanceKey
,
1127 (PVOID
)IoStatusBlock
.Information
,
1128 (TotalLength
+ 1) * sizeof(WCHAR
));
1129 if (!NT_SUCCESS(Status
))
1131 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1136 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1139 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1141 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1142 Status
= IopInitiatePnpIrp(
1143 DeviceNode
->PhysicalDeviceObject
,
1147 if (NT_SUCCESS(Status
))
1150 * FIXME: Check for valid characters, if there is invalid characters
1154 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1155 DPRINT("Compatible IDs:\n");
1158 DPRINT(" %S\n", Ptr
);
1159 Length
= wcslen(Ptr
) + 1;
1162 TotalLength
+= Length
;
1164 DPRINT("TotalLength: %hu\n", TotalLength
);
1167 RtlInitUnicodeString(&ValueName
,
1169 Status
= ZwSetValueKey(InstanceKey
,
1173 (PVOID
)IoStatusBlock
.Information
,
1174 (TotalLength
+ 1) * sizeof(WCHAR
));
1175 if (!NT_SUCCESS(Status
))
1177 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1182 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1186 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1188 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1189 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
1190 Status
= IopInitiatePnpIrp(
1191 DeviceNode
->PhysicalDeviceObject
,
1193 IRP_MN_QUERY_DEVICE_TEXT
,
1195 if (NT_SUCCESS(Status
))
1197 RtlInitUnicodeString(&ValueName
,
1199 Status
= ZwSetValueKey(InstanceKey
,
1203 (PVOID
)IoStatusBlock
.Information
,
1204 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1205 if (!NT_SUCCESS(Status
))
1207 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1212 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1215 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1217 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1218 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
1219 Status
= IopInitiatePnpIrp(
1220 DeviceNode
->PhysicalDeviceObject
,
1222 IRP_MN_QUERY_DEVICE_TEXT
,
1224 if (NT_SUCCESS(Status
))
1226 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1227 RtlInitUnicodeString(&ValueName
,
1228 L
"LocationInformation");
1229 Status
= ZwSetValueKey(InstanceKey
,
1233 (PVOID
)IoStatusBlock
.Information
,
1234 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1235 if (!NT_SUCCESS(Status
))
1237 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1242 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1245 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1247 Status
= IopInitiatePnpIrp(
1248 DeviceNode
->PhysicalDeviceObject
,
1250 IRP_MN_QUERY_BUS_INFORMATION
,
1252 if (NT_SUCCESS(Status
))
1254 PPNP_BUS_INFORMATION BusInformation
=
1255 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1257 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1258 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1259 memcpy(&DeviceNode
->BusTypeGuid
,
1260 &BusInformation
->BusTypeGuid
,
1262 ExFreePool(BusInformation
);
1266 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1268 DeviceNode
->ChildBusNumber
= -1;
1269 DeviceNode
->ChildInterfaceType
= -1;
1270 memset(&DeviceNode
->BusTypeGuid
,
1275 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1277 Status
= IopInitiatePnpIrp(
1278 DeviceNode
->PhysicalDeviceObject
,
1280 IRP_MN_QUERY_RESOURCES
,
1282 if (NT_SUCCESS(Status
))
1284 DeviceNode
->BootResources
=
1285 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1286 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1290 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1291 DeviceNode
->BootResources
= NULL
;
1294 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1296 Status
= IopInitiatePnpIrp(
1297 DeviceNode
->PhysicalDeviceObject
,
1299 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1301 if (NT_SUCCESS(Status
))
1303 DeviceNode
->ResourceRequirements
=
1304 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1308 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1309 DeviceNode
->ResourceRequirements
= NULL
;
1313 if (InstanceKey
!= NULL
)
1315 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1318 ZwClose(InstanceKey
);
1320 DeviceNode
->Flags
|= DNF_PROCESSED
;
1322 /* Report the device to the user-mode pnp manager */
1323 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1324 &DeviceNode
->InstancePath
);
1326 return STATUS_SUCCESS
;
1330 * IopActionConfigureChildServices
1332 * Retrieve configuration for all (direct) child nodes of a parent node.
1336 * Pointer to device node.
1338 * Pointer to parent node to retrieve child node configuration for.
1341 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1342 * when we reach a device node which is not a direct child of the device
1343 * node for which we configure child services for. Any errors that occur is
1344 * logged instead so that all child services have a chance of beeing
1349 IopActionConfigureChildServices(
1350 PDEVICE_NODE DeviceNode
,
1353 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1354 PDEVICE_NODE ParentDeviceNode
;
1355 PUNICODE_STRING Service
;
1358 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1360 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1363 * We are called for the parent too, but we don't need to do special
1364 * handling for this node
1366 if (DeviceNode
== ParentDeviceNode
)
1368 DPRINT("Success\n");
1369 return STATUS_SUCCESS
;
1373 * Make sure this device node is a direct child of the parent device node
1374 * that is given as an argument
1376 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1378 /* Stop the traversal immediately and indicate successful operation */
1380 return STATUS_UNSUCCESSFUL
;
1383 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1385 WCHAR RegKeyBuffer
[MAX_PATH
];
1386 UNICODE_STRING RegKey
;
1389 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1390 RegKey
.Buffer
= RegKeyBuffer
;
1393 * Retrieve configuration from Enum key
1396 Service
= &DeviceNode
->ServiceName
;
1398 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1399 RtlInitUnicodeString(Service
, NULL
);
1401 QueryTable
[0].Name
= L
"Service";
1402 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1403 QueryTable
[0].EntryContext
= Service
;
1405 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1406 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1408 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1409 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1411 if (!NT_SUCCESS(Status
))
1413 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1414 /* FIXME: Log the error */
1415 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1416 DeviceNode
->InstancePath
.Buffer
, Status
);
1417 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1418 return STATUS_SUCCESS
;
1421 if (Service
->Buffer
== NULL
)
1423 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1424 return STATUS_SUCCESS
;
1427 DPRINT("Got Service %S\n", Service
->Buffer
);
1430 return STATUS_SUCCESS
;
1434 * IopActionInitChildServices
1436 * Initialize the service for all (direct) child nodes of a parent node
1440 * Pointer to device node.
1442 * Pointer to parent node to initialize child node services for.
1444 * Load only driver marked as boot start.
1447 * If the driver image for a service is not loaded and initialized
1448 * it is done here too. We only return a status code indicating an
1449 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1450 * not a direct child of the device node for which we initialize
1451 * child services for. Any errors that occur is logged instead so
1452 * that all child services have a chance of being initialized.
1456 IopActionInitChildServices(
1457 PDEVICE_NODE DeviceNode
,
1459 BOOLEAN BootDrivers
)
1461 PDEVICE_NODE ParentDeviceNode
;
1464 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1467 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1470 * We are called for the parent too, but we don't need to do special
1471 * handling for this node
1473 if (DeviceNode
== ParentDeviceNode
)
1475 DPRINT("Success\n");
1476 return STATUS_SUCCESS
;
1480 * Make sure this device node is a direct child of the parent device node
1481 * that is given as an argument
1484 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1487 * Stop the traversal immediately and indicate unsuccessful operation
1490 return STATUS_UNSUCCESSFUL
;
1494 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1495 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1496 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1498 PMODULE_OBJECT ModuleObject
;
1499 PDRIVER_OBJECT DriverObject
;
1501 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1502 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
1504 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
1505 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
1506 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
1509 /* get existing DriverObject pointer */
1510 Status
= IopCreateDriverObject(
1512 &DeviceNode
->ServiceName
,
1516 ModuleObject
->Length
);
1518 if (NT_SUCCESS(Status
))
1520 /* Attach lower level filter drivers. */
1521 IopAttachFilterDrivers(DeviceNode
, TRUE
);
1522 /* Initialize the function driver for the device node */
1523 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1524 if (NT_SUCCESS(Status
))
1526 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1527 /* Attach upper level filter drivers. */
1528 IopAttachFilterDrivers(DeviceNode
, FALSE
);
1535 * Don't disable when trying to load only boot drivers
1539 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1540 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1542 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1543 CPRINT("Initialization of service %S failed (Status %x)\n",
1544 DeviceNode
->ServiceName
.Buffer
, Status
);
1548 DPRINT("Service %S is disabled or already initialized\n",
1549 DeviceNode
->ServiceName
.Buffer
);
1552 return STATUS_SUCCESS
;
1556 * IopActionInitAllServices
1558 * Initialize the service for all (direct) child nodes of a parent node. This
1559 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1563 IopActionInitAllServices(
1564 PDEVICE_NODE DeviceNode
,
1567 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1571 * IopActionInitBootServices
1573 * Initialize the boot start services for all (direct) child nodes of a
1574 * parent node. This function just calls IopActionInitChildServices with
1575 * BootDrivers = TRUE.
1578 IopActionInitBootServices(
1579 PDEVICE_NODE DeviceNode
,
1582 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1586 * IopInitializePnpServices
1588 * Initialize services for discovered children
1592 * Top device node to start initializing services.
1595 * When set to TRUE, only drivers marked as boot start will
1596 * be loaded. Otherwise, all drivers will be loaded.
1602 IopInitializePnpServices(
1603 IN PDEVICE_NODE DeviceNode
,
1604 IN BOOLEAN BootDrivers
)
1606 DEVICETREE_TRAVERSE_CONTEXT Context
;
1608 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1612 IopInitDeviceTreeTraverseContext(
1615 IopActionInitBootServices
,
1619 IopInitDeviceTreeTraverseContext(
1622 IopActionInitAllServices
,
1626 return IopTraverseDeviceTree(&Context
);
1631 IopInvalidateDeviceRelations(
1632 IN PDEVICE_NODE DeviceNode
,
1633 IN DEVICE_RELATION_TYPE Type
)
1635 DEVICETREE_TRAVERSE_CONTEXT Context
;
1636 PDEVICE_RELATIONS DeviceRelations
;
1637 IO_STATUS_BLOCK IoStatusBlock
;
1638 PDEVICE_NODE ChildDeviceNode
;
1639 IO_STACK_LOCATION Stack
;
1641 OBJECT_ATTRIBUTES ObjectAttributes
;
1642 UNICODE_STRING LinkName
;
1647 DPRINT("DeviceNode %x\n", DeviceNode
);
1649 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1651 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1653 Status
= IopInitiatePnpIrp(
1654 DeviceNode
->PhysicalDeviceObject
,
1656 IRP_MN_QUERY_DEVICE_RELATIONS
,
1658 if (!NT_SUCCESS(Status
))
1660 DPRINT("IopInitiatePnpIrp() failed\n");
1664 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1666 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1668 DPRINT("No PDOs\n");
1669 if (DeviceRelations
)
1671 ExFreePool(DeviceRelations
);
1673 return STATUS_SUCCESS
;
1676 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1679 * Create device nodes for all discovered devices
1682 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1684 Status
= IopCreateDeviceNode(
1686 DeviceRelations
->Objects
[i
],
1688 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1689 if (!NT_SUCCESS(Status
))
1691 DPRINT("No resources\n");
1692 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1693 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1694 ExFreePool(DeviceRelations
);
1695 return STATUS_INSUFFICIENT_RESOURCES
;
1698 ExFreePool(DeviceRelations
);
1701 * Retrieve information about all discovered children from the bus driver
1704 IopInitDeviceTreeTraverseContext(
1707 IopActionInterrogateDeviceStack
,
1710 Status
= IopTraverseDeviceTree(&Context
);
1711 if (!NT_SUCCESS(Status
))
1713 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1718 * Retrieve configuration from the registry for discovered children
1721 IopInitDeviceTreeTraverseContext(
1724 IopActionConfigureChildServices
,
1727 Status
= IopTraverseDeviceTree(&Context
);
1728 if (!NT_SUCCESS(Status
))
1730 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1735 * Get the state of the system boot. If the \\SystemRoot link isn't
1736 * created yet, we will assume that it's possible to load only boot
1740 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
1742 InitializeObjectAttributes(
1749 Status
= ZwOpenFile(
1756 if(NT_SUCCESS(Status
))
1758 BootDrivers
= FALSE
;
1765 * Initialize services for discovered children. Only boot drivers will
1766 * be loaded from boot driver!
1769 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
1770 if (!NT_SUCCESS(Status
))
1772 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
1776 return STATUS_SUCCESS
;
1786 DPRINT("PnpInit()\n");
1788 KeInitializeSpinLock(&IopDeviceTreeLock
);
1790 /* Initialize PnP-Event notification support */
1791 Status
= IopInitPlugPlayEvents();
1792 if (!NT_SUCCESS(Status
))
1794 CPRINT("IopInitPlugPlayEvents() failed\n");
1795 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1799 * Create root device node
1802 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
1803 if (!NT_SUCCESS(Status
))
1805 CPRINT("IoCreateDriverObject() failed\n");
1806 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1809 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
1811 if (!NT_SUCCESS(Status
))
1813 CPRINT("IoCreateDevice() failed\n");
1814 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1817 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
1818 if (!NT_SUCCESS(Status
))
1820 CPRINT("Insufficient resources\n");
1821 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1824 if (!IopCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
1828 CPRINT("Failed to create the instance path!\n");
1829 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_UNSUCCESSFUL
, 0, 0, 0);
1832 /* Report the device to the user-mode pnp manager */
1833 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1834 &IopRootDeviceNode
->InstancePath
);
1836 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1837 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1838 IopRootDriverObject
->DriverExtension
->AddDevice(
1839 IopRootDriverObject
,
1840 IopRootDeviceNode
->PhysicalDeviceObject
);