2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/pnpmgr.c
5 * PURPOSE: Initializes the PnP manager
7 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 /* INCLUDES ******************************************************************/
13 #include <ddk/wdmguid.h>
16 #include <internal/debug.h>
18 /* FIXME: Header mess */
19 #undef DeviceCapabilities
21 /* GLOBALS *******************************************************************/
23 PDEVICE_NODE IopRootDeviceNode
;
24 KSPIN_LOCK IopDeviceTreeLock
;
26 /* DATA **********************************************************************/
28 PDRIVER_OBJECT IopRootDriverObject
;
30 /* FUNCTIONS *****************************************************************/
34 PDEVICE_OBJECT DeviceObject
)
36 return DeviceObject
->DeviceObjectExtension
->DeviceNode
;
44 IoInvalidateDeviceRelations(
45 IN PDEVICE_OBJECT DeviceObject
,
46 IN DEVICE_RELATION_TYPE Type
)
48 IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject
), Type
);
57 IN PDEVICE_OBJECT DeviceObject
,
58 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
59 IN ULONG BufferLength
,
60 OUT PVOID PropertyBuffer
,
61 OUT PULONG ResultLength
)
63 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
68 DPRINT("IoGetDeviceProperty(%x %d)\n", DeviceObject
, DeviceProperty
);
70 if (DeviceNode
== NULL
)
71 return STATUS_INVALID_DEVICE_REQUEST
;
73 switch (DeviceProperty
)
75 case DevicePropertyBusNumber
:
76 Length
= sizeof(ULONG
);
77 Data
= &DeviceNode
->ChildBusNumber
;
80 /* Complete, untested */
81 case DevicePropertyBusTypeGuid
:
82 *ResultLength
= 39 * sizeof(WCHAR
);
83 if (BufferLength
< (39 * sizeof(WCHAR
)))
84 return STATUS_BUFFER_TOO_SMALL
;
85 swprintf((PWSTR
)PropertyBuffer
,
86 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
87 DeviceNode
->BusTypeGuid
.Data1
,
88 DeviceNode
->BusTypeGuid
.Data2
,
89 DeviceNode
->BusTypeGuid
.Data3
,
90 DeviceNode
->BusTypeGuid
.Data4
[0],
91 DeviceNode
->BusTypeGuid
.Data4
[1],
92 DeviceNode
->BusTypeGuid
.Data4
[2],
93 DeviceNode
->BusTypeGuid
.Data4
[3],
94 DeviceNode
->BusTypeGuid
.Data4
[4],
95 DeviceNode
->BusTypeGuid
.Data4
[5],
96 DeviceNode
->BusTypeGuid
.Data4
[6],
97 DeviceNode
->BusTypeGuid
.Data4
[7]);
98 return STATUS_SUCCESS
;
100 case DevicePropertyLegacyBusType
:
101 Length
= sizeof(INTERFACE_TYPE
);
102 Data
= &DeviceNode
->ChildInterfaceType
;
105 case DevicePropertyAddress
:
106 Length
= sizeof(ULONG
);
107 Data
= &DeviceNode
->Address
;
110 // case DevicePropertyUINumber:
111 // if (DeviceNode->CapabilityFlags == NULL)
112 // return STATUS_INVALID_DEVICE_REQUEST;
113 // Length = sizeof(ULONG);
114 // Data = &DeviceNode->CapabilityFlags->UINumber;
117 case DevicePropertyClassName
:
118 case DevicePropertyClassGuid
:
119 case DevicePropertyDriverKeyName
:
120 case DevicePropertyManufacturer
:
121 case DevicePropertyFriendlyName
:
122 case DevicePropertyHardwareID
:
123 case DevicePropertyCompatibleIDs
:
124 case DevicePropertyDeviceDescription
:
125 case DevicePropertyLocationInformation
:
126 case DevicePropertyUINumber
:
128 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
129 UNICODE_STRING KeyName
, ValueName
;
130 OBJECT_ATTRIBUTES ObjectAttributes
;
131 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
132 ULONG ValueInformationLength
;
136 switch (DeviceProperty
)
138 case DevicePropertyClassName
:
139 RegistryPropertyName
= L
"Class"; break;
140 case DevicePropertyClassGuid
:
141 RegistryPropertyName
= L
"ClassGuid"; break;
142 case DevicePropertyDriverKeyName
:
143 RegistryPropertyName
= L
"Driver"; break;
144 case DevicePropertyManufacturer
:
145 RegistryPropertyName
= L
"Mfg"; break;
146 case DevicePropertyFriendlyName
:
147 RegistryPropertyName
= L
"FriendlyName"; break;
148 case DevicePropertyHardwareID
:
149 RegistryPropertyName
= L
"HardwareID"; break;
150 case DevicePropertyCompatibleIDs
:
151 RegistryPropertyName
= L
"CompatibleIDs"; break;
152 case DevicePropertyDeviceDescription
:
153 RegistryPropertyName
= L
"DeviceDesc"; break;
154 case DevicePropertyLocationInformation
:
155 RegistryPropertyName
= L
"LocationInformation"; break;
156 case DevicePropertyUINumber
:
157 RegistryPropertyName
= L
"UINumber"; break;
159 RegistryPropertyName
= NULL
; break;
162 KeyNameBuffer
= ExAllocatePool(PagedPool
,
163 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
165 DPRINT("KeyNameBuffer: %x, value %S\n",
166 KeyNameBuffer
, RegistryPropertyName
);
168 if (KeyNameBuffer
== NULL
)
169 return STATUS_INSUFFICIENT_RESOURCES
;
171 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
172 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
173 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
174 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
175 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
177 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
178 ExFreePool(KeyNameBuffer
);
179 if (!NT_SUCCESS(Status
))
182 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
183 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
184 Data
[0]) + BufferLength
;
185 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
186 if (ValueInformation
== NULL
)
189 return STATUS_INSUFFICIENT_RESOURCES
;
192 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
193 KeyValuePartialInformation
, ValueInformation
,
194 ValueInformationLength
,
195 &ValueInformationLength
);
196 *ResultLength
= ValueInformation
->DataLength
;
199 if (ValueInformation
->DataLength
> BufferLength
)
200 Status
= STATUS_BUFFER_TOO_SMALL
;
202 if (!NT_SUCCESS(Status
))
204 ExFreePool(ValueInformation
);
208 /* FIXME: Verify the value (NULL-terminated, correct format). */
210 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
211 ValueInformation
->DataLength
);
212 ExFreePool(ValueInformation
);
214 return STATUS_SUCCESS
;
217 case DevicePropertyBootConfiguration
:
219 if (DeviceNode
->BootResources
->Count
!= 0)
221 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
223 Data
= &DeviceNode
->BootResources
;
226 /* FIXME: use a translated boot configuration instead */
227 case DevicePropertyBootConfigurationTranslated
:
229 if (DeviceNode
->BootResources
->Count
!= 0)
231 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
233 Data
= &DeviceNode
->BootResources
;
236 case DevicePropertyEnumeratorName
:
237 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
240 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
241 Data
= DeviceNode
->InstancePath
.Buffer
;
250 case DevicePropertyPhysicalDeviceObjectName
:
251 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
252 Data
= DeviceNode
->InstancePath
.Buffer
;
256 return STATUS_INVALID_PARAMETER_2
;
259 *ResultLength
= Length
;
260 if (BufferLength
< Length
)
261 return STATUS_BUFFER_TOO_SMALL
;
262 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
264 /* Terminate the string */
265 if (DeviceProperty
== DevicePropertyEnumeratorName
266 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
268 Ptr
= (PWSTR
)PropertyBuffer
;
269 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
272 return STATUS_SUCCESS
;
280 IoInvalidateDeviceState(
281 IN PDEVICE_OBJECT PhysicalDeviceObject
)
286 * @name IoOpenDeviceRegistryKey
288 * Open a registry key unique for a specified driver or device instance.
290 * @param DeviceObject Device to get the registry key for.
291 * @param DevInstKeyType Type of the key to return.
292 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
293 * @param DevInstRegKey Handle to the opened registry key on
302 IoOpenDeviceRegistryKey(
303 IN PDEVICE_OBJECT DeviceObject
,
304 IN ULONG DevInstKeyType
,
305 IN ACCESS_MASK DesiredAccess
,
306 OUT PHANDLE DevInstRegKey
)
308 static WCHAR RootKeyName
[] =
309 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
310 static WCHAR ProfileKeyName
[] =
311 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
312 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
313 static WCHAR EnumKeyName
[] = L
"Enum\\";
314 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters\\";
316 LPWSTR KeyNameBuffer
;
317 UNICODE_STRING KeyName
;
318 ULONG DriverKeyLength
;
319 OBJECT_ATTRIBUTES ObjectAttributes
;
320 PDEVICE_NODE DeviceNode
= NULL
;
323 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
324 return STATUS_INVALID_PARAMETER
;
327 * Calculate the length of the base key name. This is the full
328 * name for driver key or the name excluding "Device Parameters"
329 * subkey for device key.
332 KeyNameLength
= sizeof(RootKeyName
);
333 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
334 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
335 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
337 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
338 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
339 0, NULL
, &DriverKeyLength
);
340 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
342 KeyNameLength
+= DriverKeyLength
;
346 DeviceNode
= IopGetDeviceNode(DeviceObject
);
347 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
348 DeviceNode
->InstancePath
.Length
;
352 * Now allocate the buffer for the key name...
355 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
356 if (KeyNameBuffer
== NULL
)
357 return STATUS_INSUFFICIENT_RESOURCES
;
360 KeyName
.MaximumLength
= KeyNameLength
;
361 KeyName
.Buffer
= KeyNameBuffer
;
364 * ...and build the key name.
367 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
368 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
370 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
371 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
373 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
375 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
376 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
377 DriverKeyLength
, KeyNameBuffer
+
378 (KeyName
.Length
/ sizeof(WCHAR
)),
380 if (!NT_SUCCESS(Status
))
382 ExFreePool(KeyNameBuffer
);
385 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
389 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
390 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
391 if (DeviceNode
->InstancePath
.Length
== 0)
393 ExFreePool(KeyNameBuffer
);
402 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
403 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
404 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
405 ExFreePool(KeyNameBuffer
);
408 * For driver key we're done now. Also if the base key doesn't
409 * exist we can bail out with error...
412 if ((DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
) || !NT_SUCCESS(Status
))
416 * Let's go further. For device key we must open "Device Parameters"
417 * subkey and create it if it doesn't exist yet.
420 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
421 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
422 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
423 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
424 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
425 ZwClose(ObjectAttributes
.RootDirectory
);
435 IoRequestDeviceEject(
436 IN PDEVICE_OBJECT PhysicalDeviceObject
444 IopCreateUnicodeString(
445 PUNICODE_STRING Destination
,
453 RtlInitUnicodeString(Destination
, NULL
);
457 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
459 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
461 if (Destination
->Buffer
== NULL
)
466 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
468 Destination
->MaximumLength
= Length
;
470 Destination
->Length
= Length
- sizeof(WCHAR
);
476 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
480 if (PopSystemPowerDeviceNode
)
482 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
483 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
484 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
486 return STATUS_SUCCESS
;
489 return STATUS_UNSUCCESSFUL
;
494 * Creates a device node
497 * ParentNode = Pointer to parent device node
498 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
499 * to have the root device node create one
500 * (eg. for legacy drivers)
501 * DeviceNode = Pointer to storage for created device node
507 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
508 PDEVICE_OBJECT PhysicalDeviceObject
,
509 PDEVICE_NODE
*DeviceNode
)
515 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
516 ParentNode
, PhysicalDeviceObject
);
518 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
521 return STATUS_INSUFFICIENT_RESOURCES
;
524 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
526 if (!PhysicalDeviceObject
)
528 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
529 if (!NT_SUCCESS(Status
))
535 /* This is for drivers passed on the command line to ntoskrnl.exe */
536 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
537 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
540 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
542 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
546 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
547 Node
->Parent
= ParentNode
;
548 Node
->NextSibling
= ParentNode
->Child
;
549 if (ParentNode
->Child
!= NULL
)
551 ParentNode
->Child
->PrevSibling
= Node
;
553 ParentNode
->Child
= Node
;
554 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
559 return STATUS_SUCCESS
;
563 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
567 /* All children must be deleted before a parent is deleted */
568 ASSERT(!DeviceNode
->Child
);
570 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
572 ASSERT(DeviceNode
->PhysicalDeviceObject
);
574 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
576 /* Unlink from parent if it exists */
578 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
580 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
583 /* Unlink from sibling list */
585 if (DeviceNode
->PrevSibling
)
587 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
590 if (DeviceNode
->NextSibling
)
592 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
595 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
597 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
599 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
601 if (DeviceNode
->ResourceList
)
603 ExFreePool(DeviceNode
->ResourceList
);
606 if (DeviceNode
->ResourceListTranslated
)
608 ExFreePool(DeviceNode
->ResourceListTranslated
);
611 if (DeviceNode
->ResourceRequirements
)
613 ExFreePool(DeviceNode
->ResourceRequirements
);
616 if (DeviceNode
->BootResources
)
618 ExFreePool(DeviceNode
->BootResources
);
621 ExFreePool(DeviceNode
);
623 return STATUS_SUCCESS
;
628 PDEVICE_OBJECT DeviceObject
,
629 PIO_STATUS_BLOCK IoStatusBlock
,
631 PIO_STACK_LOCATION Stack OPTIONAL
)
633 PDEVICE_OBJECT TopDeviceObject
;
634 PIO_STACK_LOCATION IrpSp
;
639 /* Always call the top of the device stack */
640 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
647 Irp
= IoBuildSynchronousFsdRequest(
656 /* PNP IRPs are always initialized with a status code of
657 STATUS_NOT_IMPLEMENTED */
658 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
659 Irp
->IoStatus
.Information
= 0;
661 IrpSp
= IoGetNextIrpStackLocation(Irp
);
662 IrpSp
->MinorFunction
= MinorFunction
;
669 sizeof(Stack
->Parameters
));
672 Status
= IoCallDriver(TopDeviceObject
, Irp
);
673 if (Status
== STATUS_PENDING
)
675 KeWaitForSingleObject(
681 Status
= IoStatusBlock
->Status
;
684 ObDereferenceObject(TopDeviceObject
);
691 IopTraverseDeviceTreeNode(
692 PDEVICETREE_TRAVERSE_CONTEXT Context
)
694 PDEVICE_NODE ParentDeviceNode
;
695 PDEVICE_NODE ChildDeviceNode
;
698 /* Copy context data so we don't overwrite it in subsequent calls to this function */
699 ParentDeviceNode
= Context
->DeviceNode
;
701 /* Call the action routine */
702 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
703 if (!NT_SUCCESS(Status
))
708 /* Traversal of all children nodes */
709 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
710 ChildDeviceNode
!= NULL
;
711 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
713 /* Pass the current device node to the action routine */
714 Context
->DeviceNode
= ChildDeviceNode
;
716 Status
= IopTraverseDeviceTreeNode(Context
);
717 if (!NT_SUCCESS(Status
))
728 IopTraverseDeviceTree(
729 PDEVICETREE_TRAVERSE_CONTEXT Context
)
733 DPRINT("Context %x\n", Context
);
735 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
736 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
738 /* Start from the specified device node */
739 Context
->DeviceNode
= Context
->FirstDeviceNode
;
741 /* Recursively traverse the device tree */
742 Status
= IopTraverseDeviceTreeNode(Context
);
743 if (Status
== STATUS_UNSUCCESSFUL
)
745 /* The action routine just wanted to terminate the traversal with status
746 code STATUS_SUCCESS */
747 Status
= STATUS_SUCCESS
;
755 IopCreateDeviceKeyPath(PWSTR Path
,
758 OBJECT_ATTRIBUTES ObjectAttributes
;
759 WCHAR KeyBuffer
[MAX_PATH
];
760 UNICODE_STRING KeyName
;
768 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
770 return STATUS_INVALID_PARAMETER
;
773 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
775 /* Skip \\Registry\\ */
777 Current
= wcschr (Current
, L
'\\') + 1;
778 Current
= wcschr (Current
, L
'\\') + 1;
782 Next
= wcschr (Current
, L
'\\');
792 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
793 InitializeObjectAttributes (&ObjectAttributes
,
795 OBJ_CASE_INSENSITIVE
,
799 DPRINT("Create '%S'\n", KeyName
.Buffer
);
801 Status
= ZwCreateKey (&KeyHandle
,
808 if (!NT_SUCCESS (Status
))
810 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
817 return STATUS_SUCCESS
;
828 return STATUS_UNSUCCESSFUL
;
833 IopSetDeviceInstanceData(HANDLE InstanceKey
,
834 PDEVICE_NODE DeviceNode
)
836 OBJECT_ATTRIBUTES ObjectAttributes
;
837 UNICODE_STRING KeyName
;
843 DPRINT("IopSetDeviceInstanceData() called\n");
845 /* Create the 'LogConf' key */
846 RtlInitUnicodeString(&KeyName
,
848 InitializeObjectAttributes(&ObjectAttributes
,
850 OBJ_CASE_INSENSITIVE
,
853 Status
= ZwCreateKey(&LogConfKey
,
860 if (NT_SUCCESS(Status
))
862 /* Set 'BootConfig' value */
863 if (DeviceNode
->BootResources
!= NULL
)
865 ResCount
= DeviceNode
->BootResources
->Count
;
868 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
870 RtlInitUnicodeString(&KeyName
,
872 Status
= ZwSetValueKey(LogConfKey
,
876 &DeviceNode
->BootResources
,
881 /* Set 'BasicConfigVector' value */
882 if (DeviceNode
->ResourceRequirements
!= NULL
&&
883 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
885 RtlInitUnicodeString(&KeyName
,
886 L
"BasicConfigVector");
887 Status
= ZwSetValueKey(LogConfKey
,
890 REG_RESOURCE_REQUIREMENTS_LIST
,
891 DeviceNode
->ResourceRequirements
,
892 DeviceNode
->ResourceRequirements
->ListSize
);
899 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
901 /* Create the 'Control' key */
902 RtlInitUnicodeString(&KeyName
,
904 InitializeObjectAttributes(&ObjectAttributes
,
906 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
909 Status
= ZwCreateKey(&LogConfKey
,
916 if (NT_SUCCESS(Status
))
918 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
919 RtlInitUnicodeString(&KeyName
,
921 Status
= ZwSetValueKey(LogConfKey
,
933 DPRINT("IopSetDeviceInstanceData() done\n");
935 return STATUS_SUCCESS
;
940 IopAssignDeviceResources(
941 PDEVICE_NODE DeviceNode
)
943 PIO_RESOURCE_LIST ResourceList
;
944 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
945 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
946 ULONG NumberOfResources
= 0;
950 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
951 * by using DeviceNode->ResourceRequirements */
953 if (!DeviceNode
->ResourceRequirements
954 || DeviceNode
->ResourceRequirements
->AlternativeLists
== 0)
956 DeviceNode
->ResourceList
= DeviceNode
->ResourceListTranslated
= NULL
;
957 return STATUS_SUCCESS
;
960 /* FIXME: that's here that PnP arbiter should go */
961 /* Actually, simply use resource list #0 as assigned resource list */
962 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
963 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
965 Status
= STATUS_REVISION_MISMATCH
;
969 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
,
970 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
971 if (!DeviceNode
->ResourceList
)
973 Status
= STATUS_INSUFFICIENT_RESOURCES
;
977 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
,
978 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
979 if (!DeviceNode
->ResourceListTranslated
)
981 Status
= STATUS_INSUFFICIENT_RESOURCES
;
985 DeviceNode
->ResourceList
->Count
= 1;
986 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
987 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
988 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
989 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
991 DeviceNode
->ResourceListTranslated
->Count
= 1;
992 DeviceNode
->ResourceListTranslated
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
993 DeviceNode
->ResourceListTranslated
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
994 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Version
= 1;
995 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Revision
= 1;
997 for (i
= 0; i
< ResourceList
->Count
; i
++)
999 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1001 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1003 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1004 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1005 NumberOfResources
++;
1007 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1008 DescriptorRaw
->Type
= DescriptorTranslated
->Type
= ResourceDescriptor
->Type
;
1009 DescriptorRaw
->ShareDisposition
= DescriptorTranslated
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1010 DescriptorRaw
->Flags
= DescriptorTranslated
->Flags
= ResourceDescriptor
->Flags
;
1011 switch (ResourceDescriptor
->Type
)
1013 case CmResourceTypePort
:
1015 ULONG AddressSpace
= 0; /* IO space */
1016 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1017 DescriptorRaw
->u
.Port
.Length
= DescriptorTranslated
->u
.Port
.Length
1018 = ResourceDescriptor
->u
.Port
.Length
;
1019 if (!HalTranslateBusAddress(
1020 DeviceNode
->ResourceRequirements
->InterfaceType
,
1021 DeviceNode
->ResourceRequirements
->BusNumber
,
1022 DescriptorRaw
->u
.Port
.Start
,
1024 &DescriptorTranslated
->u
.Port
.Start
))
1026 Status
= STATUS_UNSUCCESSFUL
;
1031 case CmResourceTypeInterrupt
:
1033 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1034 /* FIXME: if IRQ 9 is in the possible range, use it.
1035 * This should be a PCI device */
1036 if (ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= 9
1037 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= 9)
1038 DescriptorRaw
->u
.Interrupt
.Vector
= 9;
1040 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1042 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1043 DeviceNode
->ResourceRequirements
->InterfaceType
,
1044 DeviceNode
->ResourceRequirements
->BusNumber
,
1045 DescriptorRaw
->u
.Interrupt
.Level
,
1046 DescriptorRaw
->u
.Interrupt
.Vector
,
1047 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1048 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1049 DescriptorTranslated
->u
.Interrupt
.Affinity
= DescriptorRaw
->u
.Interrupt
.Affinity
;
1052 case CmResourceTypeMemory
:
1054 ULONG AddressSpace
= 1; /* Memory space */
1055 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1056 DescriptorRaw
->u
.Memory
.Length
= DescriptorTranslated
->u
.Memory
.Length
1057 = ResourceDescriptor
->u
.Memory
.Length
;
1058 if (!HalTranslateBusAddress(
1059 DeviceNode
->ResourceRequirements
->InterfaceType
,
1060 DeviceNode
->ResourceRequirements
->BusNumber
,
1061 DescriptorRaw
->u
.Memory
.Start
,
1063 &DescriptorTranslated
->u
.Memory
.Start
))
1065 Status
= STATUS_UNSUCCESSFUL
;
1070 case CmResourceTypeDma
:
1072 DescriptorRaw
->u
.Dma
.Channel
= DescriptorTranslated
->u
.Dma
.Channel
1073 = ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1074 DescriptorRaw
->u
.Dma
.Port
= DescriptorTranslated
->u
.Dma
.Port
1076 DescriptorRaw
->u
.Dma
.Reserved1
= DescriptorTranslated
->u
.Dma
.Reserved1
1080 /*case CmResourceTypeBusNumber:
1082 DescriptorRaw->u.BusNumber.Start = DescriptorTranslated->u.BusNumber.Start
1083 = ResourceDescriptor->u.BusNumber.MinBusNumber;
1084 DescriptorRaw->u.BusNumber.Length = DescriptorTranslated->u.BusNumber.Length
1085 = ResourceDescriptor->u.BusNumber.Length;
1086 DescriptorRaw->u.BusNumber.Reserved = DescriptorTranslated->u.BusNumber.Reserved
1087 = ResourceDescriptor->u.BusNumber.Reserved;
1090 /*CmResourceTypeDevicePrivate:
1091 case CmResourceTypePcCardConfig:
1092 case CmResourceTypeMfCardConfig:
1095 &DescriptorRaw->u.DevicePrivate,
1096 &ResourceDescriptor->u.DevicePrivate,
1097 sizeof(ResourceDescriptor->u.DevicePrivate));
1099 &DescriptorTranslated->u.DevicePrivate,
1100 &ResourceDescriptor->u.DevicePrivate,
1101 sizeof(ResourceDescriptor->u.DevicePrivate));
1105 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1106 NumberOfResources
--;
1112 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1113 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1115 return STATUS_SUCCESS
;
1118 if (DeviceNode
->ResourceList
)
1120 ExFreePool(DeviceNode
->ResourceList
);
1121 DeviceNode
->ResourceList
= NULL
;
1123 if (DeviceNode
->ResourceListTranslated
)
1125 ExFreePool(DeviceNode
->ResourceListTranslated
);
1126 DeviceNode
->ResourceListTranslated
= NULL
;
1134 * IopActionInterrogateDeviceStack
1136 * Retrieve information for all (direct) child nodes of a parent node.
1140 * Pointer to device node.
1142 * Pointer to parent node to retrieve child node information for.
1145 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1146 * when we reach a device node which is not a direct child of the device
1147 * node for which we retrieve information of child nodes for. Any errors
1148 * that occur is logged instead so that all child services have a chance
1149 * of being interrogated.
1153 IopActionInterrogateDeviceStack(
1154 PDEVICE_NODE DeviceNode
,
1157 IO_STATUS_BLOCK IoStatusBlock
;
1158 PDEVICE_NODE ParentDeviceNode
;
1159 WCHAR InstancePath
[MAX_PATH
];
1160 IO_STACK_LOCATION Stack
;
1166 HANDLE InstanceKey
= NULL
;
1167 UNICODE_STRING ValueName
;
1168 DEVICE_CAPABILITIES DeviceCapabilities
;
1170 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1171 DPRINT("PDO %x\n", DeviceNode
->PhysicalDeviceObject
);
1173 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1176 * We are called for the parent too, but we don't need to do special
1177 * handling for this node
1180 if (DeviceNode
== ParentDeviceNode
)
1182 DPRINT("Success\n");
1183 return STATUS_SUCCESS
;
1187 * Make sure this device node is a direct child of the parent device node
1188 * that is given as an argument
1191 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1193 /* Stop the traversal immediately and indicate successful operation */
1195 return STATUS_UNSUCCESSFUL
;
1199 * FIXME: For critical errors, cleanup and disable device, but always
1200 * return STATUS_SUCCESS.
1203 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1205 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1206 Status
= IopInitiatePnpIrp(
1207 DeviceNode
->PhysicalDeviceObject
,
1211 if (NT_SUCCESS(Status
))
1213 /* Copy the device id string */
1214 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1217 * FIXME: Check for valid characters, if there is invalid characters
1223 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1226 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1228 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1229 Status
= IopInitiatePnpIrp(
1230 DeviceNode
->PhysicalDeviceObject
,
1234 if (NT_SUCCESS(Status
))
1236 /* Append the instance id string */
1237 wcscat(InstancePath
, L
"\\");
1238 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1241 * FIXME: Check for valid characters, if there is invalid characters
1247 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1250 RtlZeroMemory(&DeviceCapabilities
, sizeof(DEVICE_CAPABILITIES
));
1251 DeviceCapabilities
.Size
= sizeof(DEVICE_CAPABILITIES
);
1252 DeviceCapabilities
.Version
= 1;
1253 DeviceCapabilities
.Address
= -1;
1254 DeviceCapabilities
.UINumber
= -1;
1256 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= &DeviceCapabilities
;
1257 Status
= IopInitiatePnpIrp(
1258 DeviceNode
->PhysicalDeviceObject
,
1260 IRP_MN_QUERY_CAPABILITIES
,
1262 if (NT_SUCCESS(Status
))
1267 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1270 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1271 DeviceNode
->Address
= DeviceCapabilities
.Address
;
1273 if (!DeviceCapabilities
.UniqueID
)
1275 DPRINT("Instance ID is not unique\n");
1276 /* FIXME: Add information from parent bus driver to InstancePath */
1279 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
))
1281 DPRINT("No resources\n");
1282 /* FIXME: Cleanup and disable device */
1285 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1288 * Create registry key for the instance id, if it doesn't exist yet
1290 KeyBuffer
= ExAllocatePool(
1292 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1293 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1294 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1295 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
1297 ExFreePool(KeyBuffer
);
1298 if (!NT_SUCCESS(Status
))
1300 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1305 /* Set 'Capabilities' value */
1306 RtlInitUnicodeString(&ValueName
,
1308 Status
= ZwSetValueKey(InstanceKey
,
1312 (PVOID
)&DeviceNode
->CapabilityFlags
,
1315 /* Set 'UINumber' value */
1316 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1318 RtlInitUnicodeString(&ValueName
,
1320 Status
= ZwSetValueKey(InstanceKey
,
1324 &DeviceCapabilities
.UINumber
,
1329 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1331 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1332 Status
= IopInitiatePnpIrp(
1333 DeviceNode
->PhysicalDeviceObject
,
1337 if (NT_SUCCESS(Status
))
1340 * FIXME: Check for valid characters, if there is invalid characters
1344 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1345 DPRINT("Hardware IDs:\n");
1348 DPRINT(" %S\n", Ptr
);
1349 Length
= wcslen(Ptr
) + 1;
1352 TotalLength
+= Length
;
1354 DPRINT("TotalLength: %hu\n", TotalLength
);
1357 RtlInitUnicodeString(&ValueName
,
1359 Status
= ZwSetValueKey(InstanceKey
,
1363 (PVOID
)IoStatusBlock
.Information
,
1364 (TotalLength
+ 1) * sizeof(WCHAR
));
1365 if (!NT_SUCCESS(Status
))
1367 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1372 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1375 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1377 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1378 Status
= IopInitiatePnpIrp(
1379 DeviceNode
->PhysicalDeviceObject
,
1383 if (NT_SUCCESS(Status
))
1386 * FIXME: Check for valid characters, if there is invalid characters
1390 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1391 DPRINT("Compatible IDs:\n");
1394 DPRINT(" %S\n", Ptr
);
1395 Length
= wcslen(Ptr
) + 1;
1398 TotalLength
+= Length
;
1400 DPRINT("TotalLength: %hu\n", TotalLength
);
1403 RtlInitUnicodeString(&ValueName
,
1405 Status
= ZwSetValueKey(InstanceKey
,
1409 (PVOID
)IoStatusBlock
.Information
,
1410 (TotalLength
+ 1) * sizeof(WCHAR
));
1411 if (!NT_SUCCESS(Status
))
1413 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1418 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1422 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1424 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1425 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
1426 Status
= IopInitiatePnpIrp(
1427 DeviceNode
->PhysicalDeviceObject
,
1429 IRP_MN_QUERY_DEVICE_TEXT
,
1431 if (NT_SUCCESS(Status
))
1433 RtlInitUnicodeString(&ValueName
,
1435 Status
= ZwSetValueKey(InstanceKey
,
1439 (PVOID
)IoStatusBlock
.Information
,
1440 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1441 if (!NT_SUCCESS(Status
))
1443 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1448 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1451 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1453 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1454 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
1455 Status
= IopInitiatePnpIrp(
1456 DeviceNode
->PhysicalDeviceObject
,
1458 IRP_MN_QUERY_DEVICE_TEXT
,
1460 if (NT_SUCCESS(Status
))
1462 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1463 RtlInitUnicodeString(&ValueName
,
1464 L
"LocationInformation");
1465 Status
= ZwSetValueKey(InstanceKey
,
1469 (PVOID
)IoStatusBlock
.Information
,
1470 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1471 if (!NT_SUCCESS(Status
))
1473 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1478 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1481 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1483 Status
= IopInitiatePnpIrp(
1484 DeviceNode
->PhysicalDeviceObject
,
1486 IRP_MN_QUERY_BUS_INFORMATION
,
1488 if (NT_SUCCESS(Status
))
1490 PPNP_BUS_INFORMATION BusInformation
=
1491 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1493 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1494 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1495 memcpy(&DeviceNode
->BusTypeGuid
,
1496 &BusInformation
->BusTypeGuid
,
1498 ExFreePool(BusInformation
);
1502 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1504 DeviceNode
->ChildBusNumber
= -1;
1505 DeviceNode
->ChildInterfaceType
= -1;
1506 memset(&DeviceNode
->BusTypeGuid
,
1511 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1513 Status
= IopInitiatePnpIrp(
1514 DeviceNode
->PhysicalDeviceObject
,
1516 IRP_MN_QUERY_RESOURCES
,
1518 if (NT_SUCCESS(Status
))
1520 DeviceNode
->BootResources
=
1521 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1522 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1526 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1527 DeviceNode
->BootResources
= NULL
;
1530 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1532 Status
= IopInitiatePnpIrp(
1533 DeviceNode
->PhysicalDeviceObject
,
1535 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1537 if (NT_SUCCESS(Status
))
1539 DeviceNode
->ResourceRequirements
=
1540 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1544 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1545 DeviceNode
->ResourceRequirements
= NULL
;
1549 if (InstanceKey
!= NULL
)
1551 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1554 ZwClose(InstanceKey
);
1556 Status
= IopAssignDeviceResources(DeviceNode
);
1557 if (!NT_SUCCESS(Status
))
1559 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status
);
1562 DeviceNode
->Flags
|= DNF_PROCESSED
;
1564 /* Report the device to the user-mode pnp manager */
1565 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1566 &DeviceNode
->InstancePath
);
1568 return STATUS_SUCCESS
;
1572 * IopActionConfigureChildServices
1574 * Retrieve configuration for all (direct) child nodes of a parent node.
1578 * Pointer to device node.
1580 * Pointer to parent node to retrieve child node configuration for.
1583 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1584 * when we reach a device node which is not a direct child of the device
1585 * node for which we configure child services for. Any errors that occur is
1586 * logged instead so that all child services have a chance of beeing
1591 IopActionConfigureChildServices(
1592 PDEVICE_NODE DeviceNode
,
1595 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1596 PDEVICE_NODE ParentDeviceNode
;
1597 PUNICODE_STRING Service
;
1600 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1602 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1605 * We are called for the parent too, but we don't need to do special
1606 * handling for this node
1608 if (DeviceNode
== ParentDeviceNode
)
1610 DPRINT("Success\n");
1611 return STATUS_SUCCESS
;
1615 * Make sure this device node is a direct child of the parent device node
1616 * that is given as an argument
1618 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1620 /* Stop the traversal immediately and indicate successful operation */
1622 return STATUS_UNSUCCESSFUL
;
1625 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1627 WCHAR RegKeyBuffer
[MAX_PATH
];
1628 UNICODE_STRING RegKey
;
1631 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
1632 RegKey
.Buffer
= RegKeyBuffer
;
1635 * Retrieve configuration from Enum key
1638 Service
= &DeviceNode
->ServiceName
;
1640 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1641 RtlInitUnicodeString(Service
, NULL
);
1643 QueryTable
[0].Name
= L
"Service";
1644 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1645 QueryTable
[0].EntryContext
= Service
;
1647 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1648 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
1650 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
1651 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
1653 if (!NT_SUCCESS(Status
))
1655 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1656 /* FIXME: Log the error */
1657 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1658 DeviceNode
->InstancePath
.Buffer
, Status
);
1659 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1660 return STATUS_SUCCESS
;
1663 if (Service
->Buffer
== NULL
)
1665 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1666 return STATUS_SUCCESS
;
1669 DPRINT("Got Service %S\n", Service
->Buffer
);
1672 return STATUS_SUCCESS
;
1676 * IopActionInitChildServices
1678 * Initialize the service for all (direct) child nodes of a parent node
1682 * Pointer to device node.
1684 * Pointer to parent node to initialize child node services for.
1686 * Load only driver marked as boot start.
1689 * If the driver image for a service is not loaded and initialized
1690 * it is done here too. We only return a status code indicating an
1691 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1692 * not a direct child of the device node for which we initialize
1693 * child services for. Any errors that occur is logged instead so
1694 * that all child services have a chance of being initialized.
1698 IopActionInitChildServices(
1699 PDEVICE_NODE DeviceNode
,
1701 BOOLEAN BootDrivers
)
1703 PDEVICE_NODE ParentDeviceNode
;
1706 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1709 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1712 * We are called for the parent too, but we don't need to do special
1713 * handling for this node
1715 if (DeviceNode
== ParentDeviceNode
)
1717 DPRINT("Success\n");
1718 return STATUS_SUCCESS
;
1722 * Make sure this device node is a direct child of the parent device node
1723 * that is given as an argument
1726 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1729 * Stop the traversal immediately and indicate unsuccessful operation
1732 return STATUS_UNSUCCESSFUL
;
1736 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1737 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1738 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1740 PMODULE_OBJECT ModuleObject
;
1741 PDRIVER_OBJECT DriverObject
;
1743 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1744 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
1746 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
1747 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
1748 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
1751 /* get existing DriverObject pointer */
1752 Status
= IopGetDriverObject(
1754 &DeviceNode
->ServiceName
,
1757 if (NT_SUCCESS(Status
))
1759 /* Attach lower level filter drivers. */
1760 IopAttachFilterDrivers(DeviceNode
, TRUE
);
1761 /* Initialize the function driver for the device node */
1762 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1763 if (NT_SUCCESS(Status
))
1765 /* Attach upper level filter drivers. */
1766 IopAttachFilterDrivers(DeviceNode
, FALSE
);
1767 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1769 Status
= IopStartDevice(DeviceNode
);
1776 * Don't disable when trying to load only boot drivers
1780 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1781 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1783 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1784 CPRINT("Initialization of service %S failed (Status %x)\n",
1785 DeviceNode
->ServiceName
.Buffer
, Status
);
1789 DPRINT("Service %S is disabled or already initialized\n",
1790 DeviceNode
->ServiceName
.Buffer
);
1793 return STATUS_SUCCESS
;
1797 * IopActionInitAllServices
1799 * Initialize the service for all (direct) child nodes of a parent node. This
1800 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1804 IopActionInitAllServices(
1805 PDEVICE_NODE DeviceNode
,
1808 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1812 * IopActionInitBootServices
1814 * Initialize the boot start services for all (direct) child nodes of a
1815 * parent node. This function just calls IopActionInitChildServices with
1816 * BootDrivers = TRUE.
1819 IopActionInitBootServices(
1820 PDEVICE_NODE DeviceNode
,
1823 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1827 * IopInitializePnpServices
1829 * Initialize services for discovered children
1833 * Top device node to start initializing services.
1836 * When set to TRUE, only drivers marked as boot start will
1837 * be loaded. Otherwise, all drivers will be loaded.
1843 IopInitializePnpServices(
1844 IN PDEVICE_NODE DeviceNode
,
1845 IN BOOLEAN BootDrivers
)
1847 DEVICETREE_TRAVERSE_CONTEXT Context
;
1849 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1853 IopInitDeviceTreeTraverseContext(
1856 IopActionInitBootServices
,
1861 IopInitDeviceTreeTraverseContext(
1864 IopActionInitAllServices
,
1868 return IopTraverseDeviceTree(&Context
);
1873 IopInvalidateDeviceRelations(
1874 IN PDEVICE_NODE DeviceNode
,
1875 IN DEVICE_RELATION_TYPE Type
)
1877 DEVICETREE_TRAVERSE_CONTEXT Context
;
1878 PDEVICE_RELATIONS DeviceRelations
;
1879 IO_STATUS_BLOCK IoStatusBlock
;
1880 PDEVICE_NODE ChildDeviceNode
;
1881 IO_STACK_LOCATION Stack
;
1883 OBJECT_ATTRIBUTES ObjectAttributes
;
1884 UNICODE_STRING LinkName
;
1889 DPRINT("DeviceNode %x\n", DeviceNode
);
1891 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1893 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1895 Status
= IopInitiatePnpIrp(
1896 DeviceNode
->PhysicalDeviceObject
,
1898 IRP_MN_QUERY_DEVICE_RELATIONS
,
1900 if (!NT_SUCCESS(Status
))
1902 DPRINT("IopInitiatePnpIrp() failed\n");
1906 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1908 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1910 DPRINT("No PDOs\n");
1911 if (DeviceRelations
)
1913 ExFreePool(DeviceRelations
);
1915 return STATUS_SUCCESS
;
1918 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1921 * Create device nodes for all discovered devices
1924 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1926 Status
= IopCreateDeviceNode(
1928 DeviceRelations
->Objects
[i
],
1930 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1931 if (!NT_SUCCESS(Status
))
1933 DPRINT("No resources\n");
1934 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1935 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1936 ExFreePool(DeviceRelations
);
1937 return STATUS_INSUFFICIENT_RESOURCES
;
1940 ExFreePool(DeviceRelations
);
1943 * Retrieve information about all discovered children from the bus driver
1946 IopInitDeviceTreeTraverseContext(
1949 IopActionInterrogateDeviceStack
,
1952 Status
= IopTraverseDeviceTree(&Context
);
1953 if (!NT_SUCCESS(Status
))
1955 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1960 * Retrieve configuration from the registry for discovered children
1963 IopInitDeviceTreeTraverseContext(
1966 IopActionConfigureChildServices
,
1969 Status
= IopTraverseDeviceTree(&Context
);
1970 if (!NT_SUCCESS(Status
))
1972 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1977 * Get the state of the system boot. If the \\SystemRoot link isn't
1978 * created yet, we will assume that it's possible to load only boot
1982 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
1984 InitializeObjectAttributes(
1991 Status
= ZwOpenFile(
1998 if(NT_SUCCESS(Status
))
2000 BootDrivers
= FALSE
;
2007 * Initialize services for discovered children. Only boot drivers will
2008 * be loaded from boot driver!
2011 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2012 if (!NT_SUCCESS(Status
))
2014 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
2018 return STATUS_SUCCESS
;
2022 static NTSTATUS INIT_FUNCTION
2023 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
)
2027 HANDLE InstanceKey
= NULL
;
2030 /* Create registry key for the instance id, if it doesn't exist yet */
2031 KeyBuffer
= ExAllocatePool(PagedPool
,
2032 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
2033 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2034 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
2035 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
2037 ExFreePool(KeyBuffer
);
2038 if (!NT_SUCCESS(Status
))
2040 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2044 /* FIXME: Set 'ConfigFlags' value */
2046 ZwClose(InstanceKey
);
2050 return STATUS_SUCCESS
;
2060 DPRINT("PnpInit()\n");
2062 KeInitializeSpinLock(&IopDeviceTreeLock
);
2064 /* Initialize PnP-Event notification support */
2065 Status
= IopInitPlugPlayEvents();
2066 if (!NT_SUCCESS(Status
))
2068 CPRINT("IopInitPlugPlayEvents() failed\n");
2069 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2073 * Create root device node
2076 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
2077 if (!NT_SUCCESS(Status
))
2079 CPRINT("IoCreateDriverObject() failed\n");
2080 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2083 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2085 if (!NT_SUCCESS(Status
))
2087 CPRINT("IoCreateDevice() failed\n");
2088 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2091 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
2092 if (!NT_SUCCESS(Status
))
2094 CPRINT("Insufficient resources\n");
2095 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2098 if (!IopCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2102 CPRINT("Failed to create the instance path!\n");
2103 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_UNSUCCESSFUL
, 0, 0, 0);
2106 /* Report the device to the user-mode pnp manager */
2107 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2108 &IopRootDeviceNode
->InstancePath
);
2110 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2111 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2112 IopRootDriverObject
->DriverExtension
->AddDevice(
2113 IopRootDriverObject
,
2114 IopRootDeviceNode
->PhysicalDeviceObject
);
2123 /* Set root device instance data */
2124 Status
= IopSetRootDeviceInstanceData(IopRootDeviceNode
);
2125 if (!NT_SUCCESS(Status
))
2127 CPRINT("Failed to set instance data\n");
2128 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);