1 /* $Id: pnpmgr.c,v 1.31 2004/08/01 21:57:34 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/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);
29 #include <internal/debug.h>
32 /* GLOBALS *******************************************************************/
34 PDEVICE_NODE IopRootDeviceNode
;
35 KSPIN_LOCK IopDeviceTreeLock
;
37 /* DATA **********************************************************************/
39 PDRIVER_OBJECT IopRootDriverObject
;
41 /* FUNCTIONS *****************************************************************/
48 IoAdjustPagingPathCount(
59 IoInvalidateDeviceRelations(
60 IN PDEVICE_OBJECT DeviceObject
,
61 IN DEVICE_RELATION_TYPE Type
)
67 PDEVICE_OBJECT DeviceObject
)
69 return DeviceObject
->DeviceObjectExtension
->DeviceNode
;
78 IN PDEVICE_OBJECT DeviceObject
,
79 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
80 IN ULONG BufferLength
,
81 OUT PVOID PropertyBuffer
,
82 OUT PULONG ResultLength
)
84 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
88 DPRINT("IoGetDeviceProperty called\n");
90 if (DeviceNode
== NULL
||
91 DeviceNode
->BusInformation
== NULL
||
92 DeviceNode
->CapabilityFlags
== NULL
)
94 return STATUS_INVALID_DEVICE_REQUEST
;
100 * IRP_MN_QUERY_BUS_INFORMATION
102 switch (DeviceProperty
)
104 case DevicePropertyBusNumber
:
105 Length
= sizeof(ULONG
);
106 Data
= &DeviceNode
->BusInformation
->BusNumber
;
109 /* Complete, untested */
110 case DevicePropertyBusTypeGuid
:
111 *ResultLength
= 39 * sizeof(WCHAR
);
112 if (BufferLength
< (39 * sizeof(WCHAR
)))
113 return STATUS_BUFFER_TOO_SMALL
;
114 swprintf((PWSTR
)PropertyBuffer
,
115 L
"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
116 DeviceNode
->BusInformation
->BusTypeGuid
.Data1
,
117 DeviceNode
->BusInformation
->BusTypeGuid
.Data2
,
118 DeviceNode
->BusInformation
->BusTypeGuid
.Data3
,
119 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[0],
120 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[1],
121 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[2],
122 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[3],
123 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[4],
124 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[5],
125 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[6],
126 DeviceNode
->BusInformation
->BusTypeGuid
.Data4
[7]);
127 return STATUS_SUCCESS
;
129 case DevicePropertyLegacyBusType
:
130 Length
= sizeof(INTERFACE_TYPE
);
131 Data
= &DeviceNode
->BusInformation
->LegacyBusType
;
134 case DevicePropertyAddress
:
135 Length
= sizeof(ULONG
);
136 Data
= &DeviceNode
->CapabilityFlags
->Address
;
139 case DevicePropertyUINumber
:
140 Length
= sizeof(ULONG
);
141 Data
= &DeviceNode
->CapabilityFlags
->UINumber
;
144 case DevicePropertyBootConfiguration
:
145 case DevicePropertyBootConfigurationTranslated
:
146 case DevicePropertyClassGuid
:
147 case DevicePropertyClassName
:
148 case DevicePropertyCompatibleIDs
:
149 case DevicePropertyDeviceDescription
:
150 case DevicePropertyDriverKeyName
:
151 case DevicePropertyEnumeratorName
:
152 case DevicePropertyFriendlyName
:
153 case DevicePropertyHardwareID
:
154 case DevicePropertyLocationInformation
:
155 case DevicePropertyManufacturer
:
156 case DevicePropertyPhysicalDeviceObjectName
:
157 return STATUS_NOT_IMPLEMENTED
;
160 return STATUS_INVALID_PARAMETER_2
;
163 *ResultLength
= Length
;
164 if (BufferLength
< Length
)
165 return STATUS_BUFFER_TOO_SMALL
;
166 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
168 return STATUS_SUCCESS
;
176 IoInvalidateDeviceState(
177 IN PDEVICE_OBJECT PhysicalDeviceObject
)
186 IoOpenDeviceRegistryKey(
187 IN PDEVICE_OBJECT DeviceObject
,
188 IN ULONG DevInstKeyType
,
189 IN ACCESS_MASK DesiredAccess
,
190 OUT PHANDLE DevInstRegKey
)
192 return STATUS_NOT_IMPLEMENTED
;
200 IoRequestDeviceEject(
201 IN PDEVICE_OBJECT PhysicalDeviceObject
209 IopCreateUnicodeString(
210 PUNICODE_STRING Destination
,
218 RtlInitUnicodeString(Destination
, NULL
);
222 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
224 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
226 if (Destination
->Buffer
== NULL
)
231 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
233 Destination
->MaximumLength
= Length
;
235 Destination
->Length
= Length
- sizeof(WCHAR
);
241 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
245 if (PopSystemPowerDeviceNode
)
247 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
248 *DeviceObject
= PopSystemPowerDeviceNode
->Pdo
;
249 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
251 return STATUS_SUCCESS
;
254 return STATUS_UNSUCCESSFUL
;
257 /**********************************************************************
259 * Creates a device node
262 * ParentNode = Pointer to parent device node
263 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
264 * to have the root device node create one
265 * (eg. for legacy drivers)
266 * DeviceNode = Pointer to storage for created device node
272 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
273 PDEVICE_OBJECT PhysicalDeviceObject
,
274 PDEVICE_NODE
*DeviceNode
)
280 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
281 ParentNode
, PhysicalDeviceObject
);
283 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
286 return STATUS_INSUFFICIENT_RESOURCES
;
289 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
291 if (!PhysicalDeviceObject
)
293 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
294 if (!NT_SUCCESS(Status
))
300 /* This is for drivers passed on the command line to ntoskrnl.exe */
301 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
302 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
305 Node
->Pdo
= PhysicalDeviceObject
;
307 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
311 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
312 Node
->Parent
= ParentNode
;
313 Node
->NextSibling
= ParentNode
->Child
;
314 if (ParentNode
->Child
!= NULL
)
316 ParentNode
->Child
->PrevSibling
= Node
;
318 ParentNode
->Child
= Node
;
319 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
324 return STATUS_SUCCESS
;
328 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
332 /* All children must be deleted before a parent is deleted */
333 assert(!DeviceNode
->Child
);
335 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
337 assert(DeviceNode
->Pdo
);
339 ObDereferenceObject(DeviceNode
->Pdo
);
341 /* Unlink from parent if it exists */
343 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
345 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
348 /* Unlink from sibling list */
350 if (DeviceNode
->PrevSibling
)
352 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
355 if (DeviceNode
->NextSibling
)
357 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
360 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
362 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
364 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
366 if (DeviceNode
->CapabilityFlags
)
368 ExFreePool(DeviceNode
->CapabilityFlags
);
371 if (DeviceNode
->CmResourceList
)
373 ExFreePool(DeviceNode
->CmResourceList
);
376 if (DeviceNode
->BootResourcesList
)
378 ExFreePool(DeviceNode
->BootResourcesList
);
381 if (DeviceNode
->ResourceRequirementsList
)
383 ExFreePool(DeviceNode
->ResourceRequirementsList
);
386 RtlFreeUnicodeString(&DeviceNode
->DeviceID
);
388 RtlFreeUnicodeString(&DeviceNode
->InstanceID
);
390 RtlFreeUnicodeString(&DeviceNode
->HardwareIDs
);
392 RtlFreeUnicodeString(&DeviceNode
->CompatibleIDs
);
394 RtlFreeUnicodeString(&DeviceNode
->DeviceText
);
396 RtlFreeUnicodeString(&DeviceNode
->DeviceTextLocation
);
398 if (DeviceNode
->BusInformation
)
400 ExFreePool(DeviceNode
->BusInformation
);
403 ExFreePool(DeviceNode
);
405 return STATUS_SUCCESS
;
410 PDEVICE_OBJECT DeviceObject
,
411 PIO_STATUS_BLOCK IoStatusBlock
,
413 PIO_STACK_LOCATION Stack OPTIONAL
)
415 PDEVICE_OBJECT TopDeviceObject
;
416 PIO_STACK_LOCATION IrpSp
;
421 /* Always call the top of the device stack */
422 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
429 /* PNP IRPs are always initialized with a status code of
430 STATUS_NOT_IMPLEMENTED */
431 IoStatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
432 IoStatusBlock
->Information
= 0;
434 Irp
= IoBuildSynchronousFsdRequest(
443 IrpSp
= IoGetNextIrpStackLocation(Irp
);
444 IrpSp
->MinorFunction
= MinorFunction
;
451 sizeof(Stack
->Parameters
));
454 Status
= IoCallDriver(TopDeviceObject
, Irp
);
455 if (Status
== STATUS_PENDING
)
457 KeWaitForSingleObject(
463 Status
= IoStatusBlock
->Status
;
466 ObDereferenceObject(TopDeviceObject
);
473 IopQueryCapabilities(
475 PDEVICE_CAPABILITIES
*Capabilities
)
477 IO_STATUS_BLOCK IoStatusBlock
;
478 PDEVICE_CAPABILITIES Caps
;
479 IO_STACK_LOCATION Stack
;
482 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
484 *Capabilities
= NULL
;
486 Caps
= ExAllocatePool(PagedPool
, sizeof(DEVICE_CAPABILITIES
));
489 return STATUS_INSUFFICIENT_RESOURCES
;
492 RtlZeroMemory(Caps
, sizeof(DEVICE_CAPABILITIES
));
493 Caps
->Size
= sizeof(DEVICE_CAPABILITIES
);
498 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= Caps
;
500 Status
= IopInitiatePnpIrp(
503 IRP_MN_QUERY_CAPABILITIES
,
505 if (NT_SUCCESS(Status
))
507 *Capabilities
= Caps
;
511 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
519 IopTraverseDeviceTreeNode(
520 PDEVICETREE_TRAVERSE_CONTEXT Context
)
522 PDEVICE_NODE ParentDeviceNode
;
523 PDEVICE_NODE ChildDeviceNode
;
526 /* Copy context data so we don't overwrite it in subsequent calls to this function */
527 ParentDeviceNode
= Context
->DeviceNode
;
529 /* Call the action routine */
530 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
531 if (!NT_SUCCESS(Status
))
536 /* Traversal of all children nodes */
537 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
538 ChildDeviceNode
!= NULL
;
539 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
541 /* Pass the current device node to the action routine */
542 Context
->DeviceNode
= ChildDeviceNode
;
544 Status
= IopTraverseDeviceTreeNode(Context
);
545 if (!NT_SUCCESS(Status
))
556 IopTraverseDeviceTree(
557 PDEVICETREE_TRAVERSE_CONTEXT Context
)
561 DPRINT("Context %x\n", Context
);
563 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
564 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
566 /* Start from the specified device node */
567 Context
->DeviceNode
= Context
->FirstDeviceNode
;
569 /* Recursively traverse the device tree */
570 Status
= IopTraverseDeviceTreeNode(Context
);
571 if (Status
== STATUS_UNSUCCESSFUL
)
573 /* The action routine just wanted to terminate the traversal with status
574 code STATUS_SUCCESS */
575 Status
= STATUS_SUCCESS
;
583 IopCreateDeviceKeyPath(PWSTR Path
)
585 OBJECT_ATTRIBUTES ObjectAttributes
;
586 WCHAR KeyBuffer
[MAX_PATH
];
587 UNICODE_STRING KeyName
;
593 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
595 return STATUS_INVALID_PARAMETER
;
598 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
599 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
601 /* Skip \\Registry\\ */
602 Current
= KeyName
.Buffer
;
603 Current
= wcschr (Current
, '\\') + 1;
604 Current
= wcschr (Current
, '\\') + 1;
608 Next
= wcschr (Current
, '\\');
618 InitializeObjectAttributes (&ObjectAttributes
,
620 OBJ_CASE_INSENSITIVE
,
624 DPRINT("Create '%S'\n", KeyName
.Buffer
);
626 Status
= NtCreateKey (&KeyHandle
,
633 if (!NT_SUCCESS (Status
))
635 DPRINT ("NtCreateKey() failed with status %x\n", Status
);
648 while (Next
!= NULL
);
650 return STATUS_SUCCESS
;
655 * IopActionInterrogateDeviceStack
657 * Retrieve information for all (direct) child nodes of a parent node.
661 * Pointer to device node.
663 * Pointer to parent node to retrieve child node information for.
666 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
667 * when we reach a device node which is not a direct child of the device
668 * node for which we retrieve information of child nodes for. Any errors
669 * that occur is logged instead so that all child services have a chance
670 * of being interrogated.
674 IopActionInterrogateDeviceStack(
675 PDEVICE_NODE DeviceNode
,
678 IO_STATUS_BLOCK IoStatusBlock
;
679 PDEVICE_NODE ParentDeviceNode
;
680 WCHAR InstancePath
[MAX_PATH
];
681 IO_STACK_LOCATION Stack
;
688 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
689 DPRINT("PDO %x\n", DeviceNode
->Pdo
);
691 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
694 * We are called for the parent too, but we don't need to do special
695 * handling for this node
698 if (DeviceNode
== ParentDeviceNode
)
701 return STATUS_SUCCESS
;
705 * Make sure this device node is a direct child of the parent device node
706 * that is given as an argument
709 if (DeviceNode
->Parent
!= ParentDeviceNode
)
711 /* Stop the traversal immediately and indicate successful operation */
713 return STATUS_UNSUCCESSFUL
;
717 * FIXME: For critical errors, cleanup and disable device, but always
718 * return STATUS_SUCCESS.
721 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
723 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
724 Status
= IopInitiatePnpIrp(
729 if (NT_SUCCESS(Status
))
731 RtlInitUnicodeString(
732 &DeviceNode
->DeviceID
,
733 (PWSTR
)IoStatusBlock
.Information
);
736 * FIXME: Check for valid characters, if there is invalid characters
742 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
743 RtlInitUnicodeString(&DeviceNode
->DeviceID
, NULL
);
746 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
748 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
749 Status
= IopInitiatePnpIrp(
754 if (NT_SUCCESS(Status
))
756 RtlInitUnicodeString(
757 &DeviceNode
->InstanceID
,
758 (PWSTR
)IoStatusBlock
.Information
);
761 * FIXME: Check for valid characters, if there is invalid characters
767 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
768 RtlInitUnicodeString(&DeviceNode
->InstanceID
, NULL
);
771 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
773 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
774 Status
= IopInitiatePnpIrp(
779 if (NT_SUCCESS(Status
))
782 * FIXME: Check for valid characters, if there is invalid characters
786 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
787 DPRINT("Hardware IDs:\n");
790 DPRINT(" %S\n", Ptr
);
791 Length
= wcslen(Ptr
) + 1;
794 TotalLength
+= Length
;
796 DPRINT("TotalLength: %hu\n", TotalLength
);
799 DeviceNode
->HardwareIDs
.Length
= TotalLength
* sizeof(WCHAR
);
800 DeviceNode
->HardwareIDs
.MaximumLength
= DeviceNode
->HardwareIDs
.Length
+ sizeof(WCHAR
);
801 DeviceNode
->HardwareIDs
.Buffer
= (PWSTR
)IoStatusBlock
.Information
;
805 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
806 RtlInitUnicodeString(&DeviceNode
->HardwareIDs
, NULL
);
809 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
811 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
812 Status
= IopInitiatePnpIrp(
817 if (NT_SUCCESS(Status
))
820 * FIXME: Check for valid characters, if there is invalid characters
824 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
825 DPRINT("Compatible IDs:\n");
828 DPRINT(" %S\n", Ptr
);
829 Length
= wcslen(Ptr
) + 1;
832 TotalLength
+= Length
;
834 DPRINT("TotalLength: %hu\n", TotalLength
);
837 DeviceNode
->CompatibleIDs
.Length
= TotalLength
* sizeof(WCHAR
);
838 DeviceNode
->CompatibleIDs
.MaximumLength
= DeviceNode
->CompatibleIDs
.Length
+ sizeof(WCHAR
);
839 DeviceNode
->CompatibleIDs
.Buffer
= (PWSTR
)IoStatusBlock
.Information
;
843 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
844 RtlInitUnicodeString(&DeviceNode
->CompatibleIDs
, NULL
);
847 Status
= IopQueryCapabilities(DeviceNode
->Pdo
, &DeviceNode
->CapabilityFlags
);
848 if (NT_SUCCESS(Status
))
855 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
857 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
858 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
859 Status
= IopInitiatePnpIrp(
862 IRP_MN_QUERY_DEVICE_TEXT
,
864 if (NT_SUCCESS(Status
))
866 RtlInitUnicodeString(
867 &DeviceNode
->DeviceText
,
868 (PWSTR
)IoStatusBlock
.Information
);
872 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
873 RtlInitUnicodeString(&DeviceNode
->DeviceText
, NULL
);
876 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
878 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
879 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
880 Status
= IopInitiatePnpIrp(
883 IRP_MN_QUERY_DEVICE_TEXT
,
885 if (NT_SUCCESS(Status
))
887 RtlInitUnicodeString(
888 &DeviceNode
->DeviceTextLocation
,
889 (PWSTR
)IoStatusBlock
.Information
);
893 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
894 RtlInitUnicodeString(&DeviceNode
->DeviceTextLocation
, NULL
);
897 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
899 Status
= IopInitiatePnpIrp(
902 IRP_MN_QUERY_BUS_INFORMATION
,
904 if (NT_SUCCESS(Status
))
906 DeviceNode
->BusInformation
=
907 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
911 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
912 DeviceNode
->BusInformation
= NULL
;
915 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
917 Status
= IopInitiatePnpIrp(
920 IRP_MN_QUERY_RESOURCES
,
922 if (NT_SUCCESS(Status
))
924 DeviceNode
->BootResourcesList
=
925 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
926 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
930 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
931 DeviceNode
->BootResourcesList
= NULL
;
934 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
936 Status
= IopInitiatePnpIrp(
939 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
941 if (NT_SUCCESS(Status
))
943 DeviceNode
->ResourceRequirementsList
=
944 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
948 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
949 DeviceNode
->ResourceRequirementsList
= NULL
;
953 * Assemble the instance path for the device
956 wcscpy(InstancePath
, DeviceNode
->DeviceID
.Buffer
);
957 wcscat(InstancePath
, L
"\\");
958 wcscat(InstancePath
, DeviceNode
->InstanceID
.Buffer
);
960 if (!DeviceNode
->CapabilityFlags
->UniqueID
)
962 DPRINT("Instance ID is not unique\n");
963 /* FIXME: Add information from parent bus driver to InstancePath */
966 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
))
968 DPRINT("No resources\n");
969 /* FIXME: Cleanup and disable device */
972 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
975 * Create registry key for the instance id, if it doesn't exist yet
978 KeyBuffer
= ExAllocatePool(
980 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
981 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
982 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
983 IopCreateDeviceKeyPath(KeyBuffer
);
984 ExFreePool(KeyBuffer
);
985 DeviceNode
->Flags
|= DNF_PROCESSED
;
987 return STATUS_SUCCESS
;
991 * IopActionConfigureChildServices
993 * Retrieve configuration for all (direct) child nodes of a parent node.
997 * Pointer to device node.
999 * Pointer to parent node to retrieve child node configuration for.
1002 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1003 * when we reach a device node which is not a direct child of the device
1004 * node for which we configure child services for. Any errors that occur is
1005 * logged instead so that all child services have a chance of beeing
1010 IopActionConfigureChildServices(
1011 PDEVICE_NODE DeviceNode
,
1014 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
1015 PDEVICE_NODE ParentDeviceNode
;
1016 PUNICODE_STRING Service
;
1019 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
1021 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1024 * We are called for the parent too, but we don't need to do special
1025 * handling for this node
1027 if (DeviceNode
== ParentDeviceNode
)
1029 DPRINT("Success\n");
1030 return STATUS_SUCCESS
;
1034 * Make sure this device node is a direct child of the parent device node
1035 * that is given as an argument
1037 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1039 /* Stop the traversal immediately and indicate successful operation */
1041 return STATUS_UNSUCCESSFUL
;
1044 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
1047 * Retrieve configuration from Enum key
1050 Service
= &DeviceNode
->ServiceName
;
1052 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
1053 RtlInitUnicodeString(Service
, NULL
);
1055 QueryTable
[0].Name
= L
"Service";
1056 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
1057 QueryTable
[0].EntryContext
= Service
;
1059 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ENUM
,
1060 DeviceNode
->InstancePath
.Buffer
, QueryTable
, NULL
, NULL
);
1062 if (!NT_SUCCESS(Status
))
1064 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
1065 /* FIXME: Log the error */
1066 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1067 DeviceNode
->InstancePath
.Buffer
, Status
);
1068 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1069 return STATUS_SUCCESS
;
1072 if (Service
->Buffer
== NULL
)
1074 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1075 return STATUS_SUCCESS
;
1078 DPRINT("Got Service %S\n", Service
->Buffer
);
1081 return STATUS_SUCCESS
;
1085 * IopActionInitChildServices
1087 * Initialize the service for all (direct) child nodes of a parent node
1091 * Pointer to device node.
1093 * Pointer to parent node to initialize child node services for.
1095 * Load only driver marked as boot start.
1098 * If the driver image for a service is not loaded and initialized
1099 * it is done here too. We only return a status code indicating an
1100 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1101 * not a direct child of the device node for which we initialize
1102 * child services for. Any errors that occur is logged instead so
1103 * that all child services have a chance of being initialized.
1107 IopActionInitChildServices(
1108 PDEVICE_NODE DeviceNode
,
1110 BOOLEAN BootDrivers
)
1112 PDEVICE_NODE ParentDeviceNode
;
1115 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1118 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1121 * We are called for the parent too, but we don't need to do special
1122 * handling for this node
1124 if (DeviceNode
== ParentDeviceNode
)
1126 DPRINT("Success\n");
1127 return STATUS_SUCCESS
;
1131 * Make sure this device node is a direct child of the parent device node
1132 * that is given as an argument
1135 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1138 * Stop the traversal immediately and indicate unsuccessful operation
1141 return STATUS_UNSUCCESSFUL
;
1145 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1146 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1147 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1149 PMODULE_OBJECT ModuleObject
;
1150 PDRIVER_OBJECT DriverObject
;
1152 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
1153 if (NT_SUCCESS(Status
))
1155 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
, FALSE
, &DriverObject
);
1156 if (NT_SUCCESS(Status
))
1158 /* Attach lower level filter drivers. */
1159 IopAttachFilterDrivers(DeviceNode
, TRUE
);
1160 /* Initialize the function driver for the device node */
1161 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
1162 if (NT_SUCCESS(Status
))
1164 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1165 /* Attach upper level filter drivers. */
1166 IopAttachFilterDrivers(DeviceNode
, FALSE
);
1173 * Don't disable when trying to load only boot drivers
1177 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1178 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1180 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1181 CPRINT("Initialization of service %S failed (Status %x)\n",
1182 DeviceNode
->ServiceName
.Buffer
, Status
);
1186 DPRINT("Service %S is disabled or already initialized\n",
1187 DeviceNode
->ServiceName
.Buffer
);
1190 return STATUS_SUCCESS
;
1194 * IopActionInitAllServices
1196 * Initialize the service for all (direct) child nodes of a parent node. This
1197 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1201 IopActionInitAllServices(
1202 PDEVICE_NODE DeviceNode
,
1205 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1209 * IopActionInitBootServices
1211 * Initialize the boot start services for all (direct) child nodes of a
1212 * parent node. This function just calls IopActionInitChildServices with
1213 * BootDrivers = TRUE.
1217 IopActionInitBootServices(
1218 PDEVICE_NODE DeviceNode
,
1221 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1225 * IopInitializePnpServices
1227 * Initialize services for discovered children
1231 * Top device node to start initializing services.
1234 * When set to TRUE, only drivers marked as boot start will
1235 * be loaded. Otherwise, all drivers will be loaded.
1242 IopInitializePnpServices(
1243 IN PDEVICE_NODE DeviceNode
,
1244 IN BOOLEAN BootDrivers
)
1246 DEVICETREE_TRAVERSE_CONTEXT Context
;
1248 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1252 IopInitDeviceTreeTraverseContext(
1255 IopActionInitBootServices
,
1259 IopInitDeviceTreeTraverseContext(
1262 IopActionInitAllServices
,
1266 return IopTraverseDeviceTree(&Context
);
1271 IopInvalidateDeviceRelations(
1272 IN PDEVICE_NODE DeviceNode
,
1273 IN DEVICE_RELATION_TYPE Type
)
1275 DEVICETREE_TRAVERSE_CONTEXT Context
;
1276 PDEVICE_RELATIONS DeviceRelations
;
1277 IO_STATUS_BLOCK IoStatusBlock
;
1278 PDEVICE_NODE ChildDeviceNode
;
1279 IO_STACK_LOCATION Stack
;
1281 OBJECT_ATTRIBUTES ObjectAttributes
;
1282 UNICODE_STRING LinkName
;
1287 DPRINT("DeviceNode %x\n", DeviceNode
);
1289 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1291 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1293 Status
= IopInitiatePnpIrp(
1296 IRP_MN_QUERY_DEVICE_RELATIONS
,
1298 if (!NT_SUCCESS(Status
))
1300 DPRINT("IopInitiatePnpIrp() failed\n");
1304 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1306 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1308 DPRINT("No PDOs\n");
1309 if (DeviceRelations
)
1311 ExFreePool(DeviceRelations
);
1313 return STATUS_SUCCESS
;
1316 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1319 * Create device nodes for all discovered devices
1322 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1324 Status
= IopCreateDeviceNode(
1326 DeviceRelations
->Objects
[i
],
1328 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1329 if (!NT_SUCCESS(Status
))
1331 DPRINT("No resources\n");
1332 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1333 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1334 ExFreePool(DeviceRelations
);
1335 return STATUS_INSUFFICIENT_RESOURCES
;
1338 ExFreePool(DeviceRelations
);
1341 * Retrieve information about all discovered children from the bus driver
1344 IopInitDeviceTreeTraverseContext(
1347 IopActionInterrogateDeviceStack
,
1350 Status
= IopTraverseDeviceTree(&Context
);
1351 if (!NT_SUCCESS(Status
))
1353 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1358 * Retrieve configuration from the registry for discovered children
1361 IopInitDeviceTreeTraverseContext(
1364 IopActionConfigureChildServices
,
1367 Status
= IopTraverseDeviceTree(&Context
);
1368 if (!NT_SUCCESS(Status
))
1370 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1375 * Get the state of the system boot. If the \\SystemRoot link isn't
1376 * created yet, we will assume that it's possible to load only boot
1380 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
1382 InitializeObjectAttributes(
1389 Status
= NtOpenFile(
1397 BootDrivers
= NT_SUCCESS(Status
) ? FALSE
: TRUE
;
1402 * Initialize services for discovered children. Only boot drivers will
1403 * be loaded from boot driver!
1406 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
1407 if (!NT_SUCCESS(Status
))
1409 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
1413 return STATUS_SUCCESS
;
1423 DPRINT("PnpInit()\n");
1425 KeInitializeSpinLock(&IopDeviceTreeLock
);
1428 * Create root device node
1431 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, FALSE
, NULL
, 0);
1432 if (!NT_SUCCESS(Status
))
1434 CPRINT("IoCreateDriverObject() failed\n");
1435 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1438 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
1440 if (!NT_SUCCESS(Status
))
1442 CPRINT("IoCreateDevice() failed\n");
1443 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1446 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
1447 if (!NT_SUCCESS(Status
))
1449 CPRINT("Insufficient resources\n");
1450 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1453 IopRootDeviceNode
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1454 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1455 IopRootDriverObject
->DriverExtension
->AddDevice(
1456 IopRootDriverObject
,
1457 IopRootDeviceNode
->Pdo
);