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 #define ENUM_ROOT L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum"
24 PDEVICE_NODE IopRootDeviceNode
;
25 KSPIN_LOCK IopDeviceTreeLock
;
26 ERESOURCE PpRegistryDeviceResource
;
27 KGUARDED_MUTEX PpDeviceReferenceTableLock
;
28 RTL_AVL_TABLE PpDeviceReferenceTable
;
30 extern ULONG ExpInitializationPhase
;
32 /* DATA **********************************************************************/
34 PDRIVER_OBJECT IopRootDriverObject
;
35 PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList
= NULL
;
37 #if defined (ALLOC_PRAGMA)
38 #pragma alloc_text(INIT, PnpInit)
39 #pragma alloc_text(INIT, PnpInit2)
42 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
44 PDEVICE_OBJECT DeviceObject
;
45 DEVICE_RELATION_TYPE Type
;
46 PIO_WORKITEM WorkItem
;
47 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
51 IoSynchronousInvalidateDeviceRelations(
52 IN PDEVICE_OBJECT DeviceObject
,
53 IN DEVICE_RELATION_TYPE Type
);
56 /* FUNCTIONS *****************************************************************/
59 IopAssignDeviceResources(
60 IN PDEVICE_NODE DeviceNode
,
61 OUT ULONG
*pRequiredSize
);
63 IopTranslateDeviceResources(
64 IN PDEVICE_NODE DeviceNode
,
65 IN ULONG RequiredSize
);
69 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
71 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
76 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
77 PDRIVER_OBJECT DriverObject
)
82 if (!DriverObject
->DriverExtension
->AddDevice
)
83 return STATUS_SUCCESS
;
85 /* This is a Plug and Play driver */
86 DPRINT("Plug and Play driver found\n");
87 ASSERT(DeviceNode
->PhysicalDeviceObject
);
89 /* Check if this plug-and-play driver is used as a legacy one for this device node */
90 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
92 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
93 return STATUS_SUCCESS
;
96 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
97 &DriverObject
->DriverName
,
98 &DeviceNode
->InstancePath
);
99 Status
= DriverObject
->DriverExtension
->AddDevice(
100 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
101 if (!NT_SUCCESS(Status
))
103 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
107 /* Check if driver added a FDO above the PDO */
108 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
109 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
111 /* FIXME: What do we do? Unload the driver or just disable the device? */
112 DPRINT1("An FDO was not attached\n");
113 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
114 return STATUS_UNSUCCESSFUL
;
117 /* Check if we have a ACPI device (needed for power management) */
118 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
120 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
122 /* There can be only one system power device */
123 if (!SystemPowerDeviceNodeCreated
)
125 PopSystemPowerDeviceNode
= DeviceNode
;
126 ObReferenceObject(PopSystemPowerDeviceNode
);
127 SystemPowerDeviceNodeCreated
= TRUE
;
131 ObDereferenceObject(Fdo
);
133 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
134 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
136 return STATUS_SUCCESS
;
141 PDEVICE_NODE DeviceNode
)
143 IO_STATUS_BLOCK IoStatusBlock
;
144 IO_STACK_LOCATION Stack
;
145 ULONG RequiredLength
;
149 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
151 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
152 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
153 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
154 Status
= IopInitiatePnpIrp(
157 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
159 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
161 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
164 DeviceNode
->ResourceRequirements
= Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
166 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
167 if (NT_SUCCESS(Status
))
169 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
170 if (NT_SUCCESS(Status
))
172 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
176 DPRINT("IopTranslateDeviceResources() failed (Status 0x%08lx)\n", Status
);
181 DPRINT("IopAssignDeviceResources() failed (Status 0x%08lx)\n", Status
);
183 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
185 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
186 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
187 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
190 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and
191 * actually _depend_ on this!. This is because NT will lock the Device Node
192 * with an ERESOURCE, which of course requires APCs to be disabled.
194 KeEnterCriticalRegion();
196 Status
= IopInitiatePnpIrp(
202 KeLeaveCriticalRegion();
204 if (!NT_SUCCESS(Status
))
206 DPRINT("IopInitiatePnpIrp() failed\n");
210 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
212 DPRINT("Device needs enumeration, invalidating bus relations\n");
213 /* Invalidate device relations synchronously
214 (otherwise there will be dirty read of DeviceNode) */
215 IoSynchronousInvalidateDeviceRelations(DeviceNode
->PhysicalDeviceObject
, BusRelations
);
216 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
220 ObDereferenceObject(Fdo
);
222 if (NT_SUCCESS(Status
))
223 DeviceNode
->Flags
|= DN_STARTED
;
230 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
231 PDEVICE_CAPABILITIES DeviceCaps
)
233 IO_STATUS_BLOCK StatusBlock
;
234 IO_STACK_LOCATION Stack
;
236 /* Set up the Header */
237 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
238 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
239 DeviceCaps
->Version
= 1;
240 DeviceCaps
->Address
= -1;
241 DeviceCaps
->UINumber
= -1;
243 /* Set up the Stack */
244 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
245 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
248 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
250 IRP_MN_QUERY_CAPABILITIES
,
255 IopAsynchronousInvalidateDeviceRelations(
256 IN PDEVICE_OBJECT DeviceObject
,
257 IN PVOID InvalidateContext
)
259 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
261 IoSynchronousInvalidateDeviceRelations(
265 ObDereferenceObject(Data
->WorkItem
);
266 IoFreeWorkItem(Data
->WorkItem
);
275 IoInvalidateDeviceRelations(
276 IN PDEVICE_OBJECT DeviceObject
,
277 IN DEVICE_RELATION_TYPE Type
)
279 PIO_WORKITEM WorkItem
;
280 PINVALIDATE_DEVICE_RELATION_DATA Data
;
282 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
285 WorkItem
= IoAllocateWorkItem(DeviceObject
);
292 ObReferenceObject(DeviceObject
);
293 Data
->DeviceObject
= DeviceObject
;
295 Data
->WorkItem
= WorkItem
;
299 IopAsynchronousInvalidateDeviceRelations
,
309 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
310 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
311 IN ULONG BufferLength
,
312 OUT PVOID PropertyBuffer
,
313 OUT PULONG ResultLength
)
315 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
316 DEVICE_CAPABILITIES DeviceCaps
;
322 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
326 if (DeviceNode
== NULL
)
327 return STATUS_INVALID_DEVICE_REQUEST
;
329 switch (DeviceProperty
)
331 case DevicePropertyBusNumber
:
332 Length
= sizeof(ULONG
);
333 Data
= &DeviceNode
->ChildBusNumber
;
336 /* Complete, untested */
337 case DevicePropertyBusTypeGuid
:
339 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
340 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
342 /* Return the GUID */
343 *ResultLength
= sizeof(GUID
);
345 /* Check if the buffer given was large enough */
346 if (BufferLength
< *ResultLength
)
348 return STATUS_BUFFER_TOO_SMALL
;
352 RtlCopyMemory(PropertyBuffer
,
353 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
355 return STATUS_SUCCESS
;
359 return STATUS_OBJECT_NAME_NOT_FOUND
;
363 case DevicePropertyLegacyBusType
:
364 Length
= sizeof(INTERFACE_TYPE
);
365 Data
= &DeviceNode
->ChildInterfaceType
;
368 case DevicePropertyAddress
:
369 /* Query the device caps */
370 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
371 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
374 *ResultLength
= sizeof(ULONG
);
376 /* Check if the buffer given was large enough */
377 if (BufferLength
< *ResultLength
)
379 return STATUS_BUFFER_TOO_SMALL
;
383 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
384 return STATUS_SUCCESS
;
388 return STATUS_OBJECT_NAME_NOT_FOUND
;
392 // case DevicePropertyUINumber:
393 // if (DeviceNode->CapabilityFlags == NULL)
394 // return STATUS_INVALID_DEVICE_REQUEST;
395 // Length = sizeof(ULONG);
396 // Data = &DeviceNode->CapabilityFlags->UINumber;
399 case DevicePropertyClassName
:
400 case DevicePropertyClassGuid
:
401 case DevicePropertyDriverKeyName
:
402 case DevicePropertyManufacturer
:
403 case DevicePropertyFriendlyName
:
404 case DevicePropertyHardwareID
:
405 case DevicePropertyCompatibleIDs
:
406 case DevicePropertyDeviceDescription
:
407 case DevicePropertyLocationInformation
:
408 case DevicePropertyUINumber
:
410 LPCWSTR RegistryPropertyName
;
411 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
412 UNICODE_STRING ValueName
;
413 OBJECT_ATTRIBUTES ObjectAttributes
;
414 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
415 ULONG ValueInformationLength
;
416 HANDLE KeyHandle
, EnumRootHandle
;
419 switch (DeviceProperty
)
421 case DevicePropertyClassName
:
422 RegistryPropertyName
= L
"Class"; break;
423 case DevicePropertyClassGuid
:
424 RegistryPropertyName
= L
"ClassGuid"; break;
425 case DevicePropertyDriverKeyName
:
426 RegistryPropertyName
= L
"Driver"; break;
427 case DevicePropertyManufacturer
:
428 RegistryPropertyName
= L
"Mfg"; break;
429 case DevicePropertyFriendlyName
:
430 RegistryPropertyName
= L
"FriendlyName"; break;
431 case DevicePropertyHardwareID
:
432 RegistryPropertyName
= L
"HardwareID"; break;
433 case DevicePropertyCompatibleIDs
:
434 RegistryPropertyName
= L
"CompatibleIDs"; break;
435 case DevicePropertyDeviceDescription
:
436 RegistryPropertyName
= L
"DeviceDesc"; break;
437 case DevicePropertyLocationInformation
:
438 RegistryPropertyName
= L
"LocationInformation"; break;
439 case DevicePropertyUINumber
:
440 RegistryPropertyName
= L
"UINumber"; break;
442 /* Should not happen */
444 return STATUS_UNSUCCESSFUL
;
447 DPRINT("Registry property %S\n", RegistryPropertyName
);
450 InitializeObjectAttributes(&ObjectAttributes
, &EnumRoot
,
451 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
452 Status
= ZwOpenKey(&EnumRootHandle
, 0, &ObjectAttributes
);
453 if (!NT_SUCCESS(Status
))
455 DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status
);
459 /* Open instance key */
460 InitializeObjectAttributes(&ObjectAttributes
, &DeviceNode
->InstancePath
,
461 OBJ_CASE_INSENSITIVE
, EnumRootHandle
, NULL
);
463 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
464 if (!NT_SUCCESS(Status
))
466 DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status
);
470 /* Allocate buffer to read as much data as required by the caller */
471 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
472 Data
[0]) + BufferLength
;
473 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
474 if (!ValueInformation
)
477 return STATUS_INSUFFICIENT_RESOURCES
;
481 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
482 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
483 KeyValuePartialInformation
, ValueInformation
,
484 ValueInformationLength
,
485 &ValueInformationLength
);
489 *ResultLength
= ValueInformation
->DataLength
;
491 if (!NT_SUCCESS(Status
))
493 DPRINT1("Problem: Status=%0x08x, ResultLength = %d\n", Status
, *ResultLength
);
494 ExFreePool(ValueInformation
);
495 if (Status
== STATUS_BUFFER_OVERFLOW
)
496 return STATUS_BUFFER_TOO_SMALL
;
501 /* FIXME: Verify the value (NULL-terminated, correct format). */
502 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
503 ValueInformation
->DataLength
);
504 ExFreePool(ValueInformation
);
506 return STATUS_SUCCESS
;
509 case DevicePropertyBootConfiguration
:
511 if (DeviceNode
->BootResources
->Count
!= 0)
513 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
515 Data
= &DeviceNode
->BootResources
;
518 /* FIXME: use a translated boot configuration instead */
519 case DevicePropertyBootConfigurationTranslated
:
521 if (DeviceNode
->BootResources
->Count
!= 0)
523 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
525 Data
= &DeviceNode
->BootResources
;
528 case DevicePropertyEnumeratorName
:
529 /* A buffer overflow can't happen here, since InstancePath
530 * always contains the enumerator name followed by \\ */
531 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
533 Length
= (Ptr
- DeviceNode
->InstancePath
.Buffer
+ 1) * sizeof(WCHAR
);
534 Data
= DeviceNode
->InstancePath
.Buffer
;
537 case DevicePropertyPhysicalDeviceObjectName
:
538 /* InstancePath buffer is NULL terminated, so we can do this */
539 Length
= DeviceNode
->InstancePath
.MaximumLength
;
540 Data
= DeviceNode
->InstancePath
.Buffer
;
544 return STATUS_INVALID_PARAMETER_2
;
547 /* Prepare returned values */
548 *ResultLength
= Length
;
549 if (BufferLength
< Length
)
550 return STATUS_BUFFER_TOO_SMALL
;
551 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
553 /* NULL terminate the string (if required) */
554 if (DeviceProperty
== DevicePropertyEnumeratorName
)
555 ((LPWSTR
)PropertyBuffer
)[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
557 return STATUS_SUCCESS
;
565 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
571 * @name IoOpenDeviceRegistryKey
573 * Open a registry key unique for a specified driver or device instance.
575 * @param DeviceObject Device to get the registry key for.
576 * @param DevInstKeyType Type of the key to return.
577 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
578 * @param DevInstRegKey Handle to the opened registry key on
587 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
588 IN ULONG DevInstKeyType
,
589 IN ACCESS_MASK DesiredAccess
,
590 OUT PHANDLE DevInstRegKey
)
592 static WCHAR RootKeyName
[] =
593 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
594 static WCHAR ProfileKeyName
[] =
595 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
596 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
597 static WCHAR EnumKeyName
[] = L
"Enum\\";
598 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
600 LPWSTR KeyNameBuffer
;
601 UNICODE_STRING KeyName
;
602 ULONG DriverKeyLength
;
603 OBJECT_ATTRIBUTES ObjectAttributes
;
604 PDEVICE_NODE DeviceNode
= NULL
;
607 DPRINT("IoOpenDeviceRegistryKey() called\n");
609 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
611 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
612 return STATUS_INVALID_PARAMETER
;
616 * Calculate the length of the base key name. This is the full
617 * name for driver key or the name excluding "Device Parameters"
618 * subkey for device key.
621 KeyNameLength
= sizeof(RootKeyName
);
622 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
623 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
624 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
626 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
627 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
628 0, NULL
, &DriverKeyLength
);
629 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
631 KeyNameLength
+= DriverKeyLength
;
635 DeviceNode
= IopGetDeviceNode(DeviceObject
);
636 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
637 DeviceNode
->InstancePath
.Length
;
641 * Now allocate the buffer for the key name...
644 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
645 if (KeyNameBuffer
== NULL
)
646 return STATUS_INSUFFICIENT_RESOURCES
;
649 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
650 KeyName
.Buffer
= KeyNameBuffer
;
653 * ...and build the key name.
656 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
657 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
659 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
660 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
662 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
664 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
665 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
666 DriverKeyLength
, KeyNameBuffer
+
667 (KeyName
.Length
/ sizeof(WCHAR
)),
669 if (!NT_SUCCESS(Status
))
671 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
672 ExFreePool(KeyNameBuffer
);
675 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
679 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
680 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
681 if (DeviceNode
->InstancePath
.Length
== 0)
683 ExFreePool(KeyNameBuffer
);
692 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
693 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
694 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
695 if (!NT_SUCCESS(Status
))
697 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
698 ExFreePool(KeyNameBuffer
);
701 ExFreePool(KeyNameBuffer
);
704 * For driver key we're done now.
707 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
711 * Let's go further. For device key we must open "Device Parameters"
712 * subkey and create it if it doesn't exist yet.
715 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
716 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
717 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
718 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
719 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
720 ZwClose(ObjectAttributes
.RootDirectory
);
730 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
737 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
741 if (PopSystemPowerDeviceNode
)
743 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
744 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
745 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
747 return STATUS_SUCCESS
;
750 return STATUS_UNSUCCESSFUL
;
755 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
757 USHORT i
= 0, FoundIndex
= 0xFFFF;
761 /* Acquire the lock */
762 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
764 /* Loop all entries */
765 while (i
< IopBusTypeGuidList
->GuidCount
)
767 /* Try to find a match */
768 if (RtlCompareMemory(BusTypeGuid
,
769 &IopBusTypeGuidList
->Guids
[i
],
770 sizeof(GUID
)) == sizeof(GUID
))
779 /* Check if we have to grow the list */
780 if (IopBusTypeGuidList
->GuidCount
)
782 /* Calculate the new size */
783 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
784 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
786 /* Allocate the new copy */
787 NewList
= ExAllocatePool(PagedPool
, NewSize
);
789 /* Now copy them, decrease the size too */
790 NewSize
-= sizeof(GUID
);
791 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
793 /* Free the old list */
794 ExFreePool(IopBusTypeGuidList
);
796 /* Use the new buffer */
797 IopBusTypeGuidList
= NewList
;
800 /* Copy the new GUID */
801 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
805 /* The new entry is the index */
806 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
807 IopBusTypeGuidList
->GuidCount
++;
810 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
816 * Creates a device node
819 * ParentNode = Pointer to parent device node
820 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
821 * to have the root device node create one
822 * (eg. for legacy drivers)
823 * DeviceNode = Pointer to storage for created device node
829 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
830 PDEVICE_OBJECT PhysicalDeviceObject
,
831 PUNICODE_STRING ServiceName
,
832 PDEVICE_NODE
*DeviceNode
)
838 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
839 ParentNode
, PhysicalDeviceObject
, ServiceName
);
841 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
844 return STATUS_INSUFFICIENT_RESOURCES
;
847 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
849 if (!PhysicalDeviceObject
)
851 Status
= PnpRootCreateDevice(ServiceName
, &PhysicalDeviceObject
);
852 if (!NT_SUCCESS(Status
))
854 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
859 /* This is for drivers passed on the command line to ntoskrnl.exe */
860 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
861 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
864 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
866 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
870 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
871 Node
->Parent
= ParentNode
;
872 Node
->NextSibling
= ParentNode
->Child
;
873 if (ParentNode
->Child
!= NULL
)
875 ParentNode
->Child
->PrevSibling
= Node
;
877 ParentNode
->Child
= Node
;
878 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
879 Node
->Level
= ParentNode
->Level
+ 1;
884 return STATUS_SUCCESS
;
888 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
892 /* All children must be deleted before a parent is deleted */
893 ASSERT(!DeviceNode
->Child
);
895 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
897 ASSERT(DeviceNode
->PhysicalDeviceObject
);
899 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
901 /* Unlink from parent if it exists */
903 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
905 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
908 /* Unlink from sibling list */
910 if (DeviceNode
->PrevSibling
)
912 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
915 if (DeviceNode
->NextSibling
)
917 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
920 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
922 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
924 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
926 if (DeviceNode
->ResourceList
)
928 ExFreePool(DeviceNode
->ResourceList
);
931 if (DeviceNode
->ResourceListTranslated
)
933 ExFreePool(DeviceNode
->ResourceListTranslated
);
936 if (DeviceNode
->ResourceRequirements
)
938 ExFreePool(DeviceNode
->ResourceRequirements
);
941 if (DeviceNode
->BootResources
)
943 ExFreePool(DeviceNode
->BootResources
);
946 ExFreePool(DeviceNode
);
948 return STATUS_SUCCESS
;
952 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
953 PIO_STATUS_BLOCK IoStatusBlock
,
955 PIO_STACK_LOCATION Stack OPTIONAL
)
957 PDEVICE_OBJECT TopDeviceObject
;
958 PIO_STACK_LOCATION IrpSp
;
963 /* Always call the top of the device stack */
964 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
971 Irp
= IoBuildSynchronousFsdRequest(
980 /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */
981 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
982 Irp
->IoStatus
.Information
= 0;
984 IrpSp
= IoGetNextIrpStackLocation(Irp
);
985 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
989 RtlCopyMemory(&IrpSp
->Parameters
,
991 sizeof(Stack
->Parameters
));
994 Status
= IoCallDriver(TopDeviceObject
, Irp
);
995 if (Status
== STATUS_PENDING
)
997 KeWaitForSingleObject(&Event
,
1002 Status
= IoStatusBlock
->Status
;
1005 ObDereferenceObject(TopDeviceObject
);
1012 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1014 PDEVICE_NODE ParentDeviceNode
;
1015 PDEVICE_NODE ChildDeviceNode
;
1018 /* Copy context data so we don't overwrite it in subsequent calls to this function */
1019 ParentDeviceNode
= Context
->DeviceNode
;
1021 /* Call the action routine */
1022 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
1023 if (!NT_SUCCESS(Status
))
1028 /* Traversal of all children nodes */
1029 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
1030 ChildDeviceNode
!= NULL
;
1031 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
1033 /* Pass the current device node to the action routine */
1034 Context
->DeviceNode
= ChildDeviceNode
;
1036 Status
= IopTraverseDeviceTreeNode(Context
);
1037 if (!NT_SUCCESS(Status
))
1048 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1052 DPRINT("Context 0x%p\n", Context
);
1054 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1055 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1057 /* Start from the specified device node */
1058 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1060 /* Recursively traverse the device tree */
1061 Status
= IopTraverseDeviceTreeNode(Context
);
1062 if (Status
== STATUS_UNSUCCESSFUL
)
1064 /* The action routine just wanted to terminate the traversal with status
1065 code STATUS_SUCCESS */
1066 Status
= STATUS_SUCCESS
;
1074 * IopCreateDeviceKeyPath
1076 * Creates a registry key
1080 * Name of the key to be created.
1082 * Handle to the newly created key
1085 * This method can create nested trees, so parent of RegistryPath can
1086 * be not existant, and will be created if needed.
1090 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
1093 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
1094 HANDLE hParent
= NULL
, hKey
;
1095 OBJECT_ATTRIBUTES ObjectAttributes
;
1096 UNICODE_STRING KeyName
;
1097 LPCWSTR Current
, Last
;
1101 /* Assume failure */
1104 /* Open root key for device instances */
1105 InitializeObjectAttributes(&ObjectAttributes
,
1107 OBJ_CASE_INSENSITIVE
,
1110 Status
= ZwOpenKey(&hParent
,
1113 if (!NT_SUCCESS(Status
))
1115 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
1119 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
1120 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
1122 /* Go up to the end of the string */
1123 while (Current
<= Last
)
1125 if (Current
!= Last
&& *Current
!= '\\')
1127 /* Not the end of the string and not a separator */
1132 /* Prepare relative key name */
1133 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
1134 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
1135 DPRINT("Create '%wZ'\n", &KeyName
);
1138 InitializeObjectAttributes(&ObjectAttributes
,
1140 OBJ_CASE_INSENSITIVE
,
1143 Status
= ZwCreateKey(&hKey
,
1144 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
1151 /* Close parent key handle, we don't need it anymore */
1155 /* Key opening/creating failed? */
1156 if (!NT_SUCCESS(Status
))
1158 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
1162 /* Check if it is the end of the string */
1163 if (Current
== Last
)
1165 /* Yes, return success */
1167 return STATUS_SUCCESS
;
1170 /* Start with this new parent key */
1173 KeyName
.Buffer
= (LPWSTR
)Current
;
1176 return STATUS_UNSUCCESSFUL
;
1182 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1183 PDEVICE_NODE DeviceNode
)
1185 OBJECT_ATTRIBUTES ObjectAttributes
;
1186 UNICODE_STRING KeyName
;
1189 ULONG ListSize
, ResultLength
;
1192 DPRINT("IopSetDeviceInstanceData() called\n");
1194 /* Create the 'LogConf' key */
1195 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1196 InitializeObjectAttributes(&ObjectAttributes
,
1198 OBJ_CASE_INSENSITIVE
,
1201 Status
= ZwCreateKey(&LogConfKey
,
1208 if (NT_SUCCESS(Status
))
1210 /* Set 'BootConfig' value */
1211 if (DeviceNode
->BootResources
!= NULL
)
1213 ResCount
= DeviceNode
->BootResources
->Count
;
1216 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1218 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1219 Status
= ZwSetValueKey(LogConfKey
,
1223 &DeviceNode
->BootResources
,
1228 /* Set 'BasicConfigVector' value */
1229 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1230 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1232 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1233 Status
= ZwSetValueKey(LogConfKey
,
1236 REG_RESOURCE_REQUIREMENTS_LIST
,
1237 DeviceNode
->ResourceRequirements
,
1238 DeviceNode
->ResourceRequirements
->ListSize
);
1241 ZwClose(LogConfKey
);
1244 /* Set the 'ConfigFlags' value */
1245 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1246 Status
= ZwQueryValueKey(InstanceKey
,
1248 KeyValueBasicInformation
,
1252 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1254 /* Write the default value */
1255 ULONG DefaultConfigFlags
= 0;
1256 Status
= ZwSetValueKey(InstanceKey
,
1260 &DefaultConfigFlags
,
1261 sizeof(DefaultConfigFlags
));
1264 DPRINT("IopSetDeviceInstanceData() done\n");
1266 return STATUS_SUCCESS
;
1271 IopAssignDeviceResources(
1272 IN PDEVICE_NODE DeviceNode
,
1273 OUT ULONG
*pRequiredSize
)
1275 PIO_RESOURCE_LIST ResourceList
;
1276 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1277 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
1278 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1279 ULONG NumberOfResources
= 0;
1284 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1286 /* No resource needed for this device */
1287 DeviceNode
->ResourceList
= NULL
;
1288 return STATUS_SUCCESS
;
1291 /* Fill DeviceNode->ResourceList
1292 * FIXME: the PnP arbiter should go there!
1293 * Actually, use the BootResources if provided, else the resource list #0
1296 if (DeviceNode
->BootResources
)
1298 /* Browse the boot resources to know if we have some custom structures */
1299 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1300 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1302 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1303 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1304 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1305 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1307 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1308 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1312 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1313 if (!DeviceNode
->ResourceList
)
1315 Status
= STATUS_NO_MEMORY
;
1318 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1320 *pRequiredSize
= Size
;
1321 return STATUS_SUCCESS
;
1324 /* Ok, here, we have to use the device requirement list */
1325 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1326 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1328 Status
= STATUS_REVISION_MISMATCH
;
1332 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1333 *pRequiredSize
= Size
;
1334 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1335 if (!DeviceNode
->ResourceList
)
1337 Status
= STATUS_NO_MEMORY
;
1341 DeviceNode
->ResourceList
->Count
= 1;
1342 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1343 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1344 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1345 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1347 for (i
= 0; i
< ResourceList
->Count
; i
++)
1349 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1351 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1353 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1354 NumberOfResources
++;
1356 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1357 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
1358 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1359 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
1360 switch (ResourceDescriptor
->Type
)
1362 case CmResourceTypePort
:
1364 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1365 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
1368 case CmResourceTypeInterrupt
:
1370 INTERFACE_TYPE BusType
;
1375 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1376 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1377 /* FIXME: HACK: if we have a PCI device, we try
1378 * to keep the IRQ assigned by the BIOS */
1379 if (NT_SUCCESS(IoGetDeviceProperty(
1380 DeviceNode
->PhysicalDeviceObject
,
1381 DevicePropertyLegacyBusType
,
1382 sizeof(INTERFACE_TYPE
),
1384 &ret
)) && BusType
== PCIBus
)
1386 /* We have a PCI bus */
1387 if (NT_SUCCESS(IoGetDeviceProperty(
1388 DeviceNode
->PhysicalDeviceObject
,
1389 DevicePropertyAddress
,
1392 &ret
)) && SlotNumber
> 0)
1394 /* We have a good slot number */
1395 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1396 DeviceNode
->ResourceRequirements
->BusNumber
,
1399 0x3c /* PCI_INTERRUPT_LINE */,
1401 if (ret
!= 0 && ret
!= 2
1402 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1403 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1405 /* The device already has an assigned IRQ */
1406 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1410 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1411 DescriptorRaw
->u
.Interrupt
.Vector
,
1412 &DeviceNode
->InstancePath
);
1413 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1414 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1415 DeviceNode
->ResourceRequirements
->BusNumber
,
1418 0x3c /* PCI_INTERRUPT_LINE */,
1420 if (ret
== 0 || ret
== 2)
1427 case CmResourceTypeMemory
:
1429 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1430 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
1433 case CmResourceTypeDma
:
1435 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1436 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
1437 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
1440 case CmResourceTypeBusNumber
:
1442 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1443 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
1444 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
1447 /*CmResourceTypeDevicePrivate:
1448 case CmResourceTypePcCardConfig:
1449 case CmResourceTypeMfCardConfig:
1452 &DescriptorRaw->u.DevicePrivate,
1453 &ResourceDescriptor->u.DevicePrivate,
1454 sizeof(ResourceDescriptor->u.DevicePrivate));
1456 &DescriptorTranslated->u.DevicePrivate,
1457 &ResourceDescriptor->u.DevicePrivate,
1458 sizeof(ResourceDescriptor->u.DevicePrivate));
1462 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1463 NumberOfResources
--;
1469 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1471 return STATUS_SUCCESS
;
1474 if (DeviceNode
->ResourceList
)
1476 ExFreePool(DeviceNode
->ResourceList
);
1477 DeviceNode
->ResourceList
= NULL
;
1484 IopTranslateDeviceResources(
1485 IN PDEVICE_NODE DeviceNode
,
1486 IN ULONG RequiredSize
)
1488 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1489 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1493 if (!DeviceNode
->ResourceList
)
1495 DeviceNode
->ResourceListTranslated
= NULL
;
1496 return STATUS_SUCCESS
;
1499 /* That's easy to translate a resource list. Just copy the
1500 * untranslated one and change few fields in the copy
1502 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1503 if (!DeviceNode
->ResourceListTranslated
)
1505 Status
=STATUS_NO_MEMORY
;
1508 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1510 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1512 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1513 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1515 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1516 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1517 switch (DescriptorRaw
->Type
)
1519 case CmResourceTypePort
:
1521 ULONG AddressSpace
= 0; /* IO space */
1522 if (!HalTranslateBusAddress(
1523 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1524 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1525 DescriptorRaw
->u
.Port
.Start
,
1527 &DescriptorTranslated
->u
.Port
.Start
))
1529 Status
= STATUS_UNSUCCESSFUL
;
1534 case CmResourceTypeInterrupt
:
1536 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1537 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1538 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1539 DescriptorRaw
->u
.Interrupt
.Level
,
1540 DescriptorRaw
->u
.Interrupt
.Vector
,
1541 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1542 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1545 case CmResourceTypeMemory
:
1547 ULONG AddressSpace
= 1; /* Memory space */
1548 if (!HalTranslateBusAddress(
1549 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1550 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1551 DescriptorRaw
->u
.Memory
.Start
,
1553 &DescriptorTranslated
->u
.Memory
.Start
))
1555 Status
= STATUS_UNSUCCESSFUL
;
1560 case CmResourceTypeDma
:
1561 case CmResourceTypeBusNumber
:
1562 case CmResourceTypeDeviceSpecific
:
1566 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1567 Status
= STATUS_NOT_IMPLEMENTED
;
1572 return STATUS_SUCCESS
;
1575 /* Yes! Also delete ResourceList because ResourceList and
1576 * ResourceListTranslated should be a pair! */
1577 ExFreePool(DeviceNode
->ResourceList
);
1578 DeviceNode
->ResourceList
= NULL
;
1579 if (DeviceNode
->ResourceListTranslated
)
1581 ExFreePool(DeviceNode
->ResourceListTranslated
);
1582 DeviceNode
->ResourceList
= NULL
;
1589 * IopGetParentIdPrefix
1591 * Retrieve (or create) a string which identifies a device.
1595 * Pointer to device node.
1597 * Pointer to the string where is returned the parent node identifier
1600 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1601 * valid and its Buffer field is NULL-terminated. The caller needs to
1602 * to free the string with RtlFreeUnicodeString when it is no longer
1607 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1608 PUNICODE_STRING ParentIdPrefix
)
1610 ULONG KeyNameBufferLength
;
1611 PWSTR KeyNameBuffer
= NULL
;
1612 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1613 UNICODE_STRING KeyName
;
1614 UNICODE_STRING KeyValue
;
1615 UNICODE_STRING ValueName
;
1616 OBJECT_ATTRIBUTES ObjectAttributes
;
1621 /* HACK: As long as some devices have a NULL device
1622 * instance path, the following test is required :(
1624 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1626 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1627 &DeviceNode
->InstancePath
);
1628 return STATUS_UNSUCCESSFUL
;
1631 /* 1. Try to retrieve ParentIdPrefix from registry */
1632 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1633 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1634 if (!ParentIdPrefixInformation
)
1636 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1639 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1642 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1645 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1646 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1647 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1648 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1649 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1650 if (!NT_SUCCESS(Status
))
1652 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1653 Status
= ZwQueryValueKey(
1655 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1656 KeyNameBufferLength
, &KeyNameBufferLength
);
1657 if (NT_SUCCESS(Status
))
1659 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1660 Status
= STATUS_UNSUCCESSFUL
;
1663 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1664 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1668 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1670 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1671 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1675 /* 2. Create the ParentIdPrefix value */
1676 crc32
= RtlComputeCrc32(0,
1677 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1678 DeviceNode
->Parent
->InstancePath
.Length
);
1680 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1681 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1683 /* 3. Try to write the ParentIdPrefix to registry */
1684 Status
= ZwSetValueKey(hKey
,
1688 (PVOID
)KeyValue
.Buffer
,
1689 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1692 if (NT_SUCCESS(Status
))
1694 /* Duplicate the string to return it */
1695 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1697 ExFreePool(ParentIdPrefixInformation
);
1698 ExFreePool(KeyNameBuffer
);
1706 * IopActionInterrogateDeviceStack
1708 * Retrieve information for all (direct) child nodes of a parent node.
1712 * Pointer to device node.
1714 * Pointer to parent node to retrieve child node information for.
1717 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1718 * when we reach a device node which is not a direct child of the device
1719 * node for which we retrieve information of child nodes for. Any errors
1720 * that occur is logged instead so that all child services have a chance
1721 * of being interrogated.
1725 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1728 IO_STATUS_BLOCK IoStatusBlock
;
1729 PDEVICE_NODE ParentDeviceNode
;
1730 WCHAR InstancePath
[MAX_PATH
];
1731 IO_STACK_LOCATION Stack
;
1737 ULONG RequiredLength
;
1739 HANDLE InstanceKey
= NULL
;
1740 UNICODE_STRING ValueName
;
1741 UNICODE_STRING ParentIdPrefix
= { 0 };
1742 DEVICE_CAPABILITIES DeviceCapabilities
;
1744 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1745 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1747 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1750 * We are called for the parent too, but we don't need to do special
1751 * handling for this node
1754 if (DeviceNode
== ParentDeviceNode
)
1756 DPRINT("Success\n");
1757 return STATUS_SUCCESS
;
1761 * Make sure this device node is a direct child of the parent device node
1762 * that is given as an argument
1765 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1767 /* Stop the traversal immediately and indicate successful operation */
1769 return STATUS_UNSUCCESSFUL
;
1773 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1774 if (!NT_SUCCESS(Status
))
1776 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1781 * FIXME: For critical errors, cleanup and disable device, but always
1782 * return STATUS_SUCCESS.
1785 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1787 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1788 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1792 if (NT_SUCCESS(Status
))
1794 /* Copy the device id string */
1795 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1798 * FIXME: Check for valid characters, if there is invalid characters
1804 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1807 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1809 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1810 if (!NT_SUCCESS(Status
))
1812 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1815 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1817 if (!DeviceCapabilities
.UniqueID
)
1819 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1820 DPRINT("Instance ID is not unique\n");
1821 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1822 if (!NT_SUCCESS(Status
))
1824 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1828 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1830 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1831 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1835 if (NT_SUCCESS(Status
))
1837 /* Append the instance id string */
1838 wcscat(InstancePath
, L
"\\");
1839 if (ParentIdPrefix
.Length
> 0)
1841 /* Add information from parent bus device to InstancePath */
1842 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1843 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1844 wcscat(InstancePath
, L
"&");
1846 if (IoStatusBlock
.Information
)
1847 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1850 * FIXME: Check for valid characters, if there is invalid characters
1856 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1858 RtlFreeUnicodeString(&ParentIdPrefix
);
1860 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1862 DPRINT("No resources\n");
1863 /* FIXME: Cleanup and disable device */
1866 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1869 * Create registry key for the instance id, if it doesn't exist yet
1871 KeyBuffer
= ExAllocatePool(
1873 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1874 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1875 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1876 Status
= IopCreateDeviceKeyPath(/*KeyBuffer*/&DeviceNode
->InstancePath
, &InstanceKey
);
1877 ExFreePool(KeyBuffer
);
1878 if (!NT_SUCCESS(Status
))
1880 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1885 /* Set 'Capabilities' value */
1886 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1887 Status
= ZwSetValueKey(InstanceKey
,
1891 (PVOID
)&DeviceNode
->CapabilityFlags
,
1894 /* Set 'UINumber' value */
1895 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1897 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1898 Status
= ZwSetValueKey(InstanceKey
,
1902 &DeviceCapabilities
.UINumber
,
1907 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1909 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1910 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1914 if (NT_SUCCESS(Status
))
1917 * FIXME: Check for valid characters, if there is invalid characters
1921 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1922 DPRINT("Hardware IDs:\n");
1925 DPRINT(" %S\n", Ptr
);
1926 Length
= wcslen(Ptr
) + 1;
1929 TotalLength
+= Length
;
1931 DPRINT("TotalLength: %hu\n", TotalLength
);
1934 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1935 Status
= ZwSetValueKey(InstanceKey
,
1939 (PVOID
)IoStatusBlock
.Information
,
1940 (TotalLength
+ 1) * sizeof(WCHAR
));
1941 if (!NT_SUCCESS(Status
))
1943 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1948 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1951 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1953 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1954 Status
= IopInitiatePnpIrp(
1955 DeviceNode
->PhysicalDeviceObject
,
1959 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1962 * FIXME: Check for valid characters, if there is invalid characters
1966 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1967 DPRINT("Compatible IDs:\n");
1970 DPRINT(" %S\n", Ptr
);
1971 Length
= wcslen(Ptr
) + 1;
1974 TotalLength
+= Length
;
1976 DPRINT("TotalLength: %hu\n", TotalLength
);
1979 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1980 Status
= ZwSetValueKey(InstanceKey
,
1984 (PVOID
)IoStatusBlock
.Information
,
1985 (TotalLength
+ 1) * sizeof(WCHAR
));
1986 if (!NT_SUCCESS(Status
))
1988 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1993 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1996 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1998 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1999 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2000 Status
= IopInitiatePnpIrp(
2001 DeviceNode
->PhysicalDeviceObject
,
2003 IRP_MN_QUERY_DEVICE_TEXT
,
2005 /* This key is mandatory, so even if the Irp fails, we still write it */
2006 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2007 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2009 if (NT_SUCCESS(Status
) &&
2010 IoStatusBlock
.Information
&&
2011 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2013 /* This key is overriden when a driver is installed. Don't write the
2014 * new description if another one already exists */
2015 Status
= ZwSetValueKey(InstanceKey
,
2019 (PVOID
)IoStatusBlock
.Information
,
2020 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2024 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2025 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2027 Status
= ZwSetValueKey(InstanceKey
,
2032 DeviceDesc
.MaximumLength
);
2034 if (!NT_SUCCESS(Status
))
2036 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2042 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2044 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2045 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2046 Status
= IopInitiatePnpIrp(
2047 DeviceNode
->PhysicalDeviceObject
,
2049 IRP_MN_QUERY_DEVICE_TEXT
,
2051 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2053 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2054 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2055 Status
= ZwSetValueKey(InstanceKey
,
2059 (PVOID
)IoStatusBlock
.Information
,
2060 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2061 if (!NT_SUCCESS(Status
))
2063 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2068 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2071 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2073 Status
= IopInitiatePnpIrp(
2074 DeviceNode
->PhysicalDeviceObject
,
2076 IRP_MN_QUERY_BUS_INFORMATION
,
2078 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2080 PPNP_BUS_INFORMATION BusInformation
=
2081 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2083 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2084 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2085 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2086 ExFreePool(BusInformation
);
2090 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2092 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2093 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2094 DeviceNode
->ChildBusTypeIndex
= -1;
2097 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2099 Status
= IopInitiatePnpIrp(
2100 DeviceNode
->PhysicalDeviceObject
,
2102 IRP_MN_QUERY_RESOURCES
,
2104 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2106 DeviceNode
->BootResources
=
2107 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2108 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2112 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2113 DeviceNode
->BootResources
= NULL
;
2116 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2118 Status
= IopInitiatePnpIrp(
2119 DeviceNode
->PhysicalDeviceObject
,
2121 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2123 if (NT_SUCCESS(Status
))
2125 DeviceNode
->ResourceRequirements
=
2126 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2127 if (IoStatusBlock
.Information
)
2128 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2130 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2134 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2135 DeviceNode
->ResourceRequirements
= NULL
;
2139 if (InstanceKey
!= NULL
)
2141 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2144 ZwClose(InstanceKey
);
2146 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
2148 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
2150 /* Report the device to the user-mode pnp manager */
2151 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2152 &DeviceNode
->InstancePath
);
2155 return STATUS_SUCCESS
;
2163 IoSynchronousInvalidateDeviceRelations(
2164 IN PDEVICE_OBJECT DeviceObject
,
2165 IN DEVICE_RELATION_TYPE Type
)
2167 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2168 DEVICETREE_TRAVERSE_CONTEXT Context
;
2169 PDEVICE_RELATIONS DeviceRelations
;
2170 IO_STATUS_BLOCK IoStatusBlock
;
2171 PDEVICE_NODE ChildDeviceNode
;
2172 IO_STACK_LOCATION Stack
;
2173 BOOLEAN BootDrivers
;
2174 OBJECT_ATTRIBUTES ObjectAttributes
;
2175 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
2180 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2182 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2184 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
;
2186 Status
= IopInitiatePnpIrp(
2189 IRP_MN_QUERY_DEVICE_RELATIONS
,
2191 if (!NT_SUCCESS(Status
))
2193 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2197 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2199 if (!DeviceRelations
|| DeviceRelations
->Count
<= 0)
2201 DPRINT("No PDOs\n");
2202 if (DeviceRelations
)
2204 ExFreePool(DeviceRelations
);
2209 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2212 * Create device nodes for all discovered devices
2214 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2216 if (IopGetDeviceNode(DeviceRelations
->Objects
[i
]) != NULL
)
2218 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2221 Status
= IopCreateDeviceNode(
2223 DeviceRelations
->Objects
[i
],
2226 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2227 if (!NT_SUCCESS(Status
))
2229 DPRINT("No resources\n");
2230 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2231 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2232 ExFreePool(DeviceRelations
);
2236 ExFreePool(DeviceRelations
);
2239 * Retrieve information about all discovered children from the bus driver
2241 IopInitDeviceTreeTraverseContext(
2244 IopActionInterrogateDeviceStack
,
2247 Status
= IopTraverseDeviceTree(&Context
);
2248 if (!NT_SUCCESS(Status
))
2250 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2255 * Retrieve configuration from the registry for discovered children
2257 IopInitDeviceTreeTraverseContext(
2260 IopActionConfigureChildServices
,
2263 Status
= IopTraverseDeviceTree(&Context
);
2264 if (!NT_SUCCESS(Status
))
2266 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2271 * Get the state of the system boot. If the \\SystemRoot link isn't
2272 * created yet, we will assume that it's possible to load only boot
2275 InitializeObjectAttributes(
2281 Status
= ZwOpenFile(
2288 if (NT_SUCCESS(Status
))
2290 BootDrivers
= FALSE
;
2297 * Initialize services for discovered children. Only boot drivers will
2298 * be loaded from boot driver!
2300 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2301 if (!NT_SUCCESS(Status
))
2303 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2307 DPRINT("IopInvalidateDeviceRelations() finished\n");
2311 * IopActionConfigureChildServices
2313 * Retrieve configuration for all (direct) child nodes of a parent node.
2317 * Pointer to device node.
2319 * Pointer to parent node to retrieve child node configuration for.
2322 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2323 * when we reach a device node which is not a direct child of the device
2324 * node for which we configure child services for. Any errors that occur is
2325 * logged instead so that all child services have a chance of beeing
2330 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2333 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2334 PDEVICE_NODE ParentDeviceNode
;
2335 PUNICODE_STRING Service
;
2336 UNICODE_STRING ClassGUID
;
2339 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2341 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2344 * We are called for the parent too, but we don't need to do special
2345 * handling for this node
2347 if (DeviceNode
== ParentDeviceNode
)
2349 DPRINT("Success\n");
2350 return STATUS_SUCCESS
;
2354 * Make sure this device node is a direct child of the parent device node
2355 * that is given as an argument
2357 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2359 /* Stop the traversal immediately and indicate successful operation */
2361 return STATUS_UNSUCCESSFUL
;
2364 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2366 WCHAR RegKeyBuffer
[MAX_PATH
];
2367 UNICODE_STRING RegKey
;
2370 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2371 RegKey
.Buffer
= RegKeyBuffer
;
2374 * Retrieve configuration from Enum key
2377 Service
= &DeviceNode
->ServiceName
;
2379 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2380 RtlInitUnicodeString(Service
, NULL
);
2381 RtlInitUnicodeString(&ClassGUID
, NULL
);
2383 QueryTable
[0].Name
= L
"Service";
2384 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
2385 QueryTable
[0].EntryContext
= Service
;
2387 QueryTable
[1].Name
= L
"ClassGUID";
2388 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2389 QueryTable
[1].EntryContext
= &ClassGUID
;
2390 QueryTable
[1].DefaultType
= REG_SZ
;
2391 QueryTable
[1].DefaultData
= L
"";
2392 QueryTable
[1].DefaultLength
= 0;
2394 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2395 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2397 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2398 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2400 if (!NT_SUCCESS(Status
))
2402 /* FIXME: Log the error */
2403 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2404 &DeviceNode
->InstancePath
, Status
);
2405 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2406 return STATUS_SUCCESS
;
2409 if (Service
->Buffer
== NULL
)
2411 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2413 if (ClassGUID
.Length
!= 0)
2415 /* Device has a ClassGUID value, but no Service value.
2416 * Suppose it is using the NULL driver, so state the
2417 * device is started */
2418 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2419 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2420 DeviceNode
->Flags
|= DN_STARTED
;
2422 return STATUS_SUCCESS
;
2425 DPRINT("Got Service %S\n", Service
->Buffer
);
2428 return STATUS_SUCCESS
;
2432 * IopActionInitChildServices
2434 * Initialize the service for all (direct) child nodes of a parent node
2438 * Pointer to device node.
2440 * Pointer to parent node to initialize child node services for.
2442 * Load only driver marked as boot start.
2445 * If the driver image for a service is not loaded and initialized
2446 * it is done here too. We only return a status code indicating an
2447 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2448 * not a direct child of the device node for which we initialize
2449 * child services for. Any errors that occur is logged instead so
2450 * that all child services have a chance of being initialized.
2454 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2456 BOOLEAN BootDrivers
)
2458 PDEVICE_NODE ParentDeviceNode
;
2461 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2464 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2467 * We are called for the parent too, but we don't need to do special
2468 * handling for this node
2470 if (DeviceNode
== ParentDeviceNode
)
2472 DPRINT("Success\n");
2473 return STATUS_SUCCESS
;
2477 * Make sure this device node is a direct child of the parent device node
2478 * that is given as an argument
2481 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2484 * Stop the traversal immediately and indicate unsuccessful operation
2487 return STATUS_UNSUCCESSFUL
;
2491 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2492 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2493 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2495 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2496 PDRIVER_OBJECT DriverObject
;
2498 /* Get existing DriverObject pointer (in case the driver has
2499 already been loaded and initialized) */
2500 Status
= IopGetDriverObject(
2502 &DeviceNode
->ServiceName
,
2505 if (!NT_SUCCESS(Status
))
2507 /* Driver is not initialized, try to load it */
2508 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2510 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2512 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2513 was loaded by the bootloader */
2514 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2515 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2517 /* Initialize the driver */
2518 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2519 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2523 Status
= STATUS_SUCCESS
;
2528 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2529 &DeviceNode
->ServiceName
, Status
);
2533 /* Driver is loaded and initialized at this point */
2534 if (NT_SUCCESS(Status
))
2536 /* We have a driver for this DeviceNode */
2537 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2538 /* Attach lower level filter drivers. */
2539 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2540 /* Initialize the function driver for the device node */
2541 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2543 if (NT_SUCCESS(Status
))
2545 /* Attach upper level filter drivers. */
2546 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2547 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2549 Status
= IopStartDevice(DeviceNode
);
2553 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2554 &DeviceNode
->InstancePath
, Status
);
2560 * Don't disable when trying to load only boot drivers
2564 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2565 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2566 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2567 CPRINT("Initialization of service %S failed (Status %x)\n",
2568 DeviceNode
->ServiceName
.Buffer
, Status
);
2574 DPRINT("Device %wZ is disabled or already initialized\n",
2575 &DeviceNode
->InstancePath
);
2578 return STATUS_SUCCESS
;
2582 * IopActionInitAllServices
2584 * Initialize the service for all (direct) child nodes of a parent node. This
2585 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2589 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2592 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2596 * IopActionInitBootServices
2598 * Initialize the boot start services for all (direct) child nodes of a
2599 * parent node. This function just calls IopActionInitChildServices with
2600 * BootDrivers = TRUE.
2603 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2606 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2610 * IopInitializePnpServices
2612 * Initialize services for discovered children
2616 * Top device node to start initializing services.
2619 * When set to TRUE, only drivers marked as boot start will
2620 * be loaded. Otherwise, all drivers will be loaded.
2626 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2627 IN BOOLEAN BootDrivers
)
2629 DEVICETREE_TRAVERSE_CONTEXT Context
;
2631 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2635 IopInitDeviceTreeTraverseContext(
2638 IopActionInitBootServices
,
2643 IopInitDeviceTreeTraverseContext(
2646 IopActionInitAllServices
,
2650 return IopTraverseDeviceTree(&Context
);
2653 static NTSTATUS INIT_FUNCTION
2654 IopEnumerateDetectedDevices(
2656 IN PUNICODE_STRING RelativePath OPTIONAL
,
2658 IN BOOLEAN EnumerateSubKeys
,
2659 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2660 IN ULONG ParentBootResourcesLength
)
2662 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2663 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2664 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2665 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2666 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2667 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2668 OBJECT_ATTRIBUTES ObjectAttributes
;
2669 HANDLE hDevicesKey
= NULL
;
2670 HANDLE hDeviceKey
= NULL
;
2671 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2672 UNICODE_STRING Level2NameU
;
2673 WCHAR Level2Name
[5];
2674 ULONG IndexDevice
= 0;
2676 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2677 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2678 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2679 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2680 UNICODE_STRING DeviceName
, ValueName
;
2682 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2683 ULONG BootResourcesLength
;
2686 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2687 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2688 static ULONG DeviceIndexPci
= 0;
2690 const UNICODE_STRING IdentifierAcpi
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2691 UNICODE_STRING HardwareIdAcpi
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2692 static ULONG DeviceIndexAcpi
= 0;
2694 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2695 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2696 static ULONG DeviceIndexSerial
= 0;
2697 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2698 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2699 static ULONG DeviceIndexKeyboard
= 0;
2700 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2701 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2702 static ULONG DeviceIndexMouse
= 0;
2703 UNICODE_STRING HardwareIdKey
;
2704 PUNICODE_STRING pHardwareId
;
2705 ULONG DeviceIndex
= 0;
2709 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2710 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2711 if (!NT_SUCCESS(Status
))
2713 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2718 hDevicesKey
= hBaseKey
;
2720 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2721 if (!pDeviceInformation
)
2723 DPRINT("ExAllocatePool() failed\n");
2724 Status
= STATUS_NO_MEMORY
;
2728 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2729 if (!pValueInformation
)
2731 DPRINT("ExAllocatePool() failed\n");
2732 Status
= STATUS_NO_MEMORY
;
2738 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2739 if (Status
== STATUS_NO_MORE_ENTRIES
)
2741 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2743 ExFreePool(pDeviceInformation
);
2744 DeviceInfoLength
= RequiredSize
;
2745 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2746 if (!pDeviceInformation
)
2748 DPRINT("ExAllocatePool() failed\n");
2749 Status
= STATUS_NO_MEMORY
;
2752 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2754 if (!NT_SUCCESS(Status
))
2756 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2761 /* Open device key */
2762 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2763 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2764 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2767 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0),
2769 if (!NT_SUCCESS(Status
))
2771 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2775 /* Read boot resources, and add then to parent ones */
2776 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2777 if (Status
== STATUS_BUFFER_OVERFLOW
)
2779 ExFreePool(pValueInformation
);
2780 ValueInfoLength
= RequiredSize
;
2781 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2782 if (!pValueInformation
)
2784 DPRINT("ExAllocatePool() failed\n");
2785 ZwDeleteKey(hLevel2Key
);
2786 Status
= STATUS_NO_MEMORY
;
2789 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2791 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2793 BootResources
= ParentBootResources
;
2794 BootResourcesLength
= ParentBootResourcesLength
;
2796 else if (!NT_SUCCESS(Status
))
2798 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2801 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2803 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
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 (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2933 pHardwareId
= &HardwareIdSerial
;
2934 DeviceIndex
= DeviceIndexSerial
++;
2936 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2938 pHardwareId
= &HardwareIdKeyboard
;
2939 DeviceIndex
= DeviceIndexKeyboard
++;
2941 else if (RelativePath
&& 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 /* Prepare hardware id key (hardware id value without final \0) */
2976 HardwareIdKey
= *pHardwareId
;
2977 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2979 /* Add the detected device to Root key */
2980 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2981 Status
= ZwCreateKey(
2987 REG_OPTION_NON_VOLATILE
,
2989 if (!NT_SUCCESS(Status
))
2991 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2994 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2995 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2996 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2997 Status
= ZwCreateKey(
2999 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3003 REG_OPTION_NON_VOLATILE
,
3005 ZwClose(hLevel1Key
);
3006 if (!NT_SUCCESS(Status
))
3008 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3011 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
3012 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
3013 if (!NT_SUCCESS(Status
))
3015 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3016 ZwDeleteKey(hLevel2Key
);
3019 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3020 if (!NT_SUCCESS(Status
))
3022 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3023 ZwDeleteKey(hLevel2Key
);
3026 /* Create 'LogConf' subkey */
3027 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3028 Status
= ZwCreateKey(
3034 REG_OPTION_VOLATILE
,
3036 if (!NT_SUCCESS(Status
))
3038 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3039 ZwDeleteKey(hLevel2Key
);
3042 if (BootResourcesLength
> 0)
3044 /* Save boot resources to 'LogConf\BootConfig' */
3045 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
3046 if (!NT_SUCCESS(Status
))
3048 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3050 ZwDeleteKey(hLevel2Key
);
3057 if (BootResources
&& BootResources
!= ParentBootResources
)
3058 ExFreePool(BootResources
);
3061 ZwClose(hLevel2Key
);
3066 ZwClose(hDeviceKey
);
3071 Status
= STATUS_SUCCESS
;
3074 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
3075 ZwClose(hDevicesKey
);
3077 ZwClose(hDeviceKey
);
3078 if (pDeviceInformation
)
3079 ExFreePool(pDeviceInformation
);
3080 if (pValueInformation
)
3081 ExFreePool(pValueInformation
);
3085 static BOOLEAN INIT_FUNCTION
3086 IopIsAcpiComputer(VOID
)
3091 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3092 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3093 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3094 OBJECT_ATTRIBUTES ObjectAttributes
;
3095 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3096 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3097 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3098 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3100 ULONG IndexDevice
= 0;
3101 UNICODE_STRING DeviceName
, ValueName
;
3102 HANDLE hDevicesKey
= NULL
;
3103 HANDLE hDeviceKey
= NULL
;
3105 BOOLEAN ret
= FALSE
;
3107 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3108 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3109 if (!NT_SUCCESS(Status
))
3111 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3115 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3116 if (!pDeviceInformation
)
3118 DPRINT("ExAllocatePool() failed\n");
3119 Status
= STATUS_NO_MEMORY
;
3123 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3124 if (!pDeviceInformation
)
3126 DPRINT("ExAllocatePool() failed\n");
3127 Status
= STATUS_NO_MEMORY
;
3133 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3134 if (Status
== STATUS_NO_MORE_ENTRIES
)
3136 else if (Status
== STATUS_BUFFER_OVERFLOW
)
3138 ExFreePool(pDeviceInformation
);
3139 DeviceInfoLength
= RequiredSize
;
3140 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3141 if (!pDeviceInformation
)
3143 DPRINT("ExAllocatePool() failed\n");
3144 Status
= STATUS_NO_MEMORY
;
3147 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3149 if (!NT_SUCCESS(Status
))
3151 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3156 /* Open device key */
3157 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3158 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3159 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3164 if (!NT_SUCCESS(Status
))
3166 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3170 /* Read identifier */
3171 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3172 if (Status
== STATUS_BUFFER_OVERFLOW
)
3174 ExFreePool(pValueInformation
);
3175 ValueInfoLength
= RequiredSize
;
3176 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3177 if (!pValueInformation
)
3179 DPRINT("ExAllocatePool() failed\n");
3180 Status
= STATUS_NO_MEMORY
;
3183 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3185 if (!NT_SUCCESS(Status
))
3187 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3190 else if (pValueInformation
->Type
!= REG_SZ
)
3192 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3196 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3197 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3198 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3199 ValueName
.Length
-= sizeof(WCHAR
);
3200 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3202 DPRINT("Found ACPI BIOS\n");
3208 ZwClose(hDeviceKey
);
3213 if (pDeviceInformation
)
3214 ExFreePool(pDeviceInformation
);
3215 if (pValueInformation
)
3216 ExFreePool(pValueInformation
);
3218 ZwClose(hDevicesKey
);
3220 ZwClose(hDeviceKey
);
3225 static NTSTATUS INIT_FUNCTION
3226 IopUpdateRootKey(VOID
)
3228 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
3229 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
3230 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3231 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3232 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3233 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
3234 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3235 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3236 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3237 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3238 OBJECT_ATTRIBUTES ObjectAttributes
;
3239 HANDLE hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
3242 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3243 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3244 if (!NT_SUCCESS(Status
))
3246 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3250 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, hEnum
, NULL
);
3251 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3253 if (!NT_SUCCESS(Status
))
3255 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3259 if (IopIsAcpiComputer())
3261 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3262 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3264 if (!NT_SUCCESS(Status
))
3266 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3267 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3268 ZwClose(hHalAcpiDevice
);
3269 if (!NT_SUCCESS(Status
))
3271 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3272 if (NT_SUCCESS(Status
))
3273 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3274 if (NT_SUCCESS(Status
))
3276 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hHalAcpiId
, NULL
);
3277 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3278 if (NT_SUCCESS(Status
))
3281 ZwClose(hHalAcpiId
);
3286 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3287 Status
= ZwOpenKey(&hEnum
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3288 if (!NT_SUCCESS(Status
))
3290 /* Nothing to do, don't return with an error status */
3291 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3293 return STATUS_SUCCESS
;
3295 Status
= IopEnumerateDetectedDevices(
3308 static NTSTATUS INIT_FUNCTION
3310 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
3312 return STATUS_SUCCESS
;
3321 DPRINT("PnpInit()\n");
3323 KeInitializeSpinLock(&IopDeviceTreeLock
);
3325 /* Initialize the Bus Type GUID List */
3326 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3327 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3328 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3330 /* Initialize PnP-Event notification support */
3331 Status
= IopInitPlugPlayEvents();
3332 if (!NT_SUCCESS(Status
))
3334 CPRINT("IopInitPlugPlayEvents() failed\n");
3335 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3339 * Create root device node
3342 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
3343 if (!NT_SUCCESS(Status
))
3345 CPRINT("IoCreateDriverObject() failed\n");
3346 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3349 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3351 if (!NT_SUCCESS(Status
))
3353 CPRINT("IoCreateDevice() failed\n");
3354 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3357 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
3358 if (!NT_SUCCESS(Status
))
3360 CPRINT("Insufficient resources\n");
3361 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3364 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3367 CPRINT("Failed to create the instance path!\n");
3368 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3371 /* Report the device to the user-mode pnp manager */
3372 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3373 &IopRootDeviceNode
->InstancePath
);
3375 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3376 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3377 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3378 IopRootDriverObject
->DriverExtension
->AddDevice(
3379 IopRootDriverObject
,
3380 IopRootDeviceNode
->PhysicalDeviceObject
);
3382 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3383 Status
= IopUpdateRootKey();
3384 if (!NT_SUCCESS(Status
))
3386 CPRINT("IopUpdateRootKey() failed\n");
3387 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3391 RTL_GENERIC_COMPARE_RESULTS
3393 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3394 IN PVOID FirstStruct
,
3395 IN PVOID SecondStruct
)
3403 // The allocation function is called by the generic table package whenever
3404 // it needs to allocate memory for the table.
3409 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3419 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3428 PpInitializeDeviceReferenceTable(VOID
)
3430 /* Setup the guarded mutex and AVL table */
3431 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3432 RtlInitializeGenericTableAvl(
3433 &PpDeviceReferenceTable
,
3434 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3435 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3436 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3444 /* Initialize the resource when accessing device registry data */
3445 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3447 /* Setup the device reference AVL table */
3448 PpInitializeDeviceReferenceTable();
3456 /* Check the initialization phase */
3457 switch (ExpInitializationPhase
)
3462 return PiInitPhase0();
3468 //return PiInitPhase1();
3472 /* Don't know any other phase! Bugcheck! */
3473 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);