1 /* $Id: pnpmgr.c,v 1.4 2001/09/16 13:19:32 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 ParentNode
->Child
->PrevSibling
= Node
;
354 ParentNode
->Child
= Node
;
355 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
360 return STATUS_SUCCESS
;
364 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
368 /* All children must be deleted before a parent is deleted */
369 assert(!DeviceNode
->Child
);
371 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
373 assert(DeviceNode
->Pdo
);
375 ObDereferenceObject(DeviceNode
->Pdo
);
377 /* Unlink from parent if it exists */
379 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
381 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
384 /* Unlink from sibling list */
386 if (DeviceNode
->PrevSibling
)
388 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
391 if (DeviceNode
->NextSibling
)
393 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
396 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
398 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
400 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
402 if (DeviceNode
->CapabilityFlags
)
404 ExFreePool(DeviceNode
->CapabilityFlags
);
407 if (DeviceNode
->CmResourceList
)
409 ExFreePool(DeviceNode
->CmResourceList
);
412 if (DeviceNode
->BootResourcesList
)
414 ExFreePool(DeviceNode
->BootResourcesList
);
417 if (DeviceNode
->ResourceRequirementsList
)
419 ExFreePool(DeviceNode
->ResourceRequirementsList
);
422 RtlFreeUnicodeString(&DeviceNode
->DeviceID
);
424 RtlFreeUnicodeString(&DeviceNode
->InstanceID
);
426 RtlFreeUnicodeString(&DeviceNode
->HardwareIDs
);
428 RtlFreeUnicodeString(&DeviceNode
->CompatibleIDs
);
430 RtlFreeUnicodeString(&DeviceNode
->DeviceText
);
432 RtlFreeUnicodeString(&DeviceNode
->DeviceTextLocation
);
434 if (DeviceNode
->BusInformation
)
436 ExFreePool(DeviceNode
->BusInformation
);
439 ExFreePool(DeviceNode
);
441 return STATUS_SUCCESS
;
446 PDEVICE_OBJECT DeviceObject
,
447 PIO_STATUS_BLOCK IoStatusBlock
,
449 PIO_STACK_LOCATION Stack OPTIONAL
)
451 PDEVICE_OBJECT TopDeviceObject
;
452 PIO_STACK_LOCATION IrpSp
;
457 /* Always call the top of the device stack */
458 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
465 /* PNP IRPs are always initialized with a status code of
466 STATUS_NOT_IMPLEMENTED */
467 IoStatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
468 IoStatusBlock
->Information
= 0;
470 Irp
= IoBuildSynchronousFsdRequest(
479 IrpSp
= IoGetNextIrpStackLocation(Irp
);
480 IrpSp
->MinorFunction
= MinorFunction
;
487 sizeof(Stack
->Parameters
));
490 Status
= IoCallDriver(TopDeviceObject
, Irp
);
491 if (Status
== STATUS_PENDING
)
493 KeWaitForSingleObject(
499 Status
= IoStatusBlock
->Status
;
502 ObDereferenceObject(TopDeviceObject
);
509 IopQueryCapabilities(
511 PDEVICE_CAPABILITIES
*Capabilities
)
513 IO_STATUS_BLOCK IoStatusBlock
;
514 PDEVICE_CAPABILITIES Caps
;
515 IO_STACK_LOCATION Stack
;
518 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
520 *Capabilities
= NULL
;
522 Caps
= ExAllocatePool(PagedPool
, sizeof(DEVICE_CAPABILITIES
));
525 return STATUS_INSUFFICIENT_RESOURCES
;
528 RtlZeroMemory(Caps
, sizeof(DEVICE_CAPABILITIES
));
529 Caps
->Size
= sizeof(DEVICE_CAPABILITIES
);
534 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= Caps
;
536 Status
= IopInitiatePnpIrp(
539 IRP_MN_QUERY_CAPABILITIES
,
541 if (NT_SUCCESS(Status
))
543 *Capabilities
= Caps
;
547 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
555 IopTraverseDeviceTreeNode(
556 PDEVICETREE_TRAVERSE_CONTEXT Context
)
558 PDEVICE_NODE ParentDeviceNode
;
559 PDEVICE_NODE ChildDeviceNode
;
562 /* Copy context data so we don't overwrite it in subsequent calls to this function */
563 ParentDeviceNode
= Context
->DeviceNode
;
565 /* Call the action routine */
566 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
567 if (!NT_SUCCESS(Status
))
572 /* Traversal of all children nodes */
573 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
574 ChildDeviceNode
!= NULL
;
575 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
577 /* Pass the current device node to the action routine */
578 Context
->DeviceNode
= ChildDeviceNode
;
580 Status
= IopTraverseDeviceTreeNode(Context
);
581 if (!NT_SUCCESS(Status
))
592 IopTraverseDeviceTree(
593 PDEVICETREE_TRAVERSE_CONTEXT Context
)
597 DPRINT("Context %x\n", Context
);
599 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
600 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
602 /* Start from the specified device node */
603 Context
->DeviceNode
= Context
->FirstDeviceNode
;
605 /* Recursively traverse the device tree */
606 Status
= IopTraverseDeviceTreeNode(Context
);
607 if (Status
== STATUS_UNSUCCESSFUL
)
609 /* The action routine just wanted to terminate the traversal with status
610 code STATUS_SUCCESS */
611 Status
= STATUS_SUCCESS
;
619 IopActionInterrogateDeviceStack(
620 PDEVICE_NODE DeviceNode
,
623 * FUNCTION: Retrieve information for all (direct) child nodes of a parent node
625 * DeviceNode = Pointer to device node
626 * Context = Pointer to parent node to retrieve child node information for
628 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
629 * when we reach a device node which is not a direct child of the device node
630 * for which we retrieve information of child nodes for. Any errors that occur
631 * is logged instead so that all child services have a chance of beeing
635 IO_STATUS_BLOCK IoStatusBlock
;
636 PDEVICE_NODE ParentDeviceNode
;
637 WCHAR InstancePath
[MAX_PATH
];
638 IO_STACK_LOCATION Stack
;
641 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
643 DPRINT("PDO %x\n", DeviceNode
->Pdo
);
646 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
648 /* We are called for the parent too, but we don't need to do special
649 handling for this node */
650 if (DeviceNode
== ParentDeviceNode
)
653 return STATUS_SUCCESS
;
656 /* Make sure this device node is a direct child of the parent device node
657 that is given as an argument */
658 if (DeviceNode
->Parent
!= ParentDeviceNode
)
660 /* Stop the traversal immediately and indicate successful operation */
662 return STATUS_UNSUCCESSFUL
;
666 /* FIXME: For critical errors, cleanup and disable device, but always return STATUS_SUCCESS */
669 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
671 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
673 Status
= IopInitiatePnpIrp(
678 if (NT_SUCCESS(Status
))
680 RtlInitUnicodeString(
681 &DeviceNode
->DeviceID
,
682 (LPWSTR
)IoStatusBlock
.Information
);
684 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
688 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
689 RtlInitUnicodeString(&DeviceNode
->DeviceID
, NULL
);
693 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
695 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
697 Status
= IopInitiatePnpIrp(
702 if (NT_SUCCESS(Status
))
704 RtlInitUnicodeString(
705 &DeviceNode
->InstanceID
,
706 (LPWSTR
)IoStatusBlock
.Information
);
708 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
712 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
713 RtlInitUnicodeString(&DeviceNode
->InstanceID
, NULL
);
717 /* FIXME: SEND IRP_QUERY_ID.BusQueryHardwareIDs */
718 /* FIXME: SEND IRP_QUERY_ID.BusQueryCompatibleIDs */
721 Status
= IopQueryCapabilities(DeviceNode
->Pdo
, &DeviceNode
->CapabilityFlags
);
722 if (NT_SUCCESS(Status
))
730 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
732 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
733 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
735 Status
= IopInitiatePnpIrp(
738 IRP_MN_QUERY_DEVICE_TEXT
,
740 if (NT_SUCCESS(Status
))
742 RtlInitUnicodeString(
743 &DeviceNode
->DeviceText
,
744 (LPWSTR
)IoStatusBlock
.Information
);
748 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
749 RtlInitUnicodeString(&DeviceNode
->DeviceText
, NULL
);
753 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
755 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
756 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
758 Status
= IopInitiatePnpIrp(
761 IRP_MN_QUERY_DEVICE_TEXT
,
763 if (NT_SUCCESS(Status
))
765 RtlInitUnicodeString(
766 &DeviceNode
->DeviceTextLocation
,
767 (LPWSTR
)IoStatusBlock
.Information
);
771 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
772 RtlInitUnicodeString(&DeviceNode
->DeviceTextLocation
, NULL
);
776 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
778 Status
= IopInitiatePnpIrp(
781 IRP_MN_QUERY_BUS_INFORMATION
,
783 if (NT_SUCCESS(Status
))
785 DeviceNode
->BusInformation
=
786 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
790 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
791 DeviceNode
->BusInformation
= NULL
;
795 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
797 Status
= IopInitiatePnpIrp(
800 IRP_MN_QUERY_RESOURCES
,
802 if (NT_SUCCESS(Status
))
804 DeviceNode
->BootResourcesList
=
805 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
809 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
810 DeviceNode
->BootResourcesList
= NULL
;
814 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
816 Status
= IopInitiatePnpIrp(
819 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
821 if (NT_SUCCESS(Status
))
823 DeviceNode
->ResourceRequirementsList
=
824 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
828 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
829 DeviceNode
->ResourceRequirementsList
= NULL
;
833 /* Assemble the instance path for the device */
835 wcscpy(InstancePath
, DeviceNode
->DeviceID
.Buffer
);
836 wcscat(InstancePath
, L
"\\");
837 wcscat(InstancePath
, DeviceNode
->InstanceID
.Buffer
);
839 if (!DeviceNode
->CapabilityFlags
->UniqueID
)
841 DPRINT("Instance ID is not unique\n");
842 /* FIXME: Add information from parent bus driver to InstancePath */
845 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
)) {
846 DPRINT("No resources\n");
847 /* FIXME: Cleanup and disable device */
850 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
852 return STATUS_SUCCESS
;
857 IopActionConfigureChildServices(
858 PDEVICE_NODE DeviceNode
,
861 * FUNCTION: Retrieve configuration for all (direct) child nodes of a parent node
863 * DeviceNode = Pointer to device node
864 * Context = Pointer to parent node to retrieve child node configuration for
866 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
867 * when we reach a device node which is not a direct child of the device
868 * node for which we configure child services for. Any errors that occur is
869 * logged instead so that all child services have a chance of beeing
873 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
874 PDEVICE_NODE ParentDeviceNode
;
875 PUNICODE_STRING Service
;
879 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
881 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
883 /* We are called for the parent too, but we don't need to do special
884 handling for this node */
885 if (DeviceNode
== ParentDeviceNode
)
888 return STATUS_SUCCESS
;
891 /* Make sure this device node is a direct child of the parent device node
892 that is given as an argument */
893 if (DeviceNode
->Parent
!= ParentDeviceNode
)
895 /* Stop the traversal immediately and indicate successful operation */
897 return STATUS_UNSUCCESSFUL
;
900 /* Retrieve configuration from Enum key */
902 Service
= &DeviceNode
->ServiceName
;
904 Status
= RtlpGetRegistryHandle(
906 DeviceNode
->InstancePath
.Buffer
,
909 if (!NT_SUCCESS(Status
))
911 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status
);
915 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
917 RtlInitUnicodeString(Service
, NULL
);
919 QueryTable
[0].Name
= L
"Service";
920 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
921 QueryTable
[0].EntryContext
= Service
;
923 Status
= RtlQueryRegistryValues(
931 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status
);
933 if (!NT_SUCCESS(Status
))
935 /* FIXME: Log the error */
936 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
937 DeviceNode
->InstancePath
.Buffer
, Status
);
938 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
939 return STATUS_SUCCESS
;
942 DPRINT("Got Service %S\n", Service
->Buffer
);
944 return STATUS_SUCCESS
;
949 IopActionInitChildServices(
950 PDEVICE_NODE DeviceNode
,
953 * FUNCTION: Initialize the service for all (direct) child nodes of a parent node
955 * DeviceNode = Pointer to device node
956 * Context = Pointer to parent node to initialize child node services for
958 * If the driver image for a service is not loaded and initialized
959 * it is done here too.
960 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
961 * when we reach a device node which is not a direct child of the device
962 * node for which we initialize child services for. Any errors that occur is
963 * logged instead so that all child services have a chance of beeing
967 PDEVICE_NODE ParentDeviceNode
;
970 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
972 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
974 /* We are called for the parent too, but we don't need to do special
975 handling for this node */
976 if (DeviceNode
== ParentDeviceNode
)
979 return STATUS_SUCCESS
;
982 /* Make sure this device node is a direct child of the parent device node
983 that is given as an argument */
984 if (DeviceNode
->Parent
!= ParentDeviceNode
)
986 /* Stop the traversal immediately and indicate successful operation */
988 return STATUS_UNSUCCESSFUL
;
991 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
992 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
993 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
995 Status
= IopInitializeDeviceNodeService(DeviceNode
);
996 if (NT_SUCCESS(Status
))
998 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1002 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1004 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1005 CPRINT("Initialization of service %S failed (Status %x)\n",
1006 DeviceNode
->ServiceName
.Buffer
, Status
);
1011 DPRINT("Service %S is disabled or already initialized\n",
1012 DeviceNode
->ServiceName
.Buffer
);
1015 return STATUS_SUCCESS
;
1020 IopInterrogateBusExtender(
1021 PDEVICE_NODE DeviceNode
,
1023 BOOLEAN BootDriversOnly
)
1025 DEVICETREE_TRAVERSE_CONTEXT Context
;
1026 PDEVICE_RELATIONS DeviceRelations
;
1027 IO_STATUS_BLOCK IoStatusBlock
;
1028 PDEVICE_NODE ChildDeviceNode
;
1029 IO_STACK_LOCATION Stack
;
1033 DPRINT("DeviceNode %x Pdo %x BootDriversOnly %d\n", DeviceNode
, Pdo
, BootDriversOnly
);
1035 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1037 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1039 Status
= IopInitiatePnpIrp(
1042 IRP_MN_QUERY_DEVICE_RELATIONS
,
1044 if (!NT_SUCCESS(Status
))
1046 DPRINT("IopInitiatePnpIrp() failed\n");
1050 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1052 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1054 DPRINT("No PDOs\n");
1055 if (DeviceRelations
)
1057 ExFreePool(DeviceRelations
);
1059 return STATUS_SUCCESS
;
1062 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1068 DPRINT("DeviceRelations %x\n", DeviceRelations
);
1069 DPRINT("Count %x\n", DeviceRelations
->Count
);
1070 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1071 DPRINT("Object(PDO) %x\n", DeviceRelations
->Objects
[i
]);
1075 /* Create device nodes for all discovered devices */
1076 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1078 Status
= IopCreateDeviceNode(
1080 DeviceRelations
->Objects
[i
],
1082 if (!NT_SUCCESS(Status
))
1084 DPRINT("No resources\n");
1085 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1086 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1087 ExFreePool(DeviceRelations
);
1088 return STATUS_INSUFFICIENT_RESOURCES
;
1092 ExFreePool(DeviceRelations
);
1095 /* Retrieve information about all discovered children from the bus driver */
1097 IopInitDeviceTreeTraverseContext(
1100 IopActionInterrogateDeviceStack
,
1103 Status
= IopTraverseDeviceTree(&Context
);
1104 if (!NT_SUCCESS(Status
))
1106 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1111 /* Retrieve configuration from the registry for discovered children */
1113 IopInitDeviceTreeTraverseContext(
1116 IopActionConfigureChildServices
,
1119 Status
= IopTraverseDeviceTree(&Context
);
1120 if (!NT_SUCCESS(Status
))
1122 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1127 /* Initialize services for discovered children */
1129 IopInitDeviceTreeTraverseContext(
1132 IopActionInitChildServices
,
1135 Status
= IopTraverseDeviceTree(&Context
);
1136 if (!NT_SUCCESS(Status
))
1138 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1146 VOID
IopLoadBootStartDrivers(VOID
)
1148 IopInterrogateBusExtender(
1150 IopRootDeviceNode
->Pdo
,
1161 KeInitializeSpinLock(&IopDeviceTreeLock
);
1163 Status
= IopCreateDriverObject(&IopRootDriverObject
);
1164 if (!NT_SUCCESS(Status
))
1166 CPRINT("IoCreateDriverObject() failed\n");
1167 KeBugCheck(PHASE1_INITIALIZATION_FAILED
);
1170 Status
= IoCreateDevice(
1171 IopRootDriverObject
,
1174 FILE_DEVICE_CONTROLLER
,
1178 if (!NT_SUCCESS(Status
))
1180 CPRINT("IoCreateDevice() failed\n");
1181 KeBugCheck(PHASE1_INITIALIZATION_FAILED
);
1184 Status
= IopCreateDeviceNode(
1187 &IopRootDeviceNode
);
1188 if (!NT_SUCCESS(Status
))
1190 CPRINT("Insufficient resources\n");
1191 KeBugCheck(PHASE1_INITIALIZATION_FAILED
);
1194 IopRootDeviceNode
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1196 IopRootDeviceNode
->DriverObject
= IopRootDriverObject
;
1198 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1200 IopRootDriverObject
->DriverExtension
->AddDevice(
1201 IopRootDriverObject
,
1202 IopRootDeviceNode
->Pdo
);