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>
21 #include <ole32/guiddef.h>
22 //#include <ddk/pnpfuncs.h>
24 DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73);
25 DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR, 0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
30 #include <internal/debug.h>
33 /* GLOBALS *******************************************************************/
35 PDEVICE_NODE IopRootDeviceNode;
36 KSPIN_LOCK IopDeviceTreeLock;
38 /* DATA **********************************************************************/
40 PDRIVER_OBJECT IopRootDriverObject;
42 /* FUNCTIONS *****************************************************************/
46 IoInitializeRemoveLockEx(
47 IN PIO_REMOVE_LOCK Lock,
49 IN ULONG MaxLockedMinutes,
50 IN ULONG HighWatermark,
57 IoAcquireRemoveLockEx(
58 IN PIO_REMOVE_LOCK RemoveLock,
59 IN OPTIONAL PVOID Tag,
64 return STATUS_NOT_IMPLEMENTED;
69 IoReleaseRemoveLockEx(
70 IN PIO_REMOVE_LOCK RemoveLock,
78 IoReleaseRemoveLockAndWaitEx(
79 IN PIO_REMOVE_LOCK RemoveLock,
87 IoAdjustPagingPathCount(
95 IoGetDeviceInterfaceAlias(
96 IN PUNICODE_STRING SymbolicLinkName,
97 IN CONST GUID *AliasInterfaceClassGuid,
98 OUT PUNICODE_STRING AliasSymbolicLinkName)
100 return STATUS_NOT_IMPLEMENTED;
105 IoGetDeviceInterfaces(
106 IN CONST GUID *InterfaceClassGuid,
107 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
109 OUT PWSTR *SymbolicLinkList)
111 return STATUS_NOT_IMPLEMENTED;
117 IN PDEVICE_OBJECT DeviceObject,
118 IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
119 IN ULONG BufferLength,
120 OUT PVOID PropertyBuffer,
121 OUT PULONG ResultLength)
123 return STATUS_NOT_IMPLEMENTED;
128 IoInvalidateDeviceRelations(
129 IN PDEVICE_OBJECT DeviceObject,
130 IN DEVICE_RELATION_TYPE Type)
136 IoInvalidateDeviceState(
137 IN PDEVICE_OBJECT PhysicalDeviceObject)
143 IoOpenDeviceInterfaceRegistryKey(
144 IN PUNICODE_STRING SymbolicLinkName,
145 IN ACCESS_MASK DesiredAccess,
146 OUT PHANDLE DeviceInterfaceKey)
148 return STATUS_NOT_IMPLEMENTED;
153 IoOpenDeviceRegistryKey(
154 IN PDEVICE_OBJECT DeviceObject,
155 IN ULONG DevInstKeyType,
156 IN ACCESS_MASK DesiredAccess,
157 OUT PHANDLE DevInstRegKey)
159 return STATUS_NOT_IMPLEMENTED;
164 IoRegisterDeviceInterface(
165 IN PDEVICE_OBJECT PhysicalDeviceObject,
166 IN CONST GUID *InterfaceClassGuid,
167 IN PUNICODE_STRING ReferenceString OPTIONAL,
168 OUT PUNICODE_STRING SymbolicLinkName)
170 PWCHAR KeyNameString = L"\\Device\\Serenum";
172 if (IsEqualGUID(InterfaceClassGuid, (LPGUID)&GUID_SERENUM_BUS_ENUMERATOR)) {
173 RtlInitUnicodeString(SymbolicLinkName, KeyNameString);
174 return STATUS_SUCCESS;
176 return STATUS_INVALID_DEVICE_REQUEST;
177 // return STATUS_NOT_IMPLEMENTED;
182 IoRegisterPlugPlayNotification(
183 IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
184 IN ULONG EventCategoryFlags,
185 IN PVOID EventCategoryData OPTIONAL,
186 IN PDRIVER_OBJECT DriverObject,
187 IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine,
189 OUT PVOID *NotificationEntry)
191 return STATUS_NOT_IMPLEMENTED;
196 IoReportDetectedDevice(
197 IN PDRIVER_OBJECT DriverObject,
198 IN INTERFACE_TYPE LegacyBusType,
201 IN PCM_RESOURCE_LIST ResourceList,
202 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL,
203 IN BOOLEAN ResourceAssigned,
204 IN OUT PDEVICE_OBJECT *DeviceObject)
206 return STATUS_NOT_IMPLEMENTED;
211 IoReportResourceForDetection(
212 IN PDRIVER_OBJECT DriverObject,
213 IN PCM_RESOURCE_LIST DriverList OPTIONAL,
214 IN ULONG DriverListSize OPTIONAL,
215 IN PDEVICE_OBJECT DeviceObject OPTIONAL,
216 IN PCM_RESOURCE_LIST DeviceList OPTIONAL,
217 IN ULONG DeviceListSize OPTIONAL,
218 OUT PBOOLEAN ConflictDetected)
220 return STATUS_NOT_IMPLEMENTED;
225 IoReportTargetDeviceChange(
226 IN PDEVICE_OBJECT PhysicalDeviceObject,
227 IN PVOID NotificationStructure)
229 return STATUS_NOT_IMPLEMENTED;
234 IoReportTargetDeviceChangeAsynchronous(
235 IN PDEVICE_OBJECT PhysicalDeviceObject,
236 IN PVOID NotificationStructure,
237 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL,
238 IN PVOID Context OPTIONAL)
240 return STATUS_NOT_IMPLEMENTED;
245 IoRequestDeviceEject(
246 IN PDEVICE_OBJECT PhysicalDeviceObject)
252 IoSetDeviceInterfaceState(
253 IN PUNICODE_STRING SymbolicLinkName,
256 return STATUS_SUCCESS;
258 // return STATUS_OBJECT_NAME_EXISTS;
259 // return STATUS_OBJECT_NAME_NOT_FOUND;
260 // return STATUS_NOT_IMPLEMENTED;
265 IoUnregisterPlugPlayNotification(
266 IN PVOID NotificationEntry)
268 return STATUS_NOT_IMPLEMENTED;
273 IopCreateUnicodeString(
274 PUNICODE_STRING Destination,
282 RtlInitUnicodeString(Destination, NULL);
286 Length = (wcslen(Source) + 1) * sizeof(WCHAR);
288 Destination->Buffer = ExAllocatePool(PoolType, Length);
290 if (Destination->Buffer == NULL)
295 RtlCopyMemory(Destination->Buffer, Source, Length);
297 Destination->MaximumLength = Length;
299 Destination->Length = Length - sizeof(WCHAR);
305 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject)
309 assert(PopSystemPowerDeviceNode);
311 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
312 *DeviceObject = PopSystemPowerDeviceNode->Pdo;
313 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
315 return STATUS_SUCCESS;
318 /**********************************************************************
320 * Creates a device node
323 * ParentNode = Pointer to parent device node
324 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
325 * to have the root device node create one
326 * (eg. for legacy drivers)
327 * DeviceNode = Pointer to storage for created device node
333 IopCreateDeviceNode(PDEVICE_NODE ParentNode,
334 PDEVICE_OBJECT PhysicalDeviceObject,
335 PDEVICE_NODE *DeviceNode)
341 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
342 ParentNode, PhysicalDeviceObject);
344 Node = (PDEVICE_NODE)ExAllocatePool(PagedPool, sizeof(DEVICE_NODE));
347 return STATUS_INSUFFICIENT_RESOURCES;
350 RtlZeroMemory(Node, sizeof(DEVICE_NODE));
352 if (!PhysicalDeviceObject)
354 Status = PnpRootCreateDevice(&PhysicalDeviceObject);
355 if (!NT_SUCCESS(Status))
361 /* This is for drivers passed on the command line to ntoskrnl.exe */
362 IopDeviceNodeSetFlag(Node, DNF_STARTED);
363 IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER);
366 Node->Pdo = PhysicalDeviceObject;
370 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
371 Node->Parent = ParentNode;
372 Node->NextSibling = ParentNode->Child;
373 if (ParentNode->Child != NULL)
375 ParentNode->Child->PrevSibling = Node;
377 ParentNode->Child = Node;
378 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
383 return STATUS_SUCCESS;
387 IopFreeDeviceNode(PDEVICE_NODE DeviceNode)
391 /* All children must be deleted before a parent is deleted */
392 assert(!DeviceNode->Child);
394 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
396 assert(DeviceNode->Pdo);
398 ObDereferenceObject(DeviceNode->Pdo);
400 /* Unlink from parent if it exists */
402 if ((DeviceNode->Parent) && (DeviceNode->Parent->Child == DeviceNode))
404 DeviceNode->Parent->Child = DeviceNode->NextSibling;
407 /* Unlink from sibling list */
409 if (DeviceNode->PrevSibling)
411 DeviceNode->PrevSibling->NextSibling = DeviceNode->NextSibling;
414 if (DeviceNode->NextSibling)
416 DeviceNode->NextSibling->PrevSibling = DeviceNode->PrevSibling;
419 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
421 RtlFreeUnicodeString(&DeviceNode->InstancePath);
423 RtlFreeUnicodeString(&DeviceNode->ServiceName);
425 if (DeviceNode->CapabilityFlags)
427 ExFreePool(DeviceNode->CapabilityFlags);
430 if (DeviceNode->CmResourceList)
432 ExFreePool(DeviceNode->CmResourceList);
435 if (DeviceNode->BootResourcesList)
437 ExFreePool(DeviceNode->BootResourcesList);
440 if (DeviceNode->ResourceRequirementsList)
442 ExFreePool(DeviceNode->ResourceRequirementsList);
445 RtlFreeUnicodeString(&DeviceNode->DeviceID);
447 RtlFreeUnicodeString(&DeviceNode->InstanceID);
449 RtlFreeUnicodeString(&DeviceNode->HardwareIDs);
451 RtlFreeUnicodeString(&DeviceNode->CompatibleIDs);
453 RtlFreeUnicodeString(&DeviceNode->DeviceText);
455 RtlFreeUnicodeString(&DeviceNode->DeviceTextLocation);
457 if (DeviceNode->BusInformation)
459 ExFreePool(DeviceNode->BusInformation);
462 ExFreePool(DeviceNode);
464 return STATUS_SUCCESS;
469 PDEVICE_OBJECT DeviceObject,
470 PIO_STATUS_BLOCK IoStatusBlock,
472 PIO_STACK_LOCATION Stack OPTIONAL)
474 PDEVICE_OBJECT TopDeviceObject;
475 PIO_STACK_LOCATION IrpSp;
480 /* Always call the top of the device stack */
481 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
488 /* PNP IRPs are always initialized with a status code of
489 STATUS_NOT_IMPLEMENTED */
490 IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED;
491 IoStatusBlock->Information = 0;
493 Irp = IoBuildSynchronousFsdRequest(
502 IrpSp = IoGetNextIrpStackLocation(Irp);
503 IrpSp->MinorFunction = MinorFunction;
510 sizeof(Stack->Parameters));
513 Status = IoCallDriver(TopDeviceObject, Irp);
514 if (Status == STATUS_PENDING)
516 KeWaitForSingleObject(
522 Status = IoStatusBlock->Status;
525 ObDereferenceObject(TopDeviceObject);
532 IopQueryCapabilities(
534 PDEVICE_CAPABILITIES *Capabilities)
536 IO_STATUS_BLOCK IoStatusBlock;
537 PDEVICE_CAPABILITIES Caps;
538 IO_STACK_LOCATION Stack;
541 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
543 *Capabilities = NULL;
545 Caps = ExAllocatePool(PagedPool, sizeof(DEVICE_CAPABILITIES));
548 return STATUS_INSUFFICIENT_RESOURCES;
551 RtlZeroMemory(Caps, sizeof(DEVICE_CAPABILITIES));
552 Caps->Size = sizeof(DEVICE_CAPABILITIES);
557 Stack.Parameters.DeviceCapabilities.Capabilities = Caps;
559 Status = IopInitiatePnpIrp(
562 IRP_MN_QUERY_CAPABILITIES,
564 if (NT_SUCCESS(Status))
566 *Capabilities = Caps;
570 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
578 IopTraverseDeviceTreeNode(
579 PDEVICETREE_TRAVERSE_CONTEXT Context)
581 PDEVICE_NODE ParentDeviceNode;
582 PDEVICE_NODE ChildDeviceNode;
585 /* Copy context data so we don't overwrite it in subsequent calls to this function */
586 ParentDeviceNode = Context->DeviceNode;
588 /* Call the action routine */
589 Status = (Context->Action)(ParentDeviceNode, Context->Context);
590 if (!NT_SUCCESS(Status))
595 /* Traversal of all children nodes */
596 for (ChildDeviceNode = ParentDeviceNode->Child;
597 ChildDeviceNode != NULL;
598 ChildDeviceNode = ChildDeviceNode->NextSibling)
600 /* Pass the current device node to the action routine */
601 Context->DeviceNode = ChildDeviceNode;
603 Status = IopTraverseDeviceTreeNode(Context);
604 if (!NT_SUCCESS(Status))
615 IopTraverseDeviceTree(
616 PDEVICETREE_TRAVERSE_CONTEXT Context)
620 DPRINT("Context %x\n", Context);
622 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
623 Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context);
625 /* Start from the specified device node */
626 Context->DeviceNode = Context->FirstDeviceNode;
628 /* Recursively traverse the device tree */
629 Status = IopTraverseDeviceTreeNode(Context);
630 if (Status == STATUS_UNSUCCESSFUL)
632 /* The action routine just wanted to terminate the traversal with status
633 code STATUS_SUCCESS */
634 Status = STATUS_SUCCESS;
642 IopActionInterrogateDeviceStack(
643 PDEVICE_NODE DeviceNode,
646 * FUNCTION: Retrieve information for all (direct) child nodes of a parent node
648 * DeviceNode = Pointer to device node
649 * Context = Pointer to parent node to retrieve child node information for
651 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
652 * when we reach a device node which is not a direct child of the device node
653 * for which we retrieve information of child nodes for. Any errors that occur
654 * is logged instead so that all child services have a chance of beeing
658 IO_STATUS_BLOCK IoStatusBlock;
659 PDEVICE_NODE ParentDeviceNode;
660 WCHAR InstancePath[MAX_PATH];
661 IO_STACK_LOCATION Stack;
664 DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context);
666 DPRINT("PDO %x\n", DeviceNode->Pdo);
669 ParentDeviceNode = (PDEVICE_NODE)Context;
671 /* We are called for the parent too, but we don't need to do special
672 handling for this node */
673 if (DeviceNode == ParentDeviceNode)
676 return STATUS_SUCCESS;
679 /* Make sure this device node is a direct child of the parent device node
680 that is given as an argument */
681 if (DeviceNode->Parent != ParentDeviceNode)
683 /* Stop the traversal immediately and indicate successful operation */
685 return STATUS_UNSUCCESSFUL;
689 /* FIXME: For critical errors, cleanup and disable device, but always return STATUS_SUCCESS */
692 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
694 Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
696 Status = IopInitiatePnpIrp(
701 if (NT_SUCCESS(Status))
703 RtlInitUnicodeString(
704 &DeviceNode->DeviceID,
705 (LPWSTR)IoStatusBlock.Information);
707 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
711 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
712 RtlInitUnicodeString(&DeviceNode->DeviceID, NULL);
716 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
718 Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
720 Status = IopInitiatePnpIrp(
725 if (NT_SUCCESS(Status))
727 RtlInitUnicodeString(
728 &DeviceNode->InstanceID,
729 (LPWSTR)IoStatusBlock.Information);
731 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
735 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
736 RtlInitUnicodeString(&DeviceNode->InstanceID, NULL);
740 /* FIXME: SEND IRP_QUERY_ID.BusQueryHardwareIDs */
741 /* FIXME: SEND IRP_QUERY_ID.BusQueryCompatibleIDs */
744 Status = IopQueryCapabilities(DeviceNode->Pdo, &DeviceNode->CapabilityFlags);
745 if (NT_SUCCESS(Status))
753 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
755 Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription;
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->DeviceText,
767 (LPWSTR)IoStatusBlock.Information);
771 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
772 RtlInitUnicodeString(&DeviceNode->DeviceText, NULL);
776 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
778 Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextLocationInformation;
779 Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME
781 Status = IopInitiatePnpIrp(
784 IRP_MN_QUERY_DEVICE_TEXT,
786 if (NT_SUCCESS(Status))
788 RtlInitUnicodeString(
789 &DeviceNode->DeviceTextLocation,
790 (LPWSTR)IoStatusBlock.Information);
794 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
795 RtlInitUnicodeString(&DeviceNode->DeviceTextLocation, NULL);
799 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
801 Status = IopInitiatePnpIrp(
804 IRP_MN_QUERY_BUS_INFORMATION,
806 if (NT_SUCCESS(Status))
808 DeviceNode->BusInformation =
809 (PPNP_BUS_INFORMATION)IoStatusBlock.Information;
813 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
814 DeviceNode->BusInformation = NULL;
818 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
820 Status = IopInitiatePnpIrp(
823 IRP_MN_QUERY_RESOURCES,
825 if (NT_SUCCESS(Status))
827 DeviceNode->BootResourcesList =
828 (PCM_RESOURCE_LIST)IoStatusBlock.Information;
832 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
833 DeviceNode->BootResourcesList = NULL;
837 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
839 Status = IopInitiatePnpIrp(
842 IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
844 if (NT_SUCCESS(Status))
846 DeviceNode->ResourceRequirementsList =
847 (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
851 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
852 DeviceNode->ResourceRequirementsList = NULL;
856 /* Assemble the instance path for the device */
858 wcscpy(InstancePath, DeviceNode->DeviceID.Buffer);
859 wcscat(InstancePath, L"\\");
860 wcscat(InstancePath, DeviceNode->InstanceID.Buffer);
862 if (!DeviceNode->CapabilityFlags->UniqueID)
864 DPRINT("Instance ID is not unique\n");
865 /* FIXME: Add information from parent bus driver to InstancePath */
868 if (!IopCreateUnicodeString(&DeviceNode->InstancePath, InstancePath, PagedPool)) {
869 DPRINT("No resources\n");
870 /* FIXME: Cleanup and disable device */
873 DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
875 return STATUS_SUCCESS;
880 IopActionConfigureChildServices(
881 PDEVICE_NODE DeviceNode,
884 * FUNCTION: Retrieve configuration for all (direct) child nodes of a parent node
886 * DeviceNode = Pointer to device node
887 * Context = Pointer to parent node to retrieve child node configuration for
889 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
890 * when we reach a device node which is not a direct child of the device
891 * node for which we configure child services for. Any errors that occur is
892 * logged instead so that all child services have a chance of beeing
896 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
897 PDEVICE_NODE ParentDeviceNode;
898 PUNICODE_STRING Service;
902 DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context);
904 ParentDeviceNode = (PDEVICE_NODE)Context;
906 /* We are called for the parent too, but we don't need to do special
907 handling for this node */
908 if (DeviceNode == ParentDeviceNode)
911 return STATUS_SUCCESS;
914 /* Make sure this device node is a direct child of the parent device node
915 that is given as an argument */
916 if (DeviceNode->Parent != ParentDeviceNode)
918 /* Stop the traversal immediately and indicate successful operation */
920 return STATUS_UNSUCCESSFUL;
923 /* Retrieve configuration from Enum key */
925 Service = &DeviceNode->ServiceName;
927 Status = RtlpGetRegistryHandle(
929 DeviceNode->InstancePath.Buffer,
932 if (!NT_SUCCESS(Status))
934 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
938 RtlZeroMemory(QueryTable, sizeof(QueryTable));
940 RtlInitUnicodeString(Service, NULL);
942 QueryTable[0].Name = L"Service";
943 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
944 QueryTable[0].EntryContext = Service;
946 Status = RtlQueryRegistryValues(
954 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
956 if (!NT_SUCCESS(Status))
958 /* FIXME: Log the error */
959 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
960 DeviceNode->InstancePath.Buffer, Status);
961 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
962 return STATUS_SUCCESS;
965 DPRINT("Got Service %S\n", Service->Buffer);
967 return STATUS_SUCCESS;
972 IopActionInitChildServices(
973 PDEVICE_NODE DeviceNode,
976 * FUNCTION: Initialize the service for all (direct) child nodes of a parent node
978 * DeviceNode = Pointer to device node
979 * Context = Pointer to parent node to initialize child node services for
981 * If the driver image for a service is not loaded and initialized
982 * it is done here too.
983 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
984 * when we reach a device node which is not a direct child of the device
985 * node for which we initialize child services for. Any errors that occur is
986 * logged instead so that all child services have a chance of beeing
990 PDEVICE_NODE ParentDeviceNode;
993 DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context);
995 ParentDeviceNode = (PDEVICE_NODE)Context;
997 /* We are called for the parent too, but we don't need to do special
998 handling for this node */
999 if (DeviceNode == ParentDeviceNode)
1001 DPRINT("Success\n");
1002 return STATUS_SUCCESS;
1005 /* Make sure this device node is a direct child of the parent device node
1006 that is given as an argument */
1007 if (DeviceNode->Parent != ParentDeviceNode)
1009 /* Stop the traversal immediately and indicate successful operation */
1011 return STATUS_UNSUCCESSFUL;
1014 if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) &&
1015 !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) &&
1016 !IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED))
1018 Status = IopInitializeDeviceNodeService(DeviceNode);
1019 if (NT_SUCCESS(Status))
1021 IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
1025 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
1027 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1028 CPRINT("Initialization of service %S failed (Status %x)\n",
1029 DeviceNode->ServiceName.Buffer, Status);
1034 DPRINT("Service %S is disabled or already initialized\n",
1035 DeviceNode->ServiceName.Buffer);
1038 return STATUS_SUCCESS;
1043 IopInterrogateBusExtender(
1044 PDEVICE_NODE DeviceNode,
1046 BOOLEAN BootDriversOnly)
1048 DEVICETREE_TRAVERSE_CONTEXT Context;
1049 PDEVICE_RELATIONS DeviceRelations;
1050 IO_STATUS_BLOCK IoStatusBlock;
1051 PDEVICE_NODE ChildDeviceNode;
1052 IO_STACK_LOCATION Stack;
1056 DPRINT("DeviceNode %x Pdo %x BootDriversOnly %d\n", DeviceNode, Pdo, BootDriversOnly);
1058 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1060 Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
1062 Status = IopInitiatePnpIrp(
1065 IRP_MN_QUERY_DEVICE_RELATIONS,
1067 if (!NT_SUCCESS(Status))
1069 DPRINT("IopInitiatePnpIrp() failed\n");
1073 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1075 if ((!DeviceRelations) || (DeviceRelations->Count <= 0))
1077 DPRINT("No PDOs\n");
1078 if (DeviceRelations)
1080 ExFreePool(DeviceRelations);
1082 return STATUS_SUCCESS;
1085 DPRINT("Got %d PDOs\n", DeviceRelations->Count);
1087 /* Create device nodes for all discovered devices */
1088 for (i = 0; i < DeviceRelations->Count; i++)
1090 Status = IopCreateDeviceNode(
1092 DeviceRelations->Objects[i],
1094 if (!NT_SUCCESS(Status))
1096 DPRINT("No resources\n");
1097 for (i = 0; i < DeviceRelations->Count; i++)
1098 ObDereferenceObject(DeviceRelations->Objects[i]);
1099 ExFreePool(DeviceRelations);
1100 return STATUS_INSUFFICIENT_RESOURCES;
1104 ExFreePool(DeviceRelations);
1107 /* Retrieve information about all discovered children from the bus driver */
1109 IopInitDeviceTreeTraverseContext(
1112 IopActionInterrogateDeviceStack,
1115 Status = IopTraverseDeviceTree(&Context);
1116 if (!NT_SUCCESS(Status))
1118 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1123 /* Retrieve configuration from the registry for discovered children */
1125 IopInitDeviceTreeTraverseContext(
1128 IopActionConfigureChildServices,
1131 Status = IopTraverseDeviceTree(&Context);
1132 if (!NT_SUCCESS(Status))
1134 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1139 /* Initialize services for discovered children */
1141 IopInitDeviceTreeTraverseContext(
1144 IopActionInitChildServices,
1147 Status = IopTraverseDeviceTree(&Context);
1148 if (!NT_SUCCESS(Status))
1150 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1158 VOID IopLoadBootStartDrivers(VOID)
1160 IopInterrogateBusExtender(
1162 IopRootDeviceNode->Pdo,
1173 KeInitializeSpinLock(&IopDeviceTreeLock);
1175 Status = IopCreateDriverObject(&IopRootDriverObject, NULL, FALSE);
1176 if (!NT_SUCCESS(Status))
1178 CPRINT("IoCreateDriverObject() failed\n");
1179 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
1182 Status = IoCreateDevice(
1183 IopRootDriverObject,
1186 FILE_DEVICE_CONTROLLER,
1190 if (!NT_SUCCESS(Status))
1192 CPRINT("IoCreateDevice() failed\n");
1193 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
1196 Status = IopCreateDeviceNode(
1199 &IopRootDeviceNode);
1200 if (!NT_SUCCESS(Status))
1202 CPRINT("Insufficient resources\n");
1203 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
1206 IopRootDeviceNode->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
1208 IopRootDeviceNode->DriverObject = IopRootDriverObject;
1210 PnpRootDriverEntry(IopRootDriverObject, NULL);
1212 IopRootDriverObject->DriverExtension->AddDevice(
1213 IopRootDriverObject,
1214 IopRootDeviceNode->Pdo);