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
))
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 /* Most of PNP IRPs are initialized with a status code of
973 STATUS_NOT_IMPLEMENTED */
974 if (MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
975 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
977 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
978 Irp
->IoStatus
.Information
= 0;
980 IrpSp
= IoGetNextIrpStackLocation(Irp
);
981 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
985 RtlCopyMemory(&IrpSp
->Parameters
,
987 sizeof(Stack
->Parameters
));
990 Status
= IoCallDriver(TopDeviceObject
, Irp
);
991 if (Status
== STATUS_PENDING
)
993 KeWaitForSingleObject(&Event
,
998 Status
= IoStatusBlock
->Status
;
1001 ObDereferenceObject(TopDeviceObject
);
1008 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1010 PDEVICE_NODE ParentDeviceNode
;
1011 PDEVICE_NODE ChildDeviceNode
;
1014 /* Copy context data so we don't overwrite it in subsequent calls to this function */
1015 ParentDeviceNode
= Context
->DeviceNode
;
1017 /* Call the action routine */
1018 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
1019 if (!NT_SUCCESS(Status
))
1024 /* Traversal of all children nodes */
1025 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
1026 ChildDeviceNode
!= NULL
;
1027 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
1029 /* Pass the current device node to the action routine */
1030 Context
->DeviceNode
= ChildDeviceNode
;
1032 Status
= IopTraverseDeviceTreeNode(Context
);
1033 if (!NT_SUCCESS(Status
))
1044 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1048 DPRINT("Context 0x%p\n", Context
);
1050 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1051 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1053 /* Start from the specified device node */
1054 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1056 /* Recursively traverse the device tree */
1057 Status
= IopTraverseDeviceTreeNode(Context
);
1058 if (Status
== STATUS_UNSUCCESSFUL
)
1060 /* The action routine just wanted to terminate the traversal with status
1061 code STATUS_SUCCESS */
1062 Status
= STATUS_SUCCESS
;
1071 IopCreateDeviceKeyPath(PWSTR Path
,
1074 OBJECT_ATTRIBUTES ObjectAttributes
;
1075 WCHAR KeyBuffer
[MAX_PATH
];
1076 UNICODE_STRING KeyName
;
1084 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
1086 return STATUS_INVALID_PARAMETER
;
1089 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
1091 /* Skip \\Registry\\ */
1092 Current
= KeyBuffer
;
1093 Current
= wcschr (Current
, L
'\\') + 1;
1094 Current
= wcschr (Current
, L
'\\') + 1;
1098 Next
= wcschr (Current
, L
'\\');
1108 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
1109 InitializeObjectAttributes (&ObjectAttributes
,
1111 OBJ_CASE_INSENSITIVE
,
1115 DPRINT("Create '%S'\n", KeyName
.Buffer
);
1117 Status
= ZwCreateKey (&KeyHandle
,
1124 if (!NT_SUCCESS (Status
))
1126 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
1132 *Handle
= KeyHandle
;
1133 return STATUS_SUCCESS
;
1137 ZwClose (KeyHandle
);
1144 return STATUS_UNSUCCESSFUL
;
1150 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1151 PDEVICE_NODE DeviceNode
)
1153 OBJECT_ATTRIBUTES ObjectAttributes
;
1154 UNICODE_STRING KeyName
;
1157 ULONG ListSize
, ResultLength
;
1160 DPRINT("IopSetDeviceInstanceData() called\n");
1162 /* Create the 'LogConf' key */
1163 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1164 InitializeObjectAttributes(&ObjectAttributes
,
1166 OBJ_CASE_INSENSITIVE
,
1169 Status
= ZwCreateKey(&LogConfKey
,
1176 if (NT_SUCCESS(Status
))
1178 /* Set 'BootConfig' value */
1179 if (DeviceNode
->BootResources
!= NULL
)
1181 ResCount
= DeviceNode
->BootResources
->Count
;
1184 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1186 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1187 Status
= ZwSetValueKey(LogConfKey
,
1191 &DeviceNode
->BootResources
,
1196 /* Set 'BasicConfigVector' value */
1197 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1198 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1200 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1201 Status
= ZwSetValueKey(LogConfKey
,
1204 REG_RESOURCE_REQUIREMENTS_LIST
,
1205 DeviceNode
->ResourceRequirements
,
1206 DeviceNode
->ResourceRequirements
->ListSize
);
1209 ZwClose(LogConfKey
);
1212 /* Set the 'ConfigFlags' value */
1213 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1214 Status
= ZwQueryValueKey(InstanceKey
,
1216 KeyValueBasicInformation
,
1220 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1222 /* Write the default value */
1223 ULONG DefaultConfigFlags
= 0;
1224 Status
= ZwSetValueKey(InstanceKey
,
1228 &DefaultConfigFlags
,
1229 sizeof(DefaultConfigFlags
));
1233 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1235 /* Create the 'Control' key */
1236 RtlInitUnicodeString(&KeyName
,
1238 InitializeObjectAttributes(&ObjectAttributes
,
1240 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1243 Status
= ZwCreateKey(&LogConfKey
,
1248 REG_OPTION_VOLATILE
,
1250 if (NT_SUCCESS(Status
))
1252 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1253 RtlInitUnicodeString(&KeyName
,
1254 L
"DeviceReference");
1255 Status
= ZwSetValueKey(LogConfKey
,
1262 ZwClose(LogConfKey
);
1267 DPRINT("IopSetDeviceInstanceData() done\n");
1269 return STATUS_SUCCESS
;
1274 IopAssignDeviceResources(
1275 IN PDEVICE_NODE DeviceNode
,
1276 OUT ULONG
*pRequiredSize
)
1278 PIO_RESOURCE_LIST ResourceList
;
1279 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1280 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
1281 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1282 ULONG NumberOfResources
= 0;
1287 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1289 /* No resource needed for this device */
1290 DeviceNode
->ResourceList
= NULL
;
1291 return STATUS_SUCCESS
;
1294 /* Fill DeviceNode->ResourceList
1295 * FIXME: the PnP arbiter should go there!
1296 * Actually, use the BootResources if provided, else the resource list #0
1299 if (DeviceNode
->BootResources
)
1301 /* Browse the boot resources to know if we have some custom structures */
1302 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1303 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1305 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1306 if (pPartialResourceList
->Version
!= 1 || pPartialResourceList
->Revision
!= 1)
1308 Status
= STATUS_REVISION_MISMATCH
;
1311 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1312 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1313 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1315 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1316 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1320 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1321 if (!DeviceNode
->ResourceList
)
1323 Status
= STATUS_NO_MEMORY
;
1326 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1328 *pRequiredSize
= Size
;
1329 return STATUS_SUCCESS
;
1332 /* Ok, here, we have to use the device requirement list */
1333 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1334 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1336 Status
= STATUS_REVISION_MISMATCH
;
1340 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1341 *pRequiredSize
= Size
;
1342 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1343 if (!DeviceNode
->ResourceList
)
1345 Status
= STATUS_NO_MEMORY
;
1349 DeviceNode
->ResourceList
->Count
= 1;
1350 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1351 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1352 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1353 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1355 for (i
= 0; i
< ResourceList
->Count
; i
++)
1357 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1359 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1361 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1362 NumberOfResources
++;
1364 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1365 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
1366 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1367 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
1368 switch (ResourceDescriptor
->Type
)
1370 case CmResourceTypePort
:
1372 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1373 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
1376 case CmResourceTypeInterrupt
:
1378 INTERFACE_TYPE BusType
;
1383 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1384 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1385 /* FIXME: HACK: if we have a PCI device, we try
1386 * to keep the IRQ assigned by the BIOS */
1387 if (NT_SUCCESS(IoGetDeviceProperty(
1388 DeviceNode
->PhysicalDeviceObject
,
1389 DevicePropertyLegacyBusType
,
1390 sizeof(INTERFACE_TYPE
),
1392 &ret
)) && BusType
== PCIBus
)
1394 /* We have a PCI bus */
1395 if (NT_SUCCESS(IoGetDeviceProperty(
1396 DeviceNode
->PhysicalDeviceObject
,
1397 DevicePropertyAddress
,
1400 &ret
)) && SlotNumber
> 0)
1402 /* We have a good slot number */
1403 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1404 DeviceNode
->ResourceRequirements
->BusNumber
,
1407 0x3c /* PCI_INTERRUPT_LINE */,
1409 if (ret
!= 0 && ret
!= 2
1410 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1411 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1413 /* The device already has an assigned IRQ */
1414 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1418 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1419 DescriptorRaw
->u
.Interrupt
.Vector
,
1420 &DeviceNode
->InstancePath
);
1421 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1422 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1423 DeviceNode
->ResourceRequirements
->BusNumber
,
1426 0x3c /* PCI_INTERRUPT_LINE */,
1428 if (ret
== 0 || ret
== 2)
1435 case CmResourceTypeMemory
:
1437 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1438 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
1441 case CmResourceTypeDma
:
1443 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1444 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
1445 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
1448 case CmResourceTypeBusNumber
:
1450 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1451 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
1452 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
1455 /*CmResourceTypeDevicePrivate:
1456 case CmResourceTypePcCardConfig:
1457 case CmResourceTypeMfCardConfig:
1460 &DescriptorRaw->u.DevicePrivate,
1461 &ResourceDescriptor->u.DevicePrivate,
1462 sizeof(ResourceDescriptor->u.DevicePrivate));
1464 &DescriptorTranslated->u.DevicePrivate,
1465 &ResourceDescriptor->u.DevicePrivate,
1466 sizeof(ResourceDescriptor->u.DevicePrivate));
1470 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1471 NumberOfResources
--;
1477 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1479 return STATUS_SUCCESS
;
1482 if (DeviceNode
->ResourceList
)
1484 ExFreePool(DeviceNode
->ResourceList
);
1485 DeviceNode
->ResourceList
= NULL
;
1492 IopTranslateDeviceResources(
1493 IN PDEVICE_NODE DeviceNode
,
1494 IN ULONG RequiredSize
)
1496 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1497 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1501 if (!DeviceNode
->ResourceList
)
1503 DeviceNode
->ResourceListTranslated
= NULL
;
1504 return STATUS_SUCCESS
;
1507 /* That's easy to translate a resource list. Just copy the
1508 * untranslated one and change few fields in the copy
1510 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1511 if (!DeviceNode
->ResourceListTranslated
)
1513 Status
=STATUS_NO_MEMORY
;
1516 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1518 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1520 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1521 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1523 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1524 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1525 switch (DescriptorRaw
->Type
)
1527 case CmResourceTypePort
:
1529 ULONG AddressSpace
= 0; /* IO space */
1530 if (!HalTranslateBusAddress(
1531 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1532 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1533 DescriptorRaw
->u
.Port
.Start
,
1535 &DescriptorTranslated
->u
.Port
.Start
))
1537 Status
= STATUS_UNSUCCESSFUL
;
1542 case CmResourceTypeInterrupt
:
1544 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1545 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1546 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1547 DescriptorRaw
->u
.Interrupt
.Level
,
1548 DescriptorRaw
->u
.Interrupt
.Vector
,
1549 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1550 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1553 case CmResourceTypeMemory
:
1555 ULONG AddressSpace
= 1; /* Memory space */
1556 if (!HalTranslateBusAddress(
1557 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1558 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1559 DescriptorRaw
->u
.Memory
.Start
,
1561 &DescriptorTranslated
->u
.Memory
.Start
))
1563 Status
= STATUS_UNSUCCESSFUL
;
1568 case CmResourceTypeDma
:
1569 case CmResourceTypeBusNumber
:
1570 case CmResourceTypeDeviceSpecific
:
1574 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1575 Status
= STATUS_NOT_IMPLEMENTED
;
1580 return STATUS_SUCCESS
;
1583 /* Yes! Also delete ResourceList because ResourceList and
1584 * ResourceListTranslated should be a pair! */
1585 ExFreePool(DeviceNode
->ResourceList
);
1586 DeviceNode
->ResourceList
= NULL
;
1587 if (DeviceNode
->ResourceListTranslated
)
1589 ExFreePool(DeviceNode
->ResourceListTranslated
);
1590 DeviceNode
->ResourceList
= NULL
;
1597 * IopGetParentIdPrefix
1599 * Retrieve (or create) a string which identifies a device.
1603 * Pointer to device node.
1605 * Pointer to the string where is returned the parent node identifier
1608 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1609 * valid and its Buffer field is NULL-terminated. The caller needs to
1610 * to free the string with RtlFreeUnicodeString when it is no longer
1615 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1616 PUNICODE_STRING ParentIdPrefix
)
1618 ULONG KeyNameBufferLength
;
1619 PWSTR KeyNameBuffer
= NULL
;
1620 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1621 UNICODE_STRING KeyName
;
1622 UNICODE_STRING KeyValue
;
1623 UNICODE_STRING ValueName
;
1624 OBJECT_ATTRIBUTES ObjectAttributes
;
1629 /* HACK: As long as some devices have a NULL device
1630 * instance path, the following test is required :(
1632 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1634 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1635 &DeviceNode
->InstancePath
);
1636 return STATUS_UNSUCCESSFUL
;
1639 /* 1. Try to retrieve ParentIdPrefix from registry */
1640 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1641 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1642 if (!ParentIdPrefixInformation
)
1644 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1647 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1650 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1653 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1654 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1655 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1656 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1657 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1658 if (!NT_SUCCESS(Status
))
1660 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1661 Status
= ZwQueryValueKey(
1663 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1664 KeyNameBufferLength
, &KeyNameBufferLength
);
1665 if (NT_SUCCESS(Status
))
1667 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1668 Status
= STATUS_UNSUCCESSFUL
;
1671 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1672 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1676 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1678 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1679 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1683 /* 2. Create the ParentIdPrefix value */
1684 crc32
= RtlComputeCrc32(0,
1685 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1686 DeviceNode
->Parent
->InstancePath
.Length
);
1688 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1689 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1691 /* 3. Try to write the ParentIdPrefix to registry */
1692 Status
= ZwSetValueKey(hKey
,
1696 (PVOID
)KeyValue
.Buffer
,
1697 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1700 if (NT_SUCCESS(Status
))
1702 /* Duplicate the string to return it */
1703 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1705 ExFreePool(ParentIdPrefixInformation
);
1706 ExFreePool(KeyNameBuffer
);
1714 * IopActionInterrogateDeviceStack
1716 * Retrieve information for all (direct) child nodes of a parent node.
1720 * Pointer to device node.
1722 * Pointer to parent node to retrieve child node information for.
1725 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1726 * when we reach a device node which is not a direct child of the device
1727 * node for which we retrieve information of child nodes for. Any errors
1728 * that occur is logged instead so that all child services have a chance
1729 * of being interrogated.
1733 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1736 IO_STATUS_BLOCK IoStatusBlock
;
1737 PDEVICE_NODE ParentDeviceNode
;
1738 WCHAR InstancePath
[MAX_PATH
];
1739 IO_STACK_LOCATION Stack
;
1745 ULONG RequiredLength
;
1747 HANDLE InstanceKey
= NULL
;
1748 UNICODE_STRING ValueName
;
1749 UNICODE_STRING ParentIdPrefix
= { 0 };
1750 DEVICE_CAPABILITIES DeviceCapabilities
;
1752 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1753 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1755 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1758 * We are called for the parent too, but we don't need to do special
1759 * handling for this node
1762 if (DeviceNode
== ParentDeviceNode
)
1764 DPRINT("Success\n");
1765 return STATUS_SUCCESS
;
1769 * Make sure this device node is a direct child of the parent device node
1770 * that is given as an argument
1773 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1775 /* Stop the traversal immediately and indicate successful operation */
1777 return STATUS_UNSUCCESSFUL
;
1781 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1782 if (!NT_SUCCESS(Status
))
1784 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1789 * FIXME: For critical errors, cleanup and disable device, but always
1790 * return STATUS_SUCCESS.
1793 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1795 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1796 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1800 if (NT_SUCCESS(Status
))
1802 /* Copy the device id string */
1803 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1806 * FIXME: Check for valid characters, if there is invalid characters
1812 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1815 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1817 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1818 if (!NT_SUCCESS(Status
))
1820 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1823 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1825 if (!DeviceCapabilities
.UniqueID
)
1827 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1828 DPRINT("Instance ID is not unique\n");
1829 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1830 if (!NT_SUCCESS(Status
))
1832 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1836 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1838 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1839 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1843 if (NT_SUCCESS(Status
))
1845 /* Append the instance id string */
1846 wcscat(InstancePath
, L
"\\");
1847 if (ParentIdPrefix
.Length
> 0)
1849 /* Add information from parent bus device to InstancePath */
1850 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1851 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1852 wcscat(InstancePath
, L
"&");
1854 if (IoStatusBlock
.Information
)
1855 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1858 * FIXME: Check for valid characters, if there is invalid characters
1864 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1866 RtlFreeUnicodeString(&ParentIdPrefix
);
1868 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1870 DPRINT("No resources\n");
1871 /* FIXME: Cleanup and disable device */
1874 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1877 * Create registry key for the instance id, if it doesn't exist yet
1879 KeyBuffer
= ExAllocatePool(
1881 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1882 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1883 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1884 Status
= IopCreateDeviceKeyPath(KeyBuffer
, &InstanceKey
);
1885 ExFreePool(KeyBuffer
);
1886 if (!NT_SUCCESS(Status
))
1888 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1893 /* Set 'Capabilities' value */
1894 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1895 Status
= ZwSetValueKey(InstanceKey
,
1899 (PVOID
)&DeviceNode
->CapabilityFlags
,
1902 /* Set 'UINumber' value */
1903 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1905 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1906 Status
= ZwSetValueKey(InstanceKey
,
1910 &DeviceCapabilities
.UINumber
,
1915 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1917 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1918 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1922 if (NT_SUCCESS(Status
))
1925 * FIXME: Check for valid characters, if there is invalid characters
1929 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1930 DPRINT("Hardware IDs:\n");
1933 DPRINT(" %S\n", Ptr
);
1934 Length
= wcslen(Ptr
) + 1;
1937 TotalLength
+= Length
;
1939 DPRINT("TotalLength: %hu\n", TotalLength
);
1942 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1943 Status
= ZwSetValueKey(InstanceKey
,
1947 (PVOID
)IoStatusBlock
.Information
,
1948 (TotalLength
+ 1) * sizeof(WCHAR
));
1949 if (!NT_SUCCESS(Status
))
1951 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1956 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1959 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1961 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1962 Status
= IopInitiatePnpIrp(
1963 DeviceNode
->PhysicalDeviceObject
,
1967 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1970 * FIXME: Check for valid characters, if there is invalid characters
1974 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1975 DPRINT("Compatible IDs:\n");
1978 DPRINT(" %S\n", Ptr
);
1979 Length
= wcslen(Ptr
) + 1;
1982 TotalLength
+= Length
;
1984 DPRINT("TotalLength: %hu\n", TotalLength
);
1987 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1988 Status
= ZwSetValueKey(InstanceKey
,
1992 (PVOID
)IoStatusBlock
.Information
,
1993 (TotalLength
+ 1) * sizeof(WCHAR
));
1994 if (!NT_SUCCESS(Status
))
1996 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
2001 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2004 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2006 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2007 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2008 Status
= IopInitiatePnpIrp(
2009 DeviceNode
->PhysicalDeviceObject
,
2011 IRP_MN_QUERY_DEVICE_TEXT
,
2013 /* This key is mandatory, so even if the Irp fails, we still write it */
2014 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2015 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2017 if (NT_SUCCESS(Status
) &&
2018 IoStatusBlock
.Information
&&
2019 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2021 /* This key is overriden when a driver is installed. Don't write the
2022 * new description if another one already exists */
2023 Status
= ZwSetValueKey(InstanceKey
,
2027 (PVOID
)IoStatusBlock
.Information
,
2028 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2032 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2033 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2035 Status
= ZwSetValueKey(InstanceKey
,
2040 DeviceDesc
.MaximumLength
);
2042 if (!NT_SUCCESS(Status
))
2044 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2050 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2052 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2053 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2054 Status
= IopInitiatePnpIrp(
2055 DeviceNode
->PhysicalDeviceObject
,
2057 IRP_MN_QUERY_DEVICE_TEXT
,
2059 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2061 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2062 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2063 Status
= ZwSetValueKey(InstanceKey
,
2067 (PVOID
)IoStatusBlock
.Information
,
2068 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2069 if (!NT_SUCCESS(Status
))
2071 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2076 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2079 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2081 Status
= IopInitiatePnpIrp(
2082 DeviceNode
->PhysicalDeviceObject
,
2084 IRP_MN_QUERY_BUS_INFORMATION
,
2086 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2088 PPNP_BUS_INFORMATION BusInformation
=
2089 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2091 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2092 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2093 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2094 ExFreePool(BusInformation
);
2098 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2100 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2101 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2102 DeviceNode
->ChildBusTypeIndex
= -1;
2105 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2107 Status
= IopInitiatePnpIrp(
2108 DeviceNode
->PhysicalDeviceObject
,
2110 IRP_MN_QUERY_RESOURCES
,
2112 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2114 DeviceNode
->BootResources
=
2115 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2116 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2120 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2121 DeviceNode
->BootResources
= NULL
;
2124 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2126 Status
= IopInitiatePnpIrp(
2127 DeviceNode
->PhysicalDeviceObject
,
2129 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2131 if (NT_SUCCESS(Status
))
2133 DeviceNode
->ResourceRequirements
=
2134 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2135 if (IoStatusBlock
.Information
)
2136 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2138 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2142 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2143 DeviceNode
->ResourceRequirements
= NULL
;
2147 if (InstanceKey
!= NULL
)
2149 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2152 ZwClose(InstanceKey
);
2154 DeviceNode
->Flags
|= DNF_PROCESSED
;
2156 /* Report the device to the user-mode pnp manager */
2157 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2158 &DeviceNode
->InstancePath
);
2160 return STATUS_SUCCESS
;
2168 IoSynchronousInvalidateDeviceRelations(
2169 IN PDEVICE_OBJECT DeviceObject
,
2170 IN DEVICE_RELATION_TYPE Type
)
2172 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2173 DEVICETREE_TRAVERSE_CONTEXT Context
;
2174 PDEVICE_RELATIONS DeviceRelations
;
2175 IO_STATUS_BLOCK IoStatusBlock
;
2176 PDEVICE_NODE ChildDeviceNode
;
2177 IO_STACK_LOCATION Stack
;
2178 BOOLEAN BootDrivers
;
2179 OBJECT_ATTRIBUTES ObjectAttributes
;
2180 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
2185 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2187 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2189 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
;
2191 Status
= IopInitiatePnpIrp(
2194 IRP_MN_QUERY_DEVICE_RELATIONS
,
2196 if (!NT_SUCCESS(Status
))
2198 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2202 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2204 if (!DeviceRelations
|| DeviceRelations
->Count
<= 0)
2206 DPRINT("No PDOs\n");
2207 if (DeviceRelations
)
2209 ExFreePool(DeviceRelations
);
2214 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2217 * Create device nodes for all discovered devices
2219 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2221 if (IopGetDeviceNode(DeviceRelations
->Objects
[i
]) != NULL
)
2223 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2226 Status
= IopCreateDeviceNode(
2228 DeviceRelations
->Objects
[i
],
2231 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2232 if (!NT_SUCCESS(Status
))
2234 DPRINT("No resources\n");
2235 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2236 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2237 ExFreePool(DeviceRelations
);
2241 ExFreePool(DeviceRelations
);
2244 * Retrieve information about all discovered children from the bus driver
2246 IopInitDeviceTreeTraverseContext(
2249 IopActionInterrogateDeviceStack
,
2252 Status
= IopTraverseDeviceTree(&Context
);
2253 if (!NT_SUCCESS(Status
))
2255 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2260 * Retrieve configuration from the registry for discovered children
2262 IopInitDeviceTreeTraverseContext(
2265 IopActionConfigureChildServices
,
2268 Status
= IopTraverseDeviceTree(&Context
);
2269 if (!NT_SUCCESS(Status
))
2271 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2276 * Get the state of the system boot. If the \\SystemRoot link isn't
2277 * created yet, we will assume that it's possible to load only boot
2280 InitializeObjectAttributes(
2286 Status
= ZwOpenFile(
2293 if (NT_SUCCESS(Status
))
2295 BootDrivers
= FALSE
;
2302 * Initialize services for discovered children. Only boot drivers will
2303 * be loaded from boot driver!
2305 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2306 if (!NT_SUCCESS(Status
))
2308 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2312 DPRINT("IopInvalidateDeviceRelations() finished\n");
2316 * IopActionConfigureChildServices
2318 * Retrieve configuration for all (direct) child nodes of a parent node.
2322 * Pointer to device node.
2324 * Pointer to parent node to retrieve child node configuration for.
2327 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2328 * when we reach a device node which is not a direct child of the device
2329 * node for which we configure child services for. Any errors that occur is
2330 * logged instead so that all child services have a chance of beeing
2335 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2338 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2339 PDEVICE_NODE ParentDeviceNode
;
2340 PUNICODE_STRING Service
;
2341 UNICODE_STRING ClassGUID
;
2344 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2346 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2349 * We are called for the parent too, but we don't need to do special
2350 * handling for this node
2352 if (DeviceNode
== ParentDeviceNode
)
2354 DPRINT("Success\n");
2355 return STATUS_SUCCESS
;
2359 * Make sure this device node is a direct child of the parent device node
2360 * that is given as an argument
2362 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2364 /* Stop the traversal immediately and indicate successful operation */
2366 return STATUS_UNSUCCESSFUL
;
2369 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2371 WCHAR RegKeyBuffer
[MAX_PATH
];
2372 UNICODE_STRING RegKey
;
2375 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2376 RegKey
.Buffer
= RegKeyBuffer
;
2379 * Retrieve configuration from Enum key
2382 Service
= &DeviceNode
->ServiceName
;
2384 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2385 RtlInitUnicodeString(Service
, NULL
);
2386 RtlInitUnicodeString(&ClassGUID
, NULL
);
2388 QueryTable
[0].Name
= L
"Service";
2389 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
2390 QueryTable
[0].EntryContext
= Service
;
2392 QueryTable
[1].Name
= L
"ClassGUID";
2393 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2394 QueryTable
[1].EntryContext
= &ClassGUID
;
2395 QueryTable
[1].DefaultType
= REG_SZ
;
2396 QueryTable
[1].DefaultData
= L
"";
2397 QueryTable
[1].DefaultLength
= 0;
2399 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2400 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2402 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2403 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2405 if (!NT_SUCCESS(Status
))
2407 /* FIXME: Log the error */
2408 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2409 &DeviceNode
->InstancePath
, Status
);
2410 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2411 return STATUS_SUCCESS
;
2414 if (Service
->Buffer
== NULL
)
2416 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2418 if (ClassGUID
.Length
!= 0)
2420 /* Device has a ClassGUID value, but no Service value.
2421 * Suppose it is using the NULL driver, so state the
2422 * device is started */
2423 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2424 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2425 DeviceNode
->Flags
|= DN_STARTED
;
2427 return STATUS_SUCCESS
;
2430 DPRINT("Got Service %S\n", Service
->Buffer
);
2433 return STATUS_SUCCESS
;
2437 * IopActionInitChildServices
2439 * Initialize the service for all (direct) child nodes of a parent node
2443 * Pointer to device node.
2445 * Pointer to parent node to initialize child node services for.
2447 * Load only driver marked as boot start.
2450 * If the driver image for a service is not loaded and initialized
2451 * it is done here too. We only return a status code indicating an
2452 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2453 * not a direct child of the device node for which we initialize
2454 * child services for. Any errors that occur is logged instead so
2455 * that all child services have a chance of being initialized.
2459 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2461 BOOLEAN BootDrivers
)
2463 PDEVICE_NODE ParentDeviceNode
;
2466 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2469 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2472 * We are called for the parent too, but we don't need to do special
2473 * handling for this node
2475 if (DeviceNode
== ParentDeviceNode
)
2477 DPRINT("Success\n");
2478 return STATUS_SUCCESS
;
2482 * Make sure this device node is a direct child of the parent device node
2483 * that is given as an argument
2486 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2489 * Stop the traversal immediately and indicate unsuccessful operation
2492 return STATUS_UNSUCCESSFUL
;
2496 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2497 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2498 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2500 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2501 PDRIVER_OBJECT DriverObject
;
2503 /* Get existing DriverObject pointer (in case the driver has
2504 already been loaded and initialized) */
2505 Status
= IopGetDriverObject(
2507 &DeviceNode
->ServiceName
,
2510 if (!NT_SUCCESS(Status
))
2512 /* Driver is not initialized, try to load it */
2513 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2515 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2517 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2518 was loaded by the bootloader */
2519 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2521 /* Initialize the driver */
2522 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2523 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2527 Status
= STATUS_SUCCESS
;
2532 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2533 &DeviceNode
->ServiceName
, Status
);
2537 /* Driver is loaded and initialized at this point */
2538 if (NT_SUCCESS(Status
))
2540 /* We have a driver for this DeviceNode */
2541 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2542 /* Attach lower level filter drivers. */
2543 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2544 /* Initialize the function driver for the device node */
2545 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2547 if (NT_SUCCESS(Status
))
2549 /* Attach upper level filter drivers. */
2550 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2551 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2553 Status
= IopStartDevice(DeviceNode
);
2557 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2558 &DeviceNode
->InstancePath
, Status
);
2564 * Don't disable when trying to load only boot drivers
2568 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2569 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2570 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2571 CPRINT("Initialization of service %S failed (Status %x)\n",
2572 DeviceNode
->ServiceName
.Buffer
, Status
);
2578 DPRINT("Device %wZ is disabled or already initialized\n",
2579 &DeviceNode
->InstancePath
);
2582 return STATUS_SUCCESS
;
2586 * IopActionInitAllServices
2588 * Initialize the service for all (direct) child nodes of a parent node. This
2589 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2593 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2596 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2600 * IopActionInitBootServices
2602 * Initialize the boot start services for all (direct) child nodes of a
2603 * parent node. This function just calls IopActionInitChildServices with
2604 * BootDrivers = TRUE.
2607 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2610 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2614 * IopInitializePnpServices
2616 * Initialize services for discovered children
2620 * Top device node to start initializing services.
2623 * When set to TRUE, only drivers marked as boot start will
2624 * be loaded. Otherwise, all drivers will be loaded.
2630 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2631 IN BOOLEAN BootDrivers
)
2633 DEVICETREE_TRAVERSE_CONTEXT Context
;
2635 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2639 IopInitDeviceTreeTraverseContext(
2642 IopActionInitBootServices
,
2647 IopInitDeviceTreeTraverseContext(
2650 IopActionInitAllServices
,
2654 return IopTraverseDeviceTree(&Context
);
2657 static NTSTATUS INIT_FUNCTION
2658 IopEnumerateDetectedDevices(
2660 IN PUNICODE_STRING RelativePath
,
2662 IN BOOLEAN EnumerateSubKeys
,
2663 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2664 IN ULONG ParentBootResourcesLength
)
2666 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2667 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2668 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2669 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2670 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2671 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2672 OBJECT_ATTRIBUTES ObjectAttributes
;
2673 HANDLE hDevicesKey
= NULL
;
2674 HANDLE hDeviceKey
= NULL
;
2675 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2676 UNICODE_STRING Level2NameU
;
2677 WCHAR Level2Name
[5];
2678 ULONG IndexDevice
= 0;
2680 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2681 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2682 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2683 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2684 UNICODE_STRING DeviceName
, ValueName
;
2686 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2687 ULONG BootResourcesLength
;
2690 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI BIOS");
2691 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2692 static ULONG DeviceIndexPci
= 0;
2694 const UNICODE_STRING IdentifierAcpi
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2695 UNICODE_STRING HardwareIdAcpi
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2696 static ULONG DeviceIndexAcpi
= 0;
2698 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2699 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2700 static ULONG DeviceIndexSerial
= 0;
2701 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2702 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2703 static ULONG DeviceIndexKeyboard
= 0;
2704 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2705 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2706 static ULONG DeviceIndexMouse
= 0;
2707 PUNICODE_STRING pHardwareId
;
2708 ULONG DeviceIndex
= 0;
2710 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2711 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2712 if (!NT_SUCCESS(Status
))
2714 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2718 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2719 if (!pDeviceInformation
)
2721 DPRINT("ExAllocatePool() failed\n");
2722 Status
= STATUS_NO_MEMORY
;
2726 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2727 if (!pValueInformation
)
2729 DPRINT("ExAllocatePool() failed\n");
2730 Status
= STATUS_NO_MEMORY
;
2736 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2737 if (Status
== STATUS_NO_MORE_ENTRIES
)
2739 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2741 ExFreePool(pDeviceInformation
);
2742 DeviceInfoLength
= RequiredSize
;
2743 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2744 if (!pDeviceInformation
)
2746 DPRINT("ExAllocatePool() failed\n");
2747 Status
= STATUS_NO_MEMORY
;
2750 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2752 if (!NT_SUCCESS(Status
))
2754 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2759 /* Open device key */
2760 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2761 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2762 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2765 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0),
2767 if (!NT_SUCCESS(Status
))
2769 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2773 /* Read boot resources, and add then to parent ones */
2774 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2775 if (Status
== STATUS_BUFFER_OVERFLOW
)
2777 ExFreePool(pValueInformation
);
2778 ValueInfoLength
= RequiredSize
;
2779 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2780 if (!pValueInformation
)
2782 DPRINT("ExAllocatePool() failed\n");
2783 ZwDeleteKey(hLevel2Key
);
2784 Status
= STATUS_NO_MEMORY
;
2787 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2789 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2791 BootResources
= ParentBootResources
;
2792 BootResourcesLength
= ParentBootResourcesLength
;
2794 else if (!NT_SUCCESS(Status
))
2796 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2799 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2801 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2804 else if (((PCM_FULL_RESOURCE_DESCRIPTOR
)pValueInformation
->Data
)->PartialResourceList
.Count
== 0)
2806 BootResources
= ParentBootResources
;
2807 BootResourcesLength
= ParentBootResourcesLength
;
2811 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2813 /* Concatenate current resources and parent ones */
2814 if (ParentBootResourcesLength
== 0)
2815 BootResourcesLength
= pValueInformation
->DataLength
;
2817 BootResourcesLength
= ParentBootResourcesLength
2818 + pValueInformation
->DataLength
2820 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2823 DPRINT("ExAllocatePool() failed\n");
2826 if (ParentBootResourcesLength
== 0)
2828 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2830 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2832 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2834 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2835 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2836 ParentBootResourcesLength
- Header
);
2837 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2841 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2843 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2844 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2845 ParentBootResourcesLength
- Header
);
2847 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2848 pValueInformation
->Data
+ Header
,
2849 pValueInformation
->DataLength
- Header
);
2850 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2854 if (EnumerateSubKeys
)
2859 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2860 if (Status
== STATUS_NO_MORE_ENTRIES
)
2862 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2864 ExFreePool(pDeviceInformation
);
2865 DeviceInfoLength
= RequiredSize
;
2866 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2867 if (!pDeviceInformation
)
2869 DPRINT("ExAllocatePool() failed\n");
2870 Status
= STATUS_NO_MEMORY
;
2873 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2875 if (!NT_SUCCESS(Status
))
2877 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2881 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2882 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2884 Status
= IopEnumerateDetectedDevices(
2890 BootResourcesLength
);
2891 if (!NT_SUCCESS(Status
))
2896 /* Read identifier */
2897 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2898 if (Status
== STATUS_BUFFER_OVERFLOW
)
2900 ExFreePool(pValueInformation
);
2901 ValueInfoLength
= RequiredSize
;
2902 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2903 if (!pValueInformation
)
2905 DPRINT("ExAllocatePool() failed\n");
2906 Status
= STATUS_NO_MEMORY
;
2909 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2911 if (!NT_SUCCESS(Status
))
2913 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2915 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2918 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2920 else if (pValueInformation
->Type
!= REG_SZ
)
2922 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2927 /* Assign hardware id to this device */
2928 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2929 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2930 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2931 ValueName
.Length
-= sizeof(WCHAR
);
2934 if (RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2936 pHardwareId
= &HardwareIdSerial
;
2937 DeviceIndex
= DeviceIndexSerial
++;
2939 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2941 pHardwareId
= &HardwareIdKeyboard
;
2942 DeviceIndex
= DeviceIndexKeyboard
++;
2944 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2946 pHardwareId
= &HardwareIdMouse
;
2947 DeviceIndex
= DeviceIndexMouse
++;
2949 else if (NT_SUCCESS(Status
))
2951 /* Try to also match the device identifier */
2952 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2954 pHardwareId
= &HardwareIdPci
;
2955 DeviceIndex
= DeviceIndexPci
++;
2958 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierAcpi
, FALSE
) == 0)
2960 pHardwareId
= &HardwareIdAcpi
;
2961 DeviceIndex
= DeviceIndexAcpi
++;
2966 /* Unknown device */
2967 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2973 /* Unknown key path */
2974 DPRINT("Unknown key path %wZ\n", RelativePath
);
2978 /* Add the detected device to Root key */
2979 InitializeObjectAttributes(&ObjectAttributes
, pHardwareId
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2980 Status
= ZwCreateKey(
2986 REG_OPTION_NON_VOLATILE
,
2988 if (!NT_SUCCESS(Status
))
2990 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2993 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2994 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2995 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2996 Status
= ZwCreateKey(
2998 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3002 REG_OPTION_NON_VOLATILE
,
3004 ZwClose(hLevel1Key
);
3005 if (!NT_SUCCESS(Status
))
3007 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3010 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, pHardwareId
);
3011 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
3012 if (!NT_SUCCESS(Status
))
3014 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3015 ZwDeleteKey(hLevel2Key
);
3018 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3019 if (!NT_SUCCESS(Status
))
3021 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3022 ZwDeleteKey(hLevel2Key
);
3025 /* Create 'LogConf' subkey */
3026 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3027 Status
= ZwCreateKey(
3033 REG_OPTION_VOLATILE
,
3035 if (!NT_SUCCESS(Status
))
3037 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3038 ZwDeleteKey(hLevel2Key
);
3041 if (BootResourcesLength
> 0)
3043 /* Save boot resources to 'LogConf\BootConfig' */
3044 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
3045 if (!NT_SUCCESS(Status
))
3047 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3049 ZwDeleteKey(hLevel2Key
);
3056 if (BootResources
&& BootResources
!= ParentBootResources
)
3057 ExFreePool(BootResources
);
3060 ZwClose(hLevel2Key
);
3065 ZwClose(hDeviceKey
);
3070 Status
= STATUS_SUCCESS
;
3074 ZwClose(hDevicesKey
);
3076 ZwClose(hDeviceKey
);
3077 if (pDeviceInformation
)
3078 ExFreePool(pDeviceInformation
);
3079 if (pValueInformation
)
3080 ExFreePool(pValueInformation
);
3084 static BOOLEAN INIT_FUNCTION
3085 IopIsAcpiComputer(VOID
)
3090 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3091 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3092 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3093 OBJECT_ATTRIBUTES ObjectAttributes
;
3094 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3095 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3096 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3097 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3099 ULONG IndexDevice
= 0;
3100 UNICODE_STRING DeviceName
, ValueName
;
3101 HANDLE hDevicesKey
= NULL
;
3102 HANDLE hDeviceKey
= NULL
;
3104 BOOLEAN ret
= FALSE
;
3106 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3107 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3108 if (!NT_SUCCESS(Status
))
3110 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3114 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3115 if (!pDeviceInformation
)
3117 DPRINT("ExAllocatePool() failed\n");
3118 Status
= STATUS_NO_MEMORY
;
3122 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3123 if (!pDeviceInformation
)
3125 DPRINT("ExAllocatePool() failed\n");
3126 Status
= STATUS_NO_MEMORY
;
3132 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3133 if (Status
== STATUS_NO_MORE_ENTRIES
)
3135 else if (Status
== STATUS_BUFFER_OVERFLOW
)
3137 ExFreePool(pDeviceInformation
);
3138 DeviceInfoLength
= RequiredSize
;
3139 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3140 if (!pDeviceInformation
)
3142 DPRINT("ExAllocatePool() failed\n");
3143 Status
= STATUS_NO_MEMORY
;
3146 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3148 if (!NT_SUCCESS(Status
))
3150 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3155 /* Open device key */
3156 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3157 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3158 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3163 if (!NT_SUCCESS(Status
))
3165 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3169 /* Read identifier */
3170 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3171 if (Status
== STATUS_BUFFER_OVERFLOW
)
3173 ExFreePool(pValueInformation
);
3174 ValueInfoLength
= RequiredSize
;
3175 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3176 if (!pValueInformation
)
3178 DPRINT("ExAllocatePool() failed\n");
3179 Status
= STATUS_NO_MEMORY
;
3182 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3184 if (!NT_SUCCESS(Status
))
3186 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3189 else if (pValueInformation
->Type
!= REG_SZ
)
3191 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3195 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3196 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3197 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3198 ValueName
.Length
-= sizeof(WCHAR
);
3199 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3201 DPRINT("Found ACPI BIOS\n");
3207 ZwClose(hDeviceKey
);
3212 if (pDeviceInformation
)
3213 ExFreePool(pDeviceInformation
);
3214 if (pValueInformation
)
3215 ExFreePool(pValueInformation
);
3217 ZwClose(hDevicesKey
);
3219 ZwClose(hDeviceKey
);
3224 static NTSTATUS INIT_FUNCTION
3225 IopUpdateRootKey(VOID
)
3227 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum\\Root");
3228 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3229 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3230 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3231 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
3232 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3233 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3234 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3235 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3236 OBJECT_ATTRIBUTES ObjectAttributes
;
3237 HANDLE hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
3240 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3241 Status
= ZwOpenKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
);
3242 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3244 /* We are probably in 1st stage */
3245 return STATUS_SUCCESS
;
3247 else if (!NT_SUCCESS(Status
))
3249 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3253 if (IopIsAcpiComputer())
3255 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3256 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3258 if (!NT_SUCCESS(Status
))
3260 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3261 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3262 ZwClose(hHalAcpiDevice
);
3263 if (!NT_SUCCESS(Status
))
3265 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3266 if (NT_SUCCESS(Status
))
3267 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3268 if (NT_SUCCESS(Status
))
3270 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hHalAcpiId
, NULL
);
3271 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3272 if (NT_SUCCESS(Status
))
3275 ZwClose(hHalAcpiId
);
3280 Status
= IopEnumerateDetectedDevices(
3292 static NTSTATUS INIT_FUNCTION
3294 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
3296 return STATUS_SUCCESS
;
3305 DPRINT("PnpInit()\n");
3307 KeInitializeSpinLock(&IopDeviceTreeLock
);
3309 /* Initialize the Bus Type GUID List */
3310 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3311 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3312 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3314 /* Initialize PnP-Event notification support */
3315 Status
= IopInitPlugPlayEvents();
3316 if (!NT_SUCCESS(Status
))
3318 CPRINT("IopInitPlugPlayEvents() failed\n");
3319 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3323 * Create root device node
3326 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
3327 if (!NT_SUCCESS(Status
))
3329 CPRINT("IoCreateDriverObject() failed\n");
3330 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3333 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3335 if (!NT_SUCCESS(Status
))
3337 CPRINT("IoCreateDevice() failed\n");
3338 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3341 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
3342 if (!NT_SUCCESS(Status
))
3344 CPRINT("Insufficient resources\n");
3345 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3348 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3351 CPRINT("Failed to create the instance path!\n");
3352 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3355 /* Report the device to the user-mode pnp manager */
3356 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3357 &IopRootDeviceNode
->InstancePath
);
3359 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3360 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3361 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3362 IopRootDriverObject
->DriverExtension
->AddDevice(
3363 IopRootDriverObject
,
3364 IopRootDeviceNode
->PhysicalDeviceObject
);
3366 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3367 Status
= IopUpdateRootKey();
3368 if (!NT_SUCCESS(Status
))
3370 CPRINT("IopUpdateRootKey() failed\n");
3371 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3375 RTL_GENERIC_COMPARE_RESULTS
3377 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3378 IN PVOID FirstStruct
,
3379 IN PVOID SecondStruct
)
3387 // The allocation function is called by the generic table package whenever
3388 // it needs to allocate memory for the table.
3393 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3403 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3412 PpInitializeDeviceReferenceTable(VOID
)
3414 /* Setup the guarded mutex and AVL table */
3415 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3416 RtlInitializeGenericTableAvl(
3417 &PpDeviceReferenceTable
,
3418 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3419 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3420 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3428 /* Initialize the resource when accessing device registry data */
3429 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3431 /* Setup the device reference AVL table */
3432 PpInitializeDeviceReferenceTable();
3440 /* Check the initialization phase */
3441 switch (ExpInitializationPhase
)
3446 return PiInitPhase0();
3452 //return PiInitPhase1();
3456 /* Don't know any other phase! Bugcheck! */
3457 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);