1 /* $Id: pnpmgr.c,v 1.26 2004/03/20 17:34:25 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
)
207 IopCreateUnicodeString(
208 PUNICODE_STRING Destination
,
216 RtlInitUnicodeString(Destination
, NULL
);
220 Length
= (wcslen(Source
) + 1) * sizeof(WCHAR
);
222 Destination
->Buffer
= ExAllocatePool(PoolType
, Length
);
224 if (Destination
->Buffer
== NULL
)
229 RtlCopyMemory(Destination
->Buffer
, Source
, Length
);
231 Destination
->MaximumLength
= Length
;
233 Destination
->Length
= Length
- sizeof(WCHAR
);
239 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
243 if (PopSystemPowerDeviceNode
)
245 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
246 *DeviceObject
= PopSystemPowerDeviceNode
->Pdo
;
247 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
249 return STATUS_SUCCESS
;
252 return STATUS_UNSUCCESSFUL
;
255 /**********************************************************************
257 * Creates a device node
260 * ParentNode = Pointer to parent device node
261 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
262 * to have the root device node create one
263 * (eg. for legacy drivers)
264 * DeviceNode = Pointer to storage for created device node
270 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
271 PDEVICE_OBJECT PhysicalDeviceObject
,
272 PDEVICE_NODE
*DeviceNode
)
278 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
279 ParentNode
, PhysicalDeviceObject
);
281 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
284 return STATUS_INSUFFICIENT_RESOURCES
;
287 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
289 if (!PhysicalDeviceObject
)
291 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
292 if (!NT_SUCCESS(Status
))
298 /* This is for drivers passed on the command line to ntoskrnl.exe */
299 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
300 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
303 Node
->Pdo
= PhysicalDeviceObject
;
305 PhysicalDeviceObject
->DeviceObjectExtension
->DeviceNode
= Node
;
309 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
310 Node
->Parent
= ParentNode
;
311 Node
->NextSibling
= ParentNode
->Child
;
312 if (ParentNode
->Child
!= NULL
)
314 ParentNode
->Child
->PrevSibling
= Node
;
316 ParentNode
->Child
= Node
;
317 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
322 return STATUS_SUCCESS
;
326 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
330 /* All children must be deleted before a parent is deleted */
331 assert(!DeviceNode
->Child
);
333 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
335 assert(DeviceNode
->Pdo
);
337 ObDereferenceObject(DeviceNode
->Pdo
);
339 /* Unlink from parent if it exists */
341 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
343 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
346 /* Unlink from sibling list */
348 if (DeviceNode
->PrevSibling
)
350 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
353 if (DeviceNode
->NextSibling
)
355 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
358 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
360 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
362 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
364 if (DeviceNode
->CapabilityFlags
)
366 ExFreePool(DeviceNode
->CapabilityFlags
);
369 if (DeviceNode
->CmResourceList
)
371 ExFreePool(DeviceNode
->CmResourceList
);
374 if (DeviceNode
->BootResourcesList
)
376 ExFreePool(DeviceNode
->BootResourcesList
);
379 if (DeviceNode
->ResourceRequirementsList
)
381 ExFreePool(DeviceNode
->ResourceRequirementsList
);
384 RtlFreeUnicodeString(&DeviceNode
->DeviceID
);
386 RtlFreeUnicodeString(&DeviceNode
->InstanceID
);
388 RtlFreeUnicodeString(&DeviceNode
->HardwareIDs
);
390 RtlFreeUnicodeString(&DeviceNode
->CompatibleIDs
);
392 RtlFreeUnicodeString(&DeviceNode
->DeviceText
);
394 RtlFreeUnicodeString(&DeviceNode
->DeviceTextLocation
);
396 if (DeviceNode
->BusInformation
)
398 ExFreePool(DeviceNode
->BusInformation
);
401 ExFreePool(DeviceNode
);
403 return STATUS_SUCCESS
;
408 PDEVICE_OBJECT DeviceObject
,
409 PIO_STATUS_BLOCK IoStatusBlock
,
411 PIO_STACK_LOCATION Stack OPTIONAL
)
413 PDEVICE_OBJECT TopDeviceObject
;
414 PIO_STACK_LOCATION IrpSp
;
419 /* Always call the top of the device stack */
420 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
427 /* PNP IRPs are always initialized with a status code of
428 STATUS_NOT_IMPLEMENTED */
429 IoStatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
430 IoStatusBlock
->Information
= 0;
432 Irp
= IoBuildSynchronousFsdRequest(
441 IrpSp
= IoGetNextIrpStackLocation(Irp
);
442 IrpSp
->MinorFunction
= MinorFunction
;
449 sizeof(Stack
->Parameters
));
452 Status
= IoCallDriver(TopDeviceObject
, Irp
);
453 if (Status
== STATUS_PENDING
)
455 KeWaitForSingleObject(
461 Status
= IoStatusBlock
->Status
;
464 ObDereferenceObject(TopDeviceObject
);
471 IopQueryCapabilities(
473 PDEVICE_CAPABILITIES
*Capabilities
)
475 IO_STATUS_BLOCK IoStatusBlock
;
476 PDEVICE_CAPABILITIES Caps
;
477 IO_STACK_LOCATION Stack
;
480 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
482 *Capabilities
= NULL
;
484 Caps
= ExAllocatePool(PagedPool
, sizeof(DEVICE_CAPABILITIES
));
487 return STATUS_INSUFFICIENT_RESOURCES
;
490 RtlZeroMemory(Caps
, sizeof(DEVICE_CAPABILITIES
));
491 Caps
->Size
= sizeof(DEVICE_CAPABILITIES
);
496 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= Caps
;
498 Status
= IopInitiatePnpIrp(
501 IRP_MN_QUERY_CAPABILITIES
,
503 if (NT_SUCCESS(Status
))
505 *Capabilities
= Caps
;
509 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
517 IopTraverseDeviceTreeNode(
518 PDEVICETREE_TRAVERSE_CONTEXT Context
)
520 PDEVICE_NODE ParentDeviceNode
;
521 PDEVICE_NODE ChildDeviceNode
;
524 /* Copy context data so we don't overwrite it in subsequent calls to this function */
525 ParentDeviceNode
= Context
->DeviceNode
;
527 /* Call the action routine */
528 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
529 if (!NT_SUCCESS(Status
))
534 /* Traversal of all children nodes */
535 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
536 ChildDeviceNode
!= NULL
;
537 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
539 /* Pass the current device node to the action routine */
540 Context
->DeviceNode
= ChildDeviceNode
;
542 Status
= IopTraverseDeviceTreeNode(Context
);
543 if (!NT_SUCCESS(Status
))
554 IopTraverseDeviceTree(
555 PDEVICETREE_TRAVERSE_CONTEXT Context
)
559 DPRINT("Context %x\n", Context
);
561 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
562 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
564 /* Start from the specified device node */
565 Context
->DeviceNode
= Context
->FirstDeviceNode
;
567 /* Recursively traverse the device tree */
568 Status
= IopTraverseDeviceTreeNode(Context
);
569 if (Status
== STATUS_UNSUCCESSFUL
)
571 /* The action routine just wanted to terminate the traversal with status
572 code STATUS_SUCCESS */
573 Status
= STATUS_SUCCESS
;
581 IopCreateDeviceKeyPath(PWSTR Path
)
583 OBJECT_ATTRIBUTES ObjectAttributes
;
584 WCHAR KeyBuffer
[MAX_PATH
];
585 UNICODE_STRING KeyName
;
591 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
593 return STATUS_INVALID_PARAMETER
;
596 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
597 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
599 /* Skip \\Registry\\ */
600 Current
= KeyName
.Buffer
;
601 Current
= wcschr (Current
, '\\') + 1;
602 Current
= wcschr (Current
, '\\') + 1;
606 Next
= wcschr (Current
, '\\');
616 InitializeObjectAttributes (&ObjectAttributes
,
618 OBJ_CASE_INSENSITIVE
,
622 DPRINT("Create '%S'\n", KeyName
.Buffer
);
624 Status
= NtCreateKey (&KeyHandle
,
631 if (!NT_SUCCESS (Status
))
633 DPRINT ("NtCreateKey() failed with status %x\n", Status
);
646 while (Next
!= NULL
);
648 return STATUS_SUCCESS
;
653 * IopActionInterrogateDeviceStack
655 * Retrieve information for all (direct) child nodes of a parent node.
659 * Pointer to device node.
661 * Pointer to parent node to retrieve child node information for.
664 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
665 * when we reach a device node which is not a direct child of the device
666 * node for which we retrieve information of child nodes for. Any errors
667 * that occur is logged instead so that all child services have a chance
668 * of being interrogated.
672 IopActionInterrogateDeviceStack(
673 PDEVICE_NODE DeviceNode
,
676 IO_STATUS_BLOCK IoStatusBlock
;
677 PDEVICE_NODE ParentDeviceNode
;
678 WCHAR InstancePath
[MAX_PATH
];
679 IO_STACK_LOCATION Stack
;
683 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
684 DPRINT("PDO %x\n", DeviceNode
->Pdo
);
686 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
689 * We are called for the parent too, but we don't need to do special
690 * handling for this node
693 if (DeviceNode
== ParentDeviceNode
)
696 return STATUS_SUCCESS
;
700 * Make sure this device node is a direct child of the parent device node
701 * that is given as an argument
704 if (DeviceNode
->Parent
!= ParentDeviceNode
)
706 /* Stop the traversal immediately and indicate successful operation */
708 return STATUS_UNSUCCESSFUL
;
712 * FIXME: For critical errors, cleanup and disable device, but always
713 * return STATUS_SUCCESS.
716 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
718 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
719 Status
= IopInitiatePnpIrp(
724 if (NT_SUCCESS(Status
))
726 RtlInitUnicodeString(
727 &DeviceNode
->DeviceID
,
728 (LPWSTR
)IoStatusBlock
.Information
);
731 * FIXME: Check for valid characters, if there is invalid characters
737 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
738 RtlInitUnicodeString(&DeviceNode
->DeviceID
, NULL
);
741 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
743 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
744 Status
= IopInitiatePnpIrp(
749 if (NT_SUCCESS(Status
))
751 RtlInitUnicodeString(
752 &DeviceNode
->InstanceID
,
753 (LPWSTR
)IoStatusBlock
.Information
);
756 * FIXME: Check for valid characters, if there is invalid characters
762 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
763 RtlInitUnicodeString(&DeviceNode
->InstanceID
, NULL
);
766 /* FIXME: SEND IRP_QUERY_ID.BusQueryHardwareIDs */
767 /* FIXME: SEND IRP_QUERY_ID.BusQueryCompatibleIDs */
769 Status
= IopQueryCapabilities(DeviceNode
->Pdo
, &DeviceNode
->CapabilityFlags
);
770 if (NT_SUCCESS(Status
))
777 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
779 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
780 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; /* FIXME */
781 Status
= IopInitiatePnpIrp(
784 IRP_MN_QUERY_DEVICE_TEXT
,
786 if (NT_SUCCESS(Status
))
788 RtlInitUnicodeString(
789 &DeviceNode
->DeviceText
,
790 (LPWSTR
)IoStatusBlock
.Information
);
794 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
795 RtlInitUnicodeString(&DeviceNode
->DeviceText
, NULL
);
798 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
800 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
801 Stack
.Parameters
.QueryDeviceText
.LocaleId
= 0; // FIXME
802 Status
= IopInitiatePnpIrp(
805 IRP_MN_QUERY_DEVICE_TEXT
,
807 if (NT_SUCCESS(Status
))
809 RtlInitUnicodeString(
810 &DeviceNode
->DeviceTextLocation
,
811 (LPWSTR
)IoStatusBlock
.Information
);
815 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
816 RtlInitUnicodeString(&DeviceNode
->DeviceTextLocation
, NULL
);
819 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
821 Status
= IopInitiatePnpIrp(
824 IRP_MN_QUERY_BUS_INFORMATION
,
826 if (NT_SUCCESS(Status
))
828 DeviceNode
->BusInformation
=
829 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
833 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
834 DeviceNode
->BusInformation
= NULL
;
837 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
839 Status
= IopInitiatePnpIrp(
842 IRP_MN_QUERY_RESOURCES
,
844 if (NT_SUCCESS(Status
))
846 DeviceNode
->BootResourcesList
=
847 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
848 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
852 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
853 DeviceNode
->BootResourcesList
= NULL
;
856 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
858 Status
= IopInitiatePnpIrp(
861 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
863 if (NT_SUCCESS(Status
))
865 DeviceNode
->ResourceRequirementsList
=
866 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
870 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
871 DeviceNode
->ResourceRequirementsList
= NULL
;
875 * Assemble the instance path for the device
878 wcscpy(InstancePath
, DeviceNode
->DeviceID
.Buffer
);
879 wcscat(InstancePath
, L
"\\");
880 wcscat(InstancePath
, DeviceNode
->InstanceID
.Buffer
);
882 if (!DeviceNode
->CapabilityFlags
->UniqueID
)
884 DPRINT("Instance ID is not unique\n");
885 /* FIXME: Add information from parent bus driver to InstancePath */
888 if (!IopCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
, PagedPool
))
890 DPRINT("No resources\n");
891 /* FIXME: Cleanup and disable device */
894 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
897 * Create registry key for the instance id, if it doesn't exist yet
900 KeyBuffer
= ExAllocatePool(PagedPool
, (49 + DeviceNode
->InstancePath
.Length
) * sizeof(WCHAR
));
901 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
902 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
903 IopCreateDeviceKeyPath(KeyBuffer
);
904 ExFreePool(KeyBuffer
);
905 DeviceNode
->Flags
|= DNF_PROCESSED
;
907 return STATUS_SUCCESS
;
911 * IopActionConfigureChildServices
913 * Retrieve configuration for all (direct) child nodes of a parent node.
917 * Pointer to device node.
919 * Pointer to parent node to retrieve child node configuration for.
922 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
923 * when we reach a device node which is not a direct child of the device
924 * node for which we configure child services for. Any errors that occur is
925 * logged instead so that all child services have a chance of beeing
930 IopActionConfigureChildServices(
931 PDEVICE_NODE DeviceNode
,
934 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
935 PDEVICE_NODE ParentDeviceNode
;
936 PUNICODE_STRING Service
;
939 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
941 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
944 * We are called for the parent too, but we don't need to do special
945 * handling for this node
947 if (DeviceNode
== ParentDeviceNode
)
950 return STATUS_SUCCESS
;
954 * Make sure this device node is a direct child of the parent device node
955 * that is given as an argument
957 if (DeviceNode
->Parent
!= ParentDeviceNode
)
959 /* Stop the traversal immediately and indicate successful operation */
961 return STATUS_UNSUCCESSFUL
;
964 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
967 * Retrieve configuration from Enum key
970 Service
= &DeviceNode
->ServiceName
;
972 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
973 RtlInitUnicodeString(Service
, NULL
);
975 QueryTable
[0].Name
= L
"Service";
976 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
977 QueryTable
[0].EntryContext
= Service
;
979 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ENUM
,
980 DeviceNode
->InstancePath
.Buffer
, QueryTable
, NULL
, NULL
);
982 if (!NT_SUCCESS(Status
))
984 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
985 /* FIXME: Log the error */
986 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
987 DeviceNode
->InstancePath
.Buffer
, Status
);
988 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
989 return STATUS_SUCCESS
;
992 if (Service
->Buffer
== NULL
)
994 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
995 return STATUS_SUCCESS
;
998 DPRINT("Got Service %S\n", Service
->Buffer
);
1001 return STATUS_SUCCESS
;
1005 * IopActionInitChildServices
1007 * Initialize the service for all (direct) child nodes of a parent node
1011 * Pointer to device node.
1013 * Pointer to parent node to initialize child node services for.
1015 * Load only driver marked as boot start.
1018 * If the driver image for a service is not loaded and initialized
1019 * it is done here too. We only return a status code indicating an
1020 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1021 * not a direct child of the device node for which we initialize
1022 * child services for. Any errors that occur is logged instead so
1023 * that all child services have a chance of being initialized.
1027 IopActionInitChildServices(
1028 PDEVICE_NODE DeviceNode
,
1030 BOOLEAN BootDrivers
)
1032 PDEVICE_NODE ParentDeviceNode
;
1035 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
1038 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1041 * We are called for the parent too, but we don't need to do special
1042 * handling for this node
1044 if (DeviceNode
== ParentDeviceNode
)
1046 DPRINT("Success\n");
1047 return STATUS_SUCCESS
;
1051 * Make sure this device node is a direct child of the parent device node
1052 * that is given as an argument
1055 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1058 * Stop the traversal immediately and indicate unsuccessful operation
1061 return STATUS_UNSUCCESSFUL
;
1065 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
1066 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
1067 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
1069 Status
= IopInitializeDeviceNodeService(DeviceNode
, BootDrivers
);
1070 if (NT_SUCCESS(Status
))
1072 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
1076 * Don't disable when trying to load only boot drivers
1080 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
1081 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
1083 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1084 CPRINT("Initialization of service %S failed (Status %x)\n",
1085 DeviceNode
->ServiceName
.Buffer
, Status
);
1089 DPRINT("Service %S is disabled or already initialized\n",
1090 DeviceNode
->ServiceName
.Buffer
);
1093 return STATUS_SUCCESS
;
1097 * IopActionInitAllServices
1099 * Initialize the service for all (direct) child nodes of a parent node. This
1100 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1104 IopActionInitAllServices(
1105 PDEVICE_NODE DeviceNode
,
1108 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
1112 * IopActionInitBootServices
1114 * Initialize the boot start services for all (direct) child nodes of a
1115 * parent node. This function just calls IopActionInitChildServices with
1116 * BootDrivers = TRUE.
1120 IopActionInitBootServices(
1121 PDEVICE_NODE DeviceNode
,
1124 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
1128 * IopInitializePnpServices
1130 * Initialize services for discovered children
1134 * Top device node to start initializing services.
1136 * When set to TRUE, only drivers marked as boot start will
1137 * be loaded. Otherwise, all drivers will be loaded.
1144 IopInitializePnpServices(
1145 IN PDEVICE_NODE DeviceNode
,
1146 IN BOOLEAN BootDrivers
)
1148 DEVICETREE_TRAVERSE_CONTEXT Context
;
1150 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
1154 IopInitDeviceTreeTraverseContext(
1157 IopActionInitBootServices
,
1161 IopInitDeviceTreeTraverseContext(
1164 IopActionInitAllServices
,
1168 return IopTraverseDeviceTree(&Context
);
1173 IopInvalidateDeviceRelations(
1174 IN PDEVICE_NODE DeviceNode
,
1175 IN DEVICE_RELATION_TYPE Type
,
1176 IN BOOLEAN BootDriver
)
1178 DEVICETREE_TRAVERSE_CONTEXT Context
;
1179 PDEVICE_RELATIONS DeviceRelations
;
1180 IO_STATUS_BLOCK IoStatusBlock
;
1181 PDEVICE_NODE ChildDeviceNode
;
1182 IO_STACK_LOCATION Stack
;
1186 DPRINT("DeviceNode %x\n", DeviceNode
);
1188 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1190 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
1192 Status
= IopInitiatePnpIrp(
1195 IRP_MN_QUERY_DEVICE_RELATIONS
,
1197 if (!NT_SUCCESS(Status
))
1199 DPRINT("IopInitiatePnpIrp() failed\n");
1203 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
1205 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
1207 DPRINT("No PDOs\n");
1208 if (DeviceRelations
)
1210 ExFreePool(DeviceRelations
);
1212 return STATUS_SUCCESS
;
1215 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
1218 * Create device nodes for all discovered devices
1221 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1223 Status
= IopCreateDeviceNode(
1225 DeviceRelations
->Objects
[i
],
1227 DeviceNode
->Flags
|= DNF_ENUMERATED
;
1228 if (!NT_SUCCESS(Status
))
1230 DPRINT("No resources\n");
1231 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
1232 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
1233 ExFreePool(DeviceRelations
);
1234 return STATUS_INSUFFICIENT_RESOURCES
;
1237 ExFreePool(DeviceRelations
);
1240 * Retrieve information about all discovered children from the bus driver
1243 IopInitDeviceTreeTraverseContext(
1246 IopActionInterrogateDeviceStack
,
1249 Status
= IopTraverseDeviceTree(&Context
);
1250 if (!NT_SUCCESS(Status
))
1252 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1257 * Retrieve configuration from the registry for discovered children
1260 IopInitDeviceTreeTraverseContext(
1263 IopActionConfigureChildServices
,
1266 Status
= IopTraverseDeviceTree(&Context
);
1267 if (!NT_SUCCESS(Status
))
1269 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
1274 * Initialize services for discovered children. Only boot drivers will
1275 * be loaded from boot driver!
1278 Status
= IopInitializePnpServices(DeviceNode
, BootDriver
);
1279 if (!NT_SUCCESS(Status
))
1281 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
1285 return STATUS_SUCCESS
;
1294 DPRINT("PnpInit()\n");
1296 KeInitializeSpinLock(&IopDeviceTreeLock
);
1299 * Create root device node
1302 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, FALSE
, NULL
, 0);
1303 if (!NT_SUCCESS(Status
))
1305 CPRINT("IoCreateDriverObject() failed\n");
1306 KEBUGCHECK(PHASE1_INITIALIZATION_FAILED
);
1309 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
1311 if (!NT_SUCCESS(Status
))
1313 CPRINT("IoCreateDevice() failed\n");
1314 KEBUGCHECK(PHASE1_INITIALIZATION_FAILED
);
1317 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
1318 if (!NT_SUCCESS(Status
))
1320 CPRINT("Insufficient resources\n");
1321 KEBUGCHECK(PHASE1_INITIALIZATION_FAILED
);
1323 IopRootDeviceNode
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
1324 IopRootDeviceNode
->DriverObject
= IopRootDriverObject
;
1325 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
1326 IopRootDriverObject
->DriverExtension
->AddDevice(
1327 IopRootDriverObject
,
1328 IopRootDeviceNode
->Pdo
);