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)
8 * Hervé Poussineau (hpoussin@reactos.org)
11 /* INCLUDES ******************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS *******************************************************************/
20 PDEVICE_NODE IopRootDeviceNode
;
21 KSPIN_LOCK IopDeviceTreeLock
;
23 /* DATA **********************************************************************/
25 PDRIVER_OBJECT IopRootDriverObject
;
26 PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList
= NULL
;
28 static NTSTATUS INIT_FUNCTION
29 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
);
31 #if defined (ALLOC_PRAGMA)
32 #pragma alloc_text(INIT, IopSetRootDeviceInstanceData)
33 #pragma alloc_text(INIT, PnpInit)
34 #pragma alloc_text(INIT, PnpInit2)
38 /* FUNCTIONS *****************************************************************/
42 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
44 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
49 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
50 PDRIVER_OBJECT DriverObject
)
54 BOOLEAN IsPnpDriver
= FALSE
;
56 if (DriverObject
->DriverExtension
->AddDevice
)
58 /* This is a Plug and Play driver */
59 DPRINT("Plug and Play driver found\n");
61 ASSERT(DeviceNode
->PhysicalDeviceObject
);
63 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
64 DriverObject
->DriverExtension
->AddDevice
);
66 IsPnpDriver
= !IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
67 Status
= DriverObject
->DriverExtension
->AddDevice(
68 DriverObject
, IsPnpDriver
? DeviceNode
->PhysicalDeviceObject
: NULL
);
70 if (!NT_SUCCESS(Status
))
77 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
79 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
81 /* FIXME: What do we do? Unload the driver or just disable the device? */
82 DbgPrint("An FDO was not attached\n");
83 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
84 return STATUS_UNSUCCESSFUL
;
87 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
89 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
91 /* There can be only one system power device */
92 if (!SystemPowerDeviceNodeCreated
)
94 PopSystemPowerDeviceNode
= DeviceNode
;
95 SystemPowerDeviceNodeCreated
= TRUE
;
99 ObDereferenceObject(Fdo
);
102 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
103 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
106 return STATUS_SUCCESS
;
111 PDEVICE_NODE DeviceNode
)
113 IO_STATUS_BLOCK IoStatusBlock
;
114 IO_STACK_LOCATION Stack
;
118 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
120 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
121 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
122 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
124 Status
= IopInitiatePnpIrp(
130 if (!NT_SUCCESS(Status
))
132 DPRINT("IopInitiatePnpIrp() failed\n");
136 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
138 DPRINT("Device needs enumeration, invalidating bus relations\n");
139 Status
= IopInvalidateDeviceRelations(DeviceNode
, BusRelations
);
140 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
144 ObDereferenceObject(Fdo
);
146 if (NT_SUCCESS(Status
))
147 DeviceNode
->Flags
|= DN_STARTED
;
154 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
155 PDEVICE_CAPABILITIES DeviceCaps
)
157 IO_STATUS_BLOCK StatusBlock
;
158 IO_STACK_LOCATION Stack
;
160 /* Set up the Header */
161 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
162 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
163 DeviceCaps
->Version
= 1;
164 DeviceCaps
->Address
= -1;
165 DeviceCaps
->UINumber
= -1;
167 /* Set up the Stack */
168 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
169 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
172 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
174 IRP_MN_QUERY_CAPABILITIES
,
183 IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject
,
184 IN DEVICE_RELATION_TYPE Type
)
186 IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject
), Type
);
194 IoSynchronousInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject
,
195 IN DEVICE_RELATION_TYPE Type
)
205 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
206 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
207 IN ULONG BufferLength
,
208 OUT PVOID PropertyBuffer
,
209 OUT PULONG ResultLength
)
211 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
212 DEVICE_CAPABILITIES DeviceCaps
;
218 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
220 if (DeviceNode
== NULL
)
221 return STATUS_INVALID_DEVICE_REQUEST
;
223 switch (DeviceProperty
)
225 case DevicePropertyBusNumber
:
226 Length
= sizeof(ULONG
);
227 Data
= &DeviceNode
->ChildBusNumber
;
230 /* Complete, untested */
231 case DevicePropertyBusTypeGuid
:
233 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
234 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
236 /* Return the GUID */
237 *ResultLength
= sizeof(GUID
);
239 /* Check if the buffer given was large enough */
240 if (BufferLength
< *ResultLength
)
242 return STATUS_BUFFER_TOO_SMALL
;
246 RtlCopyMemory(PropertyBuffer
,
247 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
249 return STATUS_SUCCESS
;
253 return STATUS_OBJECT_NAME_NOT_FOUND
;
257 case DevicePropertyLegacyBusType
:
258 Length
= sizeof(INTERFACE_TYPE
);
259 Data
= &DeviceNode
->ChildInterfaceType
;
262 case DevicePropertyAddress
:
263 /* Query the device caps */
264 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
265 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
268 *ResultLength
= sizeof(ULONG
);
270 /* Check if the buffer given was large enough */
271 if (BufferLength
< *ResultLength
)
273 return STATUS_BUFFER_TOO_SMALL
;
277 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
278 return STATUS_SUCCESS
;
282 return STATUS_OBJECT_NAME_NOT_FOUND
;
286 // case DevicePropertyUINumber:
287 // if (DeviceNode->CapabilityFlags == NULL)
288 // return STATUS_INVALID_DEVICE_REQUEST;
289 // Length = sizeof(ULONG);
290 // Data = &DeviceNode->CapabilityFlags->UINumber;
293 case DevicePropertyClassName
:
294 case DevicePropertyClassGuid
:
295 case DevicePropertyDriverKeyName
:
296 case DevicePropertyManufacturer
:
297 case DevicePropertyFriendlyName
:
298 case DevicePropertyHardwareID
:
299 case DevicePropertyCompatibleIDs
:
300 case DevicePropertyDeviceDescription
:
301 case DevicePropertyLocationInformation
:
302 case DevicePropertyUINumber
:
304 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
305 UNICODE_STRING KeyName
, ValueName
;
306 OBJECT_ATTRIBUTES ObjectAttributes
;
307 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
308 ULONG ValueInformationLength
;
312 switch (DeviceProperty
)
314 case DevicePropertyClassName
:
315 RegistryPropertyName
= L
"Class"; break;
316 case DevicePropertyClassGuid
:
317 RegistryPropertyName
= L
"ClassGuid"; break;
318 case DevicePropertyDriverKeyName
:
319 RegistryPropertyName
= L
"Driver"; break;
320 case DevicePropertyManufacturer
:
321 RegistryPropertyName
= L
"Mfg"; break;
322 case DevicePropertyFriendlyName
:
323 RegistryPropertyName
= L
"FriendlyName"; break;
324 case DevicePropertyHardwareID
:
325 RegistryPropertyName
= L
"HardwareID"; break;
326 case DevicePropertyCompatibleIDs
:
327 RegistryPropertyName
= L
"CompatibleIDs"; break;
328 case DevicePropertyDeviceDescription
:
329 RegistryPropertyName
= L
"DeviceDesc"; break;
330 case DevicePropertyLocationInformation
:
331 RegistryPropertyName
= L
"LocationInformation"; break;
332 case DevicePropertyUINumber
:
333 RegistryPropertyName
= L
"UINumber"; break;
335 RegistryPropertyName
= NULL
; break;
338 KeyNameBuffer
= ExAllocatePool(PagedPool
,
339 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
341 DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer
, RegistryPropertyName
);
343 if (KeyNameBuffer
== NULL
)
344 return STATUS_INSUFFICIENT_RESOURCES
;
346 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
347 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
348 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
349 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
350 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
352 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
353 ExFreePool(KeyNameBuffer
);
354 if (!NT_SUCCESS(Status
))
357 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
358 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
359 Data
[0]) + BufferLength
;
360 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
361 if (ValueInformation
== NULL
)
364 return STATUS_INSUFFICIENT_RESOURCES
;
367 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
368 KeyValuePartialInformation
, ValueInformation
,
369 ValueInformationLength
,
370 &ValueInformationLength
);
371 *ResultLength
= ValueInformation
->DataLength
;
374 if (!NT_SUCCESS(Status
))
376 ExFreePool(ValueInformation
);
377 if (Status
== STATUS_BUFFER_OVERFLOW
)
378 return STATUS_BUFFER_TOO_SMALL
;
383 /* FIXME: Verify the value (NULL-terminated, correct format). */
385 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
386 ValueInformation
->DataLength
);
387 ExFreePool(ValueInformation
);
389 return STATUS_SUCCESS
;
392 case DevicePropertyBootConfiguration
:
394 if (DeviceNode
->BootResources
->Count
!= 0)
396 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
398 Data
= &DeviceNode
->BootResources
;
401 /* FIXME: use a translated boot configuration instead */
402 case DevicePropertyBootConfigurationTranslated
:
404 if (DeviceNode
->BootResources
->Count
!= 0)
406 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
408 Data
= &DeviceNode
->BootResources
;
411 case DevicePropertyEnumeratorName
:
412 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
415 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
416 Data
= DeviceNode
->InstancePath
.Buffer
;
425 case DevicePropertyPhysicalDeviceObjectName
:
426 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
427 Data
= DeviceNode
->InstancePath
.Buffer
;
431 return STATUS_INVALID_PARAMETER_2
;
434 *ResultLength
= Length
;
435 if (BufferLength
< Length
)
436 return STATUS_BUFFER_TOO_SMALL
;
437 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
439 /* Terminate the string */
440 if (DeviceProperty
== DevicePropertyEnumeratorName
441 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
443 Ptr
= (PWSTR
)PropertyBuffer
;
444 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
447 return STATUS_SUCCESS
;
455 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
461 * @name IoOpenDeviceRegistryKey
463 * Open a registry key unique for a specified driver or device instance.
465 * @param DeviceObject Device to get the registry key for.
466 * @param DevInstKeyType Type of the key to return.
467 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
468 * @param DevInstRegKey Handle to the opened registry key on
477 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
478 IN ULONG DevInstKeyType
,
479 IN ACCESS_MASK DesiredAccess
,
480 OUT PHANDLE DevInstRegKey
)
482 static WCHAR RootKeyName
[] =
483 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
484 static WCHAR ProfileKeyName
[] =
485 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
486 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
487 static WCHAR EnumKeyName
[] = L
"Enum\\";
488 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
490 LPWSTR KeyNameBuffer
;
491 UNICODE_STRING KeyName
;
492 ULONG DriverKeyLength
;
493 OBJECT_ATTRIBUTES ObjectAttributes
;
494 PDEVICE_NODE DeviceNode
= NULL
;
497 DPRINT("IoOpenDeviceRegistryKey() called\n");
499 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
501 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
502 return STATUS_INVALID_PARAMETER
;
506 * Calculate the length of the base key name. This is the full
507 * name for driver key or the name excluding "Device Parameters"
508 * subkey for device key.
511 KeyNameLength
= sizeof(RootKeyName
);
512 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
513 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
514 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
516 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
517 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
518 0, NULL
, &DriverKeyLength
);
519 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
521 KeyNameLength
+= DriverKeyLength
;
525 DeviceNode
= IopGetDeviceNode(DeviceObject
);
526 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
527 DeviceNode
->InstancePath
.Length
;
531 * Now allocate the buffer for the key name...
534 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
535 if (KeyNameBuffer
== NULL
)
536 return STATUS_INSUFFICIENT_RESOURCES
;
539 KeyName
.MaximumLength
= KeyNameLength
;
540 KeyName
.Buffer
= KeyNameBuffer
;
543 * ...and build the key name.
546 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
547 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
549 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
550 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
552 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
554 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
555 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
556 DriverKeyLength
, KeyNameBuffer
+
557 (KeyName
.Length
/ sizeof(WCHAR
)),
559 if (!NT_SUCCESS(Status
))
561 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
562 ExFreePool(KeyNameBuffer
);
565 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
569 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
570 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
571 if (DeviceNode
->InstancePath
.Length
== 0)
573 ExFreePool(KeyNameBuffer
);
582 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
583 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
584 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
585 if (!NT_SUCCESS(Status
))
587 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
588 ExFreePool(KeyNameBuffer
);
591 ExFreePool(KeyNameBuffer
);
594 * For driver key we're done now.
597 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
601 * Let's go further. For device key we must open "Device Parameters"
602 * subkey and create it if it doesn't exist yet.
605 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
606 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
607 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
608 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
609 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
610 ZwClose(ObjectAttributes
.RootDirectory
);
620 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
627 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
631 if (PopSystemPowerDeviceNode
)
633 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
634 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
635 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
637 return STATUS_SUCCESS
;
640 return STATUS_UNSUCCESSFUL
;
645 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
647 USHORT i
= 0, FoundIndex
= 0xFFFF;
651 /* Acquire the lock */
652 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
654 /* Loop all entries */
655 while (i
< IopBusTypeGuidList
->GuidCount
)
657 /* Try to find a match */
658 if (RtlCompareMemory(BusTypeGuid
,
659 &IopBusTypeGuidList
->Guids
[i
],
660 sizeof(GUID
)) == sizeof(GUID
))
669 /* Check if we have to grow the list */
670 if (IopBusTypeGuidList
->GuidCount
)
672 /* Calculate the new size */
673 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
674 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
676 /* Allocate the new copy */
677 NewList
= ExAllocatePool(PagedPool
, NewSize
);
679 /* Now copy them, decrease the size too */
680 NewSize
-= sizeof(GUID
);
681 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
683 /* Free the old list */
684 ExFreePool(IopBusTypeGuidList
);
686 /* Use the new buffer */
687 IopBusTypeGuidList
= NewList
;
690 /* Copy the new GUID */
691 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
695 /* The new entry is the index */
696 FoundIndex
= IopBusTypeGuidList
->GuidCount
;
697 IopBusTypeGuidList
->GuidCount
++;
700 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
706 * Creates a device node
709 * ParentNode = Pointer to parent device node
710 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
711 * to have the root device node create one
712 * (eg. for legacy drivers)
713 * DeviceNode = Pointer to storage for created device node
719 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
720 PDEVICE_OBJECT PhysicalDeviceObject
,
721 PDEVICE_NODE
*DeviceNode
)
727 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
728 ParentNode
, PhysicalDeviceObject
);
730 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
733 return STATUS_INSUFFICIENT_RESOURCES
;
736 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
738 if (!PhysicalDeviceObject
)
740 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
741 if (!NT_SUCCESS(Status
))
747 /* This is for drivers passed on the command line to ntoskrnl.exe */
748 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
749 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
752 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
754 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
758 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
759 Node
->Parent
= ParentNode
;
760 Node
->NextSibling
= ParentNode
->Child
;
761 if (ParentNode
->Child
!= NULL
)
763 ParentNode
->Child
->PrevSibling
= Node
;
765 ParentNode
->Child
= Node
;
766 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
767 Node
->Level
= ParentNode
->Level
+ 1;
772 return STATUS_SUCCESS
;
776 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
780 /* All children must be deleted before a parent is deleted */
781 ASSERT(!DeviceNode
->Child
);
783 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
785 ASSERT(DeviceNode
->PhysicalDeviceObject
);
787 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
789 /* Unlink from parent if it exists */
791 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
793 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
796 /* Unlink from sibling list */
798 if (DeviceNode
->PrevSibling
)
800 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
803 if (DeviceNode
->NextSibling
)
805 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
808 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
810 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
812 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
814 if (DeviceNode
->ResourceList
)
816 ExFreePool(DeviceNode
->ResourceList
);
819 if (DeviceNode
->ResourceListTranslated
)
821 ExFreePool(DeviceNode
->ResourceListTranslated
);
824 if (DeviceNode
->ResourceRequirements
)
826 ExFreePool(DeviceNode
->ResourceRequirements
);
829 if (DeviceNode
->BootResources
)
831 ExFreePool(DeviceNode
->BootResources
);
834 ExFreePool(DeviceNode
);
836 return STATUS_SUCCESS
;
840 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
841 PIO_STATUS_BLOCK IoStatusBlock
,
843 PIO_STACK_LOCATION Stack OPTIONAL
)
845 PDEVICE_OBJECT TopDeviceObject
;
846 PIO_STACK_LOCATION IrpSp
;
851 /* Always call the top of the device stack */
852 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
859 Irp
= IoBuildSynchronousFsdRequest(
868 /* PNP IRPs are always initialized with a status code of
869 STATUS_NOT_IMPLEMENTED */
870 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
871 Irp
->IoStatus
.Information
= 0;
873 IrpSp
= IoGetNextIrpStackLocation(Irp
);
874 IrpSp
->MinorFunction
= MinorFunction
;
878 RtlMoveMemory(&IrpSp
->Parameters
,
880 sizeof(Stack
->Parameters
));
883 Status
= IoCallDriver(TopDeviceObject
, Irp
);
884 if (Status
== STATUS_PENDING
)
886 KeWaitForSingleObject(&Event
,
891 Status
= IoStatusBlock
->Status
;
894 ObDereferenceObject(TopDeviceObject
);
901 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
903 PDEVICE_NODE ParentDeviceNode
;
904 PDEVICE_NODE ChildDeviceNode
;
907 /* Copy context data so we don't overwrite it in subsequent calls to this function */
908 ParentDeviceNode
= Context
->DeviceNode
;
910 /* Call the action routine */
911 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
912 if (!NT_SUCCESS(Status
))
917 /* Traversal of all children nodes */
918 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
919 ChildDeviceNode
!= NULL
;
920 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
922 /* Pass the current device node to the action routine */
923 Context
->DeviceNode
= ChildDeviceNode
;
925 Status
= IopTraverseDeviceTreeNode(Context
);
926 if (!NT_SUCCESS(Status
))
937 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
941 DPRINT("Context 0x%p\n", Context
);
943 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
944 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
946 /* Start from the specified device node */
947 Context
->DeviceNode
= Context
->FirstDeviceNode
;
949 /* Recursively traverse the device tree */
950 Status
= IopTraverseDeviceTreeNode(Context
);
951 if (Status
== STATUS_UNSUCCESSFUL
)
953 /* The action routine just wanted to terminate the traversal with status
954 code STATUS_SUCCESS */
955 Status
= STATUS_SUCCESS
;
964 IopCreateDeviceKeyPath(PWSTR Path
,
967 OBJECT_ATTRIBUTES ObjectAttributes
;
968 WCHAR KeyBuffer
[MAX_PATH
];
969 UNICODE_STRING KeyName
;
977 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
979 return STATUS_INVALID_PARAMETER
;
982 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
984 /* Skip \\Registry\\ */
986 Current
= wcschr (Current
, L
'\\') + 1;
987 Current
= wcschr (Current
, L
'\\') + 1;
991 Next
= wcschr (Current
, L
'\\');
1001 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
1002 InitializeObjectAttributes (&ObjectAttributes
,
1004 OBJ_CASE_INSENSITIVE
,
1008 DPRINT("Create '%S'\n", KeyName
.Buffer
);
1010 Status
= ZwCreateKey (&KeyHandle
,
1017 if (!NT_SUCCESS (Status
))
1019 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
1025 *Handle
= KeyHandle
;
1026 return STATUS_SUCCESS
;
1030 ZwClose (KeyHandle
);
1037 return STATUS_UNSUCCESSFUL
;
1043 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1044 PDEVICE_NODE DeviceNode
)
1046 OBJECT_ATTRIBUTES ObjectAttributes
;
1047 UNICODE_STRING KeyName
;
1050 ULONG ListSize
, ResultLength
;
1053 DPRINT("IopSetDeviceInstanceData() called\n");
1055 /* Create the 'LogConf' key */
1056 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1057 InitializeObjectAttributes(&ObjectAttributes
,
1059 OBJ_CASE_INSENSITIVE
,
1062 Status
= ZwCreateKey(&LogConfKey
,
1069 if (NT_SUCCESS(Status
))
1071 /* Set 'BootConfig' value */
1072 if (DeviceNode
->BootResources
!= NULL
)
1074 ResCount
= DeviceNode
->BootResources
->Count
;
1077 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1079 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1080 Status
= ZwSetValueKey(LogConfKey
,
1084 &DeviceNode
->BootResources
,
1089 /* Set 'BasicConfigVector' value */
1090 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1091 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1093 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1094 Status
= ZwSetValueKey(LogConfKey
,
1097 REG_RESOURCE_REQUIREMENTS_LIST
,
1098 DeviceNode
->ResourceRequirements
,
1099 DeviceNode
->ResourceRequirements
->ListSize
);
1102 ZwClose(LogConfKey
);
1105 /* Set the 'ConfigFlags' value */
1106 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1107 Status
= ZwQueryValueKey(InstanceKey
,
1109 KeyValueBasicInformation
,
1113 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1115 /* Write the default value */
1116 ULONG DefaultConfigFlags
= 0;
1117 Status
= ZwSetValueKey(InstanceKey
,
1121 &DefaultConfigFlags
,
1122 sizeof(DefaultConfigFlags
));
1126 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1128 /* Create the 'Control' key */
1129 RtlInitUnicodeString(&KeyName
,
1131 InitializeObjectAttributes(&ObjectAttributes
,
1133 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1136 Status
= ZwCreateKey(&LogConfKey
,
1141 REG_OPTION_VOLATILE
,
1143 if (NT_SUCCESS(Status
))
1145 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1146 RtlInitUnicodeString(&KeyName
,
1147 L
"DeviceReference");
1148 Status
= ZwSetValueKey(LogConfKey
,
1155 ZwClose(LogConfKey
);
1160 DPRINT("IopSetDeviceInstanceData() done\n");
1162 return STATUS_SUCCESS
;
1167 IopAssignDeviceResources(PDEVICE_NODE DeviceNode
)
1169 PIO_RESOURCE_LIST ResourceList
;
1170 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1171 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1172 ULONG NumberOfResources
= 0;
1176 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
1177 * by using DeviceNode->ResourceRequirements */
1179 if (!DeviceNode
->ResourceRequirements
1180 || DeviceNode
->ResourceRequirements
->AlternativeLists
== 0)
1182 DeviceNode
->ResourceList
= DeviceNode
->ResourceListTranslated
= NULL
;
1183 return STATUS_SUCCESS
;
1186 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1188 /* FIXME: that's here that PnP arbiter should go */
1189 /* Actually, simply use resource list #0 as assigned resource list */
1190 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1191 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1193 Status
= STATUS_REVISION_MISMATCH
;
1197 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
,
1198 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1199 if (!DeviceNode
->ResourceList
)
1201 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1205 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
,
1206 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1207 if (!DeviceNode
->ResourceListTranslated
)
1209 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1213 DeviceNode
->ResourceList
->Count
= 1;
1214 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1215 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1216 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1217 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1219 DeviceNode
->ResourceListTranslated
->Count
= 1;
1220 DeviceNode
->ResourceListTranslated
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1221 DeviceNode
->ResourceListTranslated
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1222 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Version
= 1;
1223 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Revision
= 1;
1225 for (i
= 0; i
< ResourceList
->Count
; i
++)
1227 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1229 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1231 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1232 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1233 NumberOfResources
++;
1235 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1236 DescriptorRaw
->Type
= DescriptorTranslated
->Type
= ResourceDescriptor
->Type
;
1237 DescriptorRaw
->ShareDisposition
= DescriptorTranslated
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1238 DescriptorRaw
->Flags
= DescriptorTranslated
->Flags
= ResourceDescriptor
->Flags
;
1239 switch (ResourceDescriptor
->Type
)
1241 case CmResourceTypePort
:
1243 ULONG AddressSpace
= 0; /* IO space */
1244 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1245 DescriptorRaw
->u
.Port
.Length
= DescriptorTranslated
->u
.Port
.Length
1246 = ResourceDescriptor
->u
.Port
.Length
;
1247 if (!HalTranslateBusAddress(
1248 DeviceNode
->ResourceRequirements
->InterfaceType
,
1249 DeviceNode
->ResourceRequirements
->BusNumber
,
1250 DescriptorRaw
->u
.Port
.Start
,
1252 &DescriptorTranslated
->u
.Port
.Start
))
1254 Status
= STATUS_UNSUCCESSFUL
;
1259 case CmResourceTypeInterrupt
:
1261 INTERFACE_TYPE BusType
;
1266 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1267 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1268 /* FIXME: HACK: if we have a PCI device, we try
1269 * to keep the IRQ assigned by the BIOS */
1270 if (NT_SUCCESS(IoGetDeviceProperty(
1271 DeviceNode
->PhysicalDeviceObject
,
1272 DevicePropertyLegacyBusType
,
1273 sizeof(INTERFACE_TYPE
),
1275 &ret
)) && BusType
== PCIBus
)
1277 /* We have a PCI bus */
1278 if (NT_SUCCESS(IoGetDeviceProperty(
1279 DeviceNode
->PhysicalDeviceObject
,
1280 DevicePropertyAddress
,
1283 &ret
)) && SlotNumber
> 0)
1285 /* We have a good slot number */
1286 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1287 DeviceNode
->ResourceRequirements
->BusNumber
,
1290 0x3c /* PCI_INTERRUPT_LINE */,
1292 if (ret
!= 0 && ret
!= 2
1293 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1294 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1296 /* The device already has an assigned IRQ */
1297 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1301 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1302 DescriptorRaw
->u
.Interrupt
.Vector
,
1303 &DeviceNode
->InstancePath
);
1304 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1305 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1306 DeviceNode
->ResourceRequirements
->BusNumber
,
1309 0x3c /* PCI_INTERRUPT_LINE */,
1311 if (ret
== 0 || ret
== 2)
1317 DescriptorTranslated
->u
.Interrupt
.Level
= 0;
1318 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1319 DeviceNode
->ResourceRequirements
->InterfaceType
,
1320 DeviceNode
->ResourceRequirements
->BusNumber
,
1321 DescriptorRaw
->u
.Interrupt
.Level
,
1322 DescriptorRaw
->u
.Interrupt
.Vector
,
1323 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1324 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1325 DescriptorTranslated
->u
.Interrupt
.Affinity
= DescriptorRaw
->u
.Interrupt
.Affinity
;
1328 case CmResourceTypeMemory
:
1330 ULONG AddressSpace
= 1; /* Memory space */
1331 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1332 DescriptorRaw
->u
.Memory
.Length
= DescriptorTranslated
->u
.Memory
.Length
1333 = ResourceDescriptor
->u
.Memory
.Length
;
1334 if (!HalTranslateBusAddress(
1335 DeviceNode
->ResourceRequirements
->InterfaceType
,
1336 DeviceNode
->ResourceRequirements
->BusNumber
,
1337 DescriptorRaw
->u
.Memory
.Start
,
1339 &DescriptorTranslated
->u
.Memory
.Start
))
1341 Status
= STATUS_UNSUCCESSFUL
;
1346 case CmResourceTypeDma
:
1348 DescriptorRaw
->u
.Dma
.Channel
= DescriptorTranslated
->u
.Dma
.Channel
1349 = ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1350 DescriptorRaw
->u
.Dma
.Port
= DescriptorTranslated
->u
.Dma
.Port
1352 DescriptorRaw
->u
.Dma
.Reserved1
= DescriptorTranslated
->u
.Dma
.Reserved1
1356 case CmResourceTypeBusNumber
:
1358 DescriptorRaw
->u
.BusNumber
.Start
= DescriptorTranslated
->u
.BusNumber
.Start
1359 = ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1360 DescriptorRaw
->u
.BusNumber
.Length
= DescriptorTranslated
->u
.BusNumber
.Length
1361 = ResourceDescriptor
->u
.BusNumber
.Length
;
1362 DescriptorRaw
->u
.BusNumber
.Reserved
= DescriptorTranslated
->u
.BusNumber
.Reserved
1363 = ResourceDescriptor
->u
.BusNumber
.Reserved
;
1366 /*CmResourceTypeDevicePrivate:
1367 case CmResourceTypePcCardConfig:
1368 case CmResourceTypeMfCardConfig:
1371 &DescriptorRaw->u.DevicePrivate,
1372 &ResourceDescriptor->u.DevicePrivate,
1373 sizeof(ResourceDescriptor->u.DevicePrivate));
1375 &DescriptorTranslated->u.DevicePrivate,
1376 &ResourceDescriptor->u.DevicePrivate,
1377 sizeof(ResourceDescriptor->u.DevicePrivate));
1381 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1382 NumberOfResources
--;
1388 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1389 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1391 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1392 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
1393 return STATUS_SUCCESS
;
1396 if (DeviceNode
->ResourceList
)
1398 ExFreePool(DeviceNode
->ResourceList
);
1399 DeviceNode
->ResourceList
= NULL
;
1401 if (DeviceNode
->ResourceListTranslated
)
1403 ExFreePool(DeviceNode
->ResourceListTranslated
);
1404 DeviceNode
->ResourceListTranslated
= NULL
;
1407 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1413 * IopGetParentIdPrefix
1415 * Retrieve (or create) a string which identifies a device.
1419 * Pointer to device node.
1421 * Pointer to the string where is returned the parent node identifier
1424 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1425 * valid and its Buffer field is NULL-terminated. The caller needs to
1426 * to free the string with RtlFreeUnicodeString when it is no longer
1431 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1432 PUNICODE_STRING ParentIdPrefix
)
1434 ULONG KeyNameBufferLength
;
1435 PWSTR KeyNameBuffer
= NULL
;
1436 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1437 UNICODE_STRING KeyName
;
1438 UNICODE_STRING KeyValue
;
1439 UNICODE_STRING ValueName
;
1440 OBJECT_ATTRIBUTES ObjectAttributes
;
1445 /* HACK: As long as some devices have a NULL device
1446 * instance path, the following test is required :(
1448 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1449 return STATUS_UNSUCCESSFUL
;
1451 /* 1. Try to retrieve ParentIdPrefix from registry */
1452 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1453 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1454 if (!ParentIdPrefixInformation
)
1456 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1459 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1462 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1465 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1466 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1467 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1468 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1469 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1470 if (!NT_SUCCESS(Status
))
1472 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1473 Status
= ZwQueryValueKey(
1475 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1476 KeyNameBufferLength
, &KeyNameBufferLength
);
1477 if (NT_SUCCESS(Status
))
1479 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1480 Status
= STATUS_UNSUCCESSFUL
;
1483 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1484 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1488 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1490 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1491 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1495 /* 2. Create the ParentIdPrefix value */
1496 crc32
= RtlComputeCrc32(0,
1497 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1498 DeviceNode
->Parent
->InstancePath
.Length
);
1500 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1501 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1503 /* 3. Try to write the ParentIdPrefix to registry */
1504 Status
= ZwSetValueKey(hKey
,
1508 (PVOID
)KeyValue
.Buffer
,
1509 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1512 if (NT_SUCCESS(Status
))
1514 /* Duplicate the string to return it */
1515 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1517 ExFreePool(ParentIdPrefixInformation
);
1518 ExFreePool(KeyNameBuffer
);
1526 * IopActionInterrogateDeviceStack
1528 * Retrieve information for all (direct) child nodes of a parent node.
1532 * Pointer to device node.
1534 * Pointer to parent node to retrieve child node information for.
1537 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1538 * when we reach a device node which is not a direct child of the device
1539 * node for which we retrieve information of child nodes for. Any errors
1540 * that occur is logged instead so that all child services have a chance
1541 * of being interrogated.
1545 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1548 IO_STATUS_BLOCK IoStatusBlock
;
1549 PDEVICE_NODE ParentDeviceNode
;
1550 WCHAR InstancePath
[MAX_PATH
];
1551 IO_STACK_LOCATION Stack
;
1557 ULONG RequiredLength
;
1559 HANDLE InstanceKey
= NULL
;
1560 UNICODE_STRING ValueName
;
1561 UNICODE_STRING ParentIdPrefix
= { 0 };
1562 DEVICE_CAPABILITIES DeviceCapabilities
;
1564 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1565 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1567 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1570 * We are called for the parent too, but we don't need to do special
1571 * handling for this node
1574 if (DeviceNode
== ParentDeviceNode
)
1576 DPRINT("Success\n");
1577 return STATUS_SUCCESS
;
1581 * Make sure this device node is a direct child of the parent device node
1582 * that is given as an argument
1585 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1587 /* Stop the traversal immediately and indicate successful operation */
1589 return STATUS_UNSUCCESSFUL
;
1593 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1594 if (!NT_SUCCESS(Status
))
1596 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1601 * FIXME: For critical errors, cleanup and disable device, but always
1602 * return STATUS_SUCCESS.
1605 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1607 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1608 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1612 if (NT_SUCCESS(Status
))
1614 /* Copy the device id string */
1615 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1618 * FIXME: Check for valid characters, if there is invalid characters
1624 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1627 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1629 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1630 if (!NT_SUCCESS(Status
))
1632 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1635 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1637 if (!DeviceCapabilities
.UniqueID
)
1639 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1640 DPRINT("Instance ID is not unique\n");
1641 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1642 if (!NT_SUCCESS(Status
))
1644 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1648 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1650 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1651 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1655 if (NT_SUCCESS(Status
))
1657 /* Append the instance id string */
1658 wcscat(InstancePath
, L
"\\");
1659 if (ParentIdPrefix
.Length
> 0)
1661 /* Add information from parent bus device to InstancePath */
1662 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1663 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1664 wcscat(InstancePath
, L
"&");
1666 if (IoStatusBlock
.Information
)
1667 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1670 * FIXME: Check for valid characters, if there is invalid characters
1676 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1678 RtlFreeUnicodeString(&ParentIdPrefix
);
1680 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1682 DPRINT("No resources\n");
1683 /* FIXME: Cleanup and disable device */
1686 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1689 * Create registry key for the instance id, if it doesn't exist yet
1691 KeyBuffer
= ExAllocatePool(
1693 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1694 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1695 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1696 Status
= IopCreateDeviceKeyPath(KeyBuffer
, &InstanceKey
);
1697 ExFreePool(KeyBuffer
);
1698 if (!NT_SUCCESS(Status
))
1700 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1705 /* Set 'Capabilities' value */
1706 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1707 Status
= ZwSetValueKey(InstanceKey
,
1711 (PVOID
)&DeviceNode
->CapabilityFlags
,
1714 /* Set 'UINumber' value */
1715 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1717 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1718 Status
= ZwSetValueKey(InstanceKey
,
1722 &DeviceCapabilities
.UINumber
,
1727 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1729 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1730 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1734 if (NT_SUCCESS(Status
))
1737 * FIXME: Check for valid characters, if there is invalid characters
1741 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1742 DPRINT("Hardware IDs:\n");
1745 DPRINT(" %S\n", Ptr
);
1746 Length
= wcslen(Ptr
) + 1;
1749 TotalLength
+= Length
;
1751 DPRINT("TotalLength: %hu\n", TotalLength
);
1754 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1755 Status
= ZwSetValueKey(InstanceKey
,
1759 (PVOID
)IoStatusBlock
.Information
,
1760 (TotalLength
+ 1) * sizeof(WCHAR
));
1761 if (!NT_SUCCESS(Status
))
1763 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1768 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1771 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1773 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1774 Status
= IopInitiatePnpIrp(
1775 DeviceNode
->PhysicalDeviceObject
,
1779 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1782 * FIXME: Check for valid characters, if there is invalid characters
1786 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1787 DPRINT("Compatible IDs:\n");
1790 DPRINT(" %S\n", Ptr
);
1791 Length
= wcslen(Ptr
) + 1;
1794 TotalLength
+= Length
;
1796 DPRINT("TotalLength: %hu\n", TotalLength
);
1799 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1800 Status
= ZwSetValueKey(InstanceKey
,
1804 (PVOID
)IoStatusBlock
.Information
,
1805 (TotalLength
+ 1) * sizeof(WCHAR
));
1806 if (!NT_SUCCESS(Status
))
1808 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1813 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1817 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1819 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1820 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1821 Status
= IopInitiatePnpIrp(
1822 DeviceNode
->PhysicalDeviceObject
,
1824 IRP_MN_QUERY_DEVICE_TEXT
,
1826 /* This key is mandatory, so even if the Irp fails, we still write it */
1827 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1828 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1830 if (NT_SUCCESS(Status
) &&
1831 IoStatusBlock
.Information
&&
1832 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1834 /* This key is overriden when a driver is installed. Don't write the
1835 * new description if another one already exists */
1836 Status
= ZwSetValueKey(InstanceKey
,
1840 (PVOID
)IoStatusBlock
.Information
,
1841 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1845 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1846 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1848 Status
= ZwSetValueKey(InstanceKey
,
1853 DeviceDesc
.MaximumLength
);
1855 if (!NT_SUCCESS(Status
))
1857 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1863 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1865 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1866 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1867 Status
= IopInitiatePnpIrp(
1868 DeviceNode
->PhysicalDeviceObject
,
1870 IRP_MN_QUERY_DEVICE_TEXT
,
1872 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1874 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1875 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1876 Status
= ZwSetValueKey(InstanceKey
,
1880 (PVOID
)IoStatusBlock
.Information
,
1881 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1882 if (!NT_SUCCESS(Status
))
1884 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1889 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1892 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1894 Status
= IopInitiatePnpIrp(
1895 DeviceNode
->PhysicalDeviceObject
,
1897 IRP_MN_QUERY_BUS_INFORMATION
,
1899 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1901 PPNP_BUS_INFORMATION BusInformation
=
1902 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1904 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1905 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1906 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1907 ExFreePool(BusInformation
);
1911 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1913 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1914 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1915 DeviceNode
->ChildBusTypeIndex
= -1;
1918 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1920 Status
= IopInitiatePnpIrp(
1921 DeviceNode
->PhysicalDeviceObject
,
1923 IRP_MN_QUERY_RESOURCES
,
1925 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1927 DeviceNode
->BootResources
=
1928 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1929 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1933 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1934 DeviceNode
->BootResources
= NULL
;
1937 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1939 Status
= IopInitiatePnpIrp(
1940 DeviceNode
->PhysicalDeviceObject
,
1942 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1944 if (NT_SUCCESS(Status
))
1946 DeviceNode
->ResourceRequirements
=
1947 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1948 if (IoStatusBlock
.Information
)
1949 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
1951 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
1955 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1956 DeviceNode
->ResourceRequirements
= NULL
;
1960 if (InstanceKey
!= NULL
)
1962 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
1965 ZwClose(InstanceKey
);
1967 Status
= IopAssignDeviceResources(DeviceNode
);
1968 if (!NT_SUCCESS(Status
))
1970 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status
);
1973 DeviceNode
->Flags
|= DNF_PROCESSED
;
1975 /* Report the device to the user-mode pnp manager */
1976 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
1977 &DeviceNode
->InstancePath
);
1979 return STATUS_SUCCESS
;
1983 * IopActionConfigureChildServices
1985 * Retrieve configuration for all (direct) child nodes of a parent node.
1989 * Pointer to device node.
1991 * Pointer to parent node to retrieve child node configuration for.
1994 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1995 * when we reach a device node which is not a direct child of the device
1996 * node for which we configure child services for. Any errors that occur is
1997 * logged instead so that all child services have a chance of beeing
2002 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2005 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2006 PDEVICE_NODE ParentDeviceNode
;
2007 PUNICODE_STRING Service
;
2008 UNICODE_STRING ClassGUID
;
2009 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
2012 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2014 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2017 * We are called for the parent too, but we don't need to do special
2018 * handling for this node
2020 if (DeviceNode
== ParentDeviceNode
)
2022 DPRINT("Success\n");
2023 return STATUS_SUCCESS
;
2027 * Make sure this device node is a direct child of the parent device node
2028 * that is given as an argument
2030 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2032 /* Stop the traversal immediately and indicate successful operation */
2034 return STATUS_UNSUCCESSFUL
;
2037 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2039 WCHAR RegKeyBuffer
[MAX_PATH
];
2040 UNICODE_STRING RegKey
;
2043 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2044 RegKey
.Buffer
= RegKeyBuffer
;
2047 * Retrieve configuration from Enum key
2050 Service
= &DeviceNode
->ServiceName
;
2052 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2053 RtlInitUnicodeString(Service
, NULL
);
2054 RtlInitUnicodeString(&ClassGUID
, NULL
);
2056 QueryTable
[0].Name
= L
"Service";
2057 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2058 QueryTable
[0].EntryContext
= Service
;
2060 QueryTable
[1].Name
= L
"ClassGUID";
2061 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2062 QueryTable
[1].EntryContext
= &ClassGUID
;
2063 QueryTable
[1].DefaultType
= REG_SZ
;
2064 QueryTable
[1].DefaultData
= &NullString
;
2065 QueryTable
[1].DefaultLength
= 0;
2067 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2068 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2070 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2071 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2073 if (!NT_SUCCESS(Status
))
2075 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
2076 /* FIXME: Log the error */
2077 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
2078 DeviceNode
->InstancePath
.Buffer
, Status
);
2079 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2080 return STATUS_SUCCESS
;
2083 if (Service
->Buffer
== NULL
)
2085 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2087 if (ClassGUID
.Length
!= 0)
2089 /* Device has a ClassGUID value, but no Service value.
2090 * Suppose it is using the NULL driver, so state the
2091 * device is started */
2092 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2093 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2094 DeviceNode
->Flags
|= DN_STARTED
;
2096 return STATUS_SUCCESS
;
2099 DPRINT("Got Service %S\n", Service
->Buffer
);
2102 return STATUS_SUCCESS
;
2106 * IopActionInitChildServices
2108 * Initialize the service for all (direct) child nodes of a parent node
2112 * Pointer to device node.
2114 * Pointer to parent node to initialize child node services for.
2116 * Load only driver marked as boot start.
2119 * If the driver image for a service is not loaded and initialized
2120 * it is done here too. We only return a status code indicating an
2121 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2122 * not a direct child of the device node for which we initialize
2123 * child services for. Any errors that occur is logged instead so
2124 * that all child services have a chance of being initialized.
2128 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2130 BOOLEAN BootDrivers
)
2132 PDEVICE_NODE ParentDeviceNode
;
2135 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2138 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2141 * We are called for the parent too, but we don't need to do special
2142 * handling for this node
2144 if (DeviceNode
== ParentDeviceNode
)
2146 DPRINT("Success\n");
2147 return STATUS_SUCCESS
;
2151 * Make sure this device node is a direct child of the parent device node
2152 * that is given as an argument
2155 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2158 * Stop the traversal immediately and indicate unsuccessful operation
2161 return STATUS_UNSUCCESSFUL
;
2165 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2166 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2167 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2169 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2170 PDRIVER_OBJECT DriverObject
;
2172 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2173 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2175 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2177 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2178 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2179 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2183 /* get existing DriverObject pointer */
2184 Status
= IopGetDriverObject(
2186 &DeviceNode
->ServiceName
,
2189 if (NT_SUCCESS(Status
))
2191 /* Attach lower level filter drivers. */
2192 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2193 /* Initialize the function driver for the device node */
2194 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2195 if (NT_SUCCESS(Status
))
2197 /* Attach upper level filter drivers. */
2198 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2199 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2201 Status
= IopStartDevice(DeviceNode
);
2208 * Don't disable when trying to load only boot drivers
2212 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2213 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2214 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2215 CPRINT("Initialization of service %S failed (Status %x)\n",
2216 DeviceNode
->ServiceName
.Buffer
, Status
);
2221 DPRINT("Service %S is disabled or already initialized\n",
2222 DeviceNode
->ServiceName
.Buffer
);
2225 return STATUS_SUCCESS
;
2229 * IopActionInitAllServices
2231 * Initialize the service for all (direct) child nodes of a parent node. This
2232 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2236 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2239 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2243 * IopActionInitBootServices
2245 * Initialize the boot start services for all (direct) child nodes of a
2246 * parent node. This function just calls IopActionInitChildServices with
2247 * BootDrivers = TRUE.
2250 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2253 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2257 * IopInitializePnpServices
2259 * Initialize services for discovered children
2263 * Top device node to start initializing services.
2266 * When set to TRUE, only drivers marked as boot start will
2267 * be loaded. Otherwise, all drivers will be loaded.
2273 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2274 IN BOOLEAN BootDrivers
)
2276 DEVICETREE_TRAVERSE_CONTEXT Context
;
2278 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2282 IopInitDeviceTreeTraverseContext(
2285 IopActionInitBootServices
,
2290 IopInitDeviceTreeTraverseContext(
2293 IopActionInitAllServices
,
2297 return IopTraverseDeviceTree(&Context
);
2302 IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode
,
2303 IN DEVICE_RELATION_TYPE Type
)
2305 DEVICETREE_TRAVERSE_CONTEXT Context
;
2306 PDEVICE_RELATIONS DeviceRelations
;
2307 IO_STATUS_BLOCK IoStatusBlock
;
2308 PDEVICE_NODE ChildDeviceNode
;
2309 IO_STACK_LOCATION Stack
;
2311 OBJECT_ATTRIBUTES ObjectAttributes
;
2312 UNICODE_STRING LinkName
;
2317 DPRINT("DeviceNode 0x%p\n", DeviceNode
);
2319 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2321 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
2323 Status
= IopInitiatePnpIrp(
2324 DeviceNode
->PhysicalDeviceObject
,
2326 IRP_MN_QUERY_DEVICE_RELATIONS
,
2328 if (!NT_SUCCESS(Status
))
2330 DPRINT("IopInitiatePnpIrp() failed\n");
2334 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2336 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
2338 DPRINT("No PDOs\n");
2339 if (DeviceRelations
)
2341 ExFreePool(DeviceRelations
);
2343 return STATUS_SUCCESS
;
2346 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2349 * Create device nodes for all discovered devices
2352 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2354 Status
= IopCreateDeviceNode(
2356 DeviceRelations
->Objects
[i
],
2358 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2359 if (!NT_SUCCESS(Status
))
2361 DPRINT("No resources\n");
2362 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2363 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2364 ExFreePool(DeviceRelations
);
2365 return STATUS_INSUFFICIENT_RESOURCES
;
2368 ExFreePool(DeviceRelations
);
2371 * Retrieve information about all discovered children from the bus driver
2374 IopInitDeviceTreeTraverseContext(
2377 IopActionInterrogateDeviceStack
,
2380 Status
= IopTraverseDeviceTree(&Context
);
2381 if (!NT_SUCCESS(Status
))
2383 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2388 * Retrieve configuration from the registry for discovered children
2391 IopInitDeviceTreeTraverseContext(
2394 IopActionConfigureChildServices
,
2397 Status
= IopTraverseDeviceTree(&Context
);
2398 if (!NT_SUCCESS(Status
))
2400 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2405 * Get the state of the system boot. If the \\SystemRoot link isn't
2406 * created yet, we will assume that it's possible to load only boot
2410 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
2412 InitializeObjectAttributes(
2419 Status
= ZwOpenFile(
2426 if(NT_SUCCESS(Status
))
2428 BootDrivers
= FALSE
;
2435 * Initialize services for discovered children. Only boot drivers will
2436 * be loaded from boot driver!
2439 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2440 if (!NT_SUCCESS(Status
))
2442 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
2446 return STATUS_SUCCESS
;
2453 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
)
2457 HANDLE InstanceKey
= NULL
;
2460 /* Create registry key for the instance id, if it doesn't exist yet */
2461 KeyBuffer
= ExAllocatePool(PagedPool
,
2462 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
2463 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2464 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
2465 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
2467 ExFreePool(KeyBuffer
);
2468 if (!NT_SUCCESS(Status
))
2470 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2474 /* FIXME: Set 'ConfigFlags' value */
2476 ZwClose(InstanceKey
);
2480 return STATUS_SUCCESS
;
2490 DPRINT("PnpInit()\n");
2492 KeInitializeSpinLock(&IopDeviceTreeLock
);
2494 /* Initialize the Bus Type GUID List */
2495 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2496 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2497 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2499 /* Initialize PnP-Event notification support */
2500 Status
= IopInitPlugPlayEvents();
2501 if (!NT_SUCCESS(Status
))
2503 CPRINT("IopInitPlugPlayEvents() failed\n");
2504 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2508 * Create root device node
2511 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
2512 if (!NT_SUCCESS(Status
))
2514 CPRINT("IoCreateDriverObject() failed\n");
2515 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2518 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2520 if (!NT_SUCCESS(Status
))
2522 CPRINT("IoCreateDevice() failed\n");
2523 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2526 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
2527 if (!NT_SUCCESS(Status
))
2529 CPRINT("Insufficient resources\n");
2530 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2533 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2536 CPRINT("Failed to create the instance path!\n");
2537 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_UNSUCCESSFUL
, 0, 0, 0);
2540 /* Report the device to the user-mode pnp manager */
2541 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2542 &IopRootDeviceNode
->InstancePath
);
2544 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2545 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2546 IopRootDriverObject
->DriverExtension
->AddDevice(
2547 IopRootDriverObject
,
2548 IopRootDeviceNode
->PhysicalDeviceObject
);
2557 /* Set root device instance data */
2558 Status
= IopSetRootDeviceInstanceData(IopRootDeviceNode
);
2559 if (!NT_SUCCESS(Status
))
2561 CPRINT("Failed to set instance data\n");
2562 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);