2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/pnpmgr.c
5 * PURPOSE: Initializes the PnP manager
7 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * Hervé Poussineau (hpoussin@reactos.org)
11 /* INCLUDES ******************************************************************/
16 #include <internal/debug.h>
20 /* GLOBALS *******************************************************************/
22 PDEVICE_NODE IopRootDeviceNode
;
23 KSPIN_LOCK IopDeviceTreeLock
;
24 ERESOURCE PpRegistryDeviceResource
;
25 KGUARDED_MUTEX PpDeviceReferenceTableLock
;
26 RTL_AVL_TABLE PpDeviceReferenceTable
;
28 extern ULONG ExpInitializationPhase
;
30 /* DATA **********************************************************************/
32 PDRIVER_OBJECT IopRootDriverObject
;
33 PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList
= NULL
;
35 #if defined (ALLOC_PRAGMA)
36 #pragma alloc_text(INIT, PnpInit)
37 #pragma alloc_text(INIT, PnpInit2)
40 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
42 PDEVICE_OBJECT DeviceObject
;
43 DEVICE_RELATION_TYPE Type
;
44 PIO_WORKITEM WorkItem
;
45 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
49 IoSynchronousInvalidateDeviceRelations(
50 IN PDEVICE_OBJECT DeviceObject
,
51 IN DEVICE_RELATION_TYPE Type
);
54 /* FUNCTIONS *****************************************************************/
57 IopAssignDeviceResources(
58 IN PDEVICE_NODE DeviceNode
,
59 OUT ULONG
*pRequiredSize
);
61 IopTranslateDeviceResources(
62 IN PDEVICE_NODE DeviceNode
,
63 IN ULONG RequiredSize
);
67 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
69 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
74 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
75 PDRIVER_OBJECT DriverObject
)
80 if (!DriverObject
->DriverExtension
->AddDevice
)
81 return STATUS_SUCCESS
;
83 /* This is a Plug and Play driver */
84 DPRINT("Plug and Play driver found\n");
85 ASSERT(DeviceNode
->PhysicalDeviceObject
);
87 /* Check if this plug-and-play driver is used as a legacy one for this device node */
88 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
90 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
91 return STATUS_SUCCESS
;
94 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
95 &DriverObject
->DriverName
,
96 &DeviceNode
->InstancePath
);
97 Status
= DriverObject
->DriverExtension
->AddDevice(
98 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
99 if (!NT_SUCCESS(Status
))
101 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
105 /* Check if driver added a FDO above the PDO */
106 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
107 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
109 /* FIXME: What do we do? Unload the driver or just disable the device? */
110 DPRINT1("An FDO was not attached\n");
111 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
112 return STATUS_UNSUCCESSFUL
;
115 /* Check if we have a ACPI device (needed for power management) */
116 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
118 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
120 /* There can be only one system power device */
121 if (!SystemPowerDeviceNodeCreated
)
123 PopSystemPowerDeviceNode
= DeviceNode
;
124 ObReferenceObject(PopSystemPowerDeviceNode
);
125 SystemPowerDeviceNodeCreated
= TRUE
;
129 ObDereferenceObject(Fdo
);
131 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
132 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
134 return STATUS_SUCCESS
;
139 PDEVICE_NODE DeviceNode
)
141 IO_STATUS_BLOCK IoStatusBlock
;
142 IO_STACK_LOCATION Stack
;
143 ULONG RequiredLength
;
147 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
149 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
150 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
151 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
152 Status
= IopInitiatePnpIrp(
155 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
157 if (!NT_SUCCESS(Status
) && Status
!= STATUS_NOT_SUPPORTED
)
159 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
162 DeviceNode
->ResourceRequirements
= Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
164 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
165 if (NT_SUCCESS(Status
))
167 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
168 if (NT_SUCCESS(Status
))
170 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
174 DPRINT("IopTranslateDeviceResources() failed (Status 0x%08lx)\n", Status
);
179 DPRINT("IopAssignDeviceResources() failed (Status 0x%08lx)\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
);
324 if (DeviceNode
== NULL
)
325 return STATUS_INVALID_DEVICE_REQUEST
;
327 switch (DeviceProperty
)
329 case DevicePropertyBusNumber
:
330 Length
= sizeof(ULONG
);
331 Data
= &DeviceNode
->ChildBusNumber
;
334 /* Complete, untested */
335 case DevicePropertyBusTypeGuid
:
337 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
338 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
340 /* Return the GUID */
341 *ResultLength
= sizeof(GUID
);
343 /* Check if the buffer given was large enough */
344 if (BufferLength
< *ResultLength
)
346 return STATUS_BUFFER_TOO_SMALL
;
350 RtlCopyMemory(PropertyBuffer
,
351 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
353 return STATUS_SUCCESS
;
357 return STATUS_OBJECT_NAME_NOT_FOUND
;
361 case DevicePropertyLegacyBusType
:
362 Length
= sizeof(INTERFACE_TYPE
);
363 Data
= &DeviceNode
->ChildInterfaceType
;
366 case DevicePropertyAddress
:
367 /* Query the device caps */
368 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
369 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
372 *ResultLength
= sizeof(ULONG
);
374 /* Check if the buffer given was large enough */
375 if (BufferLength
< *ResultLength
)
377 return STATUS_BUFFER_TOO_SMALL
;
381 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
382 return STATUS_SUCCESS
;
386 return STATUS_OBJECT_NAME_NOT_FOUND
;
390 // case DevicePropertyUINumber:
391 // if (DeviceNode->CapabilityFlags == NULL)
392 // return STATUS_INVALID_DEVICE_REQUEST;
393 // Length = sizeof(ULONG);
394 // Data = &DeviceNode->CapabilityFlags->UINumber;
397 case DevicePropertyClassName
:
398 case DevicePropertyClassGuid
:
399 case DevicePropertyDriverKeyName
:
400 case DevicePropertyManufacturer
:
401 case DevicePropertyFriendlyName
:
402 case DevicePropertyHardwareID
:
403 case DevicePropertyCompatibleIDs
:
404 case DevicePropertyDeviceDescription
:
405 case DevicePropertyLocationInformation
:
406 case DevicePropertyUINumber
:
408 LPCWSTR RegistryPropertyName
;
409 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
410 UNICODE_STRING ValueName
;
411 OBJECT_ATTRIBUTES ObjectAttributes
;
412 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
413 ULONG ValueInformationLength
;
414 HANDLE KeyHandle
, EnumRootHandle
;
417 switch (DeviceProperty
)
419 case DevicePropertyClassName
:
420 RegistryPropertyName
= L
"Class"; break;
421 case DevicePropertyClassGuid
:
422 RegistryPropertyName
= L
"ClassGuid"; break;
423 case DevicePropertyDriverKeyName
:
424 RegistryPropertyName
= L
"Driver"; break;
425 case DevicePropertyManufacturer
:
426 RegistryPropertyName
= L
"Mfg"; break;
427 case DevicePropertyFriendlyName
:
428 RegistryPropertyName
= L
"FriendlyName"; break;
429 case DevicePropertyHardwareID
:
430 RegistryPropertyName
= L
"HardwareID"; break;
431 case DevicePropertyCompatibleIDs
:
432 RegistryPropertyName
= L
"CompatibleIDs"; break;
433 case DevicePropertyDeviceDescription
:
434 RegistryPropertyName
= L
"DeviceDesc"; break;
435 case DevicePropertyLocationInformation
:
436 RegistryPropertyName
= L
"LocationInformation"; break;
437 case DevicePropertyUINumber
:
438 RegistryPropertyName
= L
"UINumber"; break;
440 /* Should not happen */
442 return STATUS_UNSUCCESSFUL
;
445 DPRINT("Registry property %S\n", RegistryPropertyName
);
448 InitializeObjectAttributes(&ObjectAttributes
, &EnumRoot
,
449 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
450 Status
= ZwOpenKey(&EnumRootHandle
, 0, &ObjectAttributes
);
451 if (!NT_SUCCESS(Status
))
453 DPRINT1("Error opening ENUM_ROOT, Status=0x%08x\n", Status
);
457 /* Open instance key */
458 InitializeObjectAttributes(&ObjectAttributes
, &DeviceNode
->InstancePath
,
459 OBJ_CASE_INSENSITIVE
, EnumRootHandle
, NULL
);
461 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
462 if (!NT_SUCCESS(Status
))
464 DPRINT1("Error opening InstancePath, Status=0x%08x\n", Status
);
468 /* Allocate buffer to read as much data as required by the caller */
469 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
470 Data
[0]) + BufferLength
;
471 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
472 if (!ValueInformation
)
475 return STATUS_INSUFFICIENT_RESOURCES
;
479 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
480 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
481 KeyValuePartialInformation
, ValueInformation
,
482 ValueInformationLength
,
483 &ValueInformationLength
);
487 *ResultLength
= ValueInformation
->DataLength
;
489 if (!NT_SUCCESS(Status
))
491 DPRINT1("Problem: Status=0x%08x, ResultLength = %d\n", Status
, *ResultLength
);
492 ExFreePool(ValueInformation
);
493 if (Status
== STATUS_BUFFER_OVERFLOW
)
494 return STATUS_BUFFER_TOO_SMALL
;
499 /* FIXME: Verify the value (NULL-terminated, correct format). */
500 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
501 ValueInformation
->DataLength
);
502 ExFreePool(ValueInformation
);
504 return STATUS_SUCCESS
;
507 case DevicePropertyBootConfiguration
:
509 if (DeviceNode
->BootResources
->Count
!= 0)
511 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
513 Data
= &DeviceNode
->BootResources
;
516 /* FIXME: use a translated boot configuration instead */
517 case DevicePropertyBootConfigurationTranslated
:
519 if (DeviceNode
->BootResources
->Count
!= 0)
521 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
523 Data
= &DeviceNode
->BootResources
;
526 case DevicePropertyEnumeratorName
:
527 /* A buffer overflow can't happen here, since InstancePath
528 * always contains the enumerator name followed by \\ */
529 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
531 Length
= (Ptr
- DeviceNode
->InstancePath
.Buffer
+ 1) * sizeof(WCHAR
);
532 Data
= DeviceNode
->InstancePath
.Buffer
;
535 case DevicePropertyPhysicalDeviceObjectName
:
536 /* InstancePath buffer is NULL terminated, so we can do this */
537 Length
= DeviceNode
->InstancePath
.MaximumLength
;
538 Data
= DeviceNode
->InstancePath
.Buffer
;
542 return STATUS_INVALID_PARAMETER_2
;
545 /* Prepare returned values */
546 *ResultLength
= Length
;
547 if (BufferLength
< Length
)
548 return STATUS_BUFFER_TOO_SMALL
;
549 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
551 /* NULL terminate the string (if required) */
552 if (DeviceProperty
== DevicePropertyEnumeratorName
)
553 ((LPWSTR
)PropertyBuffer
)[Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
555 return STATUS_SUCCESS
;
563 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
569 * @name IoOpenDeviceRegistryKey
571 * Open a registry key unique for a specified driver or device instance.
573 * @param DeviceObject Device to get the registry key for.
574 * @param DevInstKeyType Type of the key to return.
575 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
576 * @param DevInstRegKey Handle to the opened registry key on
585 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
586 IN ULONG DevInstKeyType
,
587 IN ACCESS_MASK DesiredAccess
,
588 OUT PHANDLE DevInstRegKey
)
590 static WCHAR RootKeyName
[] =
591 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
592 static WCHAR ProfileKeyName
[] =
593 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
594 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
595 static WCHAR EnumKeyName
[] = L
"Enum\\";
596 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
598 LPWSTR KeyNameBuffer
;
599 UNICODE_STRING KeyName
;
600 ULONG DriverKeyLength
;
601 OBJECT_ATTRIBUTES ObjectAttributes
;
602 PDEVICE_NODE DeviceNode
= NULL
;
605 DPRINT("IoOpenDeviceRegistryKey() called\n");
607 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
609 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
610 return STATUS_INVALID_PARAMETER
;
614 * Calculate the length of the base key name. This is the full
615 * name for driver key or the name excluding "Device Parameters"
616 * subkey for device key.
619 KeyNameLength
= sizeof(RootKeyName
);
620 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
621 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
622 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
624 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
625 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
626 0, NULL
, &DriverKeyLength
);
627 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
629 KeyNameLength
+= DriverKeyLength
;
633 DeviceNode
= IopGetDeviceNode(DeviceObject
);
634 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
635 DeviceNode
->InstancePath
.Length
;
639 * Now allocate the buffer for the key name...
642 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
643 if (KeyNameBuffer
== NULL
)
644 return STATUS_INSUFFICIENT_RESOURCES
;
647 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
648 KeyName
.Buffer
= KeyNameBuffer
;
651 * ...and build the key name.
654 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
655 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
657 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
658 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
660 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
662 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
663 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
664 DriverKeyLength
, KeyNameBuffer
+
665 (KeyName
.Length
/ sizeof(WCHAR
)),
667 if (!NT_SUCCESS(Status
))
669 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
670 ExFreePool(KeyNameBuffer
);
673 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
677 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
678 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
679 if (DeviceNode
->InstancePath
.Length
== 0)
681 ExFreePool(KeyNameBuffer
);
690 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
691 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
692 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
693 if (!NT_SUCCESS(Status
))
695 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
696 ExFreePool(KeyNameBuffer
);
699 ExFreePool(KeyNameBuffer
);
702 * For driver key we're done now.
705 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
709 * Let's go further. For device key we must open "Device Parameters"
710 * subkey and create it if it doesn't exist yet.
713 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
714 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
715 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
716 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
717 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
718 ZwClose(ObjectAttributes
.RootDirectory
);
728 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
735 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
739 if (PopSystemPowerDeviceNode
)
741 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
742 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
743 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
745 return STATUS_SUCCESS
;
748 return STATUS_UNSUCCESSFUL
;
753 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
755 USHORT i
= 0, FoundIndex
= 0xFFFF;
759 /* Acquire the lock */
760 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
762 /* Loop all entries */
763 while (i
< IopBusTypeGuidList
->GuidCount
)
765 /* Try to find a match */
766 if (RtlCompareMemory(BusTypeGuid
,
767 &IopBusTypeGuidList
->Guids
[i
],
768 sizeof(GUID
)) == sizeof(GUID
))
777 /* Check if we have to grow the list */
778 if (IopBusTypeGuidList
->GuidCount
)
780 /* Calculate the new size */
781 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
782 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
784 /* Allocate the new copy */
785 NewList
= ExAllocatePool(PagedPool
, NewSize
);
787 /* Now copy them, decrease the size too */
788 NewSize
-= sizeof(GUID
);
789 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
791 /* Free the old list */
792 ExFreePool(IopBusTypeGuidList
);
794 /* Use the new buffer */
795 IopBusTypeGuidList
= NewList
;
798 /* Copy the new GUID */
799 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
803 /* The new entry is the index */
804 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
805 IopBusTypeGuidList
->GuidCount
++;
808 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
814 * Creates a device node
817 * ParentNode = Pointer to parent device node
818 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
819 * to have the root device node create one
820 * (eg. for legacy drivers)
821 * DeviceNode = Pointer to storage for created device node
827 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
828 PDEVICE_OBJECT PhysicalDeviceObject
,
829 PUNICODE_STRING ServiceName
,
830 PDEVICE_NODE
*DeviceNode
)
836 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
837 ParentNode
, PhysicalDeviceObject
, ServiceName
);
839 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
842 return STATUS_INSUFFICIENT_RESOURCES
;
845 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
847 if (!PhysicalDeviceObject
)
849 Status
= PnpRootCreateDevice(ServiceName
, &PhysicalDeviceObject
);
850 if (!NT_SUCCESS(Status
))
852 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
857 /* This is for drivers passed on the command line to ntoskrnl.exe */
858 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
859 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
862 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
864 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
868 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
869 Node
->Parent
= ParentNode
;
870 Node
->NextSibling
= ParentNode
->Child
;
871 if (ParentNode
->Child
!= NULL
)
873 ParentNode
->Child
->PrevSibling
= Node
;
875 ParentNode
->Child
= Node
;
876 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
877 Node
->Level
= ParentNode
->Level
+ 1;
882 return STATUS_SUCCESS
;
886 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
890 /* All children must be deleted before a parent is deleted */
891 ASSERT(!DeviceNode
->Child
);
893 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
895 ASSERT(DeviceNode
->PhysicalDeviceObject
);
897 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
899 /* Unlink from parent if it exists */
901 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
903 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
906 /* Unlink from sibling list */
908 if (DeviceNode
->PrevSibling
)
910 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
913 if (DeviceNode
->NextSibling
)
915 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
918 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
920 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
922 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
924 if (DeviceNode
->ResourceList
)
926 ExFreePool(DeviceNode
->ResourceList
);
929 if (DeviceNode
->ResourceListTranslated
)
931 ExFreePool(DeviceNode
->ResourceListTranslated
);
934 if (DeviceNode
->ResourceRequirements
)
936 ExFreePool(DeviceNode
->ResourceRequirements
);
939 if (DeviceNode
->BootResources
)
941 ExFreePool(DeviceNode
->BootResources
);
944 ExFreePool(DeviceNode
);
946 return STATUS_SUCCESS
;
950 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
951 PIO_STATUS_BLOCK IoStatusBlock
,
953 PIO_STACK_LOCATION Stack OPTIONAL
)
955 PDEVICE_OBJECT TopDeviceObject
;
956 PIO_STACK_LOCATION IrpSp
;
961 /* Always call the top of the device stack */
962 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
969 Irp
= IoBuildSynchronousFsdRequest(
978 /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */
979 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
980 Irp
->IoStatus
.Information
= 0;
982 IrpSp
= IoGetNextIrpStackLocation(Irp
);
983 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
987 RtlCopyMemory(&IrpSp
->Parameters
,
989 sizeof(Stack
->Parameters
));
992 Status
= IoCallDriver(TopDeviceObject
, Irp
);
993 if (Status
== STATUS_PENDING
)
995 KeWaitForSingleObject(&Event
,
1000 Status
= IoStatusBlock
->Status
;
1003 ObDereferenceObject(TopDeviceObject
);
1010 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1012 PDEVICE_NODE ParentDeviceNode
;
1013 PDEVICE_NODE ChildDeviceNode
;
1016 /* Copy context data so we don't overwrite it in subsequent calls to this function */
1017 ParentDeviceNode
= Context
->DeviceNode
;
1019 /* Call the action routine */
1020 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
1021 if (!NT_SUCCESS(Status
))
1026 /* Traversal of all children nodes */
1027 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
1028 ChildDeviceNode
!= NULL
;
1029 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
1031 /* Pass the current device node to the action routine */
1032 Context
->DeviceNode
= ChildDeviceNode
;
1034 Status
= IopTraverseDeviceTreeNode(Context
);
1035 if (!NT_SUCCESS(Status
))
1046 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1050 DPRINT("Context 0x%p\n", Context
);
1052 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1053 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1055 /* Start from the specified device node */
1056 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1058 /* Recursively traverse the device tree */
1059 Status
= IopTraverseDeviceTreeNode(Context
);
1060 if (Status
== STATUS_UNSUCCESSFUL
)
1062 /* The action routine just wanted to terminate the traversal with status
1063 code STATUS_SUCCESS */
1064 Status
= STATUS_SUCCESS
;
1072 * IopCreateDeviceKeyPath
1074 * Creates a registry key
1078 * Name of the key to be created.
1080 * Handle to the newly created key
1083 * This method can create nested trees, so parent of RegistryPath can
1084 * be not existant, and will be created if needed.
1088 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
1091 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
1092 HANDLE hParent
= NULL
, hKey
;
1093 OBJECT_ATTRIBUTES ObjectAttributes
;
1094 UNICODE_STRING KeyName
;
1095 LPCWSTR Current
, Last
;
1099 /* Assume failure */
1102 /* Open root key for device instances */
1103 InitializeObjectAttributes(&ObjectAttributes
,
1105 OBJ_CASE_INSENSITIVE
,
1108 Status
= ZwOpenKey(&hParent
,
1111 if (!NT_SUCCESS(Status
))
1113 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
1117 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
1118 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
1120 /* Go up to the end of the string */
1121 while (Current
<= Last
)
1123 if (Current
!= Last
&& *Current
!= '\\')
1125 /* Not the end of the string and not a separator */
1130 /* Prepare relative key name */
1131 dwLength
= (ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
;
1132 KeyName
.MaximumLength
= KeyName
.Length
= dwLength
;
1133 DPRINT("Create '%wZ'\n", &KeyName
);
1136 InitializeObjectAttributes(&ObjectAttributes
,
1138 OBJ_CASE_INSENSITIVE
,
1141 Status
= ZwCreateKey(&hKey
,
1142 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
1149 /* Close parent key handle, we don't need it anymore */
1153 /* Key opening/creating failed? */
1154 if (!NT_SUCCESS(Status
))
1156 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
1160 /* Check if it is the end of the string */
1161 if (Current
== Last
)
1163 /* Yes, return success */
1165 return STATUS_SUCCESS
;
1168 /* Start with this new parent key */
1171 KeyName
.Buffer
= (LPWSTR
)Current
;
1174 return STATUS_UNSUCCESSFUL
;
1180 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1181 PDEVICE_NODE DeviceNode
)
1183 OBJECT_ATTRIBUTES ObjectAttributes
;
1184 UNICODE_STRING KeyName
;
1187 ULONG ListSize
, ResultLength
;
1190 DPRINT("IopSetDeviceInstanceData() called\n");
1192 /* Create the 'LogConf' key */
1193 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1194 InitializeObjectAttributes(&ObjectAttributes
,
1196 OBJ_CASE_INSENSITIVE
,
1199 Status
= ZwCreateKey(&LogConfKey
,
1206 if (NT_SUCCESS(Status
))
1208 /* Set 'BootConfig' value */
1209 if (DeviceNode
->BootResources
!= NULL
)
1211 ResCount
= DeviceNode
->BootResources
->Count
;
1214 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1216 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1217 Status
= ZwSetValueKey(LogConfKey
,
1221 &DeviceNode
->BootResources
,
1226 /* Set 'BasicConfigVector' value */
1227 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1228 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1230 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1231 Status
= ZwSetValueKey(LogConfKey
,
1234 REG_RESOURCE_REQUIREMENTS_LIST
,
1235 DeviceNode
->ResourceRequirements
,
1236 DeviceNode
->ResourceRequirements
->ListSize
);
1239 ZwClose(LogConfKey
);
1242 /* Set the 'ConfigFlags' value */
1243 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1244 Status
= ZwQueryValueKey(InstanceKey
,
1246 KeyValueBasicInformation
,
1250 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1252 /* Write the default value */
1253 ULONG DefaultConfigFlags
= 0;
1254 Status
= ZwSetValueKey(InstanceKey
,
1258 &DefaultConfigFlags
,
1259 sizeof(DefaultConfigFlags
));
1262 DPRINT("IopSetDeviceInstanceData() done\n");
1264 return STATUS_SUCCESS
;
1269 IopAssignDeviceResources(
1270 IN PDEVICE_NODE DeviceNode
,
1271 OUT ULONG
*pRequiredSize
)
1273 PIO_RESOURCE_LIST ResourceList
;
1274 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1275 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
1276 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1277 ULONG NumberOfResources
= 0;
1282 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1284 /* No resource needed for this device */
1285 DeviceNode
->ResourceList
= NULL
;
1286 return STATUS_SUCCESS
;
1289 /* Fill DeviceNode->ResourceList
1290 * FIXME: the PnP arbiter should go there!
1291 * Actually, use the BootResources if provided, else the resource list #0
1294 if (DeviceNode
->BootResources
)
1296 /* Browse the boot resources to know if we have some custom structures */
1297 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1298 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1300 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1301 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1302 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1303 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1305 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1306 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1310 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1311 if (!DeviceNode
->ResourceList
)
1313 Status
= STATUS_NO_MEMORY
;
1316 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1318 *pRequiredSize
= Size
;
1319 return STATUS_SUCCESS
;
1322 /* Ok, here, we have to use the device requirement list */
1323 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1324 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1326 Status
= STATUS_REVISION_MISMATCH
;
1330 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1331 *pRequiredSize
= Size
;
1332 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1333 if (!DeviceNode
->ResourceList
)
1335 Status
= STATUS_NO_MEMORY
;
1339 DeviceNode
->ResourceList
->Count
= 1;
1340 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1341 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1342 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1343 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1345 for (i
= 0; i
< ResourceList
->Count
; i
++)
1347 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1349 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1351 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1352 NumberOfResources
++;
1354 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1355 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
1356 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1357 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
1358 switch (ResourceDescriptor
->Type
)
1360 case CmResourceTypePort
:
1362 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1363 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
1366 case CmResourceTypeInterrupt
:
1368 INTERFACE_TYPE BusType
;
1373 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1374 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1375 /* FIXME: HACK: if we have a PCI device, we try
1376 * to keep the IRQ assigned by the BIOS */
1377 if (NT_SUCCESS(IoGetDeviceProperty(
1378 DeviceNode
->PhysicalDeviceObject
,
1379 DevicePropertyLegacyBusType
,
1380 sizeof(INTERFACE_TYPE
),
1382 &ret
)) && BusType
== PCIBus
)
1384 /* We have a PCI bus */
1385 if (NT_SUCCESS(IoGetDeviceProperty(
1386 DeviceNode
->PhysicalDeviceObject
,
1387 DevicePropertyAddress
,
1390 &ret
)) && SlotNumber
> 0)
1392 /* We have a good slot number */
1393 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1394 DeviceNode
->ResourceRequirements
->BusNumber
,
1397 0x3c /* PCI_INTERRUPT_LINE */,
1399 if (ret
!= 0 && ret
!= 2
1400 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1401 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1403 /* The device already has an assigned IRQ */
1404 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1408 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1409 DescriptorRaw
->u
.Interrupt
.Vector
,
1410 &DeviceNode
->InstancePath
);
1411 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1412 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1413 DeviceNode
->ResourceRequirements
->BusNumber
,
1416 0x3c /* PCI_INTERRUPT_LINE */,
1418 if (ret
== 0 || ret
== 2)
1425 case CmResourceTypeMemory
:
1427 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1428 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
1431 case CmResourceTypeDma
:
1433 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1434 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
1435 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
1438 case CmResourceTypeBusNumber
:
1440 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1441 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
1442 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
1445 /*CmResourceTypeDevicePrivate:
1446 case CmResourceTypePcCardConfig:
1447 case CmResourceTypeMfCardConfig:
1450 &DescriptorRaw->u.DevicePrivate,
1451 &ResourceDescriptor->u.DevicePrivate,
1452 sizeof(ResourceDescriptor->u.DevicePrivate));
1454 &DescriptorTranslated->u.DevicePrivate,
1455 &ResourceDescriptor->u.DevicePrivate,
1456 sizeof(ResourceDescriptor->u.DevicePrivate));
1460 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1461 NumberOfResources
--;
1467 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1469 return STATUS_SUCCESS
;
1472 if (DeviceNode
->ResourceList
)
1474 ExFreePool(DeviceNode
->ResourceList
);
1475 DeviceNode
->ResourceList
= NULL
;
1482 IopTranslateDeviceResources(
1483 IN PDEVICE_NODE DeviceNode
,
1484 IN ULONG RequiredSize
)
1486 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1487 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1491 if (!DeviceNode
->ResourceList
)
1493 DeviceNode
->ResourceListTranslated
= NULL
;
1494 return STATUS_SUCCESS
;
1497 /* That's easy to translate a resource list. Just copy the
1498 * untranslated one and change few fields in the copy
1500 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1501 if (!DeviceNode
->ResourceListTranslated
)
1503 Status
=STATUS_NO_MEMORY
;
1506 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1508 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1510 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1511 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1513 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1514 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1515 switch (DescriptorRaw
->Type
)
1517 case CmResourceTypePort
:
1519 ULONG AddressSpace
= 0; /* IO space */
1520 if (!HalTranslateBusAddress(
1521 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1522 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1523 DescriptorRaw
->u
.Port
.Start
,
1525 &DescriptorTranslated
->u
.Port
.Start
))
1527 Status
= STATUS_UNSUCCESSFUL
;
1532 case CmResourceTypeInterrupt
:
1534 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1535 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1536 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1537 DescriptorRaw
->u
.Interrupt
.Level
,
1538 DescriptorRaw
->u
.Interrupt
.Vector
,
1539 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1540 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1543 case CmResourceTypeMemory
:
1545 ULONG AddressSpace
= 1; /* Memory space */
1546 if (!HalTranslateBusAddress(
1547 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1548 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1549 DescriptorRaw
->u
.Memory
.Start
,
1551 &DescriptorTranslated
->u
.Memory
.Start
))
1553 Status
= STATUS_UNSUCCESSFUL
;
1558 case CmResourceTypeDma
:
1559 case CmResourceTypeBusNumber
:
1560 case CmResourceTypeDeviceSpecific
:
1564 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1565 Status
= STATUS_NOT_IMPLEMENTED
;
1570 return STATUS_SUCCESS
;
1573 /* Yes! Also delete ResourceList because ResourceList and
1574 * ResourceListTranslated should be a pair! */
1575 ExFreePool(DeviceNode
->ResourceList
);
1576 DeviceNode
->ResourceList
= NULL
;
1577 if (DeviceNode
->ResourceListTranslated
)
1579 ExFreePool(DeviceNode
->ResourceListTranslated
);
1580 DeviceNode
->ResourceList
= NULL
;
1587 * IopGetParentIdPrefix
1589 * Retrieve (or create) a string which identifies a device.
1593 * Pointer to device node.
1595 * Pointer to the string where is returned the parent node identifier
1598 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1599 * valid and its Buffer field is NULL-terminated. The caller needs to
1600 * to free the string with RtlFreeUnicodeString when it is no longer
1605 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1606 PUNICODE_STRING ParentIdPrefix
)
1608 ULONG KeyNameBufferLength
;
1609 PWSTR KeyNameBuffer
= NULL
;
1610 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1611 UNICODE_STRING KeyName
;
1612 UNICODE_STRING KeyValue
;
1613 UNICODE_STRING ValueName
;
1614 OBJECT_ATTRIBUTES ObjectAttributes
;
1619 /* HACK: As long as some devices have a NULL device
1620 * instance path, the following test is required :(
1622 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1624 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1625 &DeviceNode
->InstancePath
);
1626 return STATUS_UNSUCCESSFUL
;
1629 /* 1. Try to retrieve ParentIdPrefix from registry */
1630 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1631 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1632 if (!ParentIdPrefixInformation
)
1634 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1637 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1640 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1643 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1644 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1645 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1646 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1647 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1648 if (!NT_SUCCESS(Status
))
1650 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1651 Status
= ZwQueryValueKey(
1653 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1654 KeyNameBufferLength
, &KeyNameBufferLength
);
1655 if (NT_SUCCESS(Status
))
1657 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1658 Status
= STATUS_UNSUCCESSFUL
;
1661 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1662 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1666 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1668 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1669 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1673 /* 2. Create the ParentIdPrefix value */
1674 crc32
= RtlComputeCrc32(0,
1675 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1676 DeviceNode
->Parent
->InstancePath
.Length
);
1678 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1679 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1681 /* 3. Try to write the ParentIdPrefix to registry */
1682 Status
= ZwSetValueKey(hKey
,
1686 (PVOID
)KeyValue
.Buffer
,
1687 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1690 if (NT_SUCCESS(Status
))
1692 /* Duplicate the string to return it */
1693 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1695 ExFreePool(ParentIdPrefixInformation
);
1696 ExFreePool(KeyNameBuffer
);
1704 * IopActionInterrogateDeviceStack
1706 * Retrieve information for all (direct) child nodes of a parent node.
1710 * Pointer to device node.
1712 * Pointer to parent node to retrieve child node information for.
1715 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1716 * when we reach a device node which is not a direct child of the device
1717 * node for which we retrieve information of child nodes for. Any errors
1718 * that occur is logged instead so that all child services have a chance
1719 * of being interrogated.
1723 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1726 IO_STATUS_BLOCK IoStatusBlock
;
1727 PDEVICE_NODE ParentDeviceNode
;
1728 WCHAR InstancePath
[MAX_PATH
];
1729 IO_STACK_LOCATION Stack
;
1735 ULONG RequiredLength
;
1737 HANDLE InstanceKey
= NULL
;
1738 UNICODE_STRING ValueName
;
1739 UNICODE_STRING ParentIdPrefix
= { 0 };
1740 DEVICE_CAPABILITIES DeviceCapabilities
;
1742 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1743 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1745 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1748 * We are called for the parent too, but we don't need to do special
1749 * handling for this node
1752 if (DeviceNode
== ParentDeviceNode
)
1754 DPRINT("Success\n");
1755 return STATUS_SUCCESS
;
1759 * Make sure this device node is a direct child of the parent device node
1760 * that is given as an argument
1763 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1765 /* Stop the traversal immediately and indicate successful operation */
1767 return STATUS_UNSUCCESSFUL
;
1771 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1772 if (!NT_SUCCESS(Status
))
1774 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1779 * FIXME: For critical errors, cleanup and disable device, but always
1780 * return STATUS_SUCCESS.
1783 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1785 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1786 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1790 if (NT_SUCCESS(Status
))
1792 /* Copy the device id string */
1793 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1796 * FIXME: Check for valid characters, if there is invalid characters
1802 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1805 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1807 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1808 if (!NT_SUCCESS(Status
))
1810 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1813 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1815 if (!DeviceCapabilities
.UniqueID
)
1817 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1818 DPRINT("Instance ID is not unique\n");
1819 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1820 if (!NT_SUCCESS(Status
))
1822 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1826 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1828 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1829 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1833 if (NT_SUCCESS(Status
))
1835 /* Append the instance id string */
1836 wcscat(InstancePath
, L
"\\");
1837 if (ParentIdPrefix
.Length
> 0)
1839 /* Add information from parent bus device to InstancePath */
1840 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1841 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1842 wcscat(InstancePath
, L
"&");
1844 if (IoStatusBlock
.Information
)
1845 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1848 * FIXME: Check for valid characters, if there is invalid characters
1854 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1856 RtlFreeUnicodeString(&ParentIdPrefix
);
1858 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1860 DPRINT("No resources\n");
1861 /* FIXME: Cleanup and disable device */
1864 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1867 * Create registry key for the instance id, if it doesn't exist yet
1869 KeyBuffer
= ExAllocatePool(
1871 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1872 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1873 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1874 Status
= IopCreateDeviceKeyPath(/*KeyBuffer*/&DeviceNode
->InstancePath
, &InstanceKey
);
1875 ExFreePool(KeyBuffer
);
1876 if (!NT_SUCCESS(Status
))
1878 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1883 /* Set 'Capabilities' value */
1884 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1885 Status
= ZwSetValueKey(InstanceKey
,
1889 (PVOID
)&DeviceNode
->CapabilityFlags
,
1892 /* Set 'UINumber' value */
1893 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1895 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1896 Status
= ZwSetValueKey(InstanceKey
,
1900 &DeviceCapabilities
.UINumber
,
1905 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1907 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1908 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1912 if (NT_SUCCESS(Status
))
1915 * FIXME: Check for valid characters, if there is invalid characters
1919 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1920 DPRINT("Hardware IDs:\n");
1923 DPRINT(" %S\n", Ptr
);
1924 Length
= wcslen(Ptr
) + 1;
1927 TotalLength
+= Length
;
1929 DPRINT("TotalLength: %hu\n", TotalLength
);
1932 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1933 Status
= ZwSetValueKey(InstanceKey
,
1937 (PVOID
)IoStatusBlock
.Information
,
1938 (TotalLength
+ 1) * sizeof(WCHAR
));
1939 if (!NT_SUCCESS(Status
))
1941 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1946 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1949 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1951 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1952 Status
= IopInitiatePnpIrp(
1953 DeviceNode
->PhysicalDeviceObject
,
1957 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1960 * FIXME: Check for valid characters, if there is invalid characters
1964 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1965 DPRINT("Compatible IDs:\n");
1968 DPRINT(" %S\n", Ptr
);
1969 Length
= wcslen(Ptr
) + 1;
1972 TotalLength
+= Length
;
1974 DPRINT("TotalLength: %hu\n", TotalLength
);
1977 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1978 Status
= ZwSetValueKey(InstanceKey
,
1982 (PVOID
)IoStatusBlock
.Information
,
1983 (TotalLength
+ 1) * sizeof(WCHAR
));
1984 if (!NT_SUCCESS(Status
))
1986 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1991 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1994 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1996 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1997 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1998 Status
= IopInitiatePnpIrp(
1999 DeviceNode
->PhysicalDeviceObject
,
2001 IRP_MN_QUERY_DEVICE_TEXT
,
2003 /* This key is mandatory, so even if the Irp fails, we still write it */
2004 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2005 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2007 if (NT_SUCCESS(Status
) &&
2008 IoStatusBlock
.Information
&&
2009 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2011 /* This key is overriden when a driver is installed. Don't write the
2012 * new description if another one already exists */
2013 Status
= ZwSetValueKey(InstanceKey
,
2017 (PVOID
)IoStatusBlock
.Information
,
2018 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2022 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2023 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2025 Status
= ZwSetValueKey(InstanceKey
,
2030 DeviceDesc
.MaximumLength
);
2032 if (!NT_SUCCESS(Status
))
2034 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2040 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2042 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2043 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2044 Status
= IopInitiatePnpIrp(
2045 DeviceNode
->PhysicalDeviceObject
,
2047 IRP_MN_QUERY_DEVICE_TEXT
,
2049 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2051 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2052 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2053 Status
= ZwSetValueKey(InstanceKey
,
2057 (PVOID
)IoStatusBlock
.Information
,
2058 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2059 if (!NT_SUCCESS(Status
))
2061 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2066 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2069 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2071 Status
= IopInitiatePnpIrp(
2072 DeviceNode
->PhysicalDeviceObject
,
2074 IRP_MN_QUERY_BUS_INFORMATION
,
2076 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2078 PPNP_BUS_INFORMATION BusInformation
=
2079 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2081 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2082 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2083 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2084 ExFreePool(BusInformation
);
2088 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2090 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2091 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2092 DeviceNode
->ChildBusTypeIndex
= -1;
2095 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2097 Status
= IopInitiatePnpIrp(
2098 DeviceNode
->PhysicalDeviceObject
,
2100 IRP_MN_QUERY_RESOURCES
,
2102 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2104 DeviceNode
->BootResources
=
2105 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2106 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2110 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2111 DeviceNode
->BootResources
= NULL
;
2114 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2116 Status
= IopInitiatePnpIrp(
2117 DeviceNode
->PhysicalDeviceObject
,
2119 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2121 if (NT_SUCCESS(Status
))
2123 DeviceNode
->ResourceRequirements
=
2124 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2125 if (IoStatusBlock
.Information
)
2126 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2128 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2132 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2133 DeviceNode
->ResourceRequirements
= NULL
;
2137 if (InstanceKey
!= NULL
)
2139 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2142 ZwClose(InstanceKey
);
2144 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
2146 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
2148 /* Report the device to the user-mode pnp manager */
2149 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2150 &DeviceNode
->InstancePath
);
2153 return STATUS_SUCCESS
;
2161 IoSynchronousInvalidateDeviceRelations(
2162 IN PDEVICE_OBJECT DeviceObject
,
2163 IN DEVICE_RELATION_TYPE Type
)
2165 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2166 DEVICETREE_TRAVERSE_CONTEXT Context
;
2167 PDEVICE_RELATIONS DeviceRelations
;
2168 IO_STATUS_BLOCK IoStatusBlock
;
2169 PDEVICE_NODE ChildDeviceNode
;
2170 IO_STACK_LOCATION Stack
;
2171 BOOLEAN BootDrivers
;
2172 OBJECT_ATTRIBUTES ObjectAttributes
;
2173 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
2178 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2180 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2182 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
;
2184 Status
= IopInitiatePnpIrp(
2187 IRP_MN_QUERY_DEVICE_RELATIONS
,
2189 if (!NT_SUCCESS(Status
))
2191 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2195 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2197 if (!DeviceRelations
|| DeviceRelations
->Count
<= 0)
2199 DPRINT("No PDOs\n");
2200 if (DeviceRelations
)
2202 ExFreePool(DeviceRelations
);
2207 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2210 * Create device nodes for all discovered devices
2212 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2214 if (IopGetDeviceNode(DeviceRelations
->Objects
[i
]) != NULL
)
2216 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2219 Status
= IopCreateDeviceNode(
2221 DeviceRelations
->Objects
[i
],
2224 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2225 if (!NT_SUCCESS(Status
))
2227 DPRINT("No resources\n");
2228 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2229 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2230 ExFreePool(DeviceRelations
);
2234 ExFreePool(DeviceRelations
);
2237 * Retrieve information about all discovered children from the bus driver
2239 IopInitDeviceTreeTraverseContext(
2242 IopActionInterrogateDeviceStack
,
2245 Status
= IopTraverseDeviceTree(&Context
);
2246 if (!NT_SUCCESS(Status
))
2248 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2253 * Retrieve configuration from the registry for discovered children
2255 IopInitDeviceTreeTraverseContext(
2258 IopActionConfigureChildServices
,
2261 Status
= IopTraverseDeviceTree(&Context
);
2262 if (!NT_SUCCESS(Status
))
2264 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2269 * Get the state of the system boot. If the \\SystemRoot link isn't
2270 * created yet, we will assume that it's possible to load only boot
2273 InitializeObjectAttributes(
2279 Status
= ZwOpenFile(
2286 if (NT_SUCCESS(Status
))
2288 BootDrivers
= FALSE
;
2295 * Initialize services for discovered children. Only boot drivers will
2296 * be loaded from boot driver!
2298 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2299 if (!NT_SUCCESS(Status
))
2301 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2305 DPRINT("IopInvalidateDeviceRelations() finished\n");
2309 * IopActionConfigureChildServices
2311 * Retrieve configuration for all (direct) child nodes of a parent node.
2315 * Pointer to device node.
2317 * Pointer to parent node to retrieve child node configuration for.
2320 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2321 * when we reach a device node which is not a direct child of the device
2322 * node for which we configure child services for. Any errors that occur is
2323 * logged instead so that all child services have a chance of beeing
2328 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2331 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2332 PDEVICE_NODE ParentDeviceNode
;
2333 PUNICODE_STRING Service
;
2334 UNICODE_STRING ClassGUID
;
2337 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2339 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2342 * We are called for the parent too, but we don't need to do special
2343 * handling for this node
2345 if (DeviceNode
== ParentDeviceNode
)
2347 DPRINT("Success\n");
2348 return STATUS_SUCCESS
;
2352 * Make sure this device node is a direct child of the parent device node
2353 * that is given as an argument
2355 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2357 /* Stop the traversal immediately and indicate successful operation */
2359 return STATUS_UNSUCCESSFUL
;
2362 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2364 WCHAR RegKeyBuffer
[MAX_PATH
];
2365 UNICODE_STRING RegKey
;
2368 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2369 RegKey
.Buffer
= RegKeyBuffer
;
2372 * Retrieve configuration from Enum key
2375 Service
= &DeviceNode
->ServiceName
;
2377 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2378 RtlInitUnicodeString(Service
, NULL
);
2379 RtlInitUnicodeString(&ClassGUID
, NULL
);
2381 QueryTable
[0].Name
= L
"Service";
2382 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
2383 QueryTable
[0].EntryContext
= Service
;
2385 QueryTable
[1].Name
= L
"ClassGUID";
2386 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2387 QueryTable
[1].EntryContext
= &ClassGUID
;
2388 QueryTable
[1].DefaultType
= REG_SZ
;
2389 QueryTable
[1].DefaultData
= L
"";
2390 QueryTable
[1].DefaultLength
= 0;
2392 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2393 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2395 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2396 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2398 if (!NT_SUCCESS(Status
))
2400 /* FIXME: Log the error */
2401 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2402 &DeviceNode
->InstancePath
, Status
);
2403 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2404 return STATUS_SUCCESS
;
2407 if (Service
->Buffer
== NULL
)
2409 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2411 if (ClassGUID
.Length
!= 0)
2413 /* Device has a ClassGUID value, but no Service value.
2414 * Suppose it is using the NULL driver, so state the
2415 * device is started */
2416 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2417 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2418 DeviceNode
->Flags
|= DN_STARTED
;
2420 return STATUS_SUCCESS
;
2423 DPRINT("Got Service %S\n", Service
->Buffer
);
2426 return STATUS_SUCCESS
;
2430 * IopActionInitChildServices
2432 * Initialize the service for all (direct) child nodes of a parent node
2436 * Pointer to device node.
2438 * Pointer to parent node to initialize child node services for.
2440 * Load only driver marked as boot start.
2443 * If the driver image for a service is not loaded and initialized
2444 * it is done here too. We only return a status code indicating an
2445 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2446 * not a direct child of the device node for which we initialize
2447 * child services for. Any errors that occur is logged instead so
2448 * that all child services have a chance of being initialized.
2452 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2454 BOOLEAN BootDrivers
)
2456 PDEVICE_NODE ParentDeviceNode
;
2459 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2462 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2465 * We are called for the parent too, but we don't need to do special
2466 * handling for this node
2468 if (DeviceNode
== ParentDeviceNode
)
2470 DPRINT("Success\n");
2471 return STATUS_SUCCESS
;
2475 * Make sure this device node is a direct child of the parent device node
2476 * that is given as an argument
2479 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2482 * Stop the traversal immediately and indicate unsuccessful operation
2485 return STATUS_UNSUCCESSFUL
;
2489 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2490 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2491 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2493 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2494 PDRIVER_OBJECT DriverObject
;
2496 /* Get existing DriverObject pointer (in case the driver has
2497 already been loaded and initialized) */
2498 Status
= IopGetDriverObject(
2500 &DeviceNode
->ServiceName
,
2503 if (!NT_SUCCESS(Status
))
2505 /* Driver is not initialized, try to load it */
2506 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2508 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2510 /* STATUS_IMAGE_ALREADY_LOADED means this driver
2511 was loaded by the bootloader */
2512 if ((Status
!= STATUS_IMAGE_ALREADY_LOADED
) ||
2513 (Status
== STATUS_IMAGE_ALREADY_LOADED
&& !DriverObject
))
2515 /* Initialize the driver */
2516 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2517 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2521 Status
= STATUS_SUCCESS
;
2526 DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2527 &DeviceNode
->ServiceName
, Status
);
2531 /* Driver is loaded and initialized at this point */
2532 if (NT_SUCCESS(Status
))
2534 /* We have a driver for this DeviceNode */
2535 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2536 /* Attach lower level filter drivers. */
2537 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2538 /* Initialize the function driver for the device node */
2539 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2541 if (NT_SUCCESS(Status
))
2543 /* Attach upper level filter drivers. */
2544 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2545 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2547 Status
= IopStartDevice(DeviceNode
);
2551 DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n",
2552 &DeviceNode
->InstancePath
, Status
);
2558 * Don't disable when trying to load only boot drivers
2562 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2563 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2564 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2565 CPRINT("Initialization of service %S failed (Status %x)\n",
2566 DeviceNode
->ServiceName
.Buffer
, Status
);
2572 DPRINT("Device %wZ is disabled or already initialized\n",
2573 &DeviceNode
->InstancePath
);
2576 return STATUS_SUCCESS
;
2580 * IopActionInitAllServices
2582 * Initialize the service for all (direct) child nodes of a parent node. This
2583 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2587 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2590 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2594 * IopActionInitBootServices
2596 * Initialize the boot start services for all (direct) child nodes of a
2597 * parent node. This function just calls IopActionInitChildServices with
2598 * BootDrivers = TRUE.
2601 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2604 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2608 * IopInitializePnpServices
2610 * Initialize services for discovered children
2614 * Top device node to start initializing services.
2617 * When set to TRUE, only drivers marked as boot start will
2618 * be loaded. Otherwise, all drivers will be loaded.
2624 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2625 IN BOOLEAN BootDrivers
)
2627 DEVICETREE_TRAVERSE_CONTEXT Context
;
2629 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2633 IopInitDeviceTreeTraverseContext(
2636 IopActionInitBootServices
,
2641 IopInitDeviceTreeTraverseContext(
2644 IopActionInitAllServices
,
2648 return IopTraverseDeviceTree(&Context
);
2651 static NTSTATUS INIT_FUNCTION
2652 IopEnumerateDetectedDevices(
2654 IN PUNICODE_STRING RelativePath OPTIONAL
,
2656 IN BOOLEAN EnumerateSubKeys
,
2657 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2658 IN ULONG ParentBootResourcesLength
)
2660 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2661 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2662 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2663 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2664 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2665 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2666 OBJECT_ATTRIBUTES ObjectAttributes
;
2667 HANDLE hDevicesKey
= NULL
;
2668 HANDLE hDeviceKey
= NULL
;
2669 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2670 UNICODE_STRING Level2NameU
;
2671 WCHAR Level2Name
[5];
2672 ULONG IndexDevice
= 0;
2674 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2675 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2676 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2677 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2678 UNICODE_STRING DeviceName
, ValueName
;
2680 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2681 ULONG BootResourcesLength
;
2684 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI");
2685 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2686 static ULONG DeviceIndexPci
= 0;
2688 const UNICODE_STRING IdentifierAcpi
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2689 UNICODE_STRING HardwareIdAcpi
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2690 static ULONG DeviceIndexAcpi
= 0;
2692 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2693 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2694 static ULONG DeviceIndexSerial
= 0;
2695 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2696 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2697 static ULONG DeviceIndexKeyboard
= 0;
2698 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2699 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2700 static ULONG DeviceIndexMouse
= 0;
2701 UNICODE_STRING HardwareIdKey
;
2702 PUNICODE_STRING pHardwareId
;
2703 ULONG DeviceIndex
= 0;
2707 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2708 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2709 if (!NT_SUCCESS(Status
))
2711 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2716 hDevicesKey
= hBaseKey
;
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
);
2806 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2808 /* Concatenate current resources and parent ones */
2809 if (ParentBootResourcesLength
== 0)
2810 BootResourcesLength
= pValueInformation
->DataLength
;
2812 BootResourcesLength
= ParentBootResourcesLength
2813 + pValueInformation
->DataLength
2815 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2818 DPRINT("ExAllocatePool() failed\n");
2821 if (ParentBootResourcesLength
== 0)
2823 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2825 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2827 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2829 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2830 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2831 ParentBootResourcesLength
- Header
);
2832 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2836 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2838 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2839 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2840 ParentBootResourcesLength
- Header
);
2842 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2843 pValueInformation
->Data
+ Header
,
2844 pValueInformation
->DataLength
- Header
);
2845 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2849 if (EnumerateSubKeys
)
2854 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2855 if (Status
== STATUS_NO_MORE_ENTRIES
)
2857 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2859 ExFreePool(pDeviceInformation
);
2860 DeviceInfoLength
= RequiredSize
;
2861 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2862 if (!pDeviceInformation
)
2864 DPRINT("ExAllocatePool() failed\n");
2865 Status
= STATUS_NO_MEMORY
;
2868 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2870 if (!NT_SUCCESS(Status
))
2872 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2876 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2877 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2879 Status
= IopEnumerateDetectedDevices(
2885 BootResourcesLength
);
2886 if (!NT_SUCCESS(Status
))
2891 /* Read identifier */
2892 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2893 if (Status
== STATUS_BUFFER_OVERFLOW
)
2895 ExFreePool(pValueInformation
);
2896 ValueInfoLength
= RequiredSize
;
2897 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2898 if (!pValueInformation
)
2900 DPRINT("ExAllocatePool() failed\n");
2901 Status
= STATUS_NO_MEMORY
;
2904 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2906 if (!NT_SUCCESS(Status
))
2908 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2910 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2913 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2915 else if (pValueInformation
->Type
!= REG_SZ
)
2917 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2922 /* Assign hardware id to this device */
2923 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2924 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2925 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2926 ValueName
.Length
-= sizeof(WCHAR
);
2929 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2931 pHardwareId
= &HardwareIdSerial
;
2932 DeviceIndex
= DeviceIndexSerial
++;
2934 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2936 pHardwareId
= &HardwareIdKeyboard
;
2937 DeviceIndex
= DeviceIndexKeyboard
++;
2939 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2941 pHardwareId
= &HardwareIdMouse
;
2942 DeviceIndex
= DeviceIndexMouse
++;
2944 else if (NT_SUCCESS(Status
))
2946 /* Try to also match the device identifier */
2947 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2949 pHardwareId
= &HardwareIdPci
;
2950 DeviceIndex
= DeviceIndexPci
++;
2953 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierAcpi
, FALSE
) == 0)
2955 pHardwareId
= &HardwareIdAcpi
;
2956 DeviceIndex
= DeviceIndexAcpi
++;
2961 /* Unknown device */
2962 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2968 /* Unknown key path */
2969 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
2973 /* Prepare hardware id key (hardware id value without final \0) */
2974 HardwareIdKey
= *pHardwareId
;
2975 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
2977 /* Add the detected device to Root key */
2978 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2979 Status
= ZwCreateKey(
2985 REG_OPTION_NON_VOLATILE
,
2987 if (!NT_SUCCESS(Status
))
2989 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2992 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2993 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2994 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2995 Status
= ZwCreateKey(
2997 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3001 REG_OPTION_NON_VOLATILE
,
3003 ZwClose(hLevel1Key
);
3004 if (!NT_SUCCESS(Status
))
3006 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3009 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
3010 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
3011 if (!NT_SUCCESS(Status
))
3013 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3014 ZwDeleteKey(hLevel2Key
);
3017 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3018 if (!NT_SUCCESS(Status
))
3020 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3021 ZwDeleteKey(hLevel2Key
);
3024 /* Create 'LogConf' subkey */
3025 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3026 Status
= ZwCreateKey(
3032 REG_OPTION_VOLATILE
,
3034 if (!NT_SUCCESS(Status
))
3036 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3037 ZwDeleteKey(hLevel2Key
);
3040 if (BootResourcesLength
> 0)
3042 /* Save boot resources to 'LogConf\BootConfig' */
3043 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
3044 if (!NT_SUCCESS(Status
))
3046 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3048 ZwDeleteKey(hLevel2Key
);
3055 if (BootResources
&& BootResources
!= ParentBootResources
)
3056 ExFreePool(BootResources
);
3059 ZwClose(hLevel2Key
);
3064 ZwClose(hDeviceKey
);
3069 Status
= STATUS_SUCCESS
;
3072 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
3073 ZwClose(hDevicesKey
);
3075 ZwClose(hDeviceKey
);
3076 if (pDeviceInformation
)
3077 ExFreePool(pDeviceInformation
);
3078 if (pValueInformation
)
3079 ExFreePool(pValueInformation
);
3083 static BOOLEAN INIT_FUNCTION
3084 IopIsAcpiComputer(VOID
)
3089 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3090 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3091 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3092 OBJECT_ATTRIBUTES ObjectAttributes
;
3093 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3094 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3095 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3096 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3098 ULONG IndexDevice
= 0;
3099 UNICODE_STRING DeviceName
, ValueName
;
3100 HANDLE hDevicesKey
= NULL
;
3101 HANDLE hDeviceKey
= NULL
;
3103 BOOLEAN ret
= FALSE
;
3105 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3106 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3107 if (!NT_SUCCESS(Status
))
3109 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3113 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3114 if (!pDeviceInformation
)
3116 DPRINT("ExAllocatePool() failed\n");
3117 Status
= STATUS_NO_MEMORY
;
3121 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3122 if (!pDeviceInformation
)
3124 DPRINT("ExAllocatePool() failed\n");
3125 Status
= STATUS_NO_MEMORY
;
3131 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3132 if (Status
== STATUS_NO_MORE_ENTRIES
)
3134 else if (Status
== STATUS_BUFFER_OVERFLOW
)
3136 ExFreePool(pDeviceInformation
);
3137 DeviceInfoLength
= RequiredSize
;
3138 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3139 if (!pDeviceInformation
)
3141 DPRINT("ExAllocatePool() failed\n");
3142 Status
= STATUS_NO_MEMORY
;
3145 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3147 if (!NT_SUCCESS(Status
))
3149 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3154 /* Open device key */
3155 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3156 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3157 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3162 if (!NT_SUCCESS(Status
))
3164 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3168 /* Read identifier */
3169 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3170 if (Status
== STATUS_BUFFER_OVERFLOW
)
3172 ExFreePool(pValueInformation
);
3173 ValueInfoLength
= RequiredSize
;
3174 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3175 if (!pValueInformation
)
3177 DPRINT("ExAllocatePool() failed\n");
3178 Status
= STATUS_NO_MEMORY
;
3181 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3183 if (!NT_SUCCESS(Status
))
3185 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3188 else if (pValueInformation
->Type
!= REG_SZ
)
3190 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3194 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3195 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3196 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3197 ValueName
.Length
-= sizeof(WCHAR
);
3198 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3200 DPRINT("Found ACPI BIOS\n");
3206 ZwClose(hDeviceKey
);
3211 if (pDeviceInformation
)
3212 ExFreePool(pDeviceInformation
);
3213 if (pValueInformation
)
3214 ExFreePool(pValueInformation
);
3216 ZwClose(hDevicesKey
);
3218 ZwClose(hDeviceKey
);
3223 static NTSTATUS INIT_FUNCTION
3224 IopUpdateRootKey(VOID
)
3226 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
3227 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"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 hEnum
, hRoot
, hHalAcpiDevice
, hHalAcpiId
, hLogConf
;
3240 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3241 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3242 if (!NT_SUCCESS(Status
))
3244 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3248 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, hEnum
, NULL
);
3249 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3251 if (!NT_SUCCESS(Status
))
3253 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3257 if (IopIsAcpiComputer())
3259 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3260 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3262 if (!NT_SUCCESS(Status
))
3264 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3265 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3266 ZwClose(hHalAcpiDevice
);
3267 if (!NT_SUCCESS(Status
))
3269 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3270 if (NT_SUCCESS(Status
))
3271 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3272 if (NT_SUCCESS(Status
))
3274 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hHalAcpiId
, NULL
);
3275 Status
= ZwCreateKey(&hLogConf
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3276 if (NT_SUCCESS(Status
))
3279 ZwClose(hHalAcpiId
);
3284 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3285 Status
= ZwOpenKey(&hEnum
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3286 if (!NT_SUCCESS(Status
))
3288 /* Nothing to do, don't return with an error status */
3289 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3291 return STATUS_SUCCESS
;
3293 Status
= IopEnumerateDetectedDevices(
3307 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
3309 PUNICODE_STRING Name
,
3310 ACCESS_MASK DesiredAccess
)
3312 OBJECT_ATTRIBUTES ObjectAttributes
;
3319 InitializeObjectAttributes(&ObjectAttributes
,
3321 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3325 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
3330 static NTSTATUS INIT_FUNCTION
3332 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
3334 return STATUS_SUCCESS
;
3343 DPRINT("PnpInit()\n");
3345 KeInitializeSpinLock(&IopDeviceTreeLock
);
3347 /* Initialize the Bus Type GUID List */
3348 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3349 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3350 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3352 /* Initialize PnP-Event notification support */
3353 Status
= IopInitPlugPlayEvents();
3354 if (!NT_SUCCESS(Status
))
3356 CPRINT("IopInitPlugPlayEvents() failed\n");
3357 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3361 * Create root device node
3364 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
3365 if (!NT_SUCCESS(Status
))
3367 CPRINT("IoCreateDriverObject() failed\n");
3368 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3371 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3373 if (!NT_SUCCESS(Status
))
3375 CPRINT("IoCreateDevice() failed\n");
3376 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3379 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
3380 if (!NT_SUCCESS(Status
))
3382 CPRINT("Insufficient resources\n");
3383 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3386 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3389 CPRINT("Failed to create the instance path!\n");
3390 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3393 /* Report the device to the user-mode pnp manager */
3394 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3395 &IopRootDeviceNode
->InstancePath
);
3397 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3398 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3399 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3400 IopRootDriverObject
->DriverExtension
->AddDevice(
3401 IopRootDriverObject
,
3402 IopRootDeviceNode
->PhysicalDeviceObject
);
3404 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3405 Status
= IopUpdateRootKey();
3406 if (!NT_SUCCESS(Status
))
3408 CPRINT("IopUpdateRootKey() failed\n");
3409 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3413 RTL_GENERIC_COMPARE_RESULTS
3415 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3416 IN PVOID FirstStruct
,
3417 IN PVOID SecondStruct
)
3425 // The allocation function is called by the generic table package whenever
3426 // it needs to allocate memory for the table.
3431 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3441 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3450 PpInitializeDeviceReferenceTable(VOID
)
3452 /* Setup the guarded mutex and AVL table */
3453 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3454 RtlInitializeGenericTableAvl(
3455 &PpDeviceReferenceTable
,
3456 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3457 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3458 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3466 /* Initialize the resource when accessing device registry data */
3467 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3469 /* Setup the device reference AVL table */
3470 PpInitializeDeviceReferenceTable();
3478 /* Check the initialization phase */
3479 switch (ExpInitializationPhase
)
3484 return PiInitPhase0();
3490 //return PiInitPhase1();
3494 /* Don't know any other phase! Bugcheck! */
3495 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);