2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/pnpmgr.c
5 * PURPOSE: Initializes the PnP manager
7 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * Hervé Poussineau (hpoussin@reactos.org)
11 /* INCLUDES ******************************************************************/
16 #include <internal/debug.h>
20 /* GLOBALS *******************************************************************/
22 PDEVICE_NODE IopRootDeviceNode
;
23 KSPIN_LOCK IopDeviceTreeLock
;
24 ERESOURCE PpRegistryDeviceResource
;
25 KGUARDED_MUTEX PpDeviceReferenceTableLock
;
26 RTL_AVL_TABLE PpDeviceReferenceTable
;
28 extern ULONG ExpInitializationPhase
;
30 /* DATA **********************************************************************/
32 PDRIVER_OBJECT IopRootDriverObject
;
33 PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList
= NULL
;
35 #if defined (ALLOC_PRAGMA)
36 #pragma alloc_text(INIT, PnpInit)
37 #pragma alloc_text(INIT, PnpInit2)
40 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
42 PDEVICE_OBJECT DeviceObject
;
43 DEVICE_RELATION_TYPE Type
;
44 PIO_WORKITEM WorkItem
;
45 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
49 IoSynchronousInvalidateDeviceRelations(
50 IN PDEVICE_OBJECT DeviceObject
,
51 IN DEVICE_RELATION_TYPE Type
);
54 /* FUNCTIONS *****************************************************************/
57 IopAssignDeviceResources(
58 IN PDEVICE_NODE DeviceNode
,
59 OUT ULONG
*pRequiredSize
);
61 IopTranslateDeviceResources(
62 IN PDEVICE_NODE DeviceNode
,
63 IN ULONG RequiredSize
);
67 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
69 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
74 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
75 PDRIVER_OBJECT DriverObject
)
80 if (!DriverObject
->DriverExtension
->AddDevice
)
81 return STATUS_SUCCESS
;
83 /* This is a Plug and Play driver */
84 DPRINT("Plug and Play driver found\n");
85 ASSERT(DeviceNode
->PhysicalDeviceObject
);
87 /* Check if this plug-and-play driver is used as a legacy one for this device node */
88 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
90 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
91 return STATUS_SUCCESS
;
94 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
95 &DriverObject
->DriverName
,
96 &DeviceNode
->InstancePath
);
97 Status
= DriverObject
->DriverExtension
->AddDevice(
98 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
99 if (!NT_SUCCESS(Status
))
101 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
105 /* Check if driver added a FDO above the PDO */
106 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
107 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
109 /* FIXME: What do we do? Unload the driver or just disable the device? */
110 DPRINT1("An FDO was not attached\n");
111 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
112 return STATUS_UNSUCCESSFUL
;
115 /* Check if we have a ACPI device (needed for power management) */
116 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
118 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
120 /* There can be only one system power device */
121 if (!SystemPowerDeviceNodeCreated
)
123 PopSystemPowerDeviceNode
= DeviceNode
;
124 ObReferenceObject(PopSystemPowerDeviceNode
);
125 SystemPowerDeviceNodeCreated
= TRUE
;
129 ObDereferenceObject(Fdo
);
131 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
132 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
134 return STATUS_SUCCESS
;
139 PDEVICE_NODE DeviceNode
)
141 IO_STATUS_BLOCK IoStatusBlock
;
142 IO_STACK_LOCATION Stack
;
143 ULONG RequiredLength
;
147 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
149 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
150 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
151 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
152 Status
= IopInitiatePnpIrp(
155 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
157 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
159 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
162 DeviceNode
->ResourceRequirements
= Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
164 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
165 if (NT_SUCCESS(Status
))
167 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
168 if (NT_SUCCESS(Status
))
170 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
174 DPRINT("IopTranslateDeviceResources() failed (Status 0x08lx)\n", Status
);
179 DPRINT("IopAssignDeviceResources() failed (Status 0x08lx)\n", Status
);
181 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
183 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
184 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
185 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
188 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and
189 * actually _depend_ on this!. This is because NT will lock the Device Node
190 * with an ERESOURCE, which of course requires APCs to be disabled.
192 KeEnterCriticalRegion();
194 Status
= IopInitiatePnpIrp(
200 KeLeaveCriticalRegion();
202 if (!NT_SUCCESS(Status
))
204 DPRINT("IopInitiatePnpIrp() failed\n");
208 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
210 DPRINT("Device needs enumeration, invalidating bus relations\n");
211 /* Invalidate device relations synchronously
212 (otherwise there will be dirty read of DeviceNode) */
213 IoSynchronousInvalidateDeviceRelations(DeviceNode
->PhysicalDeviceObject
, BusRelations
);
214 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
218 ObDereferenceObject(Fdo
);
220 if (NT_SUCCESS(Status
))
221 DeviceNode
->Flags
|= DN_STARTED
;
228 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
229 PDEVICE_CAPABILITIES DeviceCaps
)
231 IO_STATUS_BLOCK StatusBlock
;
232 IO_STACK_LOCATION Stack
;
234 /* Set up the Header */
235 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
236 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
237 DeviceCaps
->Version
= 1;
238 DeviceCaps
->Address
= -1;
239 DeviceCaps
->UINumber
= -1;
241 /* Set up the Stack */
242 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
243 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
246 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
248 IRP_MN_QUERY_CAPABILITIES
,
253 IopAsynchronousInvalidateDeviceRelations(
254 IN PDEVICE_OBJECT DeviceObject
,
255 IN PVOID InvalidateContext
)
257 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
259 IoSynchronousInvalidateDeviceRelations(
263 ObDereferenceObject(Data
->WorkItem
);
264 IoFreeWorkItem(Data
->WorkItem
);
273 IoInvalidateDeviceRelations(
274 IN PDEVICE_OBJECT DeviceObject
,
275 IN DEVICE_RELATION_TYPE Type
)
277 PIO_WORKITEM WorkItem
;
278 PINVALIDATE_DEVICE_RELATION_DATA Data
;
280 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
283 WorkItem
= IoAllocateWorkItem(DeviceObject
);
290 ObReferenceObject(DeviceObject
);
291 Data
->DeviceObject
= DeviceObject
;
293 Data
->WorkItem
= WorkItem
;
297 IopAsynchronousInvalidateDeviceRelations
,
307 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
308 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
309 IN ULONG BufferLength
,
310 OUT PVOID PropertyBuffer
,
311 OUT PULONG ResultLength
)
313 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
314 DEVICE_CAPABILITIES DeviceCaps
;
320 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
322 if (DeviceNode
== NULL
)
323 return STATUS_INVALID_DEVICE_REQUEST
;
325 switch (DeviceProperty
)
327 case DevicePropertyBusNumber
:
328 Length
= sizeof(ULONG
);
329 Data
= &DeviceNode
->ChildBusNumber
;
332 /* Complete, untested */
333 case DevicePropertyBusTypeGuid
:
335 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
336 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
338 /* Return the GUID */
339 *ResultLength
= sizeof(GUID
);
341 /* Check if the buffer given was large enough */
342 if (BufferLength
< *ResultLength
)
344 return STATUS_BUFFER_TOO_SMALL
;
348 RtlCopyMemory(PropertyBuffer
,
349 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
351 return STATUS_SUCCESS
;
355 return STATUS_OBJECT_NAME_NOT_FOUND
;
359 case DevicePropertyLegacyBusType
:
360 Length
= sizeof(INTERFACE_TYPE
);
361 Data
= &DeviceNode
->ChildInterfaceType
;
364 case DevicePropertyAddress
:
365 /* Query the device caps */
366 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
367 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
370 *ResultLength
= sizeof(ULONG
);
372 /* Check if the buffer given was large enough */
373 if (BufferLength
< *ResultLength
)
375 return STATUS_BUFFER_TOO_SMALL
;
379 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
380 return STATUS_SUCCESS
;
384 return STATUS_OBJECT_NAME_NOT_FOUND
;
388 // case DevicePropertyUINumber:
389 // if (DeviceNode->CapabilityFlags == NULL)
390 // return STATUS_INVALID_DEVICE_REQUEST;
391 // Length = sizeof(ULONG);
392 // Data = &DeviceNode->CapabilityFlags->UINumber;
395 case DevicePropertyClassName
:
396 case DevicePropertyClassGuid
:
397 case DevicePropertyDriverKeyName
:
398 case DevicePropertyManufacturer
:
399 case DevicePropertyFriendlyName
:
400 case DevicePropertyHardwareID
:
401 case DevicePropertyCompatibleIDs
:
402 case DevicePropertyDeviceDescription
:
403 case DevicePropertyLocationInformation
:
404 case DevicePropertyUINumber
:
406 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
407 UNICODE_STRING KeyName
, ValueName
;
408 OBJECT_ATTRIBUTES ObjectAttributes
;
409 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
410 ULONG ValueInformationLength
;
414 switch (DeviceProperty
)
416 case DevicePropertyClassName
:
417 RegistryPropertyName
= L
"Class"; break;
418 case DevicePropertyClassGuid
:
419 RegistryPropertyName
= L
"ClassGuid"; break;
420 case DevicePropertyDriverKeyName
:
421 RegistryPropertyName
= L
"Driver"; break;
422 case DevicePropertyManufacturer
:
423 RegistryPropertyName
= L
"Mfg"; break;
424 case DevicePropertyFriendlyName
:
425 RegistryPropertyName
= L
"FriendlyName"; break;
426 case DevicePropertyHardwareID
:
427 RegistryPropertyName
= L
"HardwareID"; break;
428 case DevicePropertyCompatibleIDs
:
429 RegistryPropertyName
= L
"CompatibleIDs"; break;
430 case DevicePropertyDeviceDescription
:
431 RegistryPropertyName
= L
"DeviceDesc"; break;
432 case DevicePropertyLocationInformation
:
433 RegistryPropertyName
= L
"LocationInformation"; break;
434 case DevicePropertyUINumber
:
435 RegistryPropertyName
= L
"UINumber"; break;
437 RegistryPropertyName
= NULL
; break;
440 KeyNameBuffer
= ExAllocatePool(PagedPool
,
441 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
443 DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer
, RegistryPropertyName
);
445 if (KeyNameBuffer
== NULL
)
446 return STATUS_INSUFFICIENT_RESOURCES
;
448 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
449 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
450 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
451 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
452 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
454 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
455 ExFreePool(KeyNameBuffer
);
456 if (!NT_SUCCESS(Status
))
459 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
460 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
461 Data
[0]) + BufferLength
;
462 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
463 if (ValueInformation
== NULL
)
466 return STATUS_INSUFFICIENT_RESOURCES
;
469 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
470 KeyValuePartialInformation
, ValueInformation
,
471 ValueInformationLength
,
472 &ValueInformationLength
);
473 *ResultLength
= ValueInformation
->DataLength
;
476 if (!NT_SUCCESS(Status
))
478 ExFreePool(ValueInformation
);
479 if (Status
== STATUS_BUFFER_OVERFLOW
)
480 return STATUS_BUFFER_TOO_SMALL
;
485 /* FIXME: Verify the value (NULL-terminated, correct format). */
487 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
488 ValueInformation
->DataLength
);
489 ExFreePool(ValueInformation
);
491 return STATUS_SUCCESS
;
494 case DevicePropertyBootConfiguration
:
496 if (DeviceNode
->BootResources
->Count
!= 0)
498 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
500 Data
= &DeviceNode
->BootResources
;
503 /* FIXME: use a translated boot configuration instead */
504 case DevicePropertyBootConfigurationTranslated
:
506 if (DeviceNode
->BootResources
->Count
!= 0)
508 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
510 Data
= &DeviceNode
->BootResources
;
513 case DevicePropertyEnumeratorName
:
514 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
517 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
518 Data
= DeviceNode
->InstancePath
.Buffer
;
527 case DevicePropertyPhysicalDeviceObjectName
:
528 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
529 Data
= DeviceNode
->InstancePath
.Buffer
;
533 return STATUS_INVALID_PARAMETER_2
;
536 *ResultLength
= Length
;
537 if (BufferLength
< Length
)
538 return STATUS_BUFFER_TOO_SMALL
;
539 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
541 /* Terminate the string */
542 if (DeviceProperty
== DevicePropertyEnumeratorName
543 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
545 Ptr
= (PWSTR
)PropertyBuffer
;
546 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
549 return STATUS_SUCCESS
;
557 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
563 * @name IoOpenDeviceRegistryKey
565 * Open a registry key unique for a specified driver or device instance.
567 * @param DeviceObject Device to get the registry key for.
568 * @param DevInstKeyType Type of the key to return.
569 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
570 * @param DevInstRegKey Handle to the opened registry key on
579 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
580 IN ULONG DevInstKeyType
,
581 IN ACCESS_MASK DesiredAccess
,
582 OUT PHANDLE DevInstRegKey
)
584 static WCHAR RootKeyName
[] =
585 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
586 static WCHAR ProfileKeyName
[] =
587 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
588 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
589 static WCHAR EnumKeyName
[] = L
"Enum\\";
590 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
592 LPWSTR KeyNameBuffer
;
593 UNICODE_STRING KeyName
;
594 ULONG DriverKeyLength
;
595 OBJECT_ATTRIBUTES ObjectAttributes
;
596 PDEVICE_NODE DeviceNode
= NULL
;
599 DPRINT("IoOpenDeviceRegistryKey() called\n");
601 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
603 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
604 return STATUS_INVALID_PARAMETER
;
608 * Calculate the length of the base key name. This is the full
609 * name for driver key or the name excluding "Device Parameters"
610 * subkey for device key.
613 KeyNameLength
= sizeof(RootKeyName
);
614 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
615 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
616 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
618 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
619 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
620 0, NULL
, &DriverKeyLength
);
621 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
623 KeyNameLength
+= DriverKeyLength
;
627 DeviceNode
= IopGetDeviceNode(DeviceObject
);
628 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
629 DeviceNode
->InstancePath
.Length
;
633 * Now allocate the buffer for the key name...
636 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
637 if (KeyNameBuffer
== NULL
)
638 return STATUS_INSUFFICIENT_RESOURCES
;
641 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
642 KeyName
.Buffer
= KeyNameBuffer
;
645 * ...and build the key name.
648 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
649 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
651 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
652 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
654 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
656 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
657 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
658 DriverKeyLength
, KeyNameBuffer
+
659 (KeyName
.Length
/ sizeof(WCHAR
)),
661 if (!NT_SUCCESS(Status
))
663 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
664 ExFreePool(KeyNameBuffer
);
667 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
671 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
672 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
673 if (DeviceNode
->InstancePath
.Length
== 0)
675 ExFreePool(KeyNameBuffer
);
684 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
685 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
686 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
687 if (!NT_SUCCESS(Status
))
689 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
690 ExFreePool(KeyNameBuffer
);
693 ExFreePool(KeyNameBuffer
);
696 * For driver key we're done now.
699 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
703 * Let's go further. For device key we must open "Device Parameters"
704 * subkey and create it if it doesn't exist yet.
707 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
708 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
709 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
710 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
711 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
712 ZwClose(ObjectAttributes
.RootDirectory
);
722 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
729 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
733 if (PopSystemPowerDeviceNode
)
735 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
736 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
737 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
739 return STATUS_SUCCESS
;
742 return STATUS_UNSUCCESSFUL
;
747 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
749 USHORT i
= 0, FoundIndex
= 0xFFFF;
753 /* Acquire the lock */
754 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
756 /* Loop all entries */
757 while (i
< IopBusTypeGuidList
->GuidCount
)
759 /* Try to find a match */
760 if (RtlCompareMemory(BusTypeGuid
,
761 &IopBusTypeGuidList
->Guids
[i
],
762 sizeof(GUID
)) == sizeof(GUID
))
771 /* Check if we have to grow the list */
772 if (IopBusTypeGuidList
->GuidCount
)
774 /* Calculate the new size */
775 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
776 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
778 /* Allocate the new copy */
779 NewList
= ExAllocatePool(PagedPool
, NewSize
);
781 /* Now copy them, decrease the size too */
782 NewSize
-= sizeof(GUID
);
783 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
785 /* Free the old list */
786 ExFreePool(IopBusTypeGuidList
);
788 /* Use the new buffer */
789 IopBusTypeGuidList
= NewList
;
792 /* Copy the new GUID */
793 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
797 /* The new entry is the index */
798 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
799 IopBusTypeGuidList
->GuidCount
++;
802 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
808 * Creates a device node
811 * ParentNode = Pointer to parent device node
812 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
813 * to have the root device node create one
814 * (eg. for legacy drivers)
815 * DeviceNode = Pointer to storage for created device node
821 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
822 PDEVICE_OBJECT PhysicalDeviceObject
,
823 PUNICODE_STRING ServiceName
,
824 PDEVICE_NODE
*DeviceNode
)
830 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
831 ParentNode
, PhysicalDeviceObject
, ServiceName
);
833 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
836 return STATUS_INSUFFICIENT_RESOURCES
;
839 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
841 if (!PhysicalDeviceObject
)
843 Status
= PnpRootCreateDevice(ServiceName
, &PhysicalDeviceObject
);
844 if (!NT_SUCCESS(Status
))
846 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
851 /* This is for drivers passed on the command line to ntoskrnl.exe */
852 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
853 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
856 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
858 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
862 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
863 Node
->Parent
= ParentNode
;
864 Node
->NextSibling
= ParentNode
->Child
;
865 if (ParentNode
->Child
!= NULL
)
867 ParentNode
->Child
->PrevSibling
= Node
;
869 ParentNode
->Child
= Node
;
870 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
871 Node
->Level
= ParentNode
->Level
+ 1;
876 return STATUS_SUCCESS
;
880 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
884 /* All children must be deleted before a parent is deleted */
885 ASSERT(!DeviceNode
->Child
);
887 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
889 ASSERT(DeviceNode
->PhysicalDeviceObject
);
891 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
893 /* Unlink from parent if it exists */
895 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
897 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
900 /* Unlink from sibling list */
902 if (DeviceNode
->PrevSibling
)
904 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
907 if (DeviceNode
->NextSibling
)
909 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
912 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
914 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
916 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
918 if (DeviceNode
->ResourceList
)
920 ExFreePool(DeviceNode
->ResourceList
);
923 if (DeviceNode
->ResourceListTranslated
)
925 ExFreePool(DeviceNode
->ResourceListTranslated
);
928 if (DeviceNode
->ResourceRequirements
)
930 ExFreePool(DeviceNode
->ResourceRequirements
);
933 if (DeviceNode
->BootResources
)
935 ExFreePool(DeviceNode
->BootResources
);
938 ExFreePool(DeviceNode
);
940 return STATUS_SUCCESS
;
944 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
945 PIO_STATUS_BLOCK IoStatusBlock
,
947 PIO_STACK_LOCATION Stack OPTIONAL
)
949 PDEVICE_OBJECT TopDeviceObject
;
950 PIO_STACK_LOCATION IrpSp
;
955 /* Always call the top of the device stack */
956 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
963 Irp
= IoBuildSynchronousFsdRequest(
972 /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */
973 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
974 Irp
->IoStatus
.Information
= 0;
976 IrpSp
= IoGetNextIrpStackLocation(Irp
);
977 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
981 RtlCopyMemory(&IrpSp
->Parameters
,
983 sizeof(Stack
->Parameters
));
986 Status
= IoCallDriver(TopDeviceObject
, Irp
);
987 if (Status
== STATUS_PENDING
)
989 KeWaitForSingleObject(&Event
,
994 Status
= IoStatusBlock
->Status
;
997 ObDereferenceObject(TopDeviceObject
);
1004 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1006 PDEVICE_NODE ParentDeviceNode
;
1007 PDEVICE_NODE ChildDeviceNode
;
1010 /* Copy context data so we don't overwrite it in subsequent calls to this function */
1011 ParentDeviceNode
= Context
->DeviceNode
;
1013 /* Call the action routine */
1014 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
1015 if (!NT_SUCCESS(Status
))
1020 /* Traversal of all children nodes */
1021 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
1022 ChildDeviceNode
!= NULL
;
1023 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
1025 /* Pass the current device node to the action routine */
1026 Context
->DeviceNode
= ChildDeviceNode
;
1028 Status
= IopTraverseDeviceTreeNode(Context
);
1029 if (!NT_SUCCESS(Status
))
1040 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1044 DPRINT("Context 0x%p\n", Context
);
1046 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1047 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1049 /* Start from the specified device node */
1050 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1052 /* Recursively traverse the device tree */
1053 Status
= IopTraverseDeviceTreeNode(Context
);
1054 if (Status
== STATUS_UNSUCCESSFUL
)
1056 /* The action routine just wanted to terminate the traversal with status
1057 code STATUS_SUCCESS */
1058 Status
= STATUS_SUCCESS
;
1067 IopCreateDeviceKeyPath(PWSTR Path
,
1070 OBJECT_ATTRIBUTES ObjectAttributes
;
1071 WCHAR KeyBuffer
[MAX_PATH
];
1072 UNICODE_STRING KeyName
;
1080 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
1082 return STATUS_INVALID_PARAMETER
;
1085 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
1087 /* Skip \\Registry\\ */
1088 Current
= KeyBuffer
;
1089 Current
= wcschr (Current
, L
'\\') + 1;
1090 Current
= wcschr (Current
, L
'\\') + 1;
1094 Next
= wcschr (Current
, L
'\\');
1104 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
1105 InitializeObjectAttributes (&ObjectAttributes
,
1107 OBJ_CASE_INSENSITIVE
,
1111 DPRINT("Create '%S'\n", KeyName
.Buffer
);
1113 Status
= ZwCreateKey (&KeyHandle
,
1120 if (!NT_SUCCESS (Status
))
1122 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
1128 *Handle
= KeyHandle
;
1129 return STATUS_SUCCESS
;
1133 ZwClose (KeyHandle
);
1140 return STATUS_UNSUCCESSFUL
;
1146 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1147 PDEVICE_NODE DeviceNode
)
1149 OBJECT_ATTRIBUTES ObjectAttributes
;
1150 UNICODE_STRING KeyName
;
1153 ULONG ListSize
, ResultLength
;
1156 DPRINT("IopSetDeviceInstanceData() called\n");
1158 /* Create the 'LogConf' key */
1159 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1160 InitializeObjectAttributes(&ObjectAttributes
,
1162 OBJ_CASE_INSENSITIVE
,
1165 Status
= ZwCreateKey(&LogConfKey
,
1172 if (NT_SUCCESS(Status
))
1174 /* Set 'BootConfig' value */
1175 if (DeviceNode
->BootResources
!= NULL
)
1177 ResCount
= DeviceNode
->BootResources
->Count
;
1180 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1182 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1183 Status
= ZwSetValueKey(LogConfKey
,
1187 &DeviceNode
->BootResources
,
1192 /* Set 'BasicConfigVector' value */
1193 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1194 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1196 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1197 Status
= ZwSetValueKey(LogConfKey
,
1200 REG_RESOURCE_REQUIREMENTS_LIST
,
1201 DeviceNode
->ResourceRequirements
,
1202 DeviceNode
->ResourceRequirements
->ListSize
);
1205 ZwClose(LogConfKey
);
1208 /* Set the 'ConfigFlags' value */
1209 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1210 Status
= ZwQueryValueKey(InstanceKey
,
1212 KeyValueBasicInformation
,
1216 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1218 /* Write the default value */
1219 ULONG DefaultConfigFlags
= 0;
1220 Status
= ZwSetValueKey(InstanceKey
,
1224 &DefaultConfigFlags
,
1225 sizeof(DefaultConfigFlags
));
1229 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1231 /* Create the 'Control' key */
1232 RtlInitUnicodeString(&KeyName
,
1234 InitializeObjectAttributes(&ObjectAttributes
,
1236 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1239 Status
= ZwCreateKey(&LogConfKey
,
1244 REG_OPTION_VOLATILE
,
1246 if (NT_SUCCESS(Status
))
1248 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1249 RtlInitUnicodeString(&KeyName
,
1250 L
"DeviceReference");
1251 Status
= ZwSetValueKey(LogConfKey
,
1258 ZwClose(LogConfKey
);
1263 DPRINT("IopSetDeviceInstanceData() done\n");
1265 return STATUS_SUCCESS
;
1270 IopAssignDeviceResources(
1271 IN PDEVICE_NODE DeviceNode
,
1272 OUT ULONG
*pRequiredSize
)
1274 PIO_RESOURCE_LIST ResourceList
;
1275 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1276 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
1277 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1278 ULONG NumberOfResources
= 0;
1283 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1285 /* No resource needed for this device */
1286 DeviceNode
->ResourceList
= NULL
;
1287 return STATUS_SUCCESS
;
1290 /* Fill DeviceNode->ResourceList
1291 * FIXME: the PnP arbiter should go there!
1292 * Actually, use the BootResources if provided, else the resource list #0
1295 if (DeviceNode
->BootResources
)
1297 /* Browse the boot resources to know if we have some custom structures */
1298 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1299 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1301 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1302 if (pPartialResourceList
->Version
!= 1 || pPartialResourceList
->Revision
!= 1)
1304 Status
= STATUS_REVISION_MISMATCH
;
1307 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1308 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1309 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1311 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1312 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1316 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1317 if (!DeviceNode
->ResourceList
)
1319 Status
= STATUS_NO_MEMORY
;
1322 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1324 *pRequiredSize
= Size
;
1325 return STATUS_SUCCESS
;
1328 /* Ok, here, we have to use the device requirement list */
1329 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1330 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1332 Status
= STATUS_REVISION_MISMATCH
;
1336 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1337 *pRequiredSize
= Size
;
1338 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1339 if (!DeviceNode
->ResourceList
)
1341 Status
= STATUS_NO_MEMORY
;
1345 DeviceNode
->ResourceList
->Count
= 1;
1346 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1347 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1348 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1349 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1351 for (i
= 0; i
< ResourceList
->Count
; i
++)
1353 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1355 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1357 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1358 NumberOfResources
++;
1360 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1361 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
1362 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1363 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
1364 switch (ResourceDescriptor
->Type
)
1366 case CmResourceTypePort
:
1368 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1369 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
1372 case CmResourceTypeInterrupt
:
1374 INTERFACE_TYPE BusType
;
1379 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1380 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1381 /* FIXME: HACK: if we have a PCI device, we try
1382 * to keep the IRQ assigned by the BIOS */
1383 if (NT_SUCCESS(IoGetDeviceProperty(
1384 DeviceNode
->PhysicalDeviceObject
,
1385 DevicePropertyLegacyBusType
,
1386 sizeof(INTERFACE_TYPE
),
1388 &ret
)) && BusType
== PCIBus
)
1390 /* We have a PCI bus */
1391 if (NT_SUCCESS(IoGetDeviceProperty(
1392 DeviceNode
->PhysicalDeviceObject
,
1393 DevicePropertyAddress
,
1396 &ret
)) && SlotNumber
> 0)
1398 /* We have a good slot number */
1399 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1400 DeviceNode
->ResourceRequirements
->BusNumber
,
1403 0x3c /* PCI_INTERRUPT_LINE */,
1405 if (ret
!= 0 && ret
!= 2
1406 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1407 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1409 /* The device already has an assigned IRQ */
1410 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1414 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1415 DescriptorRaw
->u
.Interrupt
.Vector
,
1416 &DeviceNode
->InstancePath
);
1417 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1418 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1419 DeviceNode
->ResourceRequirements
->BusNumber
,
1422 0x3c /* PCI_INTERRUPT_LINE */,
1424 if (ret
== 0 || ret
== 2)
1431 case CmResourceTypeMemory
:
1433 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1434 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
1437 case CmResourceTypeDma
:
1439 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1440 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
1441 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
1444 case CmResourceTypeBusNumber
:
1446 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1447 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
1448 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
1451 /*CmResourceTypeDevicePrivate:
1452 case CmResourceTypePcCardConfig:
1453 case CmResourceTypeMfCardConfig:
1456 &DescriptorRaw->u.DevicePrivate,
1457 &ResourceDescriptor->u.DevicePrivate,
1458 sizeof(ResourceDescriptor->u.DevicePrivate));
1460 &DescriptorTranslated->u.DevicePrivate,
1461 &ResourceDescriptor->u.DevicePrivate,
1462 sizeof(ResourceDescriptor->u.DevicePrivate));
1466 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1467 NumberOfResources
--;
1473 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1475 return STATUS_SUCCESS
;
1478 if (DeviceNode
->ResourceList
)
1480 ExFreePool(DeviceNode
->ResourceList
);
1481 DeviceNode
->ResourceList
= NULL
;
1488 IopTranslateDeviceResources(
1489 IN PDEVICE_NODE DeviceNode
,
1490 IN ULONG RequiredSize
)
1492 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1493 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1497 if (!DeviceNode
->ResourceList
)
1499 DeviceNode
->ResourceListTranslated
= NULL
;
1500 return STATUS_SUCCESS
;
1503 /* That's easy to translate a resource list. Just copy the
1504 * untranslated one and change few fields in the copy
1506 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1507 if (!DeviceNode
->ResourceListTranslated
)
1509 Status
=STATUS_NO_MEMORY
;
1512 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1514 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1516 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1517 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1519 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1520 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1521 switch (DescriptorRaw
->Type
)
1523 case CmResourceTypePort
:
1525 ULONG AddressSpace
= 0; /* IO space */
1526 if (!HalTranslateBusAddress(
1527 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1528 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1529 DescriptorRaw
->u
.Port
.Start
,
1531 &DescriptorTranslated
->u
.Port
.Start
))
1533 Status
= STATUS_UNSUCCESSFUL
;
1538 case CmResourceTypeInterrupt
:
1540 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1541 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1542 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1543 DescriptorRaw
->u
.Interrupt
.Level
,
1544 DescriptorRaw
->u
.Interrupt
.Vector
,
1545 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1546 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1549 case CmResourceTypeMemory
:
1551 ULONG AddressSpace
= 1; /* Memory space */
1552 if (!HalTranslateBusAddress(
1553 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1554 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1555 DescriptorRaw
->u
.Memory
.Start
,
1557 &DescriptorTranslated
->u
.Memory
.Start
))
1559 Status
= STATUS_UNSUCCESSFUL
;
1564 case CmResourceTypeDma
:
1565 case CmResourceTypeBusNumber
:
1566 case CmResourceTypeDeviceSpecific
:
1570 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1571 Status
= STATUS_NOT_IMPLEMENTED
;
1576 return STATUS_SUCCESS
;
1579 /* Yes! Also delete ResourceList because ResourceList and
1580 * ResourceListTranslated should be a pair! */
1581 ExFreePool(DeviceNode
->ResourceList
);
1582 DeviceNode
->ResourceList
= NULL
;
1583 if (DeviceNode
->ResourceListTranslated
)
1585 ExFreePool(DeviceNode
->ResourceListTranslated
);
1586 DeviceNode
->ResourceList
= NULL
;
1593 * IopGetParentIdPrefix
1595 * Retrieve (or create) a string which identifies a device.
1599 * Pointer to device node.
1601 * Pointer to the string where is returned the parent node identifier
1604 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1605 * valid and its Buffer field is NULL-terminated. The caller needs to
1606 * to free the string with RtlFreeUnicodeString when it is no longer
1611 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1612 PUNICODE_STRING ParentIdPrefix
)
1614 ULONG KeyNameBufferLength
;
1615 PWSTR KeyNameBuffer
= NULL
;
1616 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1617 UNICODE_STRING KeyName
;
1618 UNICODE_STRING KeyValue
;
1619 UNICODE_STRING ValueName
;
1620 OBJECT_ATTRIBUTES ObjectAttributes
;
1625 /* HACK: As long as some devices have a NULL device
1626 * instance path, the following test is required :(
1628 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1630 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1631 &DeviceNode
->InstancePath
);
1632 return STATUS_UNSUCCESSFUL
;
1635 /* 1. Try to retrieve ParentIdPrefix from registry */
1636 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1637 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1638 if (!ParentIdPrefixInformation
)
1640 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1643 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1646 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1649 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1650 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1651 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1652 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1653 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1654 if (!NT_SUCCESS(Status
))
1656 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1657 Status
= ZwQueryValueKey(
1659 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1660 KeyNameBufferLength
, &KeyNameBufferLength
);
1661 if (NT_SUCCESS(Status
))
1663 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1664 Status
= STATUS_UNSUCCESSFUL
;
1667 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1668 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1672 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1674 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1675 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1679 /* 2. Create the ParentIdPrefix value */
1680 crc32
= RtlComputeCrc32(0,
1681 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1682 DeviceNode
->Parent
->InstancePath
.Length
);
1684 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1685 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1687 /* 3. Try to write the ParentIdPrefix to registry */
1688 Status
= ZwSetValueKey(hKey
,
1692 (PVOID
)KeyValue
.Buffer
,
1693 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1696 if (NT_SUCCESS(Status
))
1698 /* Duplicate the string to return it */
1699 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1701 ExFreePool(ParentIdPrefixInformation
);
1702 ExFreePool(KeyNameBuffer
);
1710 * IopActionInterrogateDeviceStack
1712 * Retrieve information for all (direct) child nodes of a parent node.
1716 * Pointer to device node.
1718 * Pointer to parent node to retrieve child node information for.
1721 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1722 * when we reach a device node which is not a direct child of the device
1723 * node for which we retrieve information of child nodes for. Any errors
1724 * that occur is logged instead so that all child services have a chance
1725 * of being interrogated.
1729 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1732 IO_STATUS_BLOCK IoStatusBlock
;
1733 PDEVICE_NODE ParentDeviceNode
;
1734 WCHAR InstancePath
[MAX_PATH
];
1735 IO_STACK_LOCATION Stack
;
1741 ULONG RequiredLength
;
1743 HANDLE InstanceKey
= NULL
;
1744 UNICODE_STRING ValueName
;
1745 UNICODE_STRING ParentIdPrefix
= { 0 };
1746 DEVICE_CAPABILITIES DeviceCapabilities
;
1748 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1749 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1751 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1754 * We are called for the parent too, but we don't need to do special
1755 * handling for this node
1758 if (DeviceNode
== ParentDeviceNode
)
1760 DPRINT("Success\n");
1761 return STATUS_SUCCESS
;
1765 * Make sure this device node is a direct child of the parent device node
1766 * that is given as an argument
1769 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1771 /* Stop the traversal immediately and indicate successful operation */
1773 return STATUS_UNSUCCESSFUL
;
1777 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1778 if (!NT_SUCCESS(Status
))
1780 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1785 * FIXME: For critical errors, cleanup and disable device, but always
1786 * return STATUS_SUCCESS.
1789 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1791 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1792 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1796 if (NT_SUCCESS(Status
))
1798 /* Copy the device id string */
1799 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1802 * FIXME: Check for valid characters, if there is invalid characters
1808 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1811 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1813 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1814 if (!NT_SUCCESS(Status
))
1816 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1819 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1821 if (!DeviceCapabilities
.UniqueID
)
1823 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1824 DPRINT("Instance ID is not unique\n");
1825 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1826 if (!NT_SUCCESS(Status
))
1828 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1832 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1834 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1835 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1839 if (NT_SUCCESS(Status
))
1841 /* Append the instance id string */
1842 wcscat(InstancePath
, L
"\\");
1843 if (ParentIdPrefix
.Length
> 0)
1845 /* Add information from parent bus device to InstancePath */
1846 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1847 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1848 wcscat(InstancePath
, L
"&");
1850 if (IoStatusBlock
.Information
)
1851 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1854 * FIXME: Check for valid characters, if there is invalid characters
1860 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1862 RtlFreeUnicodeString(&ParentIdPrefix
);
1864 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1866 DPRINT("No resources\n");
1867 /* FIXME: Cleanup and disable device */
1870 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1873 * Create registry key for the instance id, if it doesn't exist yet
1875 KeyBuffer
= ExAllocatePool(
1877 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1878 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1879 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1880 Status
= IopCreateDeviceKeyPath(KeyBuffer
, &InstanceKey
);
1881 ExFreePool(KeyBuffer
);
1882 if (!NT_SUCCESS(Status
))
1884 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1889 /* Set 'Capabilities' value */
1890 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1891 Status
= ZwSetValueKey(InstanceKey
,
1895 (PVOID
)&DeviceNode
->CapabilityFlags
,
1898 /* Set 'UINumber' value */
1899 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1901 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1902 Status
= ZwSetValueKey(InstanceKey
,
1906 &DeviceCapabilities
.UINumber
,
1911 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1913 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1914 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1918 if (NT_SUCCESS(Status
))
1921 * FIXME: Check for valid characters, if there is invalid characters
1925 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1926 DPRINT("Hardware IDs:\n");
1929 DPRINT(" %S\n", Ptr
);
1930 Length
= wcslen(Ptr
) + 1;
1933 TotalLength
+= Length
;
1935 DPRINT("TotalLength: %hu\n", TotalLength
);
1938 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1939 Status
= ZwSetValueKey(InstanceKey
,
1943 (PVOID
)IoStatusBlock
.Information
,
1944 (TotalLength
+ 1) * sizeof(WCHAR
));
1945 if (!NT_SUCCESS(Status
))
1947 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1952 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1955 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1957 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1958 Status
= IopInitiatePnpIrp(
1959 DeviceNode
->PhysicalDeviceObject
,
1963 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1966 * FIXME: Check for valid characters, if there is invalid characters
1970 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1971 DPRINT("Compatible IDs:\n");
1974 DPRINT(" %S\n", Ptr
);
1975 Length
= wcslen(Ptr
) + 1;
1978 TotalLength
+= Length
;
1980 DPRINT("TotalLength: %hu\n", TotalLength
);
1983 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1984 Status
= ZwSetValueKey(InstanceKey
,
1988 (PVOID
)IoStatusBlock
.Information
,
1989 (TotalLength
+ 1) * sizeof(WCHAR
));
1990 if (!NT_SUCCESS(Status
))
1992 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1997 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2000 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2002 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2003 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2004 Status
= IopInitiatePnpIrp(
2005 DeviceNode
->PhysicalDeviceObject
,
2007 IRP_MN_QUERY_DEVICE_TEXT
,
2009 /* This key is mandatory, so even if the Irp fails, we still write it */
2010 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2011 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2013 if (NT_SUCCESS(Status
) &&
2014 IoStatusBlock
.Information
&&
2015 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2017 /* This key is overriden when a driver is installed. Don't write the
2018 * new description if another one already exists */
2019 Status
= ZwSetValueKey(InstanceKey
,
2023 (PVOID
)IoStatusBlock
.Information
,
2024 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2028 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2029 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2031 Status
= ZwSetValueKey(InstanceKey
,
2036 DeviceDesc
.MaximumLength
);
2038 if (!NT_SUCCESS(Status
))
2040 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2046 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2048 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2049 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2050 Status
= IopInitiatePnpIrp(
2051 DeviceNode
->PhysicalDeviceObject
,
2053 IRP_MN_QUERY_DEVICE_TEXT
,
2055 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2057 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2058 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2059 Status
= ZwSetValueKey(InstanceKey
,
2063 (PVOID
)IoStatusBlock
.Information
,
2064 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2065 if (!NT_SUCCESS(Status
))
2067 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2072 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2075 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2077 Status
= IopInitiatePnpIrp(
2078 DeviceNode
->PhysicalDeviceObject
,
2080 IRP_MN_QUERY_BUS_INFORMATION
,
2082 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2084 PPNP_BUS_INFORMATION BusInformation
=
2085 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2087 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2088 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2089 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2090 ExFreePool(BusInformation
);
2094 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2096 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2097 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2098 DeviceNode
->ChildBusTypeIndex
= -1;
2101 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2103 Status
= IopInitiatePnpIrp(
2104 DeviceNode
->PhysicalDeviceObject
,
2106 IRP_MN_QUERY_RESOURCES
,
2108 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2110 DeviceNode
->BootResources
=
2111 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2112 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2116 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2117 DeviceNode
->BootResources
= NULL
;
2120 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2122 Status
= IopInitiatePnpIrp(
2123 DeviceNode
->PhysicalDeviceObject
,
2125 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2127 if (NT_SUCCESS(Status
))
2129 DeviceNode
->ResourceRequirements
=
2130 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2131 if (IoStatusBlock
.Information
)
2132 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2134 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2138 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2139 DeviceNode
->ResourceRequirements
= NULL
;
2143 if (InstanceKey
!= NULL
)
2145 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2148 ZwClose(InstanceKey
);
2150 DeviceNode
->Flags
|= DNF_PROCESSED
;
2152 /* Report the device to the user-mode pnp manager */
2153 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2154 &DeviceNode
->InstancePath
);
2156 return STATUS_SUCCESS
;
2164 IoSynchronousInvalidateDeviceRelations(
2165 IN PDEVICE_OBJECT DeviceObject
,
2166 IN DEVICE_RELATION_TYPE Type
)
2168 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2169 DEVICETREE_TRAVERSE_CONTEXT Context
;
2170 PDEVICE_RELATIONS DeviceRelations
;
2171 IO_STATUS_BLOCK IoStatusBlock
;
2172 PDEVICE_NODE ChildDeviceNode
;
2173 IO_STACK_LOCATION Stack
;
2174 BOOLEAN BootDrivers
;
2175 OBJECT_ATTRIBUTES ObjectAttributes
;
2176 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
2181 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2183 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2185 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
;
2187 Status
= IopInitiatePnpIrp(
2190 IRP_MN_QUERY_DEVICE_RELATIONS
,
2192 if (!NT_SUCCESS(Status
))
2194 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2198 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2200 if (!DeviceRelations
|| DeviceRelations
->Count
<= 0)
2202 DPRINT("No PDOs\n");
2203 if (DeviceRelations
)
2205 ExFreePool(DeviceRelations
);
2210 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2213 * Create device nodes for all discovered devices
2215 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2217 if (IopGetDeviceNode(DeviceRelations
->Objects
[i
]) != NULL
)
2219 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2222 Status
= IopCreateDeviceNode(
2224 DeviceRelations
->Objects
[i
],
2227 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2228 if (!NT_SUCCESS(Status
))
2230 DPRINT("No resources\n");
2231 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2232 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2233 ExFreePool(DeviceRelations
);
2237 ExFreePool(DeviceRelations
);
2240 * Retrieve information about all discovered children from the bus driver
2242 IopInitDeviceTreeTraverseContext(
2245 IopActionInterrogateDeviceStack
,
2248 Status
= IopTraverseDeviceTree(&Context
);
2249 if (!NT_SUCCESS(Status
))
2251 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2256 * Retrieve configuration from the registry for discovered children
2258 IopInitDeviceTreeTraverseContext(
2261 IopActionConfigureChildServices
,
2264 Status
= IopTraverseDeviceTree(&Context
);
2265 if (!NT_SUCCESS(Status
))
2267 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2272 * Get the state of the system boot. If the \\SystemRoot link isn't
2273 * created yet, we will assume that it's possible to load only boot
2276 InitializeObjectAttributes(
2282 Status
= ZwOpenFile(
2289 if (NT_SUCCESS(Status
))
2291 BootDrivers
= FALSE
;
2298 * Initialize services for discovered children. Only boot drivers will
2299 * be loaded from boot driver!
2301 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2302 if (!NT_SUCCESS(Status
))
2304 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2308 DPRINT("IopInvalidateDeviceRelations() finished\n");
2312 * IopActionConfigureChildServices
2314 * Retrieve configuration for all (direct) child nodes of a parent node.
2318 * Pointer to device node.
2320 * Pointer to parent node to retrieve child node configuration for.
2323 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2324 * when we reach a device node which is not a direct child of the device
2325 * node for which we configure child services for. Any errors that occur is
2326 * logged instead so that all child services have a chance of beeing
2331 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2334 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2335 PDEVICE_NODE ParentDeviceNode
;
2336 PUNICODE_STRING Service
;
2337 UNICODE_STRING ClassGUID
;
2340 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2342 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2345 * We are called for the parent too, but we don't need to do special
2346 * handling for this node
2348 if (DeviceNode
== ParentDeviceNode
)
2350 DPRINT("Success\n");
2351 return STATUS_SUCCESS
;
2355 * Make sure this device node is a direct child of the parent device node
2356 * that is given as an argument
2358 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2360 /* Stop the traversal immediately and indicate successful operation */
2362 return STATUS_UNSUCCESSFUL
;
2365 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2367 WCHAR RegKeyBuffer
[MAX_PATH
];
2368 UNICODE_STRING RegKey
;
2371 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2372 RegKey
.Buffer
= RegKeyBuffer
;
2375 * Retrieve configuration from Enum key
2378 Service
= &DeviceNode
->ServiceName
;
2380 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2381 RtlInitUnicodeString(Service
, NULL
);
2382 RtlInitUnicodeString(&ClassGUID
, NULL
);
2384 QueryTable
[0].Name
= L
"Service";
2385 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
2386 QueryTable
[0].EntryContext
= Service
;
2388 QueryTable
[1].Name
= L
"ClassGUID";
2389 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2390 QueryTable
[1].EntryContext
= &ClassGUID
;
2391 QueryTable
[1].DefaultType
= REG_SZ
;
2392 QueryTable
[1].DefaultData
= L
"";
2393 QueryTable
[1].DefaultLength
= 0;
2395 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2396 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2398 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2399 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2401 if (!NT_SUCCESS(Status
))
2403 /* FIXME: Log the error */
2404 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2405 &DeviceNode
->InstancePath
, Status
);
2406 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2407 return STATUS_SUCCESS
;
2410 if (Service
->Buffer
== NULL
)
2412 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2414 if (ClassGUID
.Length
!= 0)
2416 /* Device has a ClassGUID value, but no Service value.
2417 * Suppose it is using the NULL driver, so state the
2418 * device is started */
2419 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2420 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2421 DeviceNode
->Flags
|= DN_STARTED
;
2423 return STATUS_SUCCESS
;
2426 DPRINT("Got Service %S\n", Service
->Buffer
);
2429 return STATUS_SUCCESS
;
2433 * IopActionInitChildServices
2435 * Initialize the service for all (direct) child nodes of a parent node
2439 * Pointer to device node.
2441 * Pointer to parent node to initialize child node services for.
2443 * Load only driver marked as boot start.
2446 * If the driver image for a service is not loaded and initialized
2447 * it is done here too. We only return a status code indicating an
2448 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2449 * not a direct child of the device node for which we initialize
2450 * child services for. Any errors that occur is logged instead so
2451 * that all child services have a chance of being initialized.
2455 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2457 BOOLEAN BootDrivers
)
2459 PDEVICE_NODE ParentDeviceNode
;
2462 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2465 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2468 * We are called for the parent too, but we don't need to do special
2469 * handling for this node
2471 if (DeviceNode
== ParentDeviceNode
)
2473 DPRINT("Success\n");
2474 return STATUS_SUCCESS
;
2478 * Make sure this device node is a direct child of the parent device node
2479 * that is given as an argument
2482 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2485 * Stop the traversal immediately and indicate unsuccessful operation
2488 return STATUS_UNSUCCESSFUL
;
2492 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2493 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2494 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2496 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2497 PDRIVER_OBJECT DriverObject
;
2499 /* Get existing DriverObject pointer (in case the driver has
2500 already been loaded and initialized) */
2501 Status
= IopGetDriverObject(
2503 &DeviceNode
->ServiceName
,
2506 if (!NT_SUCCESS(Status
))
2508 /* Driver is not initialized, try to load it */
2509 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2511 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2513 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2514 was loaded by the bootloader */
2515 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2516 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2518 /* Initialize the driver */
2519 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2520 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2524 Status
= STATUS_SUCCESS
;
2529 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2530 &DeviceNode
->ServiceName
, Status
);
2534 /* Driver is loaded and initialized at this point */
2535 if (NT_SUCCESS(Status
))
2537 /* We have a driver for this DeviceNode */
2538 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2539 /* Attach lower level filter drivers. */
2540 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2541 /* Initialize the function driver for the device node */
2542 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2544 if (NT_SUCCESS(Status
))
2546 /* Attach upper level filter drivers. */
2547 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2548 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2550 Status
= IopStartDevice(DeviceNode
);
2554 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2555 &DeviceNode
->InstancePath
, Status
);
2561 * Don't disable when trying to load only boot drivers
2565 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2566 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2567 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2568 CPRINT("Initialization of service %S failed (Status %x)\n",
2569 DeviceNode
->ServiceName
.Buffer
, Status
);
2575 DPRINT("Device %wZ is disabled or already initialized\n",
2576 &DeviceNode
->InstancePath
);
2579 return STATUS_SUCCESS
;
2583 * IopActionInitAllServices
2585 * Initialize the service for all (direct) child nodes of a parent node. This
2586 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2590 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2593 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2597 * IopActionInitBootServices
2599 * Initialize the boot start services for all (direct) child nodes of a
2600 * parent node. This function just calls IopActionInitChildServices with
2601 * BootDrivers = TRUE.
2604 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2607 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2611 * IopInitializePnpServices
2613 * Initialize services for discovered children
2617 * Top device node to start initializing services.
2620 * When set to TRUE, only drivers marked as boot start will
2621 * be loaded. Otherwise, all drivers will be loaded.
2627 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2628 IN BOOLEAN BootDrivers
)
2630 DEVICETREE_TRAVERSE_CONTEXT Context
;
2632 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2636 IopInitDeviceTreeTraverseContext(
2639 IopActionInitBootServices
,
2644 IopInitDeviceTreeTraverseContext(
2647 IopActionInitAllServices
,
2651 return IopTraverseDeviceTree(&Context
);
2654 static NTSTATUS INIT_FUNCTION
2655 IopEnumerateDetectedDevices(
2657 IN PUNICODE_STRING RelativePath
,
2659 IN BOOLEAN EnumerateSubKeys
,
2660 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2661 IN ULONG ParentBootResourcesLength
)
2663 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2664 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2665 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2666 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2667 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2668 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2669 OBJECT_ATTRIBUTES ObjectAttributes
;
2670 HANDLE hDevicesKey
= NULL
;
2671 HANDLE hDeviceKey
= NULL
;
2672 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2673 UNICODE_STRING Level2NameU
;
2674 WCHAR Level2Name
[5];
2675 ULONG IndexDevice
= 0;
2677 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2678 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2679 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2680 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2681 UNICODE_STRING DeviceName
, ValueName
;
2683 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2684 ULONG BootResourcesLength
;
2687 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI BIOS");
2688 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2689 static ULONG DeviceIndexPci
= 0;
2691 const UNICODE_STRING IdentifierAcpi
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2692 UNICODE_STRING HardwareIdAcpi
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2693 static ULONG DeviceIndexAcpi
= 0;
2695 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2696 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2697 static ULONG DeviceIndexSerial
= 0;
2698 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2699 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2700 static ULONG DeviceIndexKeyboard
= 0;
2701 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2702 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2703 static ULONG DeviceIndexMouse
= 0;
2704 PUNICODE_STRING pHardwareId
;
2705 ULONG DeviceIndex
= 0;
2707 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2708 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2709 if (!NT_SUCCESS(Status
))
2711 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2715 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2716 if (!pDeviceInformation
)
2718 DPRINT("ExAllocatePool() failed\n");
2719 Status
= STATUS_NO_MEMORY
;
2723 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2724 if (!pValueInformation
)
2726 DPRINT("ExAllocatePool() failed\n");
2727 Status
= STATUS_NO_MEMORY
;
2733 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2734 if (Status
== STATUS_NO_MORE_ENTRIES
)
2736 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2738 ExFreePool(pDeviceInformation
);
2739 DeviceInfoLength
= RequiredSize
;
2740 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2741 if (!pDeviceInformation
)
2743 DPRINT("ExAllocatePool() failed\n");
2744 Status
= STATUS_NO_MEMORY
;
2747 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2749 if (!NT_SUCCESS(Status
))
2751 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2756 /* Open device key */
2757 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2758 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2759 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2762 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0),
2764 if (!NT_SUCCESS(Status
))
2766 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2770 /* Read boot resources, and add then to parent ones */
2771 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2772 if (Status
== STATUS_BUFFER_OVERFLOW
)
2774 ExFreePool(pValueInformation
);
2775 ValueInfoLength
= RequiredSize
;
2776 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2777 if (!pValueInformation
)
2779 DPRINT("ExAllocatePool() failed\n");
2780 ZwDeleteKey(hLevel2Key
);
2781 Status
= STATUS_NO_MEMORY
;
2784 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2786 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2788 BootResources
= ParentBootResources
;
2789 BootResourcesLength
= ParentBootResourcesLength
;
2791 else if (!NT_SUCCESS(Status
))
2793 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2796 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2798 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2801 else if (((PCM_FULL_RESOURCE_DESCRIPTOR
)pValueInformation
->Data
)->PartialResourceList
.Count
== 0)
2803 BootResources
= ParentBootResources
;
2804 BootResourcesLength
= ParentBootResourcesLength
;
2808 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2810 /* Concatenate current resources and parent ones */
2811 if (ParentBootResourcesLength
== 0)
2812 BootResourcesLength
= pValueInformation
->DataLength
;
2814 BootResourcesLength
= ParentBootResourcesLength
2815 + pValueInformation
->DataLength
2817 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2820 DPRINT("ExAllocatePool() failed\n");
2823 if (ParentBootResourcesLength
== 0)
2825 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2827 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2829 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2831 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2832 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2833 ParentBootResourcesLength
- Header
);
2834 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2838 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2840 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2841 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2842 ParentBootResourcesLength
- Header
);
2844 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2845 pValueInformation
->Data
+ Header
,
2846 pValueInformation
->DataLength
- Header
);
2847 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2851 if (EnumerateSubKeys
)
2856 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2857 if (Status
== STATUS_NO_MORE_ENTRIES
)
2859 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2861 ExFreePool(pDeviceInformation
);
2862 DeviceInfoLength
= RequiredSize
;
2863 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2864 if (!pDeviceInformation
)
2866 DPRINT("ExAllocatePool() failed\n");
2867 Status
= STATUS_NO_MEMORY
;
2870 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2872 if (!NT_SUCCESS(Status
))
2874 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2878 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2879 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2881 Status
= IopEnumerateDetectedDevices(
2887 BootResourcesLength
);
2888 if (!NT_SUCCESS(Status
))
2893 /* Read identifier */
2894 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2895 if (Status
== STATUS_BUFFER_OVERFLOW
)
2897 ExFreePool(pValueInformation
);
2898 ValueInfoLength
= RequiredSize
;
2899 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2900 if (!pValueInformation
)
2902 DPRINT("ExAllocatePool() failed\n");
2903 Status
= STATUS_NO_MEMORY
;
2906 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2908 if (!NT_SUCCESS(Status
))
2910 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2912 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2915 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2917 else if (pValueInformation
->Type
!= REG_SZ
)
2919 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2924 /* Assign hardware id to this device */
2925 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2926 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2927 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2928 ValueName
.Length
-= sizeof(WCHAR
);
2931 if (RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2933 pHardwareId
= &HardwareIdSerial
;
2934 DeviceIndex
= DeviceIndexSerial
++;
2936 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2938 pHardwareId
= &HardwareIdKeyboard
;
2939 DeviceIndex
= DeviceIndexKeyboard
++;
2941 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2943 pHardwareId
= &HardwareIdMouse
;
2944 DeviceIndex
= DeviceIndexMouse
++;
2946 else if (NT_SUCCESS(Status
))
2948 /* Try to also match the device identifier */
2949 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2951 pHardwareId
= &HardwareIdPci
;
2952 DeviceIndex
= DeviceIndexPci
++;
2955 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierAcpi
, FALSE
) == 0)
2957 pHardwareId
= &HardwareIdAcpi
;
2958 DeviceIndex
= DeviceIndexAcpi
++;
2963 /* Unknown device */
2964 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2970 /* Unknown key path */
2971 DPRINT("Unknown key path %wZ\n", RelativePath
);
2975 /* Add the detected device to Root key */
2976 InitializeObjectAttributes(&ObjectAttributes
, pHardwareId
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2977 Status
= ZwCreateKey(
2983 REG_OPTION_NON_VOLATILE
,
2985 if (!NT_SUCCESS(Status
))
2987 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2990 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2991 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2992 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2993 Status
= ZwCreateKey(
2995 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2999 REG_OPTION_NON_VOLATILE
,
3001 ZwClose(hLevel1Key
);
3002 if (!NT_SUCCESS(Status
))
3004 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3007 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, pHardwareId
);
3008 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
3009 if (!NT_SUCCESS(Status
))
3011 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3012 ZwDeleteKey(hLevel2Key
);
3015 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3016 if (!NT_SUCCESS(Status
))
3018 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3019 ZwDeleteKey(hLevel2Key
);
3022 /* Create 'LogConf' subkey */
3023 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3024 Status
= ZwCreateKey(
3030 REG_OPTION_VOLATILE
,
3032 if (!NT_SUCCESS(Status
))
3034 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3035 ZwDeleteKey(hLevel2Key
);
3038 if (BootResourcesLength
> 0)
3040 /* Save boot resources to 'LogConf\BootConfig' */
3041 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
3042 if (!NT_SUCCESS(Status
))
3044 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3046 ZwDeleteKey(hLevel2Key
);
3053 if (BootResources
&& BootResources
!= ParentBootResources
)
3054 ExFreePool(BootResources
);
3057 ZwClose(hLevel2Key
);
3062 ZwClose(hDeviceKey
);
3067 Status
= STATUS_SUCCESS
;
3071 ZwClose(hDevicesKey
);
3073 ZwClose(hDeviceKey
);
3074 if (pDeviceInformation
)
3075 ExFreePool(pDeviceInformation
);
3076 if (pValueInformation
)
3077 ExFreePool(pValueInformation
);
3081 static BOOLEAN INIT_FUNCTION
3082 IopIsAcpiComputer(VOID
)
3087 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3088 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3089 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3090 OBJECT_ATTRIBUTES ObjectAttributes
;
3091 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3092 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3093 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3094 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3096 ULONG IndexDevice
= 0;
3097 UNICODE_STRING DeviceName
, ValueName
;
3098 HANDLE hDevicesKey
= NULL
;
3099 HANDLE hDeviceKey
= NULL
;
3101 BOOLEAN ret
= FALSE
;
3103 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3104 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3105 if (!NT_SUCCESS(Status
))
3107 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3111 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3112 if (!pDeviceInformation
)
3114 DPRINT("ExAllocatePool() failed\n");
3115 Status
= STATUS_NO_MEMORY
;
3119 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3120 if (!pDeviceInformation
)
3122 DPRINT("ExAllocatePool() failed\n");
3123 Status
= STATUS_NO_MEMORY
;
3129 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3130 if (Status
== STATUS_NO_MORE_ENTRIES
)
3132 else if (Status
== STATUS_BUFFER_OVERFLOW
)
3134 ExFreePool(pDeviceInformation
);
3135 DeviceInfoLength
= RequiredSize
;
3136 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3137 if (!pDeviceInformation
)
3139 DPRINT("ExAllocatePool() failed\n");
3140 Status
= STATUS_NO_MEMORY
;
3143 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3145 if (!NT_SUCCESS(Status
))
3147 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3152 /* Open device key */
3153 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3154 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3155 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3160 if (!NT_SUCCESS(Status
))
3162 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3166 /* Read identifier */
3167 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3168 if (Status
== STATUS_BUFFER_OVERFLOW
)
3170 ExFreePool(pValueInformation
);
3171 ValueInfoLength
= RequiredSize
;
3172 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3173 if (!pValueInformation
)
3175 DPRINT("ExAllocatePool() failed\n");
3176 Status
= STATUS_NO_MEMORY
;
3179 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3181 if (!NT_SUCCESS(Status
))
3183 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3186 else if (pValueInformation
->Type
!= REG_SZ
)
3188 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3192 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3193 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3194 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3195 ValueName
.Length
-= sizeof(WCHAR
);
3196 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3198 DPRINT("Found ACPI BIOS\n");
3204 ZwClose(hDeviceKey
);
3209 if (pDeviceInformation
)
3210 ExFreePool(pDeviceInformation
);
3211 if (pValueInformation
)
3212 ExFreePool(pValueInformation
);
3214 ZwClose(hDevicesKey
);
3216 ZwClose(hDeviceKey
);
3221 static NTSTATUS INIT_FUNCTION
3222 IopUpdateRootKey(VOID
)
3224 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum\\Root");
3225 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3226 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3227 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3228 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
3229 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3230 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3231 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3232 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3233 OBJECT_ATTRIBUTES ObjectAttributes
;
3234 HANDLE hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
3237 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3238 Status
= ZwOpenKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
);
3239 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3241 /* We are probably in 1st stage */
3242 return STATUS_SUCCESS
;
3244 else if (!NT_SUCCESS(Status
))
3246 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3250 if (IopIsAcpiComputer())
3252 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3253 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3255 if (!NT_SUCCESS(Status
))
3257 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3258 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3259 ZwClose(hHalAcpiDevice
);
3260 if (!NT_SUCCESS(Status
))
3262 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3263 if (NT_SUCCESS(Status
))
3264 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3265 if (NT_SUCCESS(Status
))
3267 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hHalAcpiId
, NULL
);
3268 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3269 if (NT_SUCCESS(Status
))
3272 ZwClose(hHalAcpiId
);
3277 Status
= IopEnumerateDetectedDevices(
3289 static NTSTATUS INIT_FUNCTION
3291 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
3293 return STATUS_SUCCESS
;
3302 DPRINT("PnpInit()\n");
3304 KeInitializeSpinLock(&IopDeviceTreeLock
);
3306 /* Initialize the Bus Type GUID List */
3307 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3308 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3309 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3311 /* Initialize PnP-Event notification support */
3312 Status
= IopInitPlugPlayEvents();
3313 if (!NT_SUCCESS(Status
))
3315 CPRINT("IopInitPlugPlayEvents() failed\n");
3316 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3320 * Create root device node
3323 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
3324 if (!NT_SUCCESS(Status
))
3326 CPRINT("IoCreateDriverObject() failed\n");
3327 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3330 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3332 if (!NT_SUCCESS(Status
))
3334 CPRINT("IoCreateDevice() failed\n");
3335 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3338 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
3339 if (!NT_SUCCESS(Status
))
3341 CPRINT("Insufficient resources\n");
3342 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3345 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3348 CPRINT("Failed to create the instance path!\n");
3349 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3352 /* Report the device to the user-mode pnp manager */
3353 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3354 &IopRootDeviceNode
->InstancePath
);
3356 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3357 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3358 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3359 IopRootDriverObject
->DriverExtension
->AddDevice(
3360 IopRootDriverObject
,
3361 IopRootDeviceNode
->PhysicalDeviceObject
);
3363 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3364 Status
= IopUpdateRootKey();
3365 if (!NT_SUCCESS(Status
))
3367 CPRINT("IopUpdateRootKey() failed\n");
3368 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3372 RTL_GENERIC_COMPARE_RESULTS
3374 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3375 IN PVOID FirstStruct
,
3376 IN PVOID SecondStruct
)
3384 // The allocation function is called by the generic table package whenever
3385 // it needs to allocate memory for the table.
3390 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3400 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3409 PpInitializeDeviceReferenceTable(VOID
)
3411 /* Setup the guarded mutex and AVL table */
3412 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3413 RtlInitializeGenericTableAvl(
3414 &PpDeviceReferenceTable
,
3415 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3416 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3417 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3425 /* Initialize the resource when accessing device registry data */
3426 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3428 /* Setup the device reference AVL table */
3429 PpInitializeDeviceReferenceTable();
3437 /* Check the initialization phase */
3438 switch (ExpInitializationPhase
)
3443 return PiInitPhase0();
3449 //return PiInitPhase1();
3453 /* Don't know any other phase! Bugcheck! */
3454 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);