1 /* $Id: pnpmgr.c,v 1.33 2004/08/21 20:55:41 tamlin Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnpmgr/pnpmgr.c
6 * PURPOSE: Initializes the PnP manager
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 16/04/2001 CSH Created
12 /* INCLUDES ******************************************************************/
15 #include <ole32/guiddef.h>
17 DEFINE_GUID(GUID_CLASS_COMPORT
, 0x86e0d1e0L
, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73);
18 DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR
, 0x4D36E978L
, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
22 #include <internal/debug.h>
25 /* GLOBALS *******************************************************************/
27 PDEVICE_NODE IopRootDeviceNode
;
28 KSPIN_LOCK IopDeviceTreeLock
;
30 /* DATA **********************************************************************/
32 PDRIVER_OBJECT IopRootDriverObject
;
34 /* FUNCTIONS *****************************************************************/
41 IoAdjustPagingPathCount(
52 IoInvalidateDeviceRelations(
53 IN PDEVICE_OBJECT DeviceObject
,
54 IN DEVICE_RELATION_TYPE Type
)
60 PDEVICE_OBJECT DeviceObject
)
62 return DeviceObject
->DeviceObjectExtension
->DeviceNode
;
71 IN PDEVICE_OBJECT DeviceObject
,
72 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
73 IN ULONG BufferLength
,
74 OUT PVOID PropertyBuffer
,
75 OUT PULONG ResultLength
)
77 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
81 DPRINT("IoGetDeviceProperty called\n");
83 if (DeviceNode
== NULL
||
84 DeviceNode
->BusInformation
== NULL
||
85 DeviceNode
->CapabilityFlags
== NULL
)
87 return STATUS_INVALID_DEVICE_REQUEST
;
93 * IRP_MN_QUERY_BUS_INFORMATION
95 switch (DeviceProperty
)
97 case DevicePropertyBusNumber
:
98 Length
= sizeof(ULONG
);
99 Data
= &DeviceNode
->BusInformation
->BusNumber
;
102 /* Complete, untested */
103 case DevicePropertyBusTypeGuid
:
104 *ResultLength
= 39 * sizeof(WCHAR
);
105 if (BufferLength
< (39 * sizeof(WCHAR
)))
106 return STATUS_BUFFER_TOO_SMALL
;
107 swprintf((PWSTR
)PropertyBuffer
,
108 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
109 DeviceNode
->BusInformation
->BusTypeGuid
.Data1
,
110 DeviceNode
->BusInformation
->BusTypeGuid
.Data2
,
111 DeviceNode
->BusInformation
->BusTypeGuid
.Data3
,
112 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[0],
113 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[1],
114 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[2],
115 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[3],
116 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[4],
117 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[5],
118 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[6],
119 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[7]);
120 return STATUS_SUCCESS
;
122 case DevicePropertyLegacyBusType
:
123 Length
= sizeof(INTERFACE_TYPE
);
124 Data
= &DeviceNode
->BusInformation
->LegacyBusType
;
127 case DevicePropertyAddress
:
128 Length
= sizeof(ULONG
);
129 Data
= &DeviceNode
->CapabilityFlags
->Address
;
132 case DevicePropertyUINumber
:
133 Length
= sizeof(ULONG
);
134 Data
= &DeviceNode
->CapabilityFlags
->UINumber
;
137 case DevicePropertyBootConfiguration
:
138 case DevicePropertyBootConfigurationTranslated
:
139 case DevicePropertyClassGuid
:
140 case DevicePropertyClassName
:
141 case DevicePropertyCompatibleIDs
:
142 case DevicePropertyDeviceDescription
:
143 case DevicePropertyDriverKeyName
:
144 case DevicePropertyEnumeratorName
:
145 case DevicePropertyFriendlyName
:
146 case DevicePropertyHardwareID
:
147 case DevicePropertyLocationInformation
:
148 case DevicePropertyManufacturer
:
149 case DevicePropertyPhysicalDeviceObjectName
:
150 return STATUS_NOT_IMPLEMENTED
;
153 return STATUS_INVALID_PARAMETER_2
;
156 *ResultLength
= Length
;
157 if (BufferLength
< Length
)
158 return STATUS_BUFFER_TOO_SMALL
;
159 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
161 return STATUS_SUCCESS
;
169 IoInvalidateDeviceState(
170 IN PDEVICE_OBJECT PhysicalDeviceObject
)
179 IoOpenDeviceRegistryKey(
180 IN PDEVICE_OBJECT DeviceObject
,
181 IN ULONG DevInstKeyType
,
182 IN ACCESS_MASK DesiredAccess
,
183 OUT PHANDLE DevInstRegKey
)
185 return STATUS_NOT_IMPLEMENTED
;
193 IoRequestDeviceEject(
194 IN PDEVICE_OBJECT PhysicalDeviceObject
202 IopCreateUnicodeString(
203 PUNICODE_STRING Destination
,
211 RtlInitUnicodeString(Destination
, NULL
);
215 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
217 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
219 if (Destination
->Buffer
== NULL
)
224 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
226 Destination
->MaximumLength
= Length
;
228 Destination
->Length
= Length
- sizeof(WCHAR
);
234 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
238 if (PopSystemPowerDeviceNode
)
240 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
241 *DeviceObject
= PopSystemPowerDeviceNode
->Pdo
;
242 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
244 return STATUS_SUCCESS
;
247 return STATUS_UNSUCCESSFUL
;
250 /**********************************************************************
252 * Creates a device node
255 * ParentNode = Pointer to parent device node
256 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
257 * to have the root device node create one
258 * (eg. for legacy drivers)
259 * DeviceNode = Pointer to storage for created device node
265 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
266 PDEVICE_OBJECT PhysicalDeviceObject
,
267 PDEVICE_NODE
*DeviceNode
)
273 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
274 ParentNode
, PhysicalDeviceObject
);
276 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
279 return STATUS_INSUFFICIENT_RESOURCES
;
282 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
284 if (!PhysicalDeviceObject
)
286 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
287 if (!NT_SUCCESS(Status
))
293 /* This is for drivers passed on the command line to ntoskrnl.exe */
294 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
295 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
298 Node
->Pdo
= PhysicalDeviceObject
;
300 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
304 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
305 Node
->Parent
= ParentNode
;
306 Node
->NextSibling
= ParentNode
->Child
;
307 if (ParentNode
->Child
!= NULL
)
309 ParentNode
->Child
->PrevSibling
= Node
;
311 ParentNode
->Child
= Node
;
312 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
317 return STATUS_SUCCESS
;
321 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
325 /* All children must be deleted before a parent is deleted */
326 assert(!DeviceNode
->Child
);
328 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
330 assert(DeviceNode
->Pdo
);
332 ObDereferenceObject(DeviceNode
->Pdo
);
334 /* Unlink from parent if it exists */
336 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
338 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
341 /* Unlink from sibling list */
343 if (DeviceNode
->PrevSibling
)
345 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
348 if (DeviceNode
->NextSibling
)
350 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
353 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
355 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
357 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
359 if (DeviceNode
->CapabilityFlags
)
361 ExFreePool(DeviceNode
->CapabilityFlags
);
364 if (DeviceNode
->CmResourceList
)
366 ExFreePool(DeviceNode
->CmResourceList
);
369 if (DeviceNode
->BootResourcesList
)
371 ExFreePool(DeviceNode
->BootResourcesList
);
374 if (DeviceNode
->ResourceRequirementsList
)
376 ExFreePool(DeviceNode
->ResourceRequirementsList
);
379 RtlFreeUnicodeString(&DeviceNode
->DeviceID
);
381 RtlFreeUnicodeString(&DeviceNode
->InstanceID
);
383 RtlFreeUnicodeString(&DeviceNode
->HardwareIDs
);
385 RtlFreeUnicodeString(&DeviceNode
->CompatibleIDs
);
387 RtlFreeUnicodeString(&DeviceNode
->DeviceText
);
389 RtlFreeUnicodeString(&DeviceNode
->DeviceTextLocation
);
391 if (DeviceNode
->BusInformation
)
393 ExFreePool(DeviceNode
->BusInformation
);
396 ExFreePool(DeviceNode
);
398 return STATUS_SUCCESS
;
403 PDEVICE_OBJECT DeviceObject
,
404 PIO_STATUS_BLOCK IoStatusBlock
,
406 PIO_STACK_LOCATION Stack OPTIONAL
)
408 PDEVICE_OBJECT TopDeviceObject
;
409 PIO_STACK_LOCATION IrpSp
;
414 /* Always call the top of the device stack */
415 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
422 /* PNP IRPs are always initialized with a status code of
423 STATUS_NOT_IMPLEMENTED */
424 IoStatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
425 IoStatusBlock
->Information
= 0;
427 Irp
= IoBuildSynchronousFsdRequest(
436 IrpSp
= IoGetNextIrpStackLocation(Irp
);
437 IrpSp
->MinorFunction
= MinorFunction
;
444 sizeof(Stack
->Parameters
));
447 Status
= IoCallDriver(TopDeviceObject
, Irp
);
448 if (Status
== STATUS_PENDING
)
450 KeWaitForSingleObject(
456 Status
= IoStatusBlock
->Status
;
459 ObDereferenceObject(TopDeviceObject
);
466 IopQueryCapabilities(
468 PDEVICE_CAPABILITIES
*Capabilities
)
470 IO_STATUS_BLOCK IoStatusBlock
;
471 PDEVICE_CAPABILITIES Caps
;
472 IO_STACK_LOCATION Stack
;
475 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
477 *Capabilities
= NULL
;
479 Caps
= ExAllocatePool(PagedPool
, sizeof(DEVICE_CAPABILITIES
));
482 return STATUS_INSUFFICIENT_RESOURCES
;
485 RtlZeroMemory(Caps
, sizeof(DEVICE_CAPABILITIES
));
486 Caps
->Size
= sizeof(DEVICE_CAPABILITIES
);
491 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= Caps
;
493 Status
= IopInitiatePnpIrp(
496 IRP_MN_QUERY_CAPABILITIES
,
498 if (NT_SUCCESS(Status
))
500 *Capabilities
= Caps
;
504 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
512 IopTraverseDeviceTreeNode(
513 PDEVICETREE_TRAVERSE_CONTEXT Context
)
515 PDEVICE_NODE ParentDeviceNode
;
516 PDEVICE_NODE ChildDeviceNode
;
519 /* Copy context data so we don't overwrite it in subsequent calls to this function */
520 ParentDeviceNode
= Context
->DeviceNode
;
522 /* Call the action routine */
523 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
524 if (!NT_SUCCESS(Status
))
529 /* Traversal of all children nodes */
530 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
531 ChildDeviceNode
!= NULL
;
532 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
534 /* Pass the current device node to the action routine */
535 Context
->DeviceNode
= ChildDeviceNode
;
537 Status
= IopTraverseDeviceTreeNode(Context
);
538 if (!NT_SUCCESS(Status
))
549 IopTraverseDeviceTree(
550 PDEVICETREE_TRAVERSE_CONTEXT Context
)
554 DPRINT("Context %x\n", Context
);
556 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
557 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
559 /* Start from the specified device node */
560 Context
->DeviceNode
= Context
->FirstDeviceNode
;
562 /* Recursively traverse the device tree */
563 Status
= IopTraverseDeviceTreeNode(Context
);
564 if (Status
== STATUS_UNSUCCESSFUL
)
566 /* The action routine just wanted to terminate the traversal with status
567 code STATUS_SUCCESS */
568 Status
= STATUS_SUCCESS
;
576 IopCreateDeviceKeyPath(PWSTR Path
)
578 OBJECT_ATTRIBUTES ObjectAttributes
;
579 WCHAR KeyBuffer
[MAX_PATH
];
580 UNICODE_STRING KeyName
;
586 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
588 return STATUS_INVALID_PARAMETER
;
591 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
592 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
594 /* Skip \\Registry\\ */
595 Current
= KeyName
.Buffer
;
596 Current
= wcschr (Current
, '\\') + 1;
597 Current
= wcschr (Current
, '\\') + 1;
601 Next
= wcschr (Current
, '\\');
611 InitializeObjectAttributes (&ObjectAttributes
,
613 OBJ_CASE_INSENSITIVE
,
617 DPRINT("Create '%S'\n", KeyName
.Buffer
);
619 Status
= NtCreateKey (&KeyHandle
,
626 if (!NT_SUCCESS (Status
))
628 DPRINT ("NtCreateKey() failed with status %x\n", Status
);
641 while (Next
!= NULL
);
643 return STATUS_SUCCESS
;
648 * IopActionInterrogateDeviceStack
650 * Retrieve information for all (direct) child nodes of a parent node.
654 * Pointer to device node.
656 * Pointer to parent node to retrieve child node information for.
659 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
660 * when we reach a device node which is not a direct child of the device
661 * node for which we retrieve information of child nodes for. Any errors
662 * that occur is logged instead so that all child services have a chance
663 * of being interrogated.
667 IopActionInterrogateDeviceStack(
668 PDEVICE_NODE DeviceNode
,
671 IO_STATUS_BLOCK IoStatusBlock
;
672 PDEVICE_NODE ParentDeviceNode
;
673 WCHAR InstancePath
[MAX_PATH
];
674 IO_STACK_LOCATION Stack
;
681 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
682 DPRINT("PDO %x\n", DeviceNode
->Pdo
);
684 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
687 * We are called for the parent too, but we don't need to do special
688 * handling for this node
691 if (DeviceNode
== ParentDeviceNode
)
694 return STATUS_SUCCESS
;
698 * Make sure this device node is a direct child of the parent device node
699 * that is given as an argument
702 if (DeviceNode
->Parent
!= ParentDeviceNode
)
704 /* Stop the traversal immediately and indicate successful operation */
706 return STATUS_UNSUCCESSFUL
;
710 * FIXME: For critical errors, cleanup and disable device, but always
711 * return STATUS_SUCCESS.
714 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
716 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
717 Status
= IopInitiatePnpIrp(
722 if (NT_SUCCESS(Status
))
724 RtlInitUnicodeString(
725 &DeviceNode
->DeviceID
,
726 (PWSTR
)IoStatusBlock
.Information
);
729 * FIXME: Check for valid characters, if there is invalid characters
735 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
736 RtlInitUnicodeString(&DeviceNode
->DeviceID
, NULL
);
739 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
741 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
742 Status
= IopInitiatePnpIrp(
747 if (NT_SUCCESS(Status
))
749 RtlInitUnicodeString(
750 &DeviceNode
->InstanceID
,
751 (PWSTR
)IoStatusBlock
.Information
);
754 * FIXME: Check for valid characters, if there is invalid characters
760 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
761 RtlInitUnicodeString(&DeviceNode
->InstanceID
, NULL
);
764 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
766 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
767 Status
= IopInitiatePnpIrp(
772 if (NT_SUCCESS(Status
))
775 * FIXME: Check for valid characters, if there is invalid characters
779 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
780 DPRINT("Hardware IDs:\n");
783 DPRINT(" %S\n", Ptr
);
784 Length
= wcslen(Ptr
) + 1;
787 TotalLength
+= Length
;
789 DPRINT("TotalLength: %hu\n", TotalLength
);
792 DeviceNode
->HardwareIDs
.Length
= TotalLength
* sizeof(WCHAR
);
793 DeviceNode
->HardwareIDs
.MaximumLength
= DeviceNode
->HardwareIDs
.Length
+ sizeof(WCHAR
);
794 DeviceNode
->HardwareIDs
.Buffer
= (PWSTR
)IoStatusBlock
.Information
;
798 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
799 RtlInitUnicodeString(&DeviceNode
->HardwareIDs
, NULL
);
802 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
804 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
805 Status
= IopInitiatePnpIrp(
810 if (NT_SUCCESS(Status
))
813 * FIXME: Check for valid characters, if there is invalid characters
817 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
818 DPRINT("Compatible IDs:\n");
821 DPRINT(" %S\n", Ptr
);
822 Length
= wcslen(Ptr
) + 1;
825 TotalLength
+= Length
;
827 DPRINT("TotalLength: %hu\n", TotalLength
);
830 DeviceNode
->CompatibleIDs
.Length
= TotalLength
* sizeof(WCHAR
);
831 DeviceNode
->CompatibleIDs
.MaximumLength
= DeviceNode
->CompatibleIDs
.Length
+ sizeof(WCHAR
);
832 DeviceNode
->CompatibleIDs
.Buffer
= (PWSTR
)IoStatusBlock
.Information
;
836 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
837 RtlInitUnicodeString(&DeviceNode
->CompatibleIDs
, NULL
);
840 Status
= IopQueryCapabilities(DeviceNode
->Pdo
, &DeviceNode
->CapabilityFlags
);
841 if (NT_SUCCESS(Status
))
848 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
850 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
851 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
852 Status
= IopInitiatePnpIrp(
855 IRP_MN_QUERY_DEVICE_TEXT
,
857 if (NT_SUCCESS(Status
))
859 RtlInitUnicodeString(
860 &DeviceNode
->DeviceText
,
861 (PWSTR
)IoStatusBlock
.Information
);
865 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
866 RtlInitUnicodeString(&DeviceNode
->DeviceText
, NULL
);
869 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
871 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
872 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
873 Status
= IopInitiatePnpIrp(
876 IRP_MN_QUERY_DEVICE_TEXT
,
878 if (NT_SUCCESS(Status
))
880 RtlInitUnicodeString(
881 &DeviceNode
->DeviceTextLocation
,
882 (PWSTR
)IoStatusBlock
.Information
);
886 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
887 RtlInitUnicodeString(&DeviceNode
->DeviceTextLocation
, NULL
);
890 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
892 Status
= IopInitiatePnpIrp(
895 IRP_MN_QUERY_BUS_INFORMATION
,
897 if (NT_SUCCESS(Status
))
899 DeviceNode
->BusInformation
=
900 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
904 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
905 DeviceNode
->BusInformation
= NULL
;
908 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
910 Status
= IopInitiatePnpIrp(
913 IRP_MN_QUERY_RESOURCES
,
915 if (NT_SUCCESS(Status
))
917 DeviceNode
->BootResourcesList
=
918 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
919 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
923 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
924 DeviceNode
->BootResourcesList
= NULL
;
927 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
929 Status
= IopInitiatePnpIrp(
932 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
934 if (NT_SUCCESS(Status
))
936 DeviceNode
->ResourceRequirementsList
=
937 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
941 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
942 DeviceNode
->ResourceRequirementsList
= NULL
;
946 * Assemble the instance path for the device
949 wcscpy(InstancePath
, DeviceNode
->DeviceID
.Buffer
);
950 wcscat(InstancePath
, L
"\\");
951 wcscat(InstancePath
, DeviceNode
->InstanceID
.Buffer
);
953 if (!DeviceNode
->CapabilityFlags
->UniqueID
)
955 DPRINT("Instance ID is not unique\n");
956 /* FIXME: Add information from parent bus driver to InstancePath */
959 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
))
961 DPRINT("No resources\n");
962 /* FIXME: Cleanup and disable device */
965 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
968 * Create registry key for the instance id, if it doesn't exist yet
971 KeyBuffer
= ExAllocatePool(
973 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
974 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
975 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
976 IopCreateDeviceKeyPath(KeyBuffer
);
977 ExFreePool(KeyBuffer
);
978 DeviceNode
->Flags
|= DNF_PROCESSED
;
980 return STATUS_SUCCESS
;
984 * IopActionConfigureChildServices
986 * Retrieve configuration for all (direct) child nodes of a parent node.
990 * Pointer to device node.
992 * Pointer to parent node to retrieve child node configuration for.
995 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
996 * when we reach a device node which is not a direct child of the device
997 * node for which we configure child services for. Any errors that occur is
998 * logged instead so that all child services have a chance of beeing
1003 IopActionConfigureChildServices(
1004 PDEVICE_NODE DeviceNode
,
1007 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1008 PDEVICE_NODE ParentDeviceNode
;
1009 PUNICODE_STRING Service
;
1012 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1014 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1017 * We are called for the parent too, but we don't need to do special
1018 * handling for this node
1020 if (DeviceNode
== ParentDeviceNode
)
1022 DPRINT("Success\n");
1023 return STATUS_SUCCESS
;
1027 * Make sure this device node is a direct child of the parent device node
1028 * that is given as an argument
1030 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1032 /* Stop the traversal immediately and indicate successful operation */
1034 return STATUS_UNSUCCESSFUL
;
1037 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1040 * Retrieve configuration from Enum key
1043 Service
= &DeviceNode
->ServiceName
;
1045 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1046 RtlInitUnicodeString(Service
, NULL
);
1048 QueryTable
[0].Name
= L
"Service";
1049 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1050 QueryTable
[0].EntryContext
= Service
;
1052 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ENUM
,
1053 DeviceNode
->InstancePath
.Buffer
, QueryTable
, NULL
, NULL
);
1055 if (!NT_SUCCESS(Status
))
1057 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1058 /* FIXME: Log the error */
1059 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1060 DeviceNode
->InstancePath
.Buffer
, Status
);
1061 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1062 return STATUS_SUCCESS
;
1065 if (Service
->Buffer
== NULL
)
1067 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1068 return STATUS_SUCCESS
;
1071 DPRINT("Got Service %S\n", Service
->Buffer
);
1074 return STATUS_SUCCESS
;
1078 * IopActionInitChildServices
1080 * Initialize the service for all (direct) child nodes of a parent node
1084 * Pointer to device node.
1086 * Pointer to parent node to initialize child node services for.
1088 * Load only driver marked as boot start.
1091 * If the driver image for a service is not loaded and initialized
1092 * it is done here too. We only return a status code indicating an
1093 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1094 * not a direct child of the device node for which we initialize
1095 * child services for. Any errors that occur is logged instead so
1096 * that all child services have a chance of being initialized.
1100 IopActionInitChildServices(
1101 PDEVICE_NODE DeviceNode
,
1103 BOOLEAN BootDrivers
)
1105 PDEVICE_NODE ParentDeviceNode
;
1108 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1111 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1114 * We are called for the parent too, but we don't need to do special
1115 * handling for this node
1117 if (DeviceNode
== ParentDeviceNode
)
1119 DPRINT("Success\n");
1120 return STATUS_SUCCESS
;
1124 * Make sure this device node is a direct child of the parent device node
1125 * that is given as an argument
1128 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1131 * Stop the traversal immediately and indicate unsuccessful operation
1134 return STATUS_UNSUCCESSFUL
;
1138 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1139 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1140 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1142 PMODULE_OBJECT ModuleObject
;
1143 PDRIVER_OBJECT DriverObject
;
1145 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1146 if (NT_SUCCESS(Status
))
1148 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
1149 if (NT_SUCCESS(Status
))
1151 /* Attach lower level filter drivers. */
1152 IopAttachFilterDrivers(DeviceNode
, TRUE
);
1153 /* Initialize the function driver for the device node */
1154 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1155 if (NT_SUCCESS(Status
))
1157 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1158 /* Attach upper level filter drivers. */
1159 IopAttachFilterDrivers(DeviceNode
, FALSE
);
1166 * Don't disable when trying to load only boot drivers
1170 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1171 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1173 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1174 CPRINT("Initialization of service %S failed (Status %x)\n",
1175 DeviceNode
->ServiceName
.Buffer
, Status
);
1179 DPRINT("Service %S is disabled or already initialized\n",
1180 DeviceNode
->ServiceName
.Buffer
);
1183 return STATUS_SUCCESS
;
1187 * IopActionInitAllServices
1189 * Initialize the service for all (direct) child nodes of a parent node. This
1190 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1194 IopActionInitAllServices(
1195 PDEVICE_NODE DeviceNode
,
1198 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1202 * IopActionInitBootServices
1204 * Initialize the boot start services for all (direct) child nodes of a
1205 * parent node. This function just calls IopActionInitChildServices with
1206 * BootDrivers = TRUE.
1210 IopActionInitBootServices(
1211 PDEVICE_NODE DeviceNode
,
1214 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1218 * IopInitializePnpServices
1220 * Initialize services for discovered children
1224 * Top device node to start initializing services.
1227 * When set to TRUE, only drivers marked as boot start will
1228 * be loaded. Otherwise, all drivers will be loaded.
1235 IopInitializePnpServices(
1236 IN PDEVICE_NODE DeviceNode
,
1237 IN BOOLEAN BootDrivers
)
1239 DEVICETREE_TRAVERSE_CONTEXT Context
;
1241 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1245 IopInitDeviceTreeTraverseContext(
1248 IopActionInitBootServices
,
1252 IopInitDeviceTreeTraverseContext(
1255 IopActionInitAllServices
,
1259 return IopTraverseDeviceTree(&Context
);
1264 IopInvalidateDeviceRelations(
1265 IN PDEVICE_NODE DeviceNode
,
1266 IN DEVICE_RELATION_TYPE Type
)
1268 DEVICETREE_TRAVERSE_CONTEXT Context
;
1269 PDEVICE_RELATIONS DeviceRelations
;
1270 IO_STATUS_BLOCK IoStatusBlock
;
1271 PDEVICE_NODE ChildDeviceNode
;
1272 IO_STACK_LOCATION Stack
;
1274 OBJECT_ATTRIBUTES ObjectAttributes
;
1275 UNICODE_STRING LinkName
;
1280 DPRINT("DeviceNode %x\n", DeviceNode
);
1282 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1284 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1286 Status
= IopInitiatePnpIrp(
1289 IRP_MN_QUERY_DEVICE_RELATIONS
,
1291 if (!NT_SUCCESS(Status
))
1293 DPRINT("IopInitiatePnpIrp() failed\n");
1297 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1299 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1301 DPRINT("No PDOs\n");
1302 if (DeviceRelations
)
1304 ExFreePool(DeviceRelations
);
1306 return STATUS_SUCCESS
;
1309 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1312 * Create device nodes for all discovered devices
1315 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1317 Status
= IopCreateDeviceNode(
1319 DeviceRelations
->Objects
[i
],
1321 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1322 if (!NT_SUCCESS(Status
))
1324 DPRINT("No resources\n");
1325 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1326 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1327 ExFreePool(DeviceRelations
);
1328 return STATUS_INSUFFICIENT_RESOURCES
;
1331 ExFreePool(DeviceRelations
);
1334 * Retrieve information about all discovered children from the bus driver
1337 IopInitDeviceTreeTraverseContext(
1340 IopActionInterrogateDeviceStack
,
1343 Status
= IopTraverseDeviceTree(&Context
);
1344 if (!NT_SUCCESS(Status
))
1346 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1351 * Retrieve configuration from the registry for discovered children
1354 IopInitDeviceTreeTraverseContext(
1357 IopActionConfigureChildServices
,
1360 Status
= IopTraverseDeviceTree(&Context
);
1361 if (!NT_SUCCESS(Status
))
1363 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1368 * Get the state of the system boot. If the \\SystemRoot link isn't
1369 * created yet, we will assume that it's possible to load only boot
1373 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
1375 InitializeObjectAttributes(
1382 Status
= NtOpenFile(
1390 BootDrivers
= NT_SUCCESS(Status
) ? FALSE
: TRUE
;
1395 * Initialize services for discovered children. Only boot drivers will
1396 * be loaded from boot driver!
1399 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
1400 if (!NT_SUCCESS(Status
))
1402 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
1406 return STATUS_SUCCESS
;
1416 DPRINT("PnpInit()\n");
1418 KeInitializeSpinLock(&IopDeviceTreeLock
);
1421 * Create root device node
1424 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, FALSE
, NULL
, 0);
1425 if (!NT_SUCCESS(Status
))
1427 CPRINT("IoCreateDriverObject() failed\n");
1428 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1431 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
1433 if (!NT_SUCCESS(Status
))
1435 CPRINT("IoCreateDevice() failed\n");
1436 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1439 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
1440 if (!NT_SUCCESS(Status
))
1442 CPRINT("Insufficient resources\n");
1443 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1446 IopRootDeviceNode
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1447 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1448 IopRootDriverObject
->DriverExtension
->AddDevice(
1449 IopRootDriverObject
,
1450 IopRootDeviceNode
->Pdo
);