1 /* $Id: pnpmgr.c,v 1.11 2003/07/10 15:47:00 royce 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 <reactos/bugcodes.h>
16 #include <internal/io.h>
17 #include <internal/po.h>
18 #include <internal/ldr.h>
19 #include <internal/registry.h>
20 #include <internal/module.h>
22 #include <ole32/guiddef.h>
23 //#include <ddk/pnpfuncs.h>
25 DEFINE_GUID(GUID_CLASS_COMPORT
, 0x86e0d1e0L
, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73);
26 DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR
, 0x4D36E978L
, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
31 #include <internal/debug.h>
34 /* GLOBALS *******************************************************************/
36 PDEVICE_NODE IopRootDeviceNode
;
37 KSPIN_LOCK IopDeviceTreeLock
;
39 /* DATA **********************************************************************/
41 PDRIVER_OBJECT IopRootDriverObject
;
43 /* FUNCTIONS *****************************************************************/
50 IoInitializeRemoveLockEx(
51 IN PIO_REMOVE_LOCK Lock
,
53 IN ULONG MaxLockedMinutes
,
54 IN ULONG HighWatermark
,
64 IoAcquireRemoveLockEx(
65 IN PIO_REMOVE_LOCK RemoveLock
,
66 IN OPTIONAL PVOID Tag
,
71 return STATUS_NOT_IMPLEMENTED
;
79 IoReleaseRemoveLockEx(
80 IN PIO_REMOVE_LOCK RemoveLock
,
91 IoReleaseRemoveLockAndWaitEx(
92 IN PIO_REMOVE_LOCK RemoveLock
,
103 IoAdjustPagingPathCount(
105 IN BOOLEAN Increment
)
114 IoGetDeviceInterfaceAlias(
115 IN PUNICODE_STRING SymbolicLinkName
,
116 IN CONST GUID
*AliasInterfaceClassGuid
,
117 OUT PUNICODE_STRING AliasSymbolicLinkName
)
119 return STATUS_NOT_IMPLEMENTED
;
127 IoGetDeviceInterfaces(
128 IN CONST GUID
*InterfaceClassGuid
,
129 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL
,
131 OUT PWSTR
*SymbolicLinkList
)
133 return STATUS_NOT_IMPLEMENTED
;
142 IN PDEVICE_OBJECT DeviceObject
,
143 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
144 IN ULONG BufferLength
,
145 OUT PVOID PropertyBuffer
,
146 OUT PULONG ResultLength
)
148 return STATUS_NOT_IMPLEMENTED
;
156 IoInvalidateDeviceRelations(
157 IN PDEVICE_OBJECT DeviceObject
,
158 IN DEVICE_RELATION_TYPE Type
)
167 IoInvalidateDeviceState(
168 IN PDEVICE_OBJECT PhysicalDeviceObject
)
177 IoOpenDeviceInterfaceRegistryKey(
178 IN PUNICODE_STRING SymbolicLinkName
,
179 IN ACCESS_MASK DesiredAccess
,
180 OUT PHANDLE DeviceInterfaceKey
)
182 return STATUS_NOT_IMPLEMENTED
;
190 IoOpenDeviceRegistryKey(
191 IN PDEVICE_OBJECT DeviceObject
,
192 IN ULONG DevInstKeyType
,
193 IN ACCESS_MASK DesiredAccess
,
194 OUT PHANDLE DevInstRegKey
)
196 return STATUS_NOT_IMPLEMENTED
;
204 IoRegisterDeviceInterface(
205 IN PDEVICE_OBJECT PhysicalDeviceObject
,
206 IN CONST GUID
*InterfaceClassGuid
,
207 IN PUNICODE_STRING ReferenceString OPTIONAL
,
208 OUT PUNICODE_STRING SymbolicLinkName
)
210 PWCHAR KeyNameString
= L
"\\Device\\Serenum";
212 if (IsEqualGUID(InterfaceClassGuid
, (LPGUID
)&GUID_SERENUM_BUS_ENUMERATOR
)) {
213 RtlInitUnicodeString(SymbolicLinkName
, KeyNameString
);
214 return STATUS_SUCCESS
;
216 return STATUS_INVALID_DEVICE_REQUEST
;
217 // return STATUS_NOT_IMPLEMENTED;
225 IoRegisterPlugPlayNotification(
226 IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory
,
227 IN ULONG EventCategoryFlags
,
228 IN PVOID EventCategoryData OPTIONAL
,
229 IN PDRIVER_OBJECT DriverObject
,
230 IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine
,
232 OUT PVOID
*NotificationEntry
)
234 return STATUS_NOT_IMPLEMENTED
;
242 IoReportDetectedDevice(
243 IN PDRIVER_OBJECT DriverObject
,
244 IN INTERFACE_TYPE LegacyBusType
,
247 IN PCM_RESOURCE_LIST ResourceList
,
248 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL
,
249 IN BOOLEAN ResourceAssigned
,
250 IN OUT PDEVICE_OBJECT
*DeviceObject
)
252 return STATUS_NOT_IMPLEMENTED
;
260 IoReportResourceForDetection(
261 IN PDRIVER_OBJECT DriverObject
,
262 IN PCM_RESOURCE_LIST DriverList OPTIONAL
,
263 IN ULONG DriverListSize OPTIONAL
,
264 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
265 IN PCM_RESOURCE_LIST DeviceList OPTIONAL
,
266 IN ULONG DeviceListSize OPTIONAL
,
267 OUT PBOOLEAN ConflictDetected
)
269 return STATUS_NOT_IMPLEMENTED
;
277 IoReportTargetDeviceChange(
278 IN PDEVICE_OBJECT PhysicalDeviceObject
,
279 IN PVOID NotificationStructure
)
281 return STATUS_NOT_IMPLEMENTED
;
289 IoReportTargetDeviceChangeAsynchronous(
290 IN PDEVICE_OBJECT PhysicalDeviceObject
,
291 IN PVOID NotificationStructure
,
292 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL
,
293 IN PVOID Context OPTIONAL
)
295 return STATUS_NOT_IMPLEMENTED
;
303 IoRequestDeviceEject(
304 IN PDEVICE_OBJECT PhysicalDeviceObject
)
313 IoSetDeviceInterfaceState(
314 IN PUNICODE_STRING SymbolicLinkName
,
317 return STATUS_SUCCESS
;
319 // return STATUS_OBJECT_NAME_EXISTS;
320 // return STATUS_OBJECT_NAME_NOT_FOUND;
321 // return STATUS_NOT_IMPLEMENTED;
329 IoUnregisterPlugPlayNotification(
330 IN PVOID NotificationEntry
)
332 return STATUS_NOT_IMPLEMENTED
;
337 IopCreateUnicodeString(
338 PUNICODE_STRING Destination
,
346 RtlInitUnicodeString(Destination
, NULL
);
350 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
352 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
354 if (Destination
->Buffer
== NULL
)
359 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
361 Destination
->MaximumLength
= Length
;
363 Destination
->Length
= Length
- sizeof(WCHAR
);
369 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
373 assert(PopSystemPowerDeviceNode
);
375 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
376 *DeviceObject
= PopSystemPowerDeviceNode
->Pdo
;
377 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
379 return STATUS_SUCCESS
;
382 /**********************************************************************
384 * Creates a device node
387 * ParentNode = Pointer to parent device node
388 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
389 * to have the root device node create one
390 * (eg. for legacy drivers)
391 * DeviceNode = Pointer to storage for created device node
397 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
398 PDEVICE_OBJECT PhysicalDeviceObject
,
399 PDEVICE_NODE
*DeviceNode
)
405 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
406 ParentNode
, PhysicalDeviceObject
);
408 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
411 return STATUS_INSUFFICIENT_RESOURCES
;
414 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
416 if (!PhysicalDeviceObject
)
418 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
419 if (!NT_SUCCESS(Status
))
425 /* This is for drivers passed on the command line to ntoskrnl.exe */
426 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
427 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
430 Node
->Pdo
= PhysicalDeviceObject
;
434 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
435 Node
->Parent
= ParentNode
;
436 Node
->NextSibling
= ParentNode
->Child
;
437 if (ParentNode
->Child
!= NULL
)
439 ParentNode
->Child
->PrevSibling
= Node
;
441 ParentNode
->Child
= Node
;
442 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
447 return STATUS_SUCCESS
;
451 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
455 /* All children must be deleted before a parent is deleted */
456 assert(!DeviceNode
->Child
);
458 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
460 assert(DeviceNode
->Pdo
);
462 ObDereferenceObject(DeviceNode
->Pdo
);
464 /* Unlink from parent if it exists */
466 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
468 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
471 /* Unlink from sibling list */
473 if (DeviceNode
->PrevSibling
)
475 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
478 if (DeviceNode
->NextSibling
)
480 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
483 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
485 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
487 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
489 if (DeviceNode
->CapabilityFlags
)
491 ExFreePool(DeviceNode
->CapabilityFlags
);
494 if (DeviceNode
->CmResourceList
)
496 ExFreePool(DeviceNode
->CmResourceList
);
499 if (DeviceNode
->BootResourcesList
)
501 ExFreePool(DeviceNode
->BootResourcesList
);
504 if (DeviceNode
->ResourceRequirementsList
)
506 ExFreePool(DeviceNode
->ResourceRequirementsList
);
509 RtlFreeUnicodeString(&DeviceNode
->DeviceID
);
511 RtlFreeUnicodeString(&DeviceNode
->InstanceID
);
513 RtlFreeUnicodeString(&DeviceNode
->HardwareIDs
);
515 RtlFreeUnicodeString(&DeviceNode
->CompatibleIDs
);
517 RtlFreeUnicodeString(&DeviceNode
->DeviceText
);
519 RtlFreeUnicodeString(&DeviceNode
->DeviceTextLocation
);
521 if (DeviceNode
->BusInformation
)
523 ExFreePool(DeviceNode
->BusInformation
);
526 ExFreePool(DeviceNode
);
528 return STATUS_SUCCESS
;
533 PDEVICE_OBJECT DeviceObject
,
534 PIO_STATUS_BLOCK IoStatusBlock
,
536 PIO_STACK_LOCATION Stack OPTIONAL
)
538 PDEVICE_OBJECT TopDeviceObject
;
539 PIO_STACK_LOCATION IrpSp
;
544 /* Always call the top of the device stack */
545 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
552 /* PNP IRPs are always initialized with a status code of
553 STATUS_NOT_IMPLEMENTED */
554 IoStatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
555 IoStatusBlock
->Information
= 0;
557 Irp
= IoBuildSynchronousFsdRequest(
566 IrpSp
= IoGetNextIrpStackLocation(Irp
);
567 IrpSp
->MinorFunction
= MinorFunction
;
574 sizeof(Stack
->Parameters
));
577 Status
= IoCallDriver(TopDeviceObject
, Irp
);
578 if (Status
== STATUS_PENDING
)
580 KeWaitForSingleObject(
586 Status
= IoStatusBlock
->Status
;
589 ObDereferenceObject(TopDeviceObject
);
596 IopQueryCapabilities(
598 PDEVICE_CAPABILITIES
*Capabilities
)
600 IO_STATUS_BLOCK IoStatusBlock
;
601 PDEVICE_CAPABILITIES Caps
;
602 IO_STACK_LOCATION Stack
;
605 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
607 *Capabilities
= NULL
;
609 Caps
= ExAllocatePool(PagedPool
, sizeof(DEVICE_CAPABILITIES
));
612 return STATUS_INSUFFICIENT_RESOURCES
;
615 RtlZeroMemory(Caps
, sizeof(DEVICE_CAPABILITIES
));
616 Caps
->Size
= sizeof(DEVICE_CAPABILITIES
);
621 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= Caps
;
623 Status
= IopInitiatePnpIrp(
626 IRP_MN_QUERY_CAPABILITIES
,
628 if (NT_SUCCESS(Status
))
630 *Capabilities
= Caps
;
634 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
642 IopTraverseDeviceTreeNode(
643 PDEVICETREE_TRAVERSE_CONTEXT Context
)
645 PDEVICE_NODE ParentDeviceNode
;
646 PDEVICE_NODE ChildDeviceNode
;
649 /* Copy context data so we don't overwrite it in subsequent calls to this function */
650 ParentDeviceNode
= Context
->DeviceNode
;
652 /* Call the action routine */
653 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
654 if (!NT_SUCCESS(Status
))
659 /* Traversal of all children nodes */
660 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
661 ChildDeviceNode
!= NULL
;
662 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
664 /* Pass the current device node to the action routine */
665 Context
->DeviceNode
= ChildDeviceNode
;
667 Status
= IopTraverseDeviceTreeNode(Context
);
668 if (!NT_SUCCESS(Status
))
679 IopTraverseDeviceTree(
680 PDEVICETREE_TRAVERSE_CONTEXT Context
)
684 DPRINT("Context %x\n", Context
);
686 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
687 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
689 /* Start from the specified device node */
690 Context
->DeviceNode
= Context
->FirstDeviceNode
;
692 /* Recursively traverse the device tree */
693 Status
= IopTraverseDeviceTreeNode(Context
);
694 if (Status
== STATUS_UNSUCCESSFUL
)
696 /* The action routine just wanted to terminate the traversal with status
697 code STATUS_SUCCESS */
698 Status
= STATUS_SUCCESS
;
706 IopActionInterrogateDeviceStack(
707 PDEVICE_NODE DeviceNode
,
710 * FUNCTION: Retrieve information for all (direct) child nodes of a parent node
712 * DeviceNode = Pointer to device node
713 * Context = Pointer to parent node to retrieve child node information for
715 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
716 * when we reach a device node which is not a direct child of the device node
717 * for which we retrieve information of child nodes for. Any errors that occur
718 * is logged instead so that all child services have a chance of beeing
722 IO_STATUS_BLOCK IoStatusBlock
;
723 PDEVICE_NODE ParentDeviceNode
;
724 WCHAR InstancePath
[MAX_PATH
];
725 IO_STACK_LOCATION Stack
;
728 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
730 DPRINT("PDO %x\n", DeviceNode
->Pdo
);
733 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
735 /* We are called for the parent too, but we don't need to do special
736 handling for this node */
737 if (DeviceNode
== ParentDeviceNode
)
740 return STATUS_SUCCESS
;
743 /* Make sure this device node is a direct child of the parent device node
744 that is given as an argument */
745 if (DeviceNode
->Parent
!= ParentDeviceNode
)
747 /* Stop the traversal immediately and indicate successful operation */
749 return STATUS_UNSUCCESSFUL
;
753 /* FIXME: For critical errors, cleanup and disable device, but always return STATUS_SUCCESS */
756 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
758 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
760 Status
= IopInitiatePnpIrp(
765 if (NT_SUCCESS(Status
))
767 RtlInitUnicodeString(
768 &DeviceNode
->DeviceID
,
769 (LPWSTR
)IoStatusBlock
.Information
);
771 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
775 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
776 RtlInitUnicodeString(&DeviceNode
->DeviceID
, NULL
);
780 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
782 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
784 Status
= IopInitiatePnpIrp(
789 if (NT_SUCCESS(Status
))
791 RtlInitUnicodeString(
792 &DeviceNode
->InstanceID
,
793 (LPWSTR
)IoStatusBlock
.Information
);
795 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
799 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
800 RtlInitUnicodeString(&DeviceNode
->InstanceID
, NULL
);
804 /* FIXME: SEND IRP_QUERY_ID.BusQueryHardwareIDs */
805 /* FIXME: SEND IRP_QUERY_ID.BusQueryCompatibleIDs */
808 Status
= IopQueryCapabilities(DeviceNode
->Pdo
, &DeviceNode
->CapabilityFlags
);
809 if (NT_SUCCESS(Status
))
817 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
819 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
820 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
822 Status
= IopInitiatePnpIrp(
825 IRP_MN_QUERY_DEVICE_TEXT
,
827 if (NT_SUCCESS(Status
))
829 RtlInitUnicodeString(
830 &DeviceNode
->DeviceText
,
831 (LPWSTR
)IoStatusBlock
.Information
);
835 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
836 RtlInitUnicodeString(&DeviceNode
->DeviceText
, NULL
);
840 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
842 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
843 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
845 Status
= IopInitiatePnpIrp(
848 IRP_MN_QUERY_DEVICE_TEXT
,
850 if (NT_SUCCESS(Status
))
852 RtlInitUnicodeString(
853 &DeviceNode
->DeviceTextLocation
,
854 (LPWSTR
)IoStatusBlock
.Information
);
858 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
859 RtlInitUnicodeString(&DeviceNode
->DeviceTextLocation
, NULL
);
863 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
865 Status
= IopInitiatePnpIrp(
868 IRP_MN_QUERY_BUS_INFORMATION
,
870 if (NT_SUCCESS(Status
))
872 DeviceNode
->BusInformation
=
873 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
877 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
878 DeviceNode
->BusInformation
= NULL
;
882 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
884 Status
= IopInitiatePnpIrp(
887 IRP_MN_QUERY_RESOURCES
,
889 if (NT_SUCCESS(Status
))
891 DeviceNode
->BootResourcesList
=
892 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
896 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
897 DeviceNode
->BootResourcesList
= NULL
;
901 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
903 Status
= IopInitiatePnpIrp(
906 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
908 if (NT_SUCCESS(Status
))
910 DeviceNode
->ResourceRequirementsList
=
911 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
915 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
916 DeviceNode
->ResourceRequirementsList
= NULL
;
920 /* Assemble the instance path for the device */
922 wcscpy(InstancePath
, DeviceNode
->DeviceID
.Buffer
);
923 wcscat(InstancePath
, L
"\\");
924 wcscat(InstancePath
, DeviceNode
->InstanceID
.Buffer
);
926 if (!DeviceNode
->CapabilityFlags
->UniqueID
)
928 DPRINT("Instance ID is not unique\n");
929 /* FIXME: Add information from parent bus driver to InstancePath */
932 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
)) {
933 DPRINT("No resources\n");
934 /* FIXME: Cleanup and disable device */
937 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
939 return STATUS_SUCCESS
;
944 IopActionConfigureChildServices(
945 PDEVICE_NODE DeviceNode
,
948 * FUNCTION: Retrieve configuration for all (direct) child nodes of a parent node
950 * DeviceNode = Pointer to device node
951 * Context = Pointer to parent node to retrieve child node configuration for
953 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
954 * when we reach a device node which is not a direct child of the device
955 * node for which we configure child services for. Any errors that occur is
956 * logged instead so that all child services have a chance of beeing
960 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
961 PDEVICE_NODE ParentDeviceNode
;
962 PUNICODE_STRING Service
;
966 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
968 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
970 /* We are called for the parent too, but we don't need to do special
971 handling for this node */
972 if (DeviceNode
== ParentDeviceNode
)
975 return STATUS_SUCCESS
;
978 /* Make sure this device node is a direct child of the parent device node
979 that is given as an argument */
980 if (DeviceNode
->Parent
!= ParentDeviceNode
)
982 /* Stop the traversal immediately and indicate successful operation */
984 return STATUS_UNSUCCESSFUL
;
987 /* Retrieve configuration from Enum key */
989 Service
= &DeviceNode
->ServiceName
;
991 Status
= RtlpGetRegistryHandle(
993 DeviceNode
->InstancePath
.Buffer
,
996 if (!NT_SUCCESS(Status
))
998 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status
);
1002 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1004 RtlInitUnicodeString(Service
, NULL
);
1006 QueryTable
[0].Name
= L
"Service";
1007 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1008 QueryTable
[0].EntryContext
= Service
;
1010 Status
= RtlQueryRegistryValues(
1011 RTL_REGISTRY_HANDLE
,
1018 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status
);
1020 if (!NT_SUCCESS(Status
))
1022 /* FIXME: Log the error */
1023 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1024 DeviceNode
->InstancePath
.Buffer
, Status
);
1025 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1026 return STATUS_SUCCESS
;
1029 DPRINT("Got Service %S\n", Service
->Buffer
);
1031 return STATUS_SUCCESS
;
1036 IopActionInitChildServices(
1037 PDEVICE_NODE DeviceNode
,
1040 * FUNCTION: Initialize the service for all (direct) child nodes of a parent node
1042 * DeviceNode = Pointer to device node
1043 * Context = Pointer to parent node to initialize child node services for
1045 * If the driver image for a service is not loaded and initialized
1046 * it is done here too.
1047 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1048 * when we reach a device node which is not a direct child of the device
1049 * node for which we initialize child services for. Any errors that occur is
1050 * logged instead so that all child services have a chance of beeing
1054 PDEVICE_NODE ParentDeviceNode
;
1057 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
1059 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1061 /* We are called for the parent too, but we don't need to do special
1062 handling for this node */
1063 if (DeviceNode
== ParentDeviceNode
)
1065 DPRINT("Success\n");
1066 return STATUS_SUCCESS
;
1069 /* Make sure this device node is a direct child of the parent device node
1070 that is given as an argument */
1071 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1073 /* Stop the traversal immediately and indicate successful operation */
1075 return STATUS_UNSUCCESSFUL
;
1078 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1079 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1080 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1082 Status
= IopInitializeDeviceNodeService(DeviceNode
);
1083 if (NT_SUCCESS(Status
))
1085 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1089 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1091 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1092 CPRINT("Initialization of service %S failed (Status %x)\n",
1093 DeviceNode
->ServiceName
.Buffer
, Status
);
1098 DPRINT("Service %S is disabled or already initialized\n",
1099 DeviceNode
->ServiceName
.Buffer
);
1102 return STATUS_SUCCESS
;
1107 IopInterrogateBusExtender(
1108 PDEVICE_NODE DeviceNode
,
1110 BOOLEAN BootDriversOnly
)
1112 DEVICETREE_TRAVERSE_CONTEXT Context
;
1113 PDEVICE_RELATIONS DeviceRelations
;
1114 IO_STATUS_BLOCK IoStatusBlock
;
1115 PDEVICE_NODE ChildDeviceNode
;
1116 IO_STACK_LOCATION Stack
;
1120 DPRINT("DeviceNode %x Pdo %x BootDriversOnly %d\n", DeviceNode
, Pdo
, BootDriversOnly
);
1122 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1124 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
1126 Status
= IopInitiatePnpIrp(
1129 IRP_MN_QUERY_DEVICE_RELATIONS
,
1131 if (!NT_SUCCESS(Status
))
1133 DPRINT("IopInitiatePnpIrp() failed\n");
1137 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1139 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1141 DPRINT("No PDOs\n");
1142 if (DeviceRelations
)
1144 ExFreePool(DeviceRelations
);
1146 return STATUS_SUCCESS
;
1149 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1151 /* Create device nodes for all discovered devices */
1152 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1154 Status
= IopCreateDeviceNode(
1156 DeviceRelations
->Objects
[i
],
1158 if (!NT_SUCCESS(Status
))
1160 DPRINT("No resources\n");
1161 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1162 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1163 ExFreePool(DeviceRelations
);
1164 return STATUS_INSUFFICIENT_RESOURCES
;
1168 ExFreePool(DeviceRelations
);
1171 /* Retrieve information about all discovered children from the bus driver */
1173 IopInitDeviceTreeTraverseContext(
1176 IopActionInterrogateDeviceStack
,
1179 Status
= IopTraverseDeviceTree(&Context
);
1180 if (!NT_SUCCESS(Status
))
1182 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1187 /* Retrieve configuration from the registry for discovered children */
1189 IopInitDeviceTreeTraverseContext(
1192 IopActionConfigureChildServices
,
1195 Status
= IopTraverseDeviceTree(&Context
);
1196 if (!NT_SUCCESS(Status
))
1198 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1203 /* Initialize services for discovered children */
1205 IopInitDeviceTreeTraverseContext(
1208 IopActionInitChildServices
,
1211 Status
= IopTraverseDeviceTree(&Context
);
1212 if (!NT_SUCCESS(Status
))
1214 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1222 VOID
IopLoadBootStartDrivers(VOID
)
1224 IopInterrogateBusExtender(
1226 IopRootDeviceNode
->Pdo
,
1237 KeInitializeSpinLock(&IopDeviceTreeLock
);
1239 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, FALSE
);
1240 if (!NT_SUCCESS(Status
))
1242 CPRINT("IoCreateDriverObject() failed\n");
1243 KeBugCheck(PHASE1_INITIALIZATION_FAILED
);
1246 Status
= IoCreateDevice(
1247 IopRootDriverObject
,
1250 FILE_DEVICE_CONTROLLER
,
1254 if (!NT_SUCCESS(Status
))
1256 CPRINT("IoCreateDevice() failed\n");
1257 KeBugCheck(PHASE1_INITIALIZATION_FAILED
);
1260 Status
= IopCreateDeviceNode(
1263 &IopRootDeviceNode
);
1264 if (!NT_SUCCESS(Status
))
1266 CPRINT("Insufficient resources\n");
1267 KeBugCheck(PHASE1_INITIALIZATION_FAILED
);
1270 IopRootDeviceNode
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1272 IopRootDeviceNode
->DriverObject
= IopRootDriverObject
;
1274 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1276 IopRootDriverObject
->DriverExtension
->AddDevice(
1277 IopRootDriverObject
,
1278 IopRootDeviceNode
->Pdo
);