1 /* $Id: pnpmgr.c,v 1.8 2002/09/08 10:23:25 chorns Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnpmgr.c
6 * PURPOSE: Initializes the PnP manager
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 16/04/2001 CSH Created
12 /* INCLUDES ******************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/io.h>
16 #include <internal/po.h>
17 #include <internal/ldr.h>
18 #include <internal/registry.h>
19 #include <internal/module.h>
22 #include <internal/debug.h>
24 /* GLOBALS *******************************************************************/
26 PDEVICE_NODE IopRootDeviceNode
;
27 KSPIN_LOCK IopDeviceTreeLock
;
29 /* DATA **********************************************************************/
31 PDRIVER_OBJECT IopRootDriverObject
;
33 /* FUNCTIONS *****************************************************************/
37 IoInitializeRemoveLockEx(
38 IN PIO_REMOVE_LOCK Lock
,
40 IN ULONG MaxLockedMinutes
,
41 IN ULONG HighWatermark
,
48 IoAcquireRemoveLockEx(
49 IN PIO_REMOVE_LOCK RemoveLock
,
50 IN OPTIONAL PVOID Tag
,
55 return STATUS_NOT_IMPLEMENTED
;
60 IoReleaseRemoveLockEx(
61 IN PIO_REMOVE_LOCK RemoveLock
,
69 IoReleaseRemoveLockAndWaitEx(
70 IN PIO_REMOVE_LOCK RemoveLock
,
78 IoAdjustPagingPathCount(
86 IoGetDeviceInterfaceAlias(
87 IN PUNICODE_STRING SymbolicLinkName
,
88 IN CONST GUID
*AliasInterfaceClassGuid
,
89 OUT PUNICODE_STRING AliasSymbolicLinkName
)
91 return STATUS_NOT_IMPLEMENTED
;
96 IoGetDeviceInterfaces(
97 IN CONST GUID
*InterfaceClassGuid
,
98 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL
,
100 OUT PWSTR
*SymbolicLinkList
)
102 return STATUS_NOT_IMPLEMENTED
;
108 IN PDEVICE_OBJECT DeviceObject
,
109 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
110 IN ULONG BufferLength
,
111 OUT PVOID PropertyBuffer
,
112 OUT PULONG ResultLength
)
114 return STATUS_NOT_IMPLEMENTED
;
119 IoInvalidateDeviceRelations(
120 IN PDEVICE_OBJECT DeviceObject
,
121 IN DEVICE_RELATION_TYPE Type
)
127 IoInvalidateDeviceState(
128 IN PDEVICE_OBJECT PhysicalDeviceObject
)
134 IoOpenDeviceInterfaceRegistryKey(
135 IN PUNICODE_STRING SymbolicLinkName
,
136 IN ACCESS_MASK DesiredAccess
,
137 OUT PHANDLE DeviceInterfaceKey
)
139 return STATUS_NOT_IMPLEMENTED
;
144 IoOpenDeviceRegistryKey(
145 IN PDEVICE_OBJECT DeviceObject
,
146 IN ULONG DevInstKeyType
,
147 IN ACCESS_MASK DesiredAccess
,
148 OUT PHANDLE DevInstRegKey
)
150 return STATUS_NOT_IMPLEMENTED
;
155 IoRegisterDeviceInterface(
156 IN PDEVICE_OBJECT PhysicalDeviceObject
,
157 IN CONST GUID
*InterfaceClassGuid
,
158 IN PUNICODE_STRING ReferenceString OPTIONAL
,
159 OUT PUNICODE_STRING SymbolicLinkName
)
161 return STATUS_NOT_IMPLEMENTED
;
166 IoRegisterPlugPlayNotification(
167 IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory
,
168 IN ULONG EventCategoryFlags
,
169 IN PVOID EventCategoryData OPTIONAL
,
170 IN PDRIVER_OBJECT DriverObject
,
171 IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine
,
173 OUT PVOID
*NotificationEntry
)
175 return STATUS_NOT_IMPLEMENTED
;
180 IoReportDetectedDevice(
181 IN PDRIVER_OBJECT DriverObject
,
182 IN INTERFACE_TYPE LegacyBusType
,
185 IN PCM_RESOURCE_LIST ResourceList
,
186 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL
,
187 IN BOOLEAN ResourceAssigned
,
188 IN OUT PDEVICE_OBJECT
*DeviceObject
)
190 return STATUS_NOT_IMPLEMENTED
;
195 IoReportResourceForDetection(
196 IN PDRIVER_OBJECT DriverObject
,
197 IN PCM_RESOURCE_LIST DriverList OPTIONAL
,
198 IN ULONG DriverListSize OPTIONAL
,
199 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
200 IN PCM_RESOURCE_LIST DeviceList OPTIONAL
,
201 IN ULONG DeviceListSize OPTIONAL
,
202 OUT PBOOLEAN ConflictDetected
)
204 return STATUS_NOT_IMPLEMENTED
;
209 IoReportTargetDeviceChange(
210 IN PDEVICE_OBJECT PhysicalDeviceObject
,
211 IN PVOID NotificationStructure
)
213 return STATUS_NOT_IMPLEMENTED
;
218 IoReportTargetDeviceChangeAsynchronous(
219 IN PDEVICE_OBJECT PhysicalDeviceObject
,
220 IN PVOID NotificationStructure
,
221 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL
,
222 IN PVOID Context OPTIONAL
)
224 return STATUS_NOT_IMPLEMENTED
;
229 IoRequestDeviceEject(
230 IN PDEVICE_OBJECT PhysicalDeviceObject
)
236 IoSetDeviceInterfaceState(
237 IN PUNICODE_STRING SymbolicLinkName
,
240 return STATUS_NOT_IMPLEMENTED
;
245 IoUnregisterPlugPlayNotification(
246 IN PVOID NotificationEntry
)
248 return STATUS_NOT_IMPLEMENTED
;
253 IopCreateUnicodeString(
254 PUNICODE_STRING Destination
,
262 RtlInitUnicodeString(Destination
, NULL
);
266 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
268 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
270 if (Destination
->Buffer
== NULL
)
275 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
277 Destination
->MaximumLength
= Length
;
279 Destination
->Length
= Length
- sizeof(WCHAR
);
285 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
289 assert(PopSystemPowerDeviceNode
);
291 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
292 *DeviceObject
= PopSystemPowerDeviceNode
->Pdo
;
293 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
295 return STATUS_SUCCESS
;
298 /**********************************************************************
300 * Creates a device node
303 * ParentNode = Pointer to parent device node
304 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
305 * to have the root device node create one
306 * (eg. for legacy drivers)
307 * DeviceNode = Pointer to storage for created device node
313 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
314 PDEVICE_OBJECT PhysicalDeviceObject
,
315 PDEVICE_NODE
*DeviceNode
)
321 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
322 ParentNode
, PhysicalDeviceObject
);
324 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
327 return STATUS_INSUFFICIENT_RESOURCES
;
330 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
332 if (!PhysicalDeviceObject
)
334 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
335 if (!NT_SUCCESS(Status
))
341 /* This is for drivers passed on the command line to ntoskrnl.exe */
342 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
343 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
346 Node
->Pdo
= PhysicalDeviceObject
;
350 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
351 Node
->Parent
= ParentNode
;
352 Node
->NextSibling
= ParentNode
->Child
;
353 if (ParentNode
->Child
!= NULL
)
355 ParentNode
->Child
->PrevSibling
= Node
;
357 ParentNode
->Child
= Node
;
358 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
363 return STATUS_SUCCESS
;
367 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
371 /* All children must be deleted before a parent is deleted */
372 assert(!DeviceNode
->Child
);
374 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
376 assert(DeviceNode
->Pdo
);
378 ObDereferenceObject(DeviceNode
->Pdo
);
380 /* Unlink from parent if it exists */
382 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
384 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
387 /* Unlink from sibling list */
389 if (DeviceNode
->PrevSibling
)
391 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
394 if (DeviceNode
->NextSibling
)
396 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
399 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
401 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
403 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
405 if (DeviceNode
->CapabilityFlags
)
407 ExFreePool(DeviceNode
->CapabilityFlags
);
410 if (DeviceNode
->CmResourceList
)
412 ExFreePool(DeviceNode
->CmResourceList
);
415 if (DeviceNode
->BootResourcesList
)
417 ExFreePool(DeviceNode
->BootResourcesList
);
420 if (DeviceNode
->ResourceRequirementsList
)
422 ExFreePool(DeviceNode
->ResourceRequirementsList
);
425 RtlFreeUnicodeString(&DeviceNode
->DeviceID
);
427 RtlFreeUnicodeString(&DeviceNode
->InstanceID
);
429 RtlFreeUnicodeString(&DeviceNode
->HardwareIDs
);
431 RtlFreeUnicodeString(&DeviceNode
->CompatibleIDs
);
433 RtlFreeUnicodeString(&DeviceNode
->DeviceText
);
435 RtlFreeUnicodeString(&DeviceNode
->DeviceTextLocation
);
437 if (DeviceNode
->BusInformation
)
439 ExFreePool(DeviceNode
->BusInformation
);
442 ExFreePool(DeviceNode
);
444 return STATUS_SUCCESS
;
449 PDEVICE_OBJECT DeviceObject
,
450 PIO_STATUS_BLOCK IoStatusBlock
,
452 PIO_STACK_LOCATION Stack OPTIONAL
)
454 PDEVICE_OBJECT TopDeviceObject
;
455 PIO_STACK_LOCATION IrpSp
;
460 /* Always call the top of the device stack */
461 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
468 /* PNP IRPs are always initialized with a status code of
469 STATUS_NOT_IMPLEMENTED */
470 IoStatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
471 IoStatusBlock
->Information
= 0;
473 Irp
= IoBuildSynchronousFsdRequest(
482 IrpSp
= IoGetNextIrpStackLocation(Irp
);
483 IrpSp
->MinorFunction
= MinorFunction
;
490 sizeof(Stack
->Parameters
));
493 Status
= IoCallDriver(TopDeviceObject
, Irp
);
494 if (Status
== STATUS_PENDING
)
496 KeWaitForSingleObject(
502 Status
= IoStatusBlock
->Status
;
505 ObDereferenceObject(TopDeviceObject
);
512 IopQueryCapabilities(
514 PDEVICE_CAPABILITIES
*Capabilities
)
516 IO_STATUS_BLOCK IoStatusBlock
;
517 PDEVICE_CAPABILITIES Caps
;
518 IO_STACK_LOCATION Stack
;
521 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
523 *Capabilities
= NULL
;
525 Caps
= ExAllocatePool(PagedPool
, sizeof(DEVICE_CAPABILITIES
));
528 return STATUS_INSUFFICIENT_RESOURCES
;
531 RtlZeroMemory(Caps
, sizeof(DEVICE_CAPABILITIES
));
532 Caps
->Size
= sizeof(DEVICE_CAPABILITIES
);
537 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= Caps
;
539 Status
= IopInitiatePnpIrp(
542 IRP_MN_QUERY_CAPABILITIES
,
544 if (NT_SUCCESS(Status
))
546 *Capabilities
= Caps
;
550 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
558 IopTraverseDeviceTreeNode(
559 PDEVICETREE_TRAVERSE_CONTEXT Context
)
561 PDEVICE_NODE ParentDeviceNode
;
562 PDEVICE_NODE ChildDeviceNode
;
565 /* Copy context data so we don't overwrite it in subsequent calls to this function */
566 ParentDeviceNode
= Context
->DeviceNode
;
568 /* Call the action routine */
569 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
570 if (!NT_SUCCESS(Status
))
575 /* Traversal of all children nodes */
576 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
577 ChildDeviceNode
!= NULL
;
578 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
580 /* Pass the current device node to the action routine */
581 Context
->DeviceNode
= ChildDeviceNode
;
583 Status
= IopTraverseDeviceTreeNode(Context
);
584 if (!NT_SUCCESS(Status
))
595 IopTraverseDeviceTree(
596 PDEVICETREE_TRAVERSE_CONTEXT Context
)
600 DPRINT("Context %x\n", Context
);
602 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
603 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
605 /* Start from the specified device node */
606 Context
->DeviceNode
= Context
->FirstDeviceNode
;
608 /* Recursively traverse the device tree */
609 Status
= IopTraverseDeviceTreeNode(Context
);
610 if (Status
== STATUS_UNSUCCESSFUL
)
612 /* The action routine just wanted to terminate the traversal with status
613 code STATUS_SUCCESS */
614 Status
= STATUS_SUCCESS
;
622 IopActionInterrogateDeviceStack(
623 PDEVICE_NODE DeviceNode
,
626 * FUNCTION: Retrieve information for all (direct) child nodes of a parent node
628 * DeviceNode = Pointer to device node
629 * Context = Pointer to parent node to retrieve child node information for
631 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
632 * when we reach a device node which is not a direct child of the device node
633 * for which we retrieve information of child nodes for. Any errors that occur
634 * is logged instead so that all child services have a chance of beeing
638 IO_STATUS_BLOCK IoStatusBlock
;
639 PDEVICE_NODE ParentDeviceNode
;
640 WCHAR InstancePath
[MAX_PATH
];
641 IO_STACK_LOCATION Stack
;
644 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
646 DPRINT("PDO %x\n", DeviceNode
->Pdo
);
649 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
651 /* We are called for the parent too, but we don't need to do special
652 handling for this node */
653 if (DeviceNode
== ParentDeviceNode
)
656 return STATUS_SUCCESS
;
659 /* Make sure this device node is a direct child of the parent device node
660 that is given as an argument */
661 if (DeviceNode
->Parent
!= ParentDeviceNode
)
663 /* Stop the traversal immediately and indicate successful operation */
665 return STATUS_UNSUCCESSFUL
;
669 /* FIXME: For critical errors, cleanup and disable device, but always return STATUS_SUCCESS */
672 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
674 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
676 Status
= IopInitiatePnpIrp(
681 if (NT_SUCCESS(Status
))
683 RtlInitUnicodeString(
684 &DeviceNode
->DeviceID
,
685 (LPWSTR
)IoStatusBlock
.Information
);
687 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
691 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
692 RtlInitUnicodeString(&DeviceNode
->DeviceID
, NULL
);
696 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
698 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
700 Status
= IopInitiatePnpIrp(
705 if (NT_SUCCESS(Status
))
707 RtlInitUnicodeString(
708 &DeviceNode
->InstanceID
,
709 (LPWSTR
)IoStatusBlock
.Information
);
711 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
715 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
716 RtlInitUnicodeString(&DeviceNode
->InstanceID
, NULL
);
720 /* FIXME: SEND IRP_QUERY_ID.BusQueryHardwareIDs */
721 /* FIXME: SEND IRP_QUERY_ID.BusQueryCompatibleIDs */
724 Status
= IopQueryCapabilities(DeviceNode
->Pdo
, &DeviceNode
->CapabilityFlags
);
725 if (NT_SUCCESS(Status
))
733 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
735 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
736 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
738 Status
= IopInitiatePnpIrp(
741 IRP_MN_QUERY_DEVICE_TEXT
,
743 if (NT_SUCCESS(Status
))
745 RtlInitUnicodeString(
746 &DeviceNode
->DeviceText
,
747 (LPWSTR
)IoStatusBlock
.Information
);
751 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
752 RtlInitUnicodeString(&DeviceNode
->DeviceText
, NULL
);
756 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
758 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
759 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
761 Status
= IopInitiatePnpIrp(
764 IRP_MN_QUERY_DEVICE_TEXT
,
766 if (NT_SUCCESS(Status
))
768 RtlInitUnicodeString(
769 &DeviceNode
->DeviceTextLocation
,
770 (LPWSTR
)IoStatusBlock
.Information
);
774 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
775 RtlInitUnicodeString(&DeviceNode
->DeviceTextLocation
, NULL
);
779 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
781 Status
= IopInitiatePnpIrp(
784 IRP_MN_QUERY_BUS_INFORMATION
,
786 if (NT_SUCCESS(Status
))
788 DeviceNode
->BusInformation
=
789 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
793 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
794 DeviceNode
->BusInformation
= NULL
;
798 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
800 Status
= IopInitiatePnpIrp(
803 IRP_MN_QUERY_RESOURCES
,
805 if (NT_SUCCESS(Status
))
807 DeviceNode
->BootResourcesList
=
808 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
812 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
813 DeviceNode
->BootResourcesList
= NULL
;
817 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
819 Status
= IopInitiatePnpIrp(
822 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
824 if (NT_SUCCESS(Status
))
826 DeviceNode
->ResourceRequirementsList
=
827 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
831 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
832 DeviceNode
->ResourceRequirementsList
= NULL
;
836 /* Assemble the instance path for the device */
838 wcscpy(InstancePath
, DeviceNode
->DeviceID
.Buffer
);
839 wcscat(InstancePath
, L
"\\");
840 wcscat(InstancePath
, DeviceNode
->InstanceID
.Buffer
);
842 if (!DeviceNode
->CapabilityFlags
->UniqueID
)
844 DPRINT("Instance ID is not unique\n");
845 /* FIXME: Add information from parent bus driver to InstancePath */
848 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
)) {
849 DPRINT("No resources\n");
850 /* FIXME: Cleanup and disable device */
853 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
855 return STATUS_SUCCESS
;
860 IopActionConfigureChildServices(
861 PDEVICE_NODE DeviceNode
,
864 * FUNCTION: Retrieve configuration for all (direct) child nodes of a parent node
866 * DeviceNode = Pointer to device node
867 * Context = Pointer to parent node to retrieve child node configuration for
869 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
870 * when we reach a device node which is not a direct child of the device
871 * node for which we configure child services for. Any errors that occur is
872 * logged instead so that all child services have a chance of beeing
876 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
877 PDEVICE_NODE ParentDeviceNode
;
878 PUNICODE_STRING Service
;
882 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
884 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
886 /* We are called for the parent too, but we don't need to do special
887 handling for this node */
888 if (DeviceNode
== ParentDeviceNode
)
891 return STATUS_SUCCESS
;
894 /* Make sure this device node is a direct child of the parent device node
895 that is given as an argument */
896 if (DeviceNode
->Parent
!= ParentDeviceNode
)
898 /* Stop the traversal immediately and indicate successful operation */
900 return STATUS_UNSUCCESSFUL
;
903 /* Retrieve configuration from Enum key */
905 Service
= &DeviceNode
->ServiceName
;
907 Status
= RtlpGetRegistryHandle(
909 DeviceNode
->InstancePath
.Buffer
,
912 if (!NT_SUCCESS(Status
))
914 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status
);
918 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
920 RtlInitUnicodeString(Service
, NULL
);
922 QueryTable
[0].Name
= L
"Service";
923 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
924 QueryTable
[0].EntryContext
= Service
;
926 Status
= RtlQueryRegistryValues(
934 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status
);
936 if (!NT_SUCCESS(Status
))
938 /* FIXME: Log the error */
939 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
940 DeviceNode
->InstancePath
.Buffer
, Status
);
941 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
942 return STATUS_SUCCESS
;
945 DPRINT("Got Service %S\n", Service
->Buffer
);
947 return STATUS_SUCCESS
;
952 IopActionInitChildServices(
953 PDEVICE_NODE DeviceNode
,
956 * FUNCTION: Initialize the service for all (direct) child nodes of a parent node
958 * DeviceNode = Pointer to device node
959 * Context = Pointer to parent node to initialize child node services for
961 * If the driver image for a service is not loaded and initialized
962 * it is done here too.
963 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
964 * when we reach a device node which is not a direct child of the device
965 * node for which we initialize child services for. Any errors that occur is
966 * logged instead so that all child services have a chance of beeing
970 PDEVICE_NODE ParentDeviceNode
;
973 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
975 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
977 /* We are called for the parent too, but we don't need to do special
978 handling for this node */
979 if (DeviceNode
== ParentDeviceNode
)
982 return STATUS_SUCCESS
;
985 /* Make sure this device node is a direct child of the parent device node
986 that is given as an argument */
987 if (DeviceNode
->Parent
!= ParentDeviceNode
)
989 /* Stop the traversal immediately and indicate successful operation */
991 return STATUS_UNSUCCESSFUL
;
994 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
995 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
996 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
998 Status
= IopInitializeDeviceNodeService(DeviceNode
);
999 if (NT_SUCCESS(Status
))
1001 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1005 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1007 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1008 CPRINT("Initialization of service %S failed (Status %x)\n",
1009 DeviceNode
->ServiceName
.Buffer
, Status
);
1014 DPRINT("Service %S is disabled or already initialized\n",
1015 DeviceNode
->ServiceName
.Buffer
);
1018 return STATUS_SUCCESS
;
1023 IopInterrogateBusExtender(
1024 PDEVICE_NODE DeviceNode
,
1026 BOOLEAN BootDriversOnly
)
1028 DEVICETREE_TRAVERSE_CONTEXT Context
;
1029 PDEVICE_RELATIONS DeviceRelations
;
1030 IO_STATUS_BLOCK IoStatusBlock
;
1031 PDEVICE_NODE ChildDeviceNode
;
1032 IO_STACK_LOCATION Stack
;
1036 DPRINT("DeviceNode %x Pdo %x BootDriversOnly %d\n", DeviceNode
, Pdo
, BootDriversOnly
);
1038 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1040 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1042 Status
= IopInitiatePnpIrp(
1045 IRP_MN_QUERY_DEVICE_RELATIONS
,
1047 if (!NT_SUCCESS(Status
))
1049 DPRINT("IopInitiatePnpIrp() failed\n");
1053 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1055 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1057 DPRINT("No PDOs\n");
1058 if (DeviceRelations
)
1060 ExFreePool(DeviceRelations
);
1062 return STATUS_SUCCESS
;
1065 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1067 /* Create device nodes for all discovered devices */
1068 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1070 Status
= IopCreateDeviceNode(
1072 DeviceRelations
->Objects
[i
],
1074 if (!NT_SUCCESS(Status
))
1076 DPRINT("No resources\n");
1077 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1078 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1079 ExFreePool(DeviceRelations
);
1080 return STATUS_INSUFFICIENT_RESOURCES
;
1084 ExFreePool(DeviceRelations
);
1087 /* Retrieve information about all discovered children from the bus driver */
1089 IopInitDeviceTreeTraverseContext(
1092 IopActionInterrogateDeviceStack
,
1095 Status
= IopTraverseDeviceTree(&Context
);
1096 if (!NT_SUCCESS(Status
))
1098 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1103 /* Retrieve configuration from the registry for discovered children */
1105 IopInitDeviceTreeTraverseContext(
1108 IopActionConfigureChildServices
,
1111 Status
= IopTraverseDeviceTree(&Context
);
1112 if (!NT_SUCCESS(Status
))
1114 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1119 /* Initialize services for discovered children */
1121 IopInitDeviceTreeTraverseContext(
1124 IopActionInitChildServices
,
1127 Status
= IopTraverseDeviceTree(&Context
);
1128 if (!NT_SUCCESS(Status
))
1130 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1138 VOID
IopLoadBootStartDrivers(VOID
)
1140 IopInterrogateBusExtender(
1142 IopRootDeviceNode
->Pdo
,
1153 KeInitializeSpinLock(&IopDeviceTreeLock
);
1155 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, FALSE
);
1156 if (!NT_SUCCESS(Status
))
1158 CPRINT("IoCreateDriverObject() failed\n");
1159 KeBugCheck(PHASE1_INITIALIZATION_FAILED
);
1162 Status
= IoCreateDevice(
1163 IopRootDriverObject
,
1166 FILE_DEVICE_CONTROLLER
,
1170 if (!NT_SUCCESS(Status
))
1172 CPRINT("IoCreateDevice() failed\n");
1173 KeBugCheck(PHASE1_INITIALIZATION_FAILED
);
1176 Status
= IopCreateDeviceNode(
1179 &IopRootDeviceNode
);
1180 if (!NT_SUCCESS(Status
))
1182 CPRINT("Insufficient resources\n");
1183 KeBugCheck(PHASE1_INITIALIZATION_FAILED
);
1186 IopRootDeviceNode
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1188 IopRootDeviceNode
->DriverObject
= IopRootDriverObject
;
1190 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1192 IopRootDriverObject
->DriverExtension
->AddDevice(
1193 IopRootDriverObject
,
1194 IopRootDeviceNode
->Pdo
);