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,
100 IoAdjustPagingPathCount(
102 IN BOOLEAN Increment)
111 IoGetDeviceInterfaceAlias(
112 IN PUNICODE_STRING SymbolicLinkName,
113 IN CONST GUID *AliasInterfaceClassGuid,
114 OUT PUNICODE_STRING AliasSymbolicLinkName)
116 return STATUS_NOT_IMPLEMENTED;
124 IoGetDeviceInterfaces(
125 IN CONST GUID *InterfaceClassGuid,
126 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
128 OUT PWSTR *SymbolicLinkList)
130 return STATUS_NOT_IMPLEMENTED;
139 IN PDEVICE_OBJECT DeviceObject,
140 IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
141 IN ULONG BufferLength,
142 OUT PVOID PropertyBuffer,
143 OUT PULONG ResultLength)
145 return STATUS_NOT_IMPLEMENTED;
153 IoInvalidateDeviceRelations(
154 IN PDEVICE_OBJECT DeviceObject,
155 IN DEVICE_RELATION_TYPE Type)
164 IoInvalidateDeviceState(
165 IN PDEVICE_OBJECT PhysicalDeviceObject)
174 IoOpenDeviceInterfaceRegistryKey(
175 IN PUNICODE_STRING SymbolicLinkName,
176 IN ACCESS_MASK DesiredAccess,
177 OUT PHANDLE DeviceInterfaceKey)
179 return STATUS_NOT_IMPLEMENTED;
187 IoOpenDeviceRegistryKey(
188 IN PDEVICE_OBJECT DeviceObject,
189 IN ULONG DevInstKeyType,
190 IN ACCESS_MASK DesiredAccess,
191 OUT PHANDLE DevInstRegKey)
193 return STATUS_NOT_IMPLEMENTED;
201 IoRegisterDeviceInterface(
202 IN PDEVICE_OBJECT PhysicalDeviceObject,
203 IN CONST GUID *InterfaceClassGuid,
204 IN PUNICODE_STRING ReferenceString OPTIONAL,
205 OUT PUNICODE_STRING SymbolicLinkName)
207 PWCHAR KeyNameString = L"\\Device\\Serenum";
209 if (IsEqualGUID(InterfaceClassGuid, (LPGUID)&GUID_SERENUM_BUS_ENUMERATOR)) {
210 RtlInitUnicodeString(SymbolicLinkName, KeyNameString);
211 return STATUS_SUCCESS;
213 return STATUS_INVALID_DEVICE_REQUEST;
214 // return STATUS_NOT_IMPLEMENTED;
222 IoRegisterPlugPlayNotification(
223 IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
224 IN ULONG EventCategoryFlags,
225 IN PVOID EventCategoryData OPTIONAL,
226 IN PDRIVER_OBJECT DriverObject,
227 IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine,
229 OUT PVOID *NotificationEntry)
231 return STATUS_NOT_IMPLEMENTED;
239 IoReportDetectedDevice(
240 IN PDRIVER_OBJECT DriverObject,
241 IN INTERFACE_TYPE LegacyBusType,
244 IN PCM_RESOURCE_LIST ResourceList,
245 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL,
246 IN BOOLEAN ResourceAssigned,
247 IN OUT PDEVICE_OBJECT *DeviceObject)
249 return STATUS_NOT_IMPLEMENTED;
257 IoReportResourceForDetection(
258 IN PDRIVER_OBJECT DriverObject,
259 IN PCM_RESOURCE_LIST DriverList OPTIONAL,
260 IN ULONG DriverListSize OPTIONAL,
261 IN PDEVICE_OBJECT DeviceObject OPTIONAL,
262 IN PCM_RESOURCE_LIST DeviceList OPTIONAL,
263 IN ULONG DeviceListSize OPTIONAL,
264 OUT PBOOLEAN ConflictDetected)
266 return STATUS_NOT_IMPLEMENTED;
274 IoReportTargetDeviceChange(
275 IN PDEVICE_OBJECT PhysicalDeviceObject,
276 IN PVOID NotificationStructure)
278 return STATUS_NOT_IMPLEMENTED;
286 IoReportTargetDeviceChangeAsynchronous(
287 IN PDEVICE_OBJECT PhysicalDeviceObject,
288 IN PVOID NotificationStructure,
289 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL,
290 IN PVOID Context OPTIONAL)
292 return STATUS_NOT_IMPLEMENTED;
300 IoRequestDeviceEject(
301 IN PDEVICE_OBJECT PhysicalDeviceObject)
310 IoSetDeviceInterfaceState(
311 IN PUNICODE_STRING SymbolicLinkName,
314 return STATUS_SUCCESS;
316 // return STATUS_OBJECT_NAME_EXISTS;
317 // return STATUS_OBJECT_NAME_NOT_FOUND;
318 // return STATUS_NOT_IMPLEMENTED;
326 IoUnregisterPlugPlayNotification(
327 IN PVOID NotificationEntry)
329 return STATUS_NOT_IMPLEMENTED;
334 IopCreateUnicodeString(
335 PUNICODE_STRING Destination,
343 RtlInitUnicodeString(Destination, NULL);
347 Length = (wcslen(Source) + 1) * sizeof(WCHAR);
349 Destination->Buffer = ExAllocatePool(PoolType, Length);
351 if (Destination->Buffer == NULL)
356 RtlCopyMemory(Destination->Buffer, Source, Length);
358 Destination->MaximumLength = Length;
360 Destination->Length = Length - sizeof(WCHAR);
366 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject)
370 assert(PopSystemPowerDeviceNode);
372 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
373 *DeviceObject = PopSystemPowerDeviceNode->Pdo;
374 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
376 return STATUS_SUCCESS;
379 /**********************************************************************
381 * Creates a device node
384 * ParentNode = Pointer to parent device node
385 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
386 * to have the root device node create one
387 * (eg. for legacy drivers)
388 * DeviceNode = Pointer to storage for created device node
394 IopCreateDeviceNode(PDEVICE_NODE ParentNode,
395 PDEVICE_OBJECT PhysicalDeviceObject,
396 PDEVICE_NODE *DeviceNode)
402 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
403 ParentNode, PhysicalDeviceObject);
405 Node = (PDEVICE_NODE)ExAllocatePool(PagedPool, sizeof(DEVICE_NODE));
408 return STATUS_INSUFFICIENT_RESOURCES;
411 RtlZeroMemory(Node, sizeof(DEVICE_NODE));
413 if (!PhysicalDeviceObject)
415 Status = PnpRootCreateDevice(&PhysicalDeviceObject);
416 if (!NT_SUCCESS(Status))
422 /* This is for drivers passed on the command line to ntoskrnl.exe */
423 IopDeviceNodeSetFlag(Node, DNF_STARTED);
424 IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER);
427 Node->Pdo = PhysicalDeviceObject;
431 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
432 Node->Parent = ParentNode;
433 Node->NextSibling = ParentNode->Child;
434 if (ParentNode->Child != NULL)
436 ParentNode->Child->PrevSibling = Node;
438 ParentNode->Child = Node;
439 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
444 return STATUS_SUCCESS;
448 IopFreeDeviceNode(PDEVICE_NODE DeviceNode)
452 /* All children must be deleted before a parent is deleted */
453 assert(!DeviceNode->Child);
455 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
457 assert(DeviceNode->Pdo);
459 ObDereferenceObject(DeviceNode->Pdo);
461 /* Unlink from parent if it exists */
463 if ((DeviceNode->Parent) && (DeviceNode->Parent->Child == DeviceNode))
465 DeviceNode->Parent->Child = DeviceNode->NextSibling;
468 /* Unlink from sibling list */
470 if (DeviceNode->PrevSibling)
472 DeviceNode->PrevSibling->NextSibling = DeviceNode->NextSibling;
475 if (DeviceNode->NextSibling)
477 DeviceNode->NextSibling->PrevSibling = DeviceNode->PrevSibling;
480 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
482 RtlFreeUnicodeString(&DeviceNode->InstancePath);
484 RtlFreeUnicodeString(&DeviceNode->ServiceName);
486 if (DeviceNode->CapabilityFlags)
488 ExFreePool(DeviceNode->CapabilityFlags);
491 if (DeviceNode->CmResourceList)
493 ExFreePool(DeviceNode->CmResourceList);
496 if (DeviceNode->BootResourcesList)
498 ExFreePool(DeviceNode->BootResourcesList);
501 if (DeviceNode->ResourceRequirementsList)
503 ExFreePool(DeviceNode->ResourceRequirementsList);
506 RtlFreeUnicodeString(&DeviceNode->DeviceID);
508 RtlFreeUnicodeString(&DeviceNode->InstanceID);
510 RtlFreeUnicodeString(&DeviceNode->HardwareIDs);
512 RtlFreeUnicodeString(&DeviceNode->CompatibleIDs);
514 RtlFreeUnicodeString(&DeviceNode->DeviceText);
516 RtlFreeUnicodeString(&DeviceNode->DeviceTextLocation);
518 if (DeviceNode->BusInformation)
520 ExFreePool(DeviceNode->BusInformation);
523 ExFreePool(DeviceNode);
525 return STATUS_SUCCESS;
530 PDEVICE_OBJECT DeviceObject,
531 PIO_STATUS_BLOCK IoStatusBlock,
533 PIO_STACK_LOCATION Stack OPTIONAL)
535 PDEVICE_OBJECT TopDeviceObject;
536 PIO_STACK_LOCATION IrpSp;
541 /* Always call the top of the device stack */
542 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
549 /* PNP IRPs are always initialized with a status code of
550 STATUS_NOT_IMPLEMENTED */
551 IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED;
552 IoStatusBlock->Information = 0;
554 Irp = IoBuildSynchronousFsdRequest(
563 IrpSp = IoGetNextIrpStackLocation(Irp);
564 IrpSp->MinorFunction = MinorFunction;
571 sizeof(Stack->Parameters));
574 Status = IoCallDriver(TopDeviceObject, Irp);
575 if (Status == STATUS_PENDING)
577 KeWaitForSingleObject(
583 Status = IoStatusBlock->Status;
586 ObDereferenceObject(TopDeviceObject);
593 IopQueryCapabilities(
595 PDEVICE_CAPABILITIES *Capabilities)
597 IO_STATUS_BLOCK IoStatusBlock;
598 PDEVICE_CAPABILITIES Caps;
599 IO_STACK_LOCATION Stack;
602 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
604 *Capabilities = NULL;
606 Caps = ExAllocatePool(PagedPool, sizeof(DEVICE_CAPABILITIES));
609 return STATUS_INSUFFICIENT_RESOURCES;
612 RtlZeroMemory(Caps, sizeof(DEVICE_CAPABILITIES));
613 Caps->Size = sizeof(DEVICE_CAPABILITIES);
618 Stack.Parameters.DeviceCapabilities.Capabilities = Caps;
620 Status = IopInitiatePnpIrp(
623 IRP_MN_QUERY_CAPABILITIES,
625 if (NT_SUCCESS(Status))
627 *Capabilities = Caps;
631 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
639 IopTraverseDeviceTreeNode(
640 PDEVICETREE_TRAVERSE_CONTEXT Context)
642 PDEVICE_NODE ParentDeviceNode;
643 PDEVICE_NODE ChildDeviceNode;
646 /* Copy context data so we don't overwrite it in subsequent calls to this function */
647 ParentDeviceNode = Context->DeviceNode;
649 /* Call the action routine */
650 Status = (Context->Action)(ParentDeviceNode, Context->Context);
651 if (!NT_SUCCESS(Status))
656 /* Traversal of all children nodes */
657 for (ChildDeviceNode = ParentDeviceNode->Child;
658 ChildDeviceNode != NULL;
659 ChildDeviceNode = ChildDeviceNode->NextSibling)
661 /* Pass the current device node to the action routine */
662 Context->DeviceNode = ChildDeviceNode;
664 Status = IopTraverseDeviceTreeNode(Context);
665 if (!NT_SUCCESS(Status))
676 IopTraverseDeviceTree(
677 PDEVICETREE_TRAVERSE_CONTEXT Context)
681 DPRINT("Context %x\n", Context);
683 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
684 Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context);
686 /* Start from the specified device node */
687 Context->DeviceNode = Context->FirstDeviceNode;
689 /* Recursively traverse the device tree */
690 Status = IopTraverseDeviceTreeNode(Context);
691 if (Status == STATUS_UNSUCCESSFUL)
693 /* The action routine just wanted to terminate the traversal with status
694 code STATUS_SUCCESS */
695 Status = STATUS_SUCCESS;
703 IopActionInterrogateDeviceStack(
704 PDEVICE_NODE DeviceNode,
707 * FUNCTION: Retrieve information for all (direct) child nodes of a parent node
709 * DeviceNode = Pointer to device node
710 * Context = Pointer to parent node to retrieve child node information for
712 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
713 * when we reach a device node which is not a direct child of the device node
714 * for which we retrieve information of child nodes for. Any errors that occur
715 * is logged instead so that all child services have a chance of beeing
719 IO_STATUS_BLOCK IoStatusBlock;
720 PDEVICE_NODE ParentDeviceNode;
721 WCHAR InstancePath[MAX_PATH];
722 IO_STACK_LOCATION Stack;
725 DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context);
727 DPRINT("PDO %x\n", DeviceNode->Pdo);
730 ParentDeviceNode = (PDEVICE_NODE)Context;
732 /* We are called for the parent too, but we don't need to do special
733 handling for this node */
734 if (DeviceNode == ParentDeviceNode)
737 return STATUS_SUCCESS;
740 /* Make sure this device node is a direct child of the parent device node
741 that is given as an argument */
742 if (DeviceNode->Parent != ParentDeviceNode)
744 /* Stop the traversal immediately and indicate successful operation */
746 return STATUS_UNSUCCESSFUL;
750 /* FIXME: For critical errors, cleanup and disable device, but always return STATUS_SUCCESS */
753 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
755 Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
757 Status = IopInitiatePnpIrp(
762 if (NT_SUCCESS(Status))
764 RtlInitUnicodeString(
765 &DeviceNode->DeviceID,
766 (LPWSTR)IoStatusBlock.Information);
768 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
772 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
773 RtlInitUnicodeString(&DeviceNode->DeviceID, NULL);
777 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
779 Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
781 Status = IopInitiatePnpIrp(
786 if (NT_SUCCESS(Status))
788 RtlInitUnicodeString(
789 &DeviceNode->InstanceID,
790 (LPWSTR)IoStatusBlock.Information);
792 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
796 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
797 RtlInitUnicodeString(&DeviceNode->InstanceID, NULL);
801 /* FIXME: SEND IRP_QUERY_ID.BusQueryHardwareIDs */
802 /* FIXME: SEND IRP_QUERY_ID.BusQueryCompatibleIDs */
805 Status = IopQueryCapabilities(DeviceNode->Pdo, &DeviceNode->CapabilityFlags);
806 if (NT_SUCCESS(Status))
814 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
816 Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription;
817 Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME
819 Status = IopInitiatePnpIrp(
822 IRP_MN_QUERY_DEVICE_TEXT,
824 if (NT_SUCCESS(Status))
826 RtlInitUnicodeString(
827 &DeviceNode->DeviceText,
828 (LPWSTR)IoStatusBlock.Information);
832 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
833 RtlInitUnicodeString(&DeviceNode->DeviceText, NULL);
837 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
839 Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextLocationInformation;
840 Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME
842 Status = IopInitiatePnpIrp(
845 IRP_MN_QUERY_DEVICE_TEXT,
847 if (NT_SUCCESS(Status))
849 RtlInitUnicodeString(
850 &DeviceNode->DeviceTextLocation,
851 (LPWSTR)IoStatusBlock.Information);
855 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
856 RtlInitUnicodeString(&DeviceNode->DeviceTextLocation, NULL);
860 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
862 Status = IopInitiatePnpIrp(
865 IRP_MN_QUERY_BUS_INFORMATION,
867 if (NT_SUCCESS(Status))
869 DeviceNode->BusInformation =
870 (PPNP_BUS_INFORMATION)IoStatusBlock.Information;
874 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
875 DeviceNode->BusInformation = NULL;
879 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
881 Status = IopInitiatePnpIrp(
884 IRP_MN_QUERY_RESOURCES,
886 if (NT_SUCCESS(Status))
888 DeviceNode->BootResourcesList =
889 (PCM_RESOURCE_LIST)IoStatusBlock.Information;
893 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
894 DeviceNode->BootResourcesList = NULL;
898 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
900 Status = IopInitiatePnpIrp(
903 IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
905 if (NT_SUCCESS(Status))
907 DeviceNode->ResourceRequirementsList =
908 (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
912 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
913 DeviceNode->ResourceRequirementsList = NULL;
917 /* Assemble the instance path for the device */
919 wcscpy(InstancePath, DeviceNode->DeviceID.Buffer);
920 wcscat(InstancePath, L"\\");
921 wcscat(InstancePath, DeviceNode->InstanceID.Buffer);
923 if (!DeviceNode->CapabilityFlags->UniqueID)
925 DPRINT("Instance ID is not unique\n");
926 /* FIXME: Add information from parent bus driver to InstancePath */
929 if (!IopCreateUnicodeString(&DeviceNode->InstancePath, InstancePath, PagedPool)) {
930 DPRINT("No resources\n");
931 /* FIXME: Cleanup and disable device */
934 DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
936 return STATUS_SUCCESS;
941 IopActionConfigureChildServices(
942 PDEVICE_NODE DeviceNode,
945 * FUNCTION: Retrieve configuration for all (direct) child nodes of a parent node
947 * DeviceNode = Pointer to device node
948 * Context = Pointer to parent node to retrieve child node configuration for
950 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
951 * when we reach a device node which is not a direct child of the device
952 * node for which we configure child services for. Any errors that occur is
953 * logged instead so that all child services have a chance of beeing
957 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
958 PDEVICE_NODE ParentDeviceNode;
959 PUNICODE_STRING Service;
963 DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context);
965 ParentDeviceNode = (PDEVICE_NODE)Context;
967 /* We are called for the parent too, but we don't need to do special
968 handling for this node */
969 if (DeviceNode == ParentDeviceNode)
972 return STATUS_SUCCESS;
975 /* Make sure this device node is a direct child of the parent device node
976 that is given as an argument */
977 if (DeviceNode->Parent != ParentDeviceNode)
979 /* Stop the traversal immediately and indicate successful operation */
981 return STATUS_UNSUCCESSFUL;
984 /* Retrieve configuration from Enum key */
986 Service = &DeviceNode->ServiceName;
988 Status = RtlpGetRegistryHandle(
990 DeviceNode->InstancePath.Buffer,
993 if (!NT_SUCCESS(Status))
995 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status);
999 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1001 RtlInitUnicodeString(Service, NULL);
1003 QueryTable[0].Name = L"Service";
1004 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
1005 QueryTable[0].EntryContext = Service;
1007 Status = RtlQueryRegistryValues(
1008 RTL_REGISTRY_HANDLE,
1015 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
1017 if (!NT_SUCCESS(Status))
1019 /* FIXME: Log the error */
1020 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1021 DeviceNode->InstancePath.Buffer, Status);
1022 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
1023 return STATUS_SUCCESS;
1026 DPRINT("Got Service %S\n", Service->Buffer);
1028 return STATUS_SUCCESS;
1033 IopActionInitChildServices(
1034 PDEVICE_NODE DeviceNode,
1037 * FUNCTION: Initialize the service for all (direct) child nodes of a parent node
1039 * DeviceNode = Pointer to device node
1040 * Context = Pointer to parent node to initialize child node services for
1042 * If the driver image for a service is not loaded and initialized
1043 * it is done here too.
1044 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1045 * when we reach a device node which is not a direct child of the device
1046 * node for which we initialize child services for. Any errors that occur is
1047 * logged instead so that all child services have a chance of beeing
1051 PDEVICE_NODE ParentDeviceNode;
1054 DPRINT("DeviceNode %x Context %x\n", DeviceNode, Context);
1056 ParentDeviceNode = (PDEVICE_NODE)Context;
1058 /* We are called for the parent too, but we don't need to do special
1059 handling for this node */
1060 if (DeviceNode == ParentDeviceNode)
1062 DPRINT("Success\n");
1063 return STATUS_SUCCESS;
1066 /* Make sure this device node is a direct child of the parent device node
1067 that is given as an argument */
1068 if (DeviceNode->Parent != ParentDeviceNode)
1070 /* Stop the traversal immediately and indicate successful operation */
1072 return STATUS_UNSUCCESSFUL;
1075 if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) &&
1076 !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) &&
1077 !IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED))
1079 Status = IopInitializeDeviceNodeService(DeviceNode);
1080 if (NT_SUCCESS(Status))
1082 IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
1086 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
1088 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1089 CPRINT("Initialization of service %S failed (Status %x)\n",
1090 DeviceNode->ServiceName.Buffer, Status);
1095 DPRINT("Service %S is disabled or already initialized\n",
1096 DeviceNode->ServiceName.Buffer);
1099 return STATUS_SUCCESS;
1104 IopInterrogateBusExtender(
1105 PDEVICE_NODE DeviceNode,
1107 BOOLEAN BootDriversOnly)
1109 DEVICETREE_TRAVERSE_CONTEXT Context;
1110 PDEVICE_RELATIONS DeviceRelations;
1111 IO_STATUS_BLOCK IoStatusBlock;
1112 PDEVICE_NODE ChildDeviceNode;
1113 IO_STACK_LOCATION Stack;
1117 DPRINT("DeviceNode %x Pdo %x BootDriversOnly %d\n", DeviceNode, Pdo, BootDriversOnly);
1119 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1121 Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
1123 Status = IopInitiatePnpIrp(
1126 IRP_MN_QUERY_DEVICE_RELATIONS,
1128 if (!NT_SUCCESS(Status))
1130 DPRINT("IopInitiatePnpIrp() failed\n");
1134 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1136 if ((!DeviceRelations) || (DeviceRelations->Count <= 0))
1138 DPRINT("No PDOs\n");
1139 if (DeviceRelations)
1141 ExFreePool(DeviceRelations);
1143 return STATUS_SUCCESS;
1146 DPRINT("Got %d PDOs\n", DeviceRelations->Count);
1148 /* Create device nodes for all discovered devices */
1149 for (i = 0; i < DeviceRelations->Count; i++)
1151 Status = IopCreateDeviceNode(
1153 DeviceRelations->Objects[i],
1155 if (!NT_SUCCESS(Status))
1157 DPRINT("No resources\n");
1158 for (i = 0; i < DeviceRelations->Count; i++)
1159 ObDereferenceObject(DeviceRelations->Objects[i]);
1160 ExFreePool(DeviceRelations);
1161 return STATUS_INSUFFICIENT_RESOURCES;
1165 ExFreePool(DeviceRelations);
1168 /* Retrieve information about all discovered children from the bus driver */
1170 IopInitDeviceTreeTraverseContext(
1173 IopActionInterrogateDeviceStack,
1176 Status = IopTraverseDeviceTree(&Context);
1177 if (!NT_SUCCESS(Status))
1179 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1184 /* Retrieve configuration from the registry for discovered children */
1186 IopInitDeviceTreeTraverseContext(
1189 IopActionConfigureChildServices,
1192 Status = IopTraverseDeviceTree(&Context);
1193 if (!NT_SUCCESS(Status))
1195 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1200 /* Initialize services for discovered children */
1202 IopInitDeviceTreeTraverseContext(
1205 IopActionInitChildServices,
1208 Status = IopTraverseDeviceTree(&Context);
1209 if (!NT_SUCCESS(Status))
1211 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1219 VOID IopLoadBootStartDrivers(VOID)
1221 IopInterrogateBusExtender(
1223 IopRootDeviceNode->Pdo,
1234 KeInitializeSpinLock(&IopDeviceTreeLock);
1236 Status = IopCreateDriverObject(&IopRootDriverObject, NULL, FALSE, NULL, 0);
1237 if (!NT_SUCCESS(Status))
1239 CPRINT("IoCreateDriverObject() failed\n");
1240 KEBUGCHECK(PHASE1_INITIALIZATION_FAILED);
1243 Status = IoCreateDevice(
1244 IopRootDriverObject,
1247 FILE_DEVICE_CONTROLLER,
1251 if (!NT_SUCCESS(Status))
1253 CPRINT("IoCreateDevice() failed\n");
1254 KEBUGCHECK(PHASE1_INITIALIZATION_FAILED);
1257 Status = IopCreateDeviceNode(
1260 &IopRootDeviceNode);
1261 if (!NT_SUCCESS(Status))
1263 CPRINT("Insufficient resources\n");
1264 KEBUGCHECK(PHASE1_INITIALIZATION_FAILED);
1267 IopRootDeviceNode->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
1269 IopRootDeviceNode->DriverObject = IopRootDriverObject;
1271 PnpRootDriverEntry(IopRootDriverObject, NULL);
1273 IopRootDriverObject->DriverExtension->AddDevice(
1274 IopRootDriverObject,
1275 IopRootDeviceNode->Pdo);