1 /* $Id: pnpmgr.c,v 1.18 2003/09/30 15:46:59 navaraf Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnpmgr/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);
30 #include <internal/debug.h>
33 /* GLOBALS *******************************************************************/
35 PDEVICE_NODE IopRootDeviceNode
;
36 KSPIN_LOCK IopDeviceTreeLock
;
38 /* DATA **********************************************************************/
40 PDRIVER_OBJECT IopRootDriverObject
;
42 /* FUNCTIONS *****************************************************************/
49 IoAdjustPagingPathCount(
60 IoInvalidateDeviceRelations(
61 IN PDEVICE_OBJECT DeviceObject
,
62 IN DEVICE_RELATION_TYPE Type
)
67 IopQueryBusInformation(
68 PDEVICE_OBJECT DeviceObject
,
69 PPNP_BUS_INFORMATION BusInformation
)
71 IO_STATUS_BLOCK IoStatusBlock
;
72 IO_STACK_LOCATION Stack
;
74 IoStatusBlock
.Information
= (ULONG
)BusInformation
;
75 return IopInitiatePnpIrp(DeviceObject
, &IoStatusBlock
,
76 IRP_MN_QUERY_BUS_INFORMATION
, &Stack
);
85 IN PDEVICE_OBJECT DeviceObject
,
86 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
87 IN ULONG BufferLength
,
88 OUT PVOID PropertyBuffer
,
89 OUT PULONG ResultLength
)
91 PNP_BUS_INFORMATION BusInformation
;
94 DPRINT("IoGetDeviceProperty called");
99 * IRP_MN_QUERY_BUS_INFORMATION
101 switch (DeviceProperty
)
103 /* Complete, untested */
104 case DevicePropertyBusNumber
:
105 *ResultLength
= sizeof(ULONG
);
106 if (BufferLength
< sizeof(ULONG
))
107 return STATUS_BUFFER_TOO_SMALL
;
108 Status
= IopQueryBusInformation(DeviceObject
, &BusInformation
);
109 if (NT_SUCCESS(Status
))
110 *((ULONG
*)PropertyBuffer
) = BusInformation
.BusNumber
;
113 /* Complete, untested */
114 case DevicePropertyBusTypeGuid
:
115 *ResultLength
= 39 * sizeof(WCHAR
);
116 if (BufferLength
< (39 * sizeof(WCHAR
)))
117 return STATUS_BUFFER_TOO_SMALL
;
118 Status
= IopQueryBusInformation(DeviceObject
, &BusInformation
);
119 if (NT_SUCCESS(Status
))
120 swprintf((PWSTR
)PropertyBuffer
,
121 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
122 BusInformation
.BusTypeGuid
.Data1
,
123 BusInformation
.BusTypeGuid
.Data2
,
124 BusInformation
.BusTypeGuid
.Data3
,
125 BusInformation
.BusTypeGuid
.Data4
[0],
126 BusInformation
.BusTypeGuid
.Data4
[1],
127 BusInformation
.BusTypeGuid
.Data4
[2],
128 BusInformation
.BusTypeGuid
.Data4
[3],
129 BusInformation
.BusTypeGuid
.Data4
[4],
130 BusInformation
.BusTypeGuid
.Data4
[5],
131 BusInformation
.BusTypeGuid
.Data4
[6],
132 BusInformation
.BusTypeGuid
.Data4
[7]);
135 /* Complete, untested */
136 case DevicePropertyLegacyBusType
:
137 *ResultLength
= sizeof(INTERFACE_TYPE
);
138 if (BufferLength
< sizeof(INTERFACE_TYPE
))
139 return STATUS_BUFFER_TOO_SMALL
;
140 Status
= IopQueryBusInformation(DeviceObject
, &BusInformation
);
141 if (NT_SUCCESS(Status
))
142 memcpy(PropertyBuffer
, &BusInformation
.LegacyBusType
,
143 sizeof(INTERFACE_TYPE
));
146 case DevicePropertyAddress
:
147 case DevicePropertyBootConfiguration
:
148 case DevicePropertyBootConfigurationTranslated
:
149 case DevicePropertyClassGuid
:
150 case DevicePropertyClassName
:
151 case DevicePropertyCompatibleIDs
:
152 case DevicePropertyDeviceDescription
:
153 case DevicePropertyDriverKeyName
:
154 case DevicePropertyEnumeratorName
:
155 case DevicePropertyFriendlyName
:
156 case DevicePropertyHardwareID
:
157 case DevicePropertyLocationInformation
:
158 case DevicePropertyManufacturer
:
159 case DevicePropertyPhysicalDeviceObjectName
:
160 case DevicePropertyUINumber
:
164 return STATUS_INVALID_PARAMETER_2
;
167 return STATUS_NOT_IMPLEMENTED
;
175 IoInvalidateDeviceState(
176 IN PDEVICE_OBJECT PhysicalDeviceObject
)
185 IoOpenDeviceRegistryKey(
186 IN PDEVICE_OBJECT DeviceObject
,
187 IN ULONG DevInstKeyType
,
188 IN ACCESS_MASK DesiredAccess
,
189 OUT PHANDLE DevInstRegKey
)
191 return STATUS_NOT_IMPLEMENTED
;
199 IoRequestDeviceEject(
200 IN PDEVICE_OBJECT PhysicalDeviceObject
)
206 IopCreateUnicodeString(
207 PUNICODE_STRING Destination
,
215 RtlInitUnicodeString(Destination
, NULL
);
219 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
221 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
223 if (Destination
->Buffer
== NULL
)
228 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
230 Destination
->MaximumLength
= Length
;
232 Destination
->Length
= Length
- sizeof(WCHAR
);
238 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
242 assert(PopSystemPowerDeviceNode
);
244 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
245 *DeviceObject
= PopSystemPowerDeviceNode
->Pdo
;
246 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
248 return STATUS_SUCCESS
;
251 /**********************************************************************
253 * Creates a device node
256 * ParentNode = Pointer to parent device node
257 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
258 * to have the root device node create one
259 * (eg. for legacy drivers)
260 * DeviceNode = Pointer to storage for created device node
266 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
267 PDEVICE_OBJECT PhysicalDeviceObject
,
268 PDEVICE_NODE
*DeviceNode
)
274 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
275 ParentNode
, PhysicalDeviceObject
);
277 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
280 return STATUS_INSUFFICIENT_RESOURCES
;
283 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
285 if (!PhysicalDeviceObject
)
287 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
288 if (!NT_SUCCESS(Status
))
294 /* This is for drivers passed on the command line to ntoskrnl.exe */
295 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
296 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
299 Node
->Pdo
= PhysicalDeviceObject
;
303 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
304 Node
->Parent
= ParentNode
;
305 Node
->NextSibling
= ParentNode
->Child
;
306 if (ParentNode
->Child
!= NULL
)
308 ParentNode
->Child
->PrevSibling
= Node
;
310 ParentNode
->Child
= Node
;
311 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
316 return STATUS_SUCCESS
;
320 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
324 /* All children must be deleted before a parent is deleted */
325 assert(!DeviceNode
->Child
);
327 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
329 assert(DeviceNode
->Pdo
);
331 ObDereferenceObject(DeviceNode
->Pdo
);
333 /* Unlink from parent if it exists */
335 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
337 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
340 /* Unlink from sibling list */
342 if (DeviceNode
->PrevSibling
)
344 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
347 if (DeviceNode
->NextSibling
)
349 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
352 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
354 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
356 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
358 if (DeviceNode
->CapabilityFlags
)
360 ExFreePool(DeviceNode
->CapabilityFlags
);
363 if (DeviceNode
->CmResourceList
)
365 ExFreePool(DeviceNode
->CmResourceList
);
368 if (DeviceNode
->BootResourcesList
)
370 ExFreePool(DeviceNode
->BootResourcesList
);
373 if (DeviceNode
->ResourceRequirementsList
)
375 ExFreePool(DeviceNode
->ResourceRequirementsList
);
378 RtlFreeUnicodeString(&DeviceNode
->DeviceID
);
380 RtlFreeUnicodeString(&DeviceNode
->InstanceID
);
382 RtlFreeUnicodeString(&DeviceNode
->HardwareIDs
);
384 RtlFreeUnicodeString(&DeviceNode
->CompatibleIDs
);
386 RtlFreeUnicodeString(&DeviceNode
->DeviceText
);
388 RtlFreeUnicodeString(&DeviceNode
->DeviceTextLocation
);
390 if (DeviceNode
->BusInformation
)
392 ExFreePool(DeviceNode
->BusInformation
);
395 ExFreePool(DeviceNode
);
397 return STATUS_SUCCESS
;
402 PDEVICE_OBJECT DeviceObject
,
403 PIO_STATUS_BLOCK IoStatusBlock
,
405 PIO_STACK_LOCATION Stack OPTIONAL
)
407 PDEVICE_OBJECT TopDeviceObject
;
408 PIO_STACK_LOCATION IrpSp
;
413 /* Always call the top of the device stack */
414 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
421 /* PNP IRPs are always initialized with a status code of
422 STATUS_NOT_IMPLEMENTED */
423 IoStatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
424 IoStatusBlock
->Information
= 0;
426 Irp
= IoBuildSynchronousFsdRequest(
435 IrpSp
= IoGetNextIrpStackLocation(Irp
);
436 IrpSp
->MinorFunction
= MinorFunction
;
443 sizeof(Stack
->Parameters
));
446 Status
= IoCallDriver(TopDeviceObject
, Irp
);
447 if (Status
== STATUS_PENDING
)
449 KeWaitForSingleObject(
455 Status
= IoStatusBlock
->Status
;
458 ObDereferenceObject(TopDeviceObject
);
465 IopQueryCapabilities(
467 PDEVICE_CAPABILITIES
*Capabilities
)
469 IO_STATUS_BLOCK IoStatusBlock
;
470 PDEVICE_CAPABILITIES Caps
;
471 IO_STACK_LOCATION Stack
;
474 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
476 *Capabilities
= NULL
;
478 Caps
= ExAllocatePool(PagedPool
, sizeof(DEVICE_CAPABILITIES
));
481 return STATUS_INSUFFICIENT_RESOURCES
;
484 RtlZeroMemory(Caps
, sizeof(DEVICE_CAPABILITIES
));
485 Caps
->Size
= sizeof(DEVICE_CAPABILITIES
);
490 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= Caps
;
492 Status
= IopInitiatePnpIrp(
495 IRP_MN_QUERY_CAPABILITIES
,
497 if (NT_SUCCESS(Status
))
499 *Capabilities
= Caps
;
503 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
511 IopTraverseDeviceTreeNode(
512 PDEVICETREE_TRAVERSE_CONTEXT Context
)
514 PDEVICE_NODE ParentDeviceNode
;
515 PDEVICE_NODE ChildDeviceNode
;
518 /* Copy context data so we don't overwrite it in subsequent calls to this function */
519 ParentDeviceNode
= Context
->DeviceNode
;
521 /* Call the action routine */
522 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
523 if (!NT_SUCCESS(Status
))
528 /* Traversal of all children nodes */
529 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
530 ChildDeviceNode
!= NULL
;
531 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
533 /* Pass the current device node to the action routine */
534 Context
->DeviceNode
= ChildDeviceNode
;
536 Status
= IopTraverseDeviceTreeNode(Context
);
537 if (!NT_SUCCESS(Status
))
548 IopTraverseDeviceTree(
549 PDEVICETREE_TRAVERSE_CONTEXT Context
)
553 DPRINT("Context %x\n", Context
);
555 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
556 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
558 /* Start from the specified device node */
559 Context
->DeviceNode
= Context
->FirstDeviceNode
;
561 /* Recursively traverse the device tree */
562 Status
= IopTraverseDeviceTreeNode(Context
);
563 if (Status
== STATUS_UNSUCCESSFUL
)
565 /* The action routine just wanted to terminate the traversal with status
566 code STATUS_SUCCESS */
567 Status
= STATUS_SUCCESS
;
575 IopActionInterrogateDeviceStack(
576 PDEVICE_NODE DeviceNode
,
579 * FUNCTION: Retrieve information for all (direct) child nodes of a parent node
581 * DeviceNode = Pointer to device node
582 * Context = Pointer to parent node to retrieve child node information for
584 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
585 * when we reach a device node which is not a direct child of the device node
586 * for which we retrieve information of child nodes for. Any errors that occur
587 * is logged instead so that all child services have a chance of beeing
591 IO_STATUS_BLOCK IoStatusBlock
;
592 PDEVICE_NODE ParentDeviceNode
;
593 WCHAR InstancePath
[MAX_PATH
];
594 IO_STACK_LOCATION Stack
;
598 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
600 DPRINT("PDO %x\n", DeviceNode
->Pdo
);
603 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
605 /* We are called for the parent too, but we don't need to do special
606 handling for this node */
607 if (DeviceNode
== ParentDeviceNode
)
610 return STATUS_SUCCESS
;
613 /* Make sure this device node is a direct child of the parent device node
614 that is given as an argument */
615 if (DeviceNode
->Parent
!= ParentDeviceNode
)
617 /* Stop the traversal immediately and indicate successful operation */
619 return STATUS_UNSUCCESSFUL
;
623 /* FIXME: For critical errors, cleanup and disable device, but always return STATUS_SUCCESS */
626 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
628 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
630 Status
= IopInitiatePnpIrp(
635 if (NT_SUCCESS(Status
))
637 RtlInitUnicodeString(
638 &DeviceNode
->DeviceID
,
639 (LPWSTR
)IoStatusBlock
.Information
);
641 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
645 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
646 RtlInitUnicodeString(&DeviceNode
->DeviceID
, NULL
);
650 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
652 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
654 Status
= IopInitiatePnpIrp(
659 if (NT_SUCCESS(Status
))
661 RtlInitUnicodeString(
662 &DeviceNode
->InstanceID
,
663 (LPWSTR
)IoStatusBlock
.Information
);
665 /* FIXME: Check for valid characters, if there is invalid characters then bugcheck */
669 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
670 RtlInitUnicodeString(&DeviceNode
->InstanceID
, NULL
);
674 /* FIXME: SEND IRP_QUERY_ID.BusQueryHardwareIDs */
675 /* FIXME: SEND IRP_QUERY_ID.BusQueryCompatibleIDs */
678 Status
= IopQueryCapabilities(DeviceNode
->Pdo
, &DeviceNode
->CapabilityFlags
);
679 if (NT_SUCCESS(Status
))
687 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
689 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
690 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
692 Status
= IopInitiatePnpIrp(
695 IRP_MN_QUERY_DEVICE_TEXT
,
697 if (NT_SUCCESS(Status
))
699 RtlInitUnicodeString(
700 &DeviceNode
->DeviceText
,
701 (LPWSTR
)IoStatusBlock
.Information
);
705 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
706 RtlInitUnicodeString(&DeviceNode
->DeviceText
, NULL
);
710 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
712 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
713 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
715 Status
= IopInitiatePnpIrp(
718 IRP_MN_QUERY_DEVICE_TEXT
,
720 if (NT_SUCCESS(Status
))
722 RtlInitUnicodeString(
723 &DeviceNode
->DeviceTextLocation
,
724 (LPWSTR
)IoStatusBlock
.Information
);
728 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
729 RtlInitUnicodeString(&DeviceNode
->DeviceTextLocation
, NULL
);
733 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
735 Status
= IopInitiatePnpIrp(
738 IRP_MN_QUERY_BUS_INFORMATION
,
740 if (NT_SUCCESS(Status
))
742 DeviceNode
->BusInformation
=
743 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
747 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
748 DeviceNode
->BusInformation
= NULL
;
752 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
754 Status
= IopInitiatePnpIrp(
757 IRP_MN_QUERY_RESOURCES
,
759 if (NT_SUCCESS(Status
))
761 DeviceNode
->BootResourcesList
=
762 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
766 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
767 DeviceNode
->BootResourcesList
= NULL
;
771 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
773 Status
= IopInitiatePnpIrp(
776 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
778 if (NT_SUCCESS(Status
))
780 DeviceNode
->ResourceRequirementsList
=
781 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
785 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
786 DeviceNode
->ResourceRequirementsList
= NULL
;
790 /* Assemble the instance path for the device */
792 wcscpy(InstancePath
, DeviceNode
->DeviceID
.Buffer
);
793 wcscat(InstancePath
, L
"\\");
794 wcscat(InstancePath
, DeviceNode
->InstanceID
.Buffer
);
796 if (!DeviceNode
->CapabilityFlags
->UniqueID
)
798 DPRINT("Instance ID is not unique\n");
799 /* FIXME: Add information from parent bus driver to InstancePath */
802 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
)) {
803 DPRINT("No resources\n");
804 /* FIXME: Cleanup and disable device */
807 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
810 * Create registry key for the instance id, if it doesn't exist yet
812 KeyBuffer
= ExAllocatePool(PagedPool
, (49 + DeviceNode
->InstancePath
.Length
) * sizeof(WCHAR
));
813 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
814 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
815 RtlpCreateRegistryKeyPath(KeyBuffer
);
816 ExFreePool(KeyBuffer
);
817 DeviceNode
->Flags
|= DNF_PROCESSED
;
819 return STATUS_SUCCESS
;
824 IopActionConfigureChildServices(
825 PDEVICE_NODE DeviceNode
,
828 * FUNCTION: Retrieve configuration for all (direct) child nodes of a parent node
830 * DeviceNode = Pointer to device node
831 * Context = Pointer to parent node to retrieve child node configuration for
833 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
834 * when we reach a device node which is not a direct child of the device
835 * node for which we configure child services for. Any errors that occur is
836 * logged instead so that all child services have a chance of beeing
841 * FIXME: There are two versions of this function: one that creates registry
842 * and one that doesn't. The second is the right, but could not be used because
843 * there is not automatic parent key generation.
845 * Update: It could propably be used now, but there's no need anymore.
850 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
851 PDEVICE_NODE ParentDeviceNode
;
852 PUNICODE_STRING Service
;
855 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
857 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
859 /* We are called for the parent too, but we don't need to do special
860 handling for this node */
861 if (DeviceNode
== ParentDeviceNode
)
864 return STATUS_SUCCESS
;
867 /* Make sure this device node is a direct child of the parent device node
868 that is given as an argument */
869 if (DeviceNode
->Parent
!= ParentDeviceNode
)
871 /* Stop the traversal immediately and indicate successful operation */
873 return STATUS_UNSUCCESSFUL
;
876 /* Retrieve configuration from Enum key */
878 Service
= &DeviceNode
->ServiceName
;
880 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
882 RtlInitUnicodeString(Service
, NULL
);
884 QueryTable
[0].Name
= L
"Service";
885 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
886 QueryTable
[0].EntryContext
= Service
;
888 Status
= RtlQueryRegistryValues(
890 DeviceNode
->InstancePath
.Buffer
,
895 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status
);
896 DPRINT("Key: %S\n", DeviceNode
->InstancePath
.Buffer
);
898 if (!NT_SUCCESS(Status
))
900 /* FIXME: Log the error */
901 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
902 DeviceNode
->InstancePath
.Buffer
, Status
);
903 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
904 return STATUS_SUCCESS
;
907 if (Service
->Buffer
== NULL
)
909 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
910 return STATUS_SUCCESS
;
913 DPRINT("Got Service %S\n", Service
->Buffer
);
915 return STATUS_SUCCESS
;
917 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
918 PDEVICE_NODE ParentDeviceNode
;
919 PUNICODE_STRING Service
;
923 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
925 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
927 /* We are called for the parent too, but we don't need to do special
928 handling for this node */
929 if (DeviceNode
== ParentDeviceNode
)
932 return STATUS_SUCCESS
;
935 /* Make sure this device node is a direct child of the parent device node
936 that is given as an argument */
937 if (DeviceNode
->Parent
!= ParentDeviceNode
)
939 /* Stop the traversal immediately and indicate successful operation */
941 return STATUS_UNSUCCESSFUL
;
944 /* Retrieve configuration from Enum key */
946 Service
= &DeviceNode
->ServiceName
;
948 Status
= RtlpGetRegistryHandle(
950 DeviceNode
->InstancePath
.Buffer
,
953 if (!NT_SUCCESS(Status
))
955 DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status
);
959 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
961 RtlInitUnicodeString(Service
, NULL
);
963 QueryTable
[0].Name
= L
"Service";
964 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
965 QueryTable
[0].EntryContext
= Service
;
967 Status
= RtlQueryRegistryValues(
975 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status
);
977 if (!NT_SUCCESS(Status
))
979 /* FIXME: Log the error */
980 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
981 DeviceNode
->InstancePath
.Buffer
, Status
);
982 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
983 return STATUS_SUCCESS
;
986 DPRINT("Got Service %S\n", Service
->Buffer
);
988 return STATUS_SUCCESS
;
994 IopActionInitChildServices(
995 PDEVICE_NODE DeviceNode
,
998 * FUNCTION: Initialize the service for all (direct) child nodes of a parent node
1000 * DeviceNode = Pointer to device node
1001 * Context = Pointer to parent node to initialize child node services for
1003 * If the driver image for a service is not loaded and initialized
1004 * it is done here too.
1005 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1006 * when we reach a device node which is not a direct child of the device
1007 * node for which we initialize child services for. Any errors that occur is
1008 * logged instead so that all child services have a chance of beeing
1012 PDEVICE_NODE ParentDeviceNode
;
1015 DPRINT("DeviceNode %x Context %x\n", DeviceNode
, Context
);
1017 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1019 /* We are called for the parent too, but we don't need to do special
1020 handling for this node */
1021 if (DeviceNode
== ParentDeviceNode
)
1023 DPRINT("Success\n");
1024 return STATUS_SUCCESS
;
1027 /* Make sure this device node is a direct child of the parent device node
1028 that is given as an argument */
1029 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1031 /* Stop the traversal immediately and indicate successful operation */
1033 return STATUS_UNSUCCESSFUL
;
1036 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1037 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1038 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1040 Status
= IopInitializeDeviceNodeService(DeviceNode
);
1041 if (NT_SUCCESS(Status
))
1043 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1047 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1049 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1050 CPRINT("Initialization of service %S failed (Status %x)\n",
1051 DeviceNode
->ServiceName
.Buffer
, Status
);
1056 DPRINT("Service %S is disabled or already initialized\n",
1057 DeviceNode
->ServiceName
.Buffer
);
1060 return STATUS_SUCCESS
;
1065 IopInvalidateDeviceRelations(
1066 IN PDEVICE_NODE DeviceNode
,
1067 IN DEVICE_RELATION_TYPE Type
)
1069 DEVICETREE_TRAVERSE_CONTEXT Context
;
1070 PDEVICE_RELATIONS DeviceRelations
;
1071 IO_STATUS_BLOCK IoStatusBlock
;
1072 PDEVICE_NODE ChildDeviceNode
;
1073 IO_STACK_LOCATION Stack
;
1077 DPRINT("DeviceNode %x Pdo %x\n", DeviceNode
, Pdo
);
1079 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1081 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1083 Status
= IopInitiatePnpIrp(
1086 IRP_MN_QUERY_DEVICE_RELATIONS
,
1088 if (!NT_SUCCESS(Status
))
1090 DPRINT("IopInitiatePnpIrp() failed\n");
1094 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1096 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1098 DPRINT("No PDOs\n");
1099 if (DeviceRelations
)
1101 ExFreePool(DeviceRelations
);
1103 return STATUS_SUCCESS
;
1106 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1108 /* Create device nodes for all discovered devices */
1109 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1111 Status
= IopCreateDeviceNode(
1113 DeviceRelations
->Objects
[i
],
1115 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1116 if (!NT_SUCCESS(Status
))
1118 DPRINT("No resources\n");
1119 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1120 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1121 ExFreePool(DeviceRelations
);
1122 return STATUS_INSUFFICIENT_RESOURCES
;
1126 ExFreePool(DeviceRelations
);
1129 /* Retrieve information about all discovered children from the bus driver */
1131 IopInitDeviceTreeTraverseContext(
1134 IopActionInterrogateDeviceStack
,
1137 Status
= IopTraverseDeviceTree(&Context
);
1138 if (!NT_SUCCESS(Status
))
1140 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1145 /* Retrieve configuration from the registry for discovered children */
1147 IopInitDeviceTreeTraverseContext(
1150 IopActionConfigureChildServices
,
1153 Status
= IopTraverseDeviceTree(&Context
);
1154 if (!NT_SUCCESS(Status
))
1156 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1161 /* Initialize services for discovered children */
1163 IopInitDeviceTreeTraverseContext(
1166 IopActionInitChildServices
,
1169 Status
= IopTraverseDeviceTree(&Context
);
1170 if (!NT_SUCCESS(Status
))
1172 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1176 return STATUS_SUCCESS
;
1179 VOID
IopLoadBootStartDrivers(VOID
)
1181 IopInvalidateDeviceRelations(IopRootDeviceNode
, BusRelations
);
1191 KeInitializeSpinLock(&IopDeviceTreeLock
);
1193 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, FALSE
, NULL
, 0);
1194 if (!NT_SUCCESS(Status
))
1196 CPRINT("IoCreateDriverObject() failed\n");
1197 KEBUGCHECK(PHASE1_INITIALIZATION_FAILED
);
1200 Status
= IoCreateDevice(
1201 IopRootDriverObject
,
1204 FILE_DEVICE_CONTROLLER
,
1208 if (!NT_SUCCESS(Status
))
1210 CPRINT("IoCreateDevice() failed\n");
1211 KEBUGCHECK(PHASE1_INITIALIZATION_FAILED
);
1214 Status
= IopCreateDeviceNode(
1217 &IopRootDeviceNode
);
1218 if (!NT_SUCCESS(Status
))
1220 CPRINT("Insufficient resources\n");
1221 KEBUGCHECK(PHASE1_INITIALIZATION_FAILED
);
1224 IopRootDeviceNode
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1226 IopRootDeviceNode
->DriverObject
= IopRootDriverObject
;
1228 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1230 IopRootDriverObject
->DriverExtension
->AddDevice(
1231 IopRootDriverObject
,
1232 IopRootDeviceNode
->Pdo
);