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 *****************************************************************/
47 IoInitializeRemoveLockEx(
48 IN PIO_REMOVE_LOCK Lock,
50 IN ULONG MaxLockedMinutes,
51 IN ULONG HighWatermark,
58 IoAcquireRemoveLockEx(
59 IN PIO_REMOVE_LOCK RemoveLock,
60 IN OPTIONAL PVOID Tag,
65 return STATUS_NOT_IMPLEMENTED;
70 IoReleaseRemoveLockEx(
71 IN PIO_REMOVE_LOCK RemoveLock,
79 IoReleaseRemoveLockAndWaitEx(
80 IN PIO_REMOVE_LOCK RemoveLock,
88 IoAdjustPagingPathCount(
96 IoGetDeviceInterfaceAlias(
97 IN PUNICODE_STRING SymbolicLinkName,
98 IN CONST GUID *AliasInterfaceClassGuid,
99 OUT PUNICODE_STRING AliasSymbolicLinkName)
101 return STATUS_NOT_IMPLEMENTED;
106 IoGetDeviceInterfaces(
107 IN CONST GUID *InterfaceClassGuid,
108 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
110 OUT PWSTR *SymbolicLinkList)
112 return STATUS_NOT_IMPLEMENTED;
118 IN PDEVICE_OBJECT DeviceObject,
119 IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
120 IN ULONG BufferLength,
121 OUT PVOID PropertyBuffer,
122 OUT PULONG ResultLength)
124 return STATUS_NOT_IMPLEMENTED;
129 IoInvalidateDeviceRelations(
130 IN PDEVICE_OBJECT DeviceObject,
131 IN DEVICE_RELATION_TYPE Type)
137 IoInvalidateDeviceState(
138 IN PDEVICE_OBJECT PhysicalDeviceObject)
144 IoOpenDeviceInterfaceRegistryKey(
145 IN PUNICODE_STRING SymbolicLinkName,
146 IN ACCESS_MASK DesiredAccess,
147 OUT PHANDLE DeviceInterfaceKey)
149 return STATUS_NOT_IMPLEMENTED;
154 IoOpenDeviceRegistryKey(
155 IN PDEVICE_OBJECT DeviceObject,
156 IN ULONG DevInstKeyType,
157 IN ACCESS_MASK DesiredAccess,
158 OUT PHANDLE DevInstRegKey)
160 return STATUS_NOT_IMPLEMENTED;
165 IoRegisterDeviceInterface(
166 IN PDEVICE_OBJECT PhysicalDeviceObject,
167 IN CONST GUID *InterfaceClassGuid,
168 IN PUNICODE_STRING ReferenceString OPTIONAL,
169 OUT PUNICODE_STRING SymbolicLinkName)
171 PWCHAR KeyNameString = L"\\Device\\Serenum";
173 if (IsEqualGUID(InterfaceClassGuid, (LPGUID)&GUID_SERENUM_BUS_ENUMERATOR)) {
174 RtlInitUnicodeString(SymbolicLinkName, KeyNameString);
175 return STATUS_SUCCESS;
177 return STATUS_INVALID_DEVICE_REQUEST;
178 // return STATUS_NOT_IMPLEMENTED;
183 IoRegisterPlugPlayNotification(
184 IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
185 IN ULONG EventCategoryFlags,
186 IN PVOID EventCategoryData OPTIONAL,
187 IN PDRIVER_OBJECT DriverObject,
188 IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine,
190 OUT PVOID *NotificationEntry)
192 return STATUS_NOT_IMPLEMENTED;
197 IoReportDetectedDevice(
198 IN PDRIVER_OBJECT DriverObject,
199 IN INTERFACE_TYPE LegacyBusType,
202 IN PCM_RESOURCE_LIST ResourceList,
203 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL,
204 IN BOOLEAN ResourceAssigned,
205 IN OUT PDEVICE_OBJECT *DeviceObject)
207 return STATUS_NOT_IMPLEMENTED;
212 IoReportResourceForDetection(
213 IN PDRIVER_OBJECT DriverObject,
214 IN PCM_RESOURCE_LIST DriverList OPTIONAL,
215 IN ULONG DriverListSize OPTIONAL,
216 IN PDEVICE_OBJECT DeviceObject OPTIONAL,
217 IN PCM_RESOURCE_LIST DeviceList OPTIONAL,
218 IN ULONG DeviceListSize OPTIONAL,
219 OUT PBOOLEAN ConflictDetected)
221 return STATUS_NOT_IMPLEMENTED;
226 IoReportTargetDeviceChange(
227 IN PDEVICE_OBJECT PhysicalDeviceObject,
228 IN PVOID NotificationStructure)
230 return STATUS_NOT_IMPLEMENTED;
235 IoReportTargetDeviceChangeAsynchronous(
236 IN PDEVICE_OBJECT PhysicalDeviceObject,
237 IN PVOID NotificationStructure,
238 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL,
239 IN PVOID Context OPTIONAL)
241 return STATUS_NOT_IMPLEMENTED;
246 IoRequestDeviceEject(
247 IN PDEVICE_OBJECT PhysicalDeviceObject)
253 IoSetDeviceInterfaceState(
254 IN PUNICODE_STRING SymbolicLinkName,
257 return STATUS_SUCCESS;
259 // return STATUS_OBJECT_NAME_EXISTS;
260 // return STATUS_OBJECT_NAME_NOT_FOUND;
261 // return STATUS_NOT_IMPLEMENTED;
266 IoUnregisterPlugPlayNotification(
267 IN PVOID NotificationEntry)
269 return STATUS_NOT_IMPLEMENTED;
274 IopCreateUnicodeString(
275 PUNICODE_STRING Destination,
283 RtlInitUnicodeString(Destination, NULL);
287 Length = (wcslen(Source) + 1) * sizeof(WCHAR);
289 Destination->Buffer = ExAllocatePool(PoolType, Length);
291 if (Destination->Buffer == NULL)
296 RtlCopyMemory(Destination->Buffer, Source, Length);
298 Destination->MaximumLength = Length;
300 Destination->Length = Length - sizeof(WCHAR);
306 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject)
310 assert(PopSystemPowerDeviceNode);
312 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
313 *DeviceObject = PopSystemPowerDeviceNode->Pdo;
314 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
316 return STATUS_SUCCESS;
319 /**********************************************************************
321 * Creates a device node
324 * ParentNode = Pointer to parent device node
325 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
326 * to have the root device node create one
327 * (eg. for legacy drivers)
328 * DeviceNode = Pointer to storage for created device node
334 IopCreateDeviceNode(PDEVICE_NODE ParentNode,
335 PDEVICE_OBJECT PhysicalDeviceObject,
336 PDEVICE_NODE *DeviceNode)
342 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
343 ParentNode, PhysicalDeviceObject);
345 Node = (PDEVICE_NODE)ExAllocatePool(PagedPool, sizeof(DEVICE_NODE));
348 return STATUS_INSUFFICIENT_RESOURCES;
351 RtlZeroMemory(Node, sizeof(DEVICE_NODE));
353 if (!PhysicalDeviceObject)
355 Status = PnpRootCreateDevice(&PhysicalDeviceObject);
356 if (!NT_SUCCESS(Status))
362 /* This is for drivers passed on the command line to ntoskrnl.exe */
363 IopDeviceNodeSetFlag(Node, DNF_STARTED);
364 IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER);
367 Node->Pdo = PhysicalDeviceObject;
371 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
372 Node->Parent = ParentNode;
373 Node->NextSibling = ParentNode->Child;
374 if (ParentNode->Child != NULL)
376 ParentNode->Child->PrevSibling = Node;
378 ParentNode->Child = Node;
379 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
384 return STATUS_SUCCESS;
388 IopFreeDeviceNode(PDEVICE_NODE DeviceNode)
392 /* All children must be deleted before a parent is deleted */
393 assert(!DeviceNode->Child);
395 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
397 assert(DeviceNode->Pdo);
399 ObDereferenceObject(DeviceNode->Pdo);
401 /* Unlink from parent if it exists */
403 if ((DeviceNode->Parent) && (DeviceNode->Parent->Child == DeviceNode))
405 DeviceNode->Parent->Child = DeviceNode->NextSibling;
408 /* Unlink from sibling list */
410 if (DeviceNode->PrevSibling)
412 DeviceNode->PrevSibling->NextSibling = DeviceNode->NextSibling;
415 if (DeviceNode->NextSibling)
417 DeviceNode->NextSibling->PrevSibling = DeviceNode->PrevSibling;
420 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
422 RtlFreeUnicodeString(&DeviceNode->InstancePath);
424 RtlFreeUnicodeString(&DeviceNode->ServiceName);
426 if (DeviceNode->CapabilityFlags)
428 ExFreePool(DeviceNode->CapabilityFlags);
431 if (DeviceNode->CmResourceList)
433 ExFreePool(DeviceNode->CmResourceList);
436 if (DeviceNode->BootResourcesList)
438 ExFreePool(DeviceNode->BootResourcesList);
441 if (DeviceNode->ResourceRequirementsList)
443 ExFreePool(DeviceNode->ResourceRequirementsList);
446 RtlFreeUnicodeString(&DeviceNode->DeviceID);
448 RtlFreeUnicodeString(&DeviceNode->InstanceID);
450 RtlFreeUnicodeString(&DeviceNode->HardwareIDs);
452 RtlFreeUnicodeString(&DeviceNode->CompatibleIDs);
454 RtlFreeUnicodeString(&DeviceNode->DeviceText);
456 RtlFreeUnicodeString(&DeviceNode->DeviceTextLocation);
458 if (DeviceNode->BusInformation)
460 ExFreePool(DeviceNode->BusInformation);
463 ExFreePool(DeviceNode);
465 return STATUS_SUCCESS;
470 PDEVICE_OBJECT DeviceObject,
471 PIO_STATUS_BLOCK IoStatusBlock,
473 PIO_STACK_LOCATION Stack OPTIONAL)
475 PDEVICE_OBJECT TopDeviceObject;
476 PIO_STACK_LOCATION IrpSp;
481 /* Always call the top of the device stack */
482 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
489 /* PNP IRPs are always initialized with a status code of
490 STATUS_NOT_IMPLEMENTED */
491 IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED;
492 IoStatusBlock->Information = 0;
494 Irp = IoBuildSynchronousFsdRequest(
503 IrpSp = IoGetNextIrpStackLocation(Irp);
504 IrpSp->MinorFunction = MinorFunction;
511 sizeof(Stack->Parameters));
514 Status = IoCallDriver(TopDeviceObject, Irp);
515 if (Status == STATUS_PENDING)
517 KeWaitForSingleObject(
523 Status = IoStatusBlock->Status;
526 ObDereferenceObject(TopDeviceObject);
533 IopQueryCapabilities(
535 PDEVICE_CAPABILITIES *Capabilities)
537 IO_STATUS_BLOCK IoStatusBlock;
538 PDEVICE_CAPABILITIES Caps;
539 IO_STACK_LOCATION Stack;
542 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
544 *Capabilities = NULL;
546 Caps = ExAllocatePool(PagedPool, sizeof(DEVICE_CAPABILITIES));
549 return STATUS_INSUFFICIENT_RESOURCES;
552 RtlZeroMemory(Caps, sizeof(DEVICE_CAPABILITIES));
553 Caps->Size = sizeof(DEVICE_CAPABILITIES);
558 Stack.Parameters.DeviceCapabilities.Capabilities = Caps;
560 Status = IopInitiatePnpIrp(
563 IRP_MN_QUERY_CAPABILITIES,
565 if (NT_SUCCESS(Status))
567 *Capabilities = Caps;
571 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
579 IopTraverseDeviceTreeNode(
580 PDEVICETREE_TRAVERSE_CONTEXT Context)
582 PDEVICE_NODE ParentDeviceNode;
583 PDEVICE_NODE ChildDeviceNode;
586 /* Copy context data so we don't overwrite it in subsequent calls to this function */
587 ParentDeviceNode = Context->DeviceNode;
589 /* Call the action routine */
590 Status = (Context->Action)(ParentDeviceNode, Context->Context);
591 if (!NT_SUCCESS(Status))
596 /* Traversal of all children nodes */
597 for (ChildDeviceNode = ParentDeviceNode->Child;
598 ChildDeviceNode != NULL;
599 ChildDeviceNode = ChildDeviceNode->NextSibling)
601 /* Pass the current device node to the action routine */
602 Context->DeviceNode = ChildDeviceNode;
604 Status = IopTraverseDeviceTreeNode(Context);
605 if (!NT_SUCCESS(Status))
616 IopTraverseDeviceTree(
617 PDEVICETREE_TRAVERSE_CONTEXT Context)
621 DPRINT("Context %x\n", Context);
623 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
624 Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context);
626 /* Start from the specified device node */
627 Context->DeviceNode = Context->FirstDeviceNode;
629 /* Recursively traverse the device tree */
630 Status = IopTraverseDeviceTreeNode(Context);
631 if (Status == STATUS_UNSUCCESSFUL)
633 /* The action routine just wanted to terminate the traversal with status
634 code STATUS_SUCCESS */
635 Status = STATUS_SUCCESS;
643 IopActionInterrogateDeviceStack(
644 PDEVICE_NODE DeviceNode,
647 * FUNCTION: Retrieve information for all (direct) child nodes of a parent node
649 * DeviceNode = Pointer to device node
650 * Context = Pointer to parent node to retrieve child node information for
652 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
653 * when we reach a device node which is not a direct child of the device node
654 * for which we retrieve information of child nodes for. Any errors that occur
655 * is logged instead so that all child services have a chance of beeing
659 IO_STATUS_BLOCK IoStatusBlock;
660 PDEVICE_NODE ParentDeviceNode;
661 WCHAR InstancePath[MAX_PATH];
662 IO_STACK_LOCATION Stack;
665 DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context);
667 DPRINT("PDO %x\n", DeviceNode->Pdo);
670 ParentDeviceNode = (PDEVICE_NODE)Context;
672 /* We are called for the parent too, but we don't need to do special
673 handling for this node */
674 if (DeviceNode == ParentDeviceNode)
677 return STATUS_SUCCESS;
680 /* Make sure this device node is a direct child of the parent device node
681 that is given as an argument */
682 if (DeviceNode->Parent != ParentDeviceNode)
684 /* Stop the traversal immediately and indicate successful operation */
686 return STATUS_UNSUCCESSFUL;
690 /* FIXME: For critical errors, cleanup and disable device, but always return STATUS_SUCCESS */
693 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
695 Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
697 Status = IopInitiatePnpIrp(
702 if (NT_SUCCESS(Status))
704 RtlInitUnicodeString(
705 &DeviceNode->DeviceID,
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->DeviceID, NULL);
717 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
719 Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
721 Status = IopInitiatePnpIrp(
726 if (NT_SUCCESS(Status))
728 RtlInitUnicodeString(
729 &DeviceNode->InstanceID,
730 (LPWSTR)IoStatusBlock.Information);
732 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
736 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
737 RtlInitUnicodeString(&DeviceNode->InstanceID, NULL);
741 /* FIXME: SEND IRP_QUERY_ID.BusQueryHardwareIDs */
742 /* FIXME: SEND IRP_QUERY_ID.BusQueryCompatibleIDs */
745 Status = IopQueryCapabilities(DeviceNode->Pdo, &DeviceNode->CapabilityFlags);
746 if (NT_SUCCESS(Status))
754 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
756 Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription;
757 Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME
759 Status = IopInitiatePnpIrp(
762 IRP_MN_QUERY_DEVICE_TEXT,
764 if (NT_SUCCESS(Status))
766 RtlInitUnicodeString(
767 &DeviceNode->DeviceText,
768 (LPWSTR)IoStatusBlock.Information);
772 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
773 RtlInitUnicodeString(&DeviceNode->DeviceText, NULL);
777 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
779 Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextLocationInformation;
780 Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME
782 Status = IopInitiatePnpIrp(
785 IRP_MN_QUERY_DEVICE_TEXT,
787 if (NT_SUCCESS(Status))
789 RtlInitUnicodeString(
790 &DeviceNode->DeviceTextLocation,
791 (LPWSTR)IoStatusBlock.Information);
795 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
796 RtlInitUnicodeString(&DeviceNode->DeviceTextLocation, NULL);
800 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
802 Status = IopInitiatePnpIrp(
805 IRP_MN_QUERY_BUS_INFORMATION,
807 if (NT_SUCCESS(Status))
809 DeviceNode->BusInformation =
810 (PPNP_BUS_INFORMATION)IoStatusBlock.Information;
814 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
815 DeviceNode->BusInformation = NULL;
819 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
821 Status = IopInitiatePnpIrp(
824 IRP_MN_QUERY_RESOURCES,
826 if (NT_SUCCESS(Status))
828 DeviceNode->BootResourcesList =
829 (PCM_RESOURCE_LIST)IoStatusBlock.Information;
833 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
834 DeviceNode->BootResourcesList = NULL;
838 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
840 Status = IopInitiatePnpIrp(
843 IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
845 if (NT_SUCCESS(Status))
847 DeviceNode->ResourceRequirementsList =
848 (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
852 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
853 DeviceNode->ResourceRequirementsList = NULL;
857 /* Assemble the instance path for the device */
859 wcscpy(InstancePath, DeviceNode->DeviceID.Buffer);
860 wcscat(InstancePath, L"\\");
861 wcscat(InstancePath, DeviceNode->InstanceID.Buffer);
863 if (!DeviceNode->CapabilityFlags->UniqueID)
865 DPRINT("Instance ID is not unique\n");
866 /* FIXME: Add information from parent bus driver to InstancePath */
869 if (!IopCreateUnicodeString(&DeviceNode->InstancePath, InstancePath, PagedPool)) {
870 DPRINT("No resources\n");
871 /* FIXME: Cleanup and disable device */
874 DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
876 return STATUS_SUCCESS;
881 IopActionConfigureChildServices(
882 PDEVICE_NODE DeviceNode,
885 * FUNCTION: Retrieve configuration for all (direct) child nodes of a parent node
887 * DeviceNode = Pointer to device node
888 * Context = Pointer to parent node to retrieve child node configuration for
890 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
891 * when we reach a device node which is not a direct child of the device
892 * node for which we configure child services for. Any errors that occur is
893 * logged instead so that all child services have a chance of beeing
897 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
898 PDEVICE_NODE ParentDeviceNode;
899 PUNICODE_STRING Service;
903 DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context);
905 ParentDeviceNode = (PDEVICE_NODE)Context;
907 /* We are called for the parent too, but we don't need to do special
908 handling for this node */
909 if (DeviceNode == ParentDeviceNode)
912 return STATUS_SUCCESS;
915 /* Make sure this device node is a direct child of the parent device node
916 that is given as an argument */
917 if (DeviceNode->Parent != ParentDeviceNode)
919 /* Stop the traversal immediately and indicate successful operation */
921 return STATUS_UNSUCCESSFUL;
924 /* Retrieve configuration from Enum key */
926 Service = &DeviceNode->ServiceName;
928 Status = RtlpGetRegistryHandle(
930 DeviceNode->InstancePath.Buffer,
933 if (!NT_SUCCESS(Status))
935 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
939 RtlZeroMemory(QueryTable, sizeof(QueryTable));
941 RtlInitUnicodeString(Service, NULL);
943 QueryTable[0].Name = L"Service";
944 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
945 QueryTable[0].EntryContext = Service;
947 Status = RtlQueryRegistryValues(
955 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
957 if (!NT_SUCCESS(Status))
959 /* FIXME: Log the error */
960 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
961 DeviceNode->InstancePath.Buffer, Status);
962 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
963 return STATUS_SUCCESS;
966 DPRINT("Got Service %S\n", Service->Buffer);
968 return STATUS_SUCCESS;
973 IopActionInitChildServices(
974 PDEVICE_NODE DeviceNode,
977 * FUNCTION: Initialize the service for all (direct) child nodes of a parent node
979 * DeviceNode = Pointer to device node
980 * Context = Pointer to parent node to initialize child node services for
982 * If the driver image for a service is not loaded and initialized
983 * it is done here too.
984 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
985 * when we reach a device node which is not a direct child of the device
986 * node for which we initialize child services for. Any errors that occur is
987 * logged instead so that all child services have a chance of beeing
991 PDEVICE_NODE ParentDeviceNode;
994 DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context);
996 ParentDeviceNode = (PDEVICE_NODE)Context;
998 /* We are called for the parent too, but we don't need to do special
999 handling for this node */
1000 if (DeviceNode == ParentDeviceNode)
1002 DPRINT("Success\n");
1003 return STATUS_SUCCESS;
1006 /* Make sure this device node is a direct child of the parent device node
1007 that is given as an argument */
1008 if (DeviceNode->Parent != ParentDeviceNode)
1010 /* Stop the traversal immediately and indicate successful operation */
1012 return STATUS_UNSUCCESSFUL;
1015 if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) &&
1016 !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) &&
1017 !IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED))
1019 Status = IopInitializeDeviceNodeService(DeviceNode);
1020 if (NT_SUCCESS(Status))
1022 IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
1026 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
1028 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1029 CPRINT("Initialization of service %S failed (Status %x)\n",
1030 DeviceNode->ServiceName.Buffer, Status);
1035 DPRINT("Service %S is disabled or already initialized\n",
1036 DeviceNode->ServiceName.Buffer);
1039 return STATUS_SUCCESS;
1044 IopInterrogateBusExtender(
1045 PDEVICE_NODE DeviceNode,
1047 BOOLEAN BootDriversOnly)
1049 DEVICETREE_TRAVERSE_CONTEXT Context;
1050 PDEVICE_RELATIONS DeviceRelations;
1051 IO_STATUS_BLOCK IoStatusBlock;
1052 PDEVICE_NODE ChildDeviceNode;
1053 IO_STACK_LOCATION Stack;
1057 DPRINT("DeviceNode %x Pdo %x BootDriversOnly %d\n", DeviceNode, Pdo, BootDriversOnly);
1059 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1061 Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
1063 Status = IopInitiatePnpIrp(
1066 IRP_MN_QUERY_DEVICE_RELATIONS,
1068 if (!NT_SUCCESS(Status))
1070 DPRINT("IopInitiatePnpIrp() failed\n");
1074 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1076 if ((!DeviceRelations) || (DeviceRelations->Count <= 0))
1078 DPRINT("No PDOs\n");
1079 if (DeviceRelations)
1081 ExFreePool(DeviceRelations);
1083 return STATUS_SUCCESS;
1086 DPRINT("Got %d PDOs\n", DeviceRelations->Count);
1088 /* Create device nodes for all discovered devices */
1089 for (i = 0; i < DeviceRelations->Count; i++)
1091 Status = IopCreateDeviceNode(
1093 DeviceRelations->Objects[i],
1095 if (!NT_SUCCESS(Status))
1097 DPRINT("No resources\n");
1098 for (i = 0; i < DeviceRelations->Count; i++)
1099 ObDereferenceObject(DeviceRelations->Objects[i]);
1100 ExFreePool(DeviceRelations);
1101 return STATUS_INSUFFICIENT_RESOURCES;
1105 ExFreePool(DeviceRelations);
1108 /* Retrieve information about all discovered children from the bus driver */
1110 IopInitDeviceTreeTraverseContext(
1113 IopActionInterrogateDeviceStack,
1116 Status = IopTraverseDeviceTree(&Context);
1117 if (!NT_SUCCESS(Status))
1119 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1124 /* Retrieve configuration from the registry for discovered children */
1126 IopInitDeviceTreeTraverseContext(
1129 IopActionConfigureChildServices,
1132 Status = IopTraverseDeviceTree(&Context);
1133 if (!NT_SUCCESS(Status))
1135 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1140 /* Initialize services for discovered children */
1142 IopInitDeviceTreeTraverseContext(
1145 IopActionInitChildServices,
1148 Status = IopTraverseDeviceTree(&Context);
1149 if (!NT_SUCCESS(Status))
1151 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1159 VOID IopLoadBootStartDrivers(VOID)
1161 IopInterrogateBusExtender(
1163 IopRootDeviceNode->Pdo,
1174 KeInitializeSpinLock(&IopDeviceTreeLock);
1176 Status = IopCreateDriverObject(&IopRootDriverObject, NULL, FALSE);
1177 if (!NT_SUCCESS(Status))
1179 CPRINT("IoCreateDriverObject() failed\n");
1180 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
1183 Status = IoCreateDevice(
1184 IopRootDriverObject,
1187 FILE_DEVICE_CONTROLLER,
1191 if (!NT_SUCCESS(Status))
1193 CPRINT("IoCreateDevice() failed\n");
1194 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
1197 Status = IopCreateDeviceNode(
1200 &IopRootDeviceNode);
1201 if (!NT_SUCCESS(Status))
1203 CPRINT("Insufficient resources\n");
1204 KeBugCheck(PHASE1_INITIALIZATION_FAILED);
1207 IopRootDeviceNode->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
1209 IopRootDeviceNode->DriverObject = IopRootDriverObject;
1211 PnpRootDriverEntry(IopRootDriverObject, NULL);
1213 IopRootDriverObject->DriverExtension->AddDevice(
1214 IopRootDriverObject,
1215 IopRootDeviceNode->Pdo);