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>
18 /* GLOBALS *******************************************************************/
20 PDEVICE_NODE IopRootDeviceNode
;
21 KSPIN_LOCK IopDeviceTreeLock
;
23 /* DATA **********************************************************************/
25 PDRIVER_OBJECT IopRootDriverObject
;
26 PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList
= NULL
;
28 #if defined (ALLOC_PRAGMA)
29 #pragma alloc_text(INIT, PnpInit)
30 #pragma alloc_text(INIT, PnpInit2)
31 #pragma alloc_text(INIT, IopUpdateRootKey)
32 #pragma alloc_text(INIT, IopEnumerateDetectedDevices)
33 #pragma alloc_text(INIT, IopIsAcpiComputer)
36 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
38 DEVICE_RELATION_TYPE Type
;
39 PIO_WORKITEM WorkItem
;
42 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
45 IopInvalidateDeviceRelations(
46 IN PDEVICE_OBJECT DeviceObject
,
47 IN PVOID InvalidateContext
);
49 /* FUNCTIONS *****************************************************************/
53 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
55 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
60 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
61 PDRIVER_OBJECT DriverObject
)
65 BOOLEAN IsPnpDriver
= FALSE
;
67 if (DriverObject
->DriverExtension
->AddDevice
)
69 /* This is a Plug and Play driver */
70 DPRINT("Plug and Play driver found\n");
72 ASSERT(DeviceNode
->PhysicalDeviceObject
);
74 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
75 DriverObject
->DriverExtension
->AddDevice
);
77 IsPnpDriver
= !IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
78 Status
= DriverObject
->DriverExtension
->AddDevice(
79 DriverObject
, IsPnpDriver
? DeviceNode
->PhysicalDeviceObject
: NULL
);
81 if (!NT_SUCCESS(Status
))
88 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
90 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
92 /* FIXME: What do we do? Unload the driver or just disable the device? */
93 DbgPrint("An FDO was not attached\n");
94 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
95 return STATUS_UNSUCCESSFUL
;
98 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
100 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
102 /* There can be only one system power device */
103 if (!SystemPowerDeviceNodeCreated
)
105 PopSystemPowerDeviceNode
= DeviceNode
;
106 SystemPowerDeviceNodeCreated
= TRUE
;
110 ObDereferenceObject(Fdo
);
113 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
114 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
117 return STATUS_SUCCESS
;
122 PDEVICE_NODE DeviceNode
)
124 IO_STATUS_BLOCK IoStatusBlock
;
125 IO_STACK_LOCATION Stack
;
129 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
131 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
132 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
133 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
135 Status
= IopInitiatePnpIrp(
141 if (!NT_SUCCESS(Status
))
143 DPRINT("IopInitiatePnpIrp() failed\n");
147 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
149 DPRINT("Device needs enumeration, invalidating bus relations\n");
150 IoInvalidateDeviceRelations(DeviceNode
->PhysicalDeviceObject
, BusRelations
);
151 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
155 ObDereferenceObject(Fdo
);
157 if (NT_SUCCESS(Status
))
158 DeviceNode
->Flags
|= DN_STARTED
;
165 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
166 PDEVICE_CAPABILITIES DeviceCaps
)
168 IO_STATUS_BLOCK StatusBlock
;
169 IO_STACK_LOCATION Stack
;
171 /* Set up the Header */
172 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
173 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
174 DeviceCaps
->Version
= 1;
175 DeviceCaps
->Address
= -1;
176 DeviceCaps
->UINumber
= -1;
178 /* Set up the Stack */
179 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
180 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
183 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
185 IRP_MN_QUERY_CAPABILITIES
,
194 IoInvalidateDeviceRelations(
195 IN PDEVICE_OBJECT DeviceObject
,
196 IN DEVICE_RELATION_TYPE Type
)
198 PIO_WORKITEM WorkItem
;
199 PINVALIDATE_DEVICE_RELATION_DATA Data
;
201 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
204 WorkItem
= IoAllocateWorkItem(DeviceObject
);
212 Data
->WorkItem
= WorkItem
;
217 IopInvalidateDeviceRelations
,
227 IoSynchronousInvalidateDeviceRelations(
228 IN PDEVICE_OBJECT DeviceObject
,
229 IN DEVICE_RELATION_TYPE Type
)
231 PIO_WORKITEM WorkItem
;
232 PINVALIDATE_DEVICE_RELATION_DATA Data
;
235 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
238 WorkItem
= IoAllocateWorkItem(DeviceObject
);
245 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
247 Data
->WorkItem
= WorkItem
;
248 Data
->Event
= &Event
;
252 IopInvalidateDeviceRelations
,
256 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
265 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
266 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
267 IN ULONG BufferLength
,
268 OUT PVOID PropertyBuffer
,
269 OUT PULONG ResultLength
)
271 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
272 DEVICE_CAPABILITIES DeviceCaps
;
278 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
280 if (DeviceNode
== NULL
)
281 return STATUS_INVALID_DEVICE_REQUEST
;
283 switch (DeviceProperty
)
285 case DevicePropertyBusNumber
:
286 Length
= sizeof(ULONG
);
287 Data
= &DeviceNode
->ChildBusNumber
;
290 /* Complete, untested */
291 case DevicePropertyBusTypeGuid
:
293 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
294 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
296 /* Return the GUID */
297 *ResultLength
= sizeof(GUID
);
299 /* Check if the buffer given was large enough */
300 if (BufferLength
< *ResultLength
)
302 return STATUS_BUFFER_TOO_SMALL
;
306 RtlCopyMemory(PropertyBuffer
,
307 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
309 return STATUS_SUCCESS
;
313 return STATUS_OBJECT_NAME_NOT_FOUND
;
317 case DevicePropertyLegacyBusType
:
318 Length
= sizeof(INTERFACE_TYPE
);
319 Data
= &DeviceNode
->ChildInterfaceType
;
322 case DevicePropertyAddress
:
323 /* Query the device caps */
324 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
325 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
328 *ResultLength
= sizeof(ULONG
);
330 /* Check if the buffer given was large enough */
331 if (BufferLength
< *ResultLength
)
333 return STATUS_BUFFER_TOO_SMALL
;
337 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
338 return STATUS_SUCCESS
;
342 return STATUS_OBJECT_NAME_NOT_FOUND
;
346 // case DevicePropertyUINumber:
347 // if (DeviceNode->CapabilityFlags == NULL)
348 // return STATUS_INVALID_DEVICE_REQUEST;
349 // Length = sizeof(ULONG);
350 // Data = &DeviceNode->CapabilityFlags->UINumber;
353 case DevicePropertyClassName
:
354 case DevicePropertyClassGuid
:
355 case DevicePropertyDriverKeyName
:
356 case DevicePropertyManufacturer
:
357 case DevicePropertyFriendlyName
:
358 case DevicePropertyHardwareID
:
359 case DevicePropertyCompatibleIDs
:
360 case DevicePropertyDeviceDescription
:
361 case DevicePropertyLocationInformation
:
362 case DevicePropertyUINumber
:
364 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
365 UNICODE_STRING KeyName
, ValueName
;
366 OBJECT_ATTRIBUTES ObjectAttributes
;
367 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
368 ULONG ValueInformationLength
;
372 switch (DeviceProperty
)
374 case DevicePropertyClassName
:
375 RegistryPropertyName
= L
"Class"; break;
376 case DevicePropertyClassGuid
:
377 RegistryPropertyName
= L
"ClassGuid"; break;
378 case DevicePropertyDriverKeyName
:
379 RegistryPropertyName
= L
"Driver"; break;
380 case DevicePropertyManufacturer
:
381 RegistryPropertyName
= L
"Mfg"; break;
382 case DevicePropertyFriendlyName
:
383 RegistryPropertyName
= L
"FriendlyName"; break;
384 case DevicePropertyHardwareID
:
385 RegistryPropertyName
= L
"HardwareID"; break;
386 case DevicePropertyCompatibleIDs
:
387 RegistryPropertyName
= L
"CompatibleIDs"; break;
388 case DevicePropertyDeviceDescription
:
389 RegistryPropertyName
= L
"DeviceDesc"; break;
390 case DevicePropertyLocationInformation
:
391 RegistryPropertyName
= L
"LocationInformation"; break;
392 case DevicePropertyUINumber
:
393 RegistryPropertyName
= L
"UINumber"; break;
395 RegistryPropertyName
= NULL
; break;
398 KeyNameBuffer
= ExAllocatePool(PagedPool
,
399 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
401 DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer
, RegistryPropertyName
);
403 if (KeyNameBuffer
== NULL
)
404 return STATUS_INSUFFICIENT_RESOURCES
;
406 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
407 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
408 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
409 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
410 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
412 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
413 ExFreePool(KeyNameBuffer
);
414 if (!NT_SUCCESS(Status
))
417 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
418 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
419 Data
[0]) + BufferLength
;
420 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
421 if (ValueInformation
== NULL
)
424 return STATUS_INSUFFICIENT_RESOURCES
;
427 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
428 KeyValuePartialInformation
, ValueInformation
,
429 ValueInformationLength
,
430 &ValueInformationLength
);
431 *ResultLength
= ValueInformation
->DataLength
;
434 if (!NT_SUCCESS(Status
))
436 ExFreePool(ValueInformation
);
437 if (Status
== STATUS_BUFFER_OVERFLOW
)
438 return STATUS_BUFFER_TOO_SMALL
;
443 /* FIXME: Verify the value (NULL-terminated, correct format). */
445 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
446 ValueInformation
->DataLength
);
447 ExFreePool(ValueInformation
);
449 return STATUS_SUCCESS
;
452 case DevicePropertyBootConfiguration
:
454 if (DeviceNode
->BootResources
->Count
!= 0)
456 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
458 Data
= &DeviceNode
->BootResources
;
461 /* FIXME: use a translated boot configuration instead */
462 case DevicePropertyBootConfigurationTranslated
:
464 if (DeviceNode
->BootResources
->Count
!= 0)
466 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
468 Data
= &DeviceNode
->BootResources
;
471 case DevicePropertyEnumeratorName
:
472 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
475 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
476 Data
= DeviceNode
->InstancePath
.Buffer
;
485 case DevicePropertyPhysicalDeviceObjectName
:
486 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
487 Data
= DeviceNode
->InstancePath
.Buffer
;
491 return STATUS_INVALID_PARAMETER_2
;
494 *ResultLength
= Length
;
495 if (BufferLength
< Length
)
496 return STATUS_BUFFER_TOO_SMALL
;
497 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
499 /* Terminate the string */
500 if (DeviceProperty
== DevicePropertyEnumeratorName
501 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
503 Ptr
= (PWSTR
)PropertyBuffer
;
504 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
507 return STATUS_SUCCESS
;
515 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
521 * @name IoOpenDeviceRegistryKey
523 * Open a registry key unique for a specified driver or device instance.
525 * @param DeviceObject Device to get the registry key for.
526 * @param DevInstKeyType Type of the key to return.
527 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
528 * @param DevInstRegKey Handle to the opened registry key on
537 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
538 IN ULONG DevInstKeyType
,
539 IN ACCESS_MASK DesiredAccess
,
540 OUT PHANDLE DevInstRegKey
)
542 static WCHAR RootKeyName
[] =
543 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
544 static WCHAR ProfileKeyName
[] =
545 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
546 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
547 static WCHAR EnumKeyName
[] = L
"Enum\\";
548 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
550 LPWSTR KeyNameBuffer
;
551 UNICODE_STRING KeyName
;
552 ULONG DriverKeyLength
;
553 OBJECT_ATTRIBUTES ObjectAttributes
;
554 PDEVICE_NODE DeviceNode
= NULL
;
557 DPRINT("IoOpenDeviceRegistryKey() called\n");
559 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
561 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
562 return STATUS_INVALID_PARAMETER
;
566 * Calculate the length of the base key name. This is the full
567 * name for driver key or the name excluding "Device Parameters"
568 * subkey for device key.
571 KeyNameLength
= sizeof(RootKeyName
);
572 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
573 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
574 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
576 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
577 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
578 0, NULL
, &DriverKeyLength
);
579 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
581 KeyNameLength
+= DriverKeyLength
;
585 DeviceNode
= IopGetDeviceNode(DeviceObject
);
586 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
587 DeviceNode
->InstancePath
.Length
;
591 * Now allocate the buffer for the key name...
594 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
595 if (KeyNameBuffer
== NULL
)
596 return STATUS_INSUFFICIENT_RESOURCES
;
599 KeyName
.MaximumLength
= KeyNameLength
;
600 KeyName
.Buffer
= KeyNameBuffer
;
603 * ...and build the key name.
606 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
607 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
609 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
610 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
612 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
614 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
615 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
616 DriverKeyLength
, KeyNameBuffer
+
617 (KeyName
.Length
/ sizeof(WCHAR
)),
619 if (!NT_SUCCESS(Status
))
621 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
622 ExFreePool(KeyNameBuffer
);
625 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
629 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
630 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
631 if (DeviceNode
->InstancePath
.Length
== 0)
633 ExFreePool(KeyNameBuffer
);
642 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
643 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
644 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
645 if (!NT_SUCCESS(Status
))
647 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
648 ExFreePool(KeyNameBuffer
);
651 ExFreePool(KeyNameBuffer
);
654 * For driver key we're done now.
657 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
661 * Let's go further. For device key we must open "Device Parameters"
662 * subkey and create it if it doesn't exist yet.
665 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
666 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
667 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
668 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
669 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
670 ZwClose(ObjectAttributes
.RootDirectory
);
680 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
687 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
691 if (PopSystemPowerDeviceNode
)
693 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
694 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
695 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
697 return STATUS_SUCCESS
;
700 return STATUS_UNSUCCESSFUL
;
705 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
707 USHORT i
= 0, FoundIndex
= 0xFFFF;
711 /* Acquire the lock */
712 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
714 /* Loop all entries */
715 while (i
< IopBusTypeGuidList
->GuidCount
)
717 /* Try to find a match */
718 if (RtlCompareMemory(BusTypeGuid
,
719 &IopBusTypeGuidList
->Guids
[i
],
720 sizeof(GUID
)) == sizeof(GUID
))
729 /* Check if we have to grow the list */
730 if (IopBusTypeGuidList
->GuidCount
)
732 /* Calculate the new size */
733 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
734 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
736 /* Allocate the new copy */
737 NewList
= ExAllocatePool(PagedPool
, NewSize
);
739 /* Now copy them, decrease the size too */
740 NewSize
-= sizeof(GUID
);
741 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
743 /* Free the old list */
744 ExFreePool(IopBusTypeGuidList
);
746 /* Use the new buffer */
747 IopBusTypeGuidList
= NewList
;
750 /* Copy the new GUID */
751 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
755 /* The new entry is the index */
756 FoundIndex
= IopBusTypeGuidList
->GuidCount
;
757 IopBusTypeGuidList
->GuidCount
++;
760 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
766 * Creates a device node
769 * ParentNode = Pointer to parent device node
770 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
771 * to have the root device node create one
772 * (eg. for legacy drivers)
773 * DeviceNode = Pointer to storage for created device node
779 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
780 PDEVICE_OBJECT PhysicalDeviceObject
,
781 PDEVICE_NODE
*DeviceNode
)
787 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
788 ParentNode
, PhysicalDeviceObject
);
790 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
793 return STATUS_INSUFFICIENT_RESOURCES
;
796 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
798 if (!PhysicalDeviceObject
)
800 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
801 if (!NT_SUCCESS(Status
))
807 /* This is for drivers passed on the command line to ntoskrnl.exe */
808 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
809 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
812 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
814 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
818 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
819 Node
->Parent
= ParentNode
;
820 Node
->NextSibling
= ParentNode
->Child
;
821 if (ParentNode
->Child
!= NULL
)
823 ParentNode
->Child
->PrevSibling
= Node
;
825 ParentNode
->Child
= Node
;
826 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
827 Node
->Level
= ParentNode
->Level
+ 1;
832 return STATUS_SUCCESS
;
836 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
840 /* All children must be deleted before a parent is deleted */
841 ASSERT(!DeviceNode
->Child
);
843 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
845 ASSERT(DeviceNode
->PhysicalDeviceObject
);
847 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
849 /* Unlink from parent if it exists */
851 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
853 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
856 /* Unlink from sibling list */
858 if (DeviceNode
->PrevSibling
)
860 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
863 if (DeviceNode
->NextSibling
)
865 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
868 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
870 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
872 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
874 if (DeviceNode
->ResourceList
)
876 ExFreePool(DeviceNode
->ResourceList
);
879 if (DeviceNode
->ResourceListTranslated
)
881 ExFreePool(DeviceNode
->ResourceListTranslated
);
884 if (DeviceNode
->ResourceRequirements
)
886 ExFreePool(DeviceNode
->ResourceRequirements
);
889 if (DeviceNode
->BootResources
)
891 ExFreePool(DeviceNode
->BootResources
);
894 ExFreePool(DeviceNode
);
896 return STATUS_SUCCESS
;
900 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
901 PIO_STATUS_BLOCK IoStatusBlock
,
903 PIO_STACK_LOCATION Stack OPTIONAL
)
905 PDEVICE_OBJECT TopDeviceObject
;
906 PIO_STACK_LOCATION IrpSp
;
911 /* Always call the top of the device stack */
912 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
919 Irp
= IoBuildSynchronousFsdRequest(
928 /* PNP IRPs are always initialized with a status code of
929 STATUS_NOT_IMPLEMENTED */
930 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
931 Irp
->IoStatus
.Information
= 0;
933 IrpSp
= IoGetNextIrpStackLocation(Irp
);
934 IrpSp
->MinorFunction
= MinorFunction
;
938 RtlMoveMemory(&IrpSp
->Parameters
,
940 sizeof(Stack
->Parameters
));
943 Status
= IoCallDriver(TopDeviceObject
, Irp
);
944 if (Status
== STATUS_PENDING
)
946 KeWaitForSingleObject(&Event
,
951 Status
= IoStatusBlock
->Status
;
954 ObDereferenceObject(TopDeviceObject
);
961 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
963 PDEVICE_NODE ParentDeviceNode
;
964 PDEVICE_NODE ChildDeviceNode
;
967 /* Copy context data so we don't overwrite it in subsequent calls to this function */
968 ParentDeviceNode
= Context
->DeviceNode
;
970 /* Call the action routine */
971 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
972 if (!NT_SUCCESS(Status
))
977 /* Traversal of all children nodes */
978 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
979 ChildDeviceNode
!= NULL
;
980 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
982 /* Pass the current device node to the action routine */
983 Context
->DeviceNode
= ChildDeviceNode
;
985 Status
= IopTraverseDeviceTreeNode(Context
);
986 if (!NT_SUCCESS(Status
))
997 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1001 DPRINT("Context 0x%p\n", Context
);
1003 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1004 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1006 /* Start from the specified device node */
1007 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1009 /* Recursively traverse the device tree */
1010 Status
= IopTraverseDeviceTreeNode(Context
);
1011 if (Status
== STATUS_UNSUCCESSFUL
)
1013 /* The action routine just wanted to terminate the traversal with status
1014 code STATUS_SUCCESS */
1015 Status
= STATUS_SUCCESS
;
1024 IopCreateDeviceKeyPath(PWSTR Path
,
1027 OBJECT_ATTRIBUTES ObjectAttributes
;
1028 WCHAR KeyBuffer
[MAX_PATH
];
1029 UNICODE_STRING KeyName
;
1037 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
1039 return STATUS_INVALID_PARAMETER
;
1042 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
1044 /* Skip \\Registry\\ */
1045 Current
= KeyBuffer
;
1046 Current
= wcschr (Current
, L
'\\') + 1;
1047 Current
= wcschr (Current
, L
'\\') + 1;
1051 Next
= wcschr (Current
, L
'\\');
1061 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
1062 InitializeObjectAttributes (&ObjectAttributes
,
1064 OBJ_CASE_INSENSITIVE
,
1068 DPRINT("Create '%S'\n", KeyName
.Buffer
);
1070 Status
= ZwCreateKey (&KeyHandle
,
1077 if (!NT_SUCCESS (Status
))
1079 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
1085 *Handle
= KeyHandle
;
1086 return STATUS_SUCCESS
;
1090 ZwClose (KeyHandle
);
1097 return STATUS_UNSUCCESSFUL
;
1103 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1104 PDEVICE_NODE DeviceNode
)
1106 OBJECT_ATTRIBUTES ObjectAttributes
;
1107 UNICODE_STRING KeyName
;
1110 ULONG ListSize
, ResultLength
;
1113 DPRINT("IopSetDeviceInstanceData() called\n");
1115 /* Create the 'LogConf' key */
1116 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1117 InitializeObjectAttributes(&ObjectAttributes
,
1119 OBJ_CASE_INSENSITIVE
,
1122 Status
= ZwCreateKey(&LogConfKey
,
1129 if (NT_SUCCESS(Status
))
1131 /* Set 'BootConfig' value */
1132 if (DeviceNode
->BootResources
!= NULL
)
1134 ResCount
= DeviceNode
->BootResources
->Count
;
1137 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1139 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1140 Status
= ZwSetValueKey(LogConfKey
,
1144 &DeviceNode
->BootResources
,
1149 /* Set 'BasicConfigVector' value */
1150 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1151 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1153 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1154 Status
= ZwSetValueKey(LogConfKey
,
1157 REG_RESOURCE_REQUIREMENTS_LIST
,
1158 DeviceNode
->ResourceRequirements
,
1159 DeviceNode
->ResourceRequirements
->ListSize
);
1162 ZwClose(LogConfKey
);
1165 /* Set the 'ConfigFlags' value */
1166 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1167 Status
= ZwQueryValueKey(InstanceKey
,
1169 KeyValueBasicInformation
,
1173 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1175 /* Write the default value */
1176 ULONG DefaultConfigFlags
= 0;
1177 Status
= ZwSetValueKey(InstanceKey
,
1181 &DefaultConfigFlags
,
1182 sizeof(DefaultConfigFlags
));
1186 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1188 /* Create the 'Control' key */
1189 RtlInitUnicodeString(&KeyName
,
1191 InitializeObjectAttributes(&ObjectAttributes
,
1193 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1196 Status
= ZwCreateKey(&LogConfKey
,
1201 REG_OPTION_VOLATILE
,
1203 if (NT_SUCCESS(Status
))
1205 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1206 RtlInitUnicodeString(&KeyName
,
1207 L
"DeviceReference");
1208 Status
= ZwSetValueKey(LogConfKey
,
1215 ZwClose(LogConfKey
);
1220 DPRINT("IopSetDeviceInstanceData() done\n");
1222 return STATUS_SUCCESS
;
1227 IopAssignDeviceResources(
1228 IN PDEVICE_NODE DeviceNode
,
1229 OUT ULONG
*pRequiredSize
)
1231 PIO_RESOURCE_LIST ResourceList
;
1232 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1233 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
1234 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1235 ULONG NumberOfResources
= 0;
1240 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1242 /* No resource needed for this device */
1243 DeviceNode
->ResourceList
= NULL
;
1244 return STATUS_SUCCESS
;
1247 /* Fill DeviceNode->ResourceList
1248 * FIXME: the PnP arbiter should go there!
1249 * Actually, use the BootResources if provided, else the resource list #0
1252 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1254 if (DeviceNode
->BootResources
)
1256 /* Browse the boot resources to know if we have some custom structures */
1257 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1258 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1260 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1261 if (pPartialResourceList
->Version
!= 1 || pPartialResourceList
->Revision
!= 1)
1263 Status
= STATUS_REVISION_MISMATCH
;
1266 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1267 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1268 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1270 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1271 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1275 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1276 if (!DeviceNode
->ResourceList
)
1278 Status
= STATUS_NO_MEMORY
;
1281 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1283 *pRequiredSize
= Size
;
1284 return STATUS_SUCCESS
;
1287 /* Ok, here, we have to use the device requirement list */
1288 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1290 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1291 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1293 Status
= STATUS_REVISION_MISMATCH
;
1297 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1298 *pRequiredSize
= Size
;
1299 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1300 if (!DeviceNode
->ResourceList
)
1302 Status
= STATUS_NO_MEMORY
;
1306 DeviceNode
->ResourceList
->Count
= 1;
1307 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1308 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1309 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1310 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1312 for (i
= 0; i
< ResourceList
->Count
; i
++)
1314 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1316 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1318 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1319 NumberOfResources
++;
1321 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1322 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
1323 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1324 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
1325 switch (ResourceDescriptor
->Type
)
1327 case CmResourceTypePort
:
1329 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1330 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
1333 case CmResourceTypeInterrupt
:
1335 INTERFACE_TYPE BusType
;
1340 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1341 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1342 /* FIXME: HACK: if we have a PCI device, we try
1343 * to keep the IRQ assigned by the BIOS */
1344 if (NT_SUCCESS(IoGetDeviceProperty(
1345 DeviceNode
->PhysicalDeviceObject
,
1346 DevicePropertyLegacyBusType
,
1347 sizeof(INTERFACE_TYPE
),
1349 &ret
)) && BusType
== PCIBus
)
1351 /* We have a PCI bus */
1352 if (NT_SUCCESS(IoGetDeviceProperty(
1353 DeviceNode
->PhysicalDeviceObject
,
1354 DevicePropertyAddress
,
1357 &ret
)) && SlotNumber
> 0)
1359 /* We have a good slot number */
1360 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1361 DeviceNode
->ResourceRequirements
->BusNumber
,
1364 0x3c /* PCI_INTERRUPT_LINE */,
1366 if (ret
!= 0 && ret
!= 2
1367 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1368 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1370 /* The device already has an assigned IRQ */
1371 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1375 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1376 DescriptorRaw
->u
.Interrupt
.Vector
,
1377 &DeviceNode
->InstancePath
);
1378 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1379 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1380 DeviceNode
->ResourceRequirements
->BusNumber
,
1383 0x3c /* PCI_INTERRUPT_LINE */,
1385 if (ret
== 0 || ret
== 2)
1392 case CmResourceTypeMemory
:
1394 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1395 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
1398 case CmResourceTypeDma
:
1400 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1401 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
1402 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
1405 case CmResourceTypeBusNumber
:
1407 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1408 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
1409 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
1412 /*CmResourceTypeDevicePrivate:
1413 case CmResourceTypePcCardConfig:
1414 case CmResourceTypeMfCardConfig:
1417 &DescriptorRaw->u.DevicePrivate,
1418 &ResourceDescriptor->u.DevicePrivate,
1419 sizeof(ResourceDescriptor->u.DevicePrivate));
1421 &DescriptorTranslated->u.DevicePrivate,
1422 &ResourceDescriptor->u.DevicePrivate,
1423 sizeof(ResourceDescriptor->u.DevicePrivate));
1427 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1428 NumberOfResources
--;
1434 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1436 return STATUS_SUCCESS
;
1439 if (DeviceNode
->ResourceList
)
1441 ExFreePool(DeviceNode
->ResourceList
);
1442 DeviceNode
->ResourceList
= NULL
;
1449 IopTranslateDeviceResources(
1450 IN PDEVICE_NODE DeviceNode
,
1451 IN ULONG RequiredSize
)
1453 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1454 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1458 if (!DeviceNode
->ResourceList
)
1460 DeviceNode
->ResourceListTranslated
= NULL
;
1461 return STATUS_SUCCESS
;
1464 /* That's easy to translate a resource list. Just copy the
1465 * untranslated one and change few fields in the copy
1467 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1468 if (!DeviceNode
->ResourceListTranslated
)
1470 Status
=STATUS_NO_MEMORY
;
1473 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1475 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1477 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1478 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1480 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1481 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1482 switch (DescriptorRaw
->Type
)
1484 case CmResourceTypePort
:
1486 ULONG AddressSpace
= 0; /* IO space */
1487 if (!HalTranslateBusAddress(
1488 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1489 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1490 DescriptorRaw
->u
.Port
.Start
,
1492 &DescriptorTranslated
->u
.Port
.Start
))
1494 Status
= STATUS_UNSUCCESSFUL
;
1499 case CmResourceTypeInterrupt
:
1501 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1502 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1503 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1504 DescriptorRaw
->u
.Interrupt
.Level
,
1505 DescriptorRaw
->u
.Interrupt
.Vector
,
1506 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1507 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1510 case CmResourceTypeMemory
:
1512 ULONG AddressSpace
= 1; /* Memory space */
1513 if (!HalTranslateBusAddress(
1514 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1515 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1516 DescriptorRaw
->u
.Memory
.Start
,
1518 &DescriptorTranslated
->u
.Memory
.Start
))
1520 Status
= STATUS_UNSUCCESSFUL
;
1525 case CmResourceTypeDma
:
1526 case CmResourceTypeBusNumber
:
1527 case CmResourceTypeDeviceSpecific
:
1531 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1532 Status
= STATUS_NOT_IMPLEMENTED
;
1537 return STATUS_SUCCESS
;
1540 /* Yes! Also delete ResourceList because ResourceList and
1541 * ResourceListTranslated should be a pair! */
1542 ExFreePool(DeviceNode
->ResourceList
);
1543 DeviceNode
->ResourceList
= NULL
;
1544 if (DeviceNode
->ResourceListTranslated
)
1546 ExFreePool(DeviceNode
->ResourceListTranslated
);
1547 DeviceNode
->ResourceList
= NULL
;
1554 * IopGetParentIdPrefix
1556 * Retrieve (or create) a string which identifies a device.
1560 * Pointer to device node.
1562 * Pointer to the string where is returned the parent node identifier
1565 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1566 * valid and its Buffer field is NULL-terminated. The caller needs to
1567 * to free the string with RtlFreeUnicodeString when it is no longer
1572 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1573 PUNICODE_STRING ParentIdPrefix
)
1575 ULONG KeyNameBufferLength
;
1576 PWSTR KeyNameBuffer
= NULL
;
1577 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1578 UNICODE_STRING KeyName
;
1579 UNICODE_STRING KeyValue
;
1580 UNICODE_STRING ValueName
;
1581 OBJECT_ATTRIBUTES ObjectAttributes
;
1586 /* HACK: As long as some devices have a NULL device
1587 * instance path, the following test is required :(
1589 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1590 return STATUS_UNSUCCESSFUL
;
1592 /* 1. Try to retrieve ParentIdPrefix from registry */
1593 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1594 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1595 if (!ParentIdPrefixInformation
)
1597 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1600 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1603 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1606 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1607 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1608 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1609 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1610 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1611 if (!NT_SUCCESS(Status
))
1613 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1614 Status
= ZwQueryValueKey(
1616 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1617 KeyNameBufferLength
, &KeyNameBufferLength
);
1618 if (NT_SUCCESS(Status
))
1620 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1621 Status
= STATUS_UNSUCCESSFUL
;
1624 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1625 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1629 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1631 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1632 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1636 /* 2. Create the ParentIdPrefix value */
1637 crc32
= RtlComputeCrc32(0,
1638 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1639 DeviceNode
->Parent
->InstancePath
.Length
);
1641 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1642 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1644 /* 3. Try to write the ParentIdPrefix to registry */
1645 Status
= ZwSetValueKey(hKey
,
1649 (PVOID
)KeyValue
.Buffer
,
1650 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1653 if (NT_SUCCESS(Status
))
1655 /* Duplicate the string to return it */
1656 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1658 ExFreePool(ParentIdPrefixInformation
);
1659 ExFreePool(KeyNameBuffer
);
1667 * IopActionInterrogateDeviceStack
1669 * Retrieve information for all (direct) child nodes of a parent node.
1673 * Pointer to device node.
1675 * Pointer to parent node to retrieve child node information for.
1678 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1679 * when we reach a device node which is not a direct child of the device
1680 * node for which we retrieve information of child nodes for. Any errors
1681 * that occur is logged instead so that all child services have a chance
1682 * of being interrogated.
1686 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1689 IO_STATUS_BLOCK IoStatusBlock
;
1690 PDEVICE_NODE ParentDeviceNode
;
1691 WCHAR InstancePath
[MAX_PATH
];
1692 IO_STACK_LOCATION Stack
;
1698 ULONG RequiredLength
;
1700 HANDLE InstanceKey
= NULL
;
1701 UNICODE_STRING ValueName
;
1702 UNICODE_STRING ParentIdPrefix
= { 0 };
1703 DEVICE_CAPABILITIES DeviceCapabilities
;
1705 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1706 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1708 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1711 * We are called for the parent too, but we don't need to do special
1712 * handling for this node
1715 if (DeviceNode
== ParentDeviceNode
)
1717 DPRINT("Success\n");
1718 return STATUS_SUCCESS
;
1722 * Make sure this device node is a direct child of the parent device node
1723 * that is given as an argument
1726 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1728 /* Stop the traversal immediately and indicate successful operation */
1730 return STATUS_UNSUCCESSFUL
;
1734 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1735 if (!NT_SUCCESS(Status
))
1737 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1742 * FIXME: For critical errors, cleanup and disable device, but always
1743 * return STATUS_SUCCESS.
1746 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1748 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1749 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1753 if (NT_SUCCESS(Status
))
1755 /* Copy the device id string */
1756 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1759 * FIXME: Check for valid characters, if there is invalid characters
1765 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1768 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1770 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1771 if (!NT_SUCCESS(Status
))
1773 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1776 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1778 if (!DeviceCapabilities
.UniqueID
)
1780 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1781 DPRINT("Instance ID is not unique\n");
1782 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1783 if (!NT_SUCCESS(Status
))
1785 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1789 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1791 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1792 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1796 if (NT_SUCCESS(Status
))
1798 /* Append the instance id string */
1799 wcscat(InstancePath
, L
"\\");
1800 if (ParentIdPrefix
.Length
> 0)
1802 /* Add information from parent bus device to InstancePath */
1803 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1804 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1805 wcscat(InstancePath
, L
"&");
1807 if (IoStatusBlock
.Information
)
1808 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1811 * FIXME: Check for valid characters, if there is invalid characters
1817 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1819 RtlFreeUnicodeString(&ParentIdPrefix
);
1821 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1823 DPRINT("No resources\n");
1824 /* FIXME: Cleanup and disable device */
1827 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1830 * Create registry key for the instance id, if it doesn't exist yet
1832 KeyBuffer
= ExAllocatePool(
1834 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1835 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1836 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1837 Status
= IopCreateDeviceKeyPath(KeyBuffer
, &InstanceKey
);
1838 ExFreePool(KeyBuffer
);
1839 if (!NT_SUCCESS(Status
))
1841 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1846 /* Set 'Capabilities' value */
1847 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1848 Status
= ZwSetValueKey(InstanceKey
,
1852 (PVOID
)&DeviceNode
->CapabilityFlags
,
1855 /* Set 'UINumber' value */
1856 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1858 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1859 Status
= ZwSetValueKey(InstanceKey
,
1863 &DeviceCapabilities
.UINumber
,
1868 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1870 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1871 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1875 if (NT_SUCCESS(Status
))
1878 * FIXME: Check for valid characters, if there is invalid characters
1882 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1883 DPRINT("Hardware IDs:\n");
1886 DPRINT(" %S\n", Ptr
);
1887 Length
= wcslen(Ptr
) + 1;
1890 TotalLength
+= Length
;
1892 DPRINT("TotalLength: %hu\n", TotalLength
);
1895 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1896 Status
= ZwSetValueKey(InstanceKey
,
1900 (PVOID
)IoStatusBlock
.Information
,
1901 (TotalLength
+ 1) * sizeof(WCHAR
));
1902 if (!NT_SUCCESS(Status
))
1904 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1909 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1912 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1914 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1915 Status
= IopInitiatePnpIrp(
1916 DeviceNode
->PhysicalDeviceObject
,
1920 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1923 * FIXME: Check for valid characters, if there is invalid characters
1927 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1928 DPRINT("Compatible IDs:\n");
1931 DPRINT(" %S\n", Ptr
);
1932 Length
= wcslen(Ptr
) + 1;
1935 TotalLength
+= Length
;
1937 DPRINT("TotalLength: %hu\n", TotalLength
);
1940 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1941 Status
= ZwSetValueKey(InstanceKey
,
1945 (PVOID
)IoStatusBlock
.Information
,
1946 (TotalLength
+ 1) * sizeof(WCHAR
));
1947 if (!NT_SUCCESS(Status
))
1949 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1954 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1958 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1960 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1961 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1962 Status
= IopInitiatePnpIrp(
1963 DeviceNode
->PhysicalDeviceObject
,
1965 IRP_MN_QUERY_DEVICE_TEXT
,
1967 /* This key is mandatory, so even if the Irp fails, we still write it */
1968 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1969 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1971 if (NT_SUCCESS(Status
) &&
1972 IoStatusBlock
.Information
&&
1973 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1975 /* This key is overriden when a driver is installed. Don't write the
1976 * new description if another one already exists */
1977 Status
= ZwSetValueKey(InstanceKey
,
1981 (PVOID
)IoStatusBlock
.Information
,
1982 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1986 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1987 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1989 Status
= ZwSetValueKey(InstanceKey
,
1994 DeviceDesc
.MaximumLength
);
1996 if (!NT_SUCCESS(Status
))
1998 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2004 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2006 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2007 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2008 Status
= IopInitiatePnpIrp(
2009 DeviceNode
->PhysicalDeviceObject
,
2011 IRP_MN_QUERY_DEVICE_TEXT
,
2013 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2015 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2016 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2017 Status
= ZwSetValueKey(InstanceKey
,
2021 (PVOID
)IoStatusBlock
.Information
,
2022 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2023 if (!NT_SUCCESS(Status
))
2025 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2030 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2033 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2035 Status
= IopInitiatePnpIrp(
2036 DeviceNode
->PhysicalDeviceObject
,
2038 IRP_MN_QUERY_BUS_INFORMATION
,
2040 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2042 PPNP_BUS_INFORMATION BusInformation
=
2043 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2045 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2046 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2047 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2048 ExFreePool(BusInformation
);
2052 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2054 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2055 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2056 DeviceNode
->ChildBusTypeIndex
= -1;
2059 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2061 Status
= IopInitiatePnpIrp(
2062 DeviceNode
->PhysicalDeviceObject
,
2064 IRP_MN_QUERY_RESOURCES
,
2066 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2068 DeviceNode
->BootResources
=
2069 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2070 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2074 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2075 DeviceNode
->BootResources
= NULL
;
2078 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2080 Status
= IopInitiatePnpIrp(
2081 DeviceNode
->PhysicalDeviceObject
,
2083 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2085 if (NT_SUCCESS(Status
))
2087 DeviceNode
->ResourceRequirements
=
2088 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2089 if (IoStatusBlock
.Information
)
2090 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2092 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2096 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2097 DeviceNode
->ResourceRequirements
= NULL
;
2101 if (InstanceKey
!= NULL
)
2103 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2106 ZwClose(InstanceKey
);
2108 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
2109 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
2110 if (NT_SUCCESS(Status
))
2112 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
2113 if (NT_SUCCESS(Status
))
2115 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
2119 DPRINT("IopTranslateDeviceResources() failed (Status 0x08lx)\n", Status
);
2124 DPRINT("IopAssignDeviceResources() failed (Status 0x08lx)\n", Status
);
2126 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
2128 DeviceNode
->Flags
|= DNF_PROCESSED
;
2130 /* Report the device to the user-mode pnp manager */
2131 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2132 &DeviceNode
->InstancePath
);
2134 return STATUS_SUCCESS
;
2138 * IopActionConfigureChildServices
2140 * Retrieve configuration for all (direct) child nodes of a parent node.
2144 * Pointer to device node.
2146 * Pointer to parent node to retrieve child node configuration for.
2149 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2150 * when we reach a device node which is not a direct child of the device
2151 * node for which we configure child services for. Any errors that occur is
2152 * logged instead so that all child services have a chance of beeing
2157 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2160 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2161 PDEVICE_NODE ParentDeviceNode
;
2162 PUNICODE_STRING Service
;
2163 UNICODE_STRING ClassGUID
;
2164 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
2167 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2169 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2172 * We are called for the parent too, but we don't need to do special
2173 * handling for this node
2175 if (DeviceNode
== ParentDeviceNode
)
2177 DPRINT("Success\n");
2178 return STATUS_SUCCESS
;
2182 * Make sure this device node is a direct child of the parent device node
2183 * that is given as an argument
2185 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2187 /* Stop the traversal immediately and indicate successful operation */
2189 return STATUS_UNSUCCESSFUL
;
2192 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2194 WCHAR RegKeyBuffer
[MAX_PATH
];
2195 UNICODE_STRING RegKey
;
2198 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2199 RegKey
.Buffer
= RegKeyBuffer
;
2202 * Retrieve configuration from Enum key
2205 Service
= &DeviceNode
->ServiceName
;
2207 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2208 RtlInitUnicodeString(Service
, NULL
);
2209 RtlInitUnicodeString(&ClassGUID
, NULL
);
2211 QueryTable
[0].Name
= L
"Service";
2212 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2213 QueryTable
[0].EntryContext
= Service
;
2215 QueryTable
[1].Name
= L
"ClassGUID";
2216 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2217 QueryTable
[1].EntryContext
= &ClassGUID
;
2218 QueryTable
[1].DefaultType
= REG_SZ
;
2219 QueryTable
[1].DefaultData
= &NullString
;
2220 QueryTable
[1].DefaultLength
= 0;
2222 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2223 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2225 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2226 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2228 if (!NT_SUCCESS(Status
))
2230 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
2231 /* FIXME: Log the error */
2232 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
2233 DeviceNode
->InstancePath
.Buffer
, Status
);
2234 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2235 return STATUS_SUCCESS
;
2238 if (Service
->Buffer
== NULL
)
2240 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2242 if (ClassGUID
.Length
!= 0)
2244 /* Device has a ClassGUID value, but no Service value.
2245 * Suppose it is using the NULL driver, so state the
2246 * device is started */
2247 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2248 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2249 DeviceNode
->Flags
|= DN_STARTED
;
2251 return STATUS_SUCCESS
;
2254 DPRINT("Got Service %S\n", Service
->Buffer
);
2257 return STATUS_SUCCESS
;
2261 * IopActionInitChildServices
2263 * Initialize the service for all (direct) child nodes of a parent node
2267 * Pointer to device node.
2269 * Pointer to parent node to initialize child node services for.
2271 * Load only driver marked as boot start.
2274 * If the driver image for a service is not loaded and initialized
2275 * it is done here too. We only return a status code indicating an
2276 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2277 * not a direct child of the device node for which we initialize
2278 * child services for. Any errors that occur is logged instead so
2279 * that all child services have a chance of being initialized.
2283 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2285 BOOLEAN BootDrivers
)
2287 PDEVICE_NODE ParentDeviceNode
;
2290 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2293 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2296 * We are called for the parent too, but we don't need to do special
2297 * handling for this node
2299 if (DeviceNode
== ParentDeviceNode
)
2301 DPRINT("Success\n");
2302 return STATUS_SUCCESS
;
2306 * Make sure this device node is a direct child of the parent device node
2307 * that is given as an argument
2310 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2313 * Stop the traversal immediately and indicate unsuccessful operation
2316 return STATUS_UNSUCCESSFUL
;
2320 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2321 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2322 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2324 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2325 PDRIVER_OBJECT DriverObject
;
2327 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2328 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2330 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2332 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2333 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2334 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2338 /* get existing DriverObject pointer */
2339 Status
= IopGetDriverObject(
2341 &DeviceNode
->ServiceName
,
2344 if (NT_SUCCESS(Status
))
2346 /* Attach lower level filter drivers. */
2347 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2348 /* Initialize the function driver for the device node */
2349 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2350 if (NT_SUCCESS(Status
))
2352 /* Attach upper level filter drivers. */
2353 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2354 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2356 Status
= IopStartDevice(DeviceNode
);
2363 * Don't disable when trying to load only boot drivers
2367 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2368 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2369 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2370 CPRINT("Initialization of service %S failed (Status %x)\n",
2371 DeviceNode
->ServiceName
.Buffer
, Status
);
2376 DPRINT("Service %S is disabled or already initialized\n",
2377 DeviceNode
->ServiceName
.Buffer
);
2380 return STATUS_SUCCESS
;
2384 * IopActionInitAllServices
2386 * Initialize the service for all (direct) child nodes of a parent node. This
2387 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2391 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2394 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2398 * IopActionInitBootServices
2400 * Initialize the boot start services for all (direct) child nodes of a
2401 * parent node. This function just calls IopActionInitChildServices with
2402 * BootDrivers = TRUE.
2405 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2408 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2412 * IopInitializePnpServices
2414 * Initialize services for discovered children
2418 * Top device node to start initializing services.
2421 * When set to TRUE, only drivers marked as boot start will
2422 * be loaded. Otherwise, all drivers will be loaded.
2428 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2429 IN BOOLEAN BootDrivers
)
2431 DEVICETREE_TRAVERSE_CONTEXT Context
;
2433 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2437 IopInitDeviceTreeTraverseContext(
2440 IopActionInitBootServices
,
2445 IopInitDeviceTreeTraverseContext(
2448 IopActionInitAllServices
,
2452 return IopTraverseDeviceTree(&Context
);
2455 /* Invalidate device list enumerated by a device node.
2456 * The call can be make synchronous by defining the Event field
2457 * of the INVALIDATE_DEVICE_RELATION_DATA structure
2459 static VOID CALLBACK
2460 IopInvalidateDeviceRelations(
2461 IN PDEVICE_OBJECT DeviceObject
,
2462 IN PVOID InvalidateContext
) /* PINVALIDATE_DEVICE_RELATION_DATA */
2464 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
2465 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2466 PKEVENT Event
= Data
->Event
;
2467 DEVICETREE_TRAVERSE_CONTEXT Context
;
2468 PDEVICE_RELATIONS DeviceRelations
;
2469 IO_STATUS_BLOCK IoStatusBlock
;
2470 PDEVICE_NODE ChildDeviceNode
;
2471 IO_STACK_LOCATION Stack
;
2472 BOOLEAN BootDrivers
;
2473 OBJECT_ATTRIBUTES ObjectAttributes
;
2474 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
2479 DPRINT("DeviceObject 0x%p, Type %d\n", DeviceObject
, Type
);
2481 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2483 Stack
.Parameters
.QueryDeviceRelations
.Type
= Data
->Type
;
2485 Status
= IopInitiatePnpIrp(
2488 IRP_MN_QUERY_DEVICE_RELATIONS
,
2490 if (!NT_SUCCESS(Status
))
2492 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2496 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2498 if (!DeviceRelations
|| DeviceRelations
->Count
<= 0)
2500 DPRINT("No PDOs\n");
2501 if (DeviceRelations
)
2503 ExFreePool(DeviceRelations
);
2505 Status
= STATUS_SUCCESS
;
2509 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2512 * Create device nodes for all discovered devices
2514 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2516 Status
= IopCreateDeviceNode(
2518 DeviceRelations
->Objects
[i
],
2520 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2521 if (!NT_SUCCESS(Status
))
2523 DPRINT("No resources\n");
2524 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2525 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2526 ExFreePool(DeviceRelations
);
2527 Status
= STATUS_NO_MEMORY
;
2531 ExFreePool(DeviceRelations
);
2534 * Retrieve information about all discovered children from the bus driver
2536 IopInitDeviceTreeTraverseContext(
2539 IopActionInterrogateDeviceStack
,
2542 Status
= IopTraverseDeviceTree(&Context
);
2543 if (!NT_SUCCESS(Status
))
2545 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2550 * Retrieve configuration from the registry for discovered children
2552 IopInitDeviceTreeTraverseContext(
2555 IopActionConfigureChildServices
,
2558 Status
= IopTraverseDeviceTree(&Context
);
2559 if (!NT_SUCCESS(Status
))
2561 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2566 * Get the state of the system boot. If the \\SystemRoot link isn't
2567 * created yet, we will assume that it's possible to load only boot
2570 InitializeObjectAttributes(
2576 Status
= ZwOpenFile(
2583 if (NT_SUCCESS(Status
))
2585 BootDrivers
= FALSE
;
2592 * Initialize services for discovered children. Only boot drivers will
2593 * be loaded from boot driver!
2595 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2596 if (!NT_SUCCESS(Status
))
2598 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2602 DPRINT("IopInvalidateDeviceRelations() finished\n");
2603 Status
= STATUS_SUCCESS
;
2606 IoFreeWorkItem(Data
->WorkItem
);
2609 Data
->Status
= Status
;
2610 KeSetEvent(Event
, 0, FALSE
);
2622 DPRINT("PnpInit()\n");
2624 KeInitializeSpinLock(&IopDeviceTreeLock
);
2626 /* Initialize the Bus Type GUID List */
2627 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2628 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2629 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2631 /* Initialize PnP-Event notification support */
2632 Status
= IopInitPlugPlayEvents();
2633 if (!NT_SUCCESS(Status
))
2635 CPRINT("IopInitPlugPlayEvents() failed\n");
2636 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2640 * Create root device node
2643 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
2644 if (!NT_SUCCESS(Status
))
2646 CPRINT("IoCreateDriverObject() failed\n");
2647 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2650 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2652 if (!NT_SUCCESS(Status
))
2654 CPRINT("IoCreateDevice() failed\n");
2655 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2658 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
2659 if (!NT_SUCCESS(Status
))
2661 CPRINT("Insufficient resources\n");
2662 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2665 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2668 CPRINT("Failed to create the instance path!\n");
2669 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
2672 /* Report the device to the user-mode pnp manager */
2673 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2674 &IopRootDeviceNode
->InstancePath
);
2676 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2677 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2678 IopRootDriverObject
->DriverExtension
->AddDevice(
2679 IopRootDriverObject
,
2680 IopRootDeviceNode
->PhysicalDeviceObject
);
2683 static NTSTATUS INIT_FUNCTION
2684 IopEnumerateDetectedDevices(
2686 IN PUNICODE_STRING RelativePath
,
2688 IN BOOLEAN EnumerateSubKeys
,
2689 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2690 IN ULONG ParentBootResourcesLength
)
2692 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2693 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2694 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2695 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2696 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2697 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2698 OBJECT_ATTRIBUTES ObjectAttributes
;
2699 HANDLE hDevicesKey
= NULL
;
2700 HANDLE hDeviceKey
= NULL
;
2701 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2702 UNICODE_STRING Level2NameU
;
2703 WCHAR Level2Name
[5];
2704 ULONG IndexDevice
= 0;
2706 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2707 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2708 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2709 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2710 UNICODE_STRING DeviceName
, ValueName
;
2712 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2713 ULONG BootResourcesLength
;
2716 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI BIOS");
2717 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2718 static ULONG DeviceIndexPci
= 0;
2719 /*const UNICODE_STRING IdentifierAcpi = RTL_CONSTANT_STRING(L"ACPI BIOS");
2720 UNICODE_STRING HardwareIdAcpi = RTL_CONSTANT_STRING(L"*PNP0C08\0");
2721 static ULONG DeviceIndexAcpi = 0;*/
2722 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2723 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2724 static ULONG DeviceIndexSerial
= 0;
2725 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2726 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2727 static ULONG DeviceIndexKeyboard
= 0;
2728 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2729 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2730 static ULONG DeviceIndexMouse
= 0;
2731 PUNICODE_STRING pHardwareId
;
2732 ULONG DeviceIndex
= 0;
2734 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2735 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2736 if (!NT_SUCCESS(Status
))
2738 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2742 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2743 if (!pDeviceInformation
)
2745 DPRINT("ExAllocatePool() failed\n");
2746 Status
= STATUS_NO_MEMORY
;
2750 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2751 if (!pValueInformation
)
2753 DPRINT("ExAllocatePool() failed\n");
2754 Status
= STATUS_NO_MEMORY
;
2760 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2761 if (Status
== STATUS_NO_MORE_ENTRIES
)
2763 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2765 ExFreePool(pDeviceInformation
);
2766 DeviceInfoLength
= RequiredSize
;
2767 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2768 if (!pDeviceInformation
)
2770 DPRINT("ExAllocatePool() failed\n");
2771 Status
= STATUS_NO_MEMORY
;
2774 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2776 if (!NT_SUCCESS(Status
))
2778 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2783 /* Open device key */
2784 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2785 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2786 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2789 KEY_QUERY_VALUE
+ EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0,
2791 if (!NT_SUCCESS(Status
))
2793 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2797 /* Read boot resources, and add then to parent ones */
2798 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2799 if (Status
== STATUS_BUFFER_OVERFLOW
)
2801 ExFreePool(pValueInformation
);
2802 ValueInfoLength
= RequiredSize
;
2803 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2804 if (!pValueInformation
)
2806 DPRINT("ExAllocatePool() failed\n");
2807 ZwDeleteKey(hLevel2Key
);
2808 Status
= STATUS_NO_MEMORY
;
2811 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2813 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2815 BootResources
= ParentBootResources
;
2816 BootResourcesLength
= ParentBootResourcesLength
;
2818 else if (!NT_SUCCESS(Status
))
2820 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2823 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2825 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2828 else if (((PCM_FULL_RESOURCE_DESCRIPTOR
)pValueInformation
->Data
)->PartialResourceList
.Count
== 0)
2830 BootResources
= ParentBootResources
;
2831 BootResourcesLength
= ParentBootResourcesLength
;
2835 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2837 /* Concatenate current resources and parent ones */
2838 if (ParentBootResourcesLength
== 0)
2839 BootResourcesLength
= pValueInformation
->DataLength
;
2841 BootResourcesLength
= ParentBootResourcesLength
2842 + pValueInformation
->DataLength
2844 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2847 DPRINT("ExAllocatePool() failed\n");
2850 if (ParentBootResourcesLength
== 0)
2852 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2854 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2856 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2858 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2859 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2860 ParentBootResourcesLength
- Header
);
2861 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2865 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2867 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2868 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2869 ParentBootResourcesLength
- Header
);
2871 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2872 pValueInformation
->Data
+ Header
,
2873 pValueInformation
->DataLength
- Header
);
2874 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2878 if (EnumerateSubKeys
)
2883 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2884 if (Status
== STATUS_NO_MORE_ENTRIES
)
2886 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2888 ExFreePool(pDeviceInformation
);
2889 DeviceInfoLength
= RequiredSize
;
2890 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2891 if (!pDeviceInformation
)
2893 DPRINT("ExAllocatePool() failed\n");
2894 Status
= STATUS_NO_MEMORY
;
2897 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2899 if (!NT_SUCCESS(Status
))
2901 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2905 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2906 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2908 Status
= IopEnumerateDetectedDevices(
2914 BootResourcesLength
);
2915 if (!NT_SUCCESS(Status
))
2920 /* Read identifier */
2921 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2922 if (Status
== STATUS_BUFFER_OVERFLOW
)
2924 ExFreePool(pValueInformation
);
2925 ValueInfoLength
= RequiredSize
;
2926 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2927 if (!pValueInformation
)
2929 DPRINT("ExAllocatePool() failed\n");
2930 Status
= STATUS_NO_MEMORY
;
2933 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2935 if (!NT_SUCCESS(Status
))
2937 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2939 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2943 else if (pValueInformation
->Type
!= REG_SZ
)
2945 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2950 /* Assign hardware id to this device */
2951 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2952 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2953 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2954 ValueName
.Length
-= sizeof(WCHAR
);
2957 if (RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2959 pHardwareId
= &HardwareIdSerial
;
2960 DeviceIndex
= DeviceIndexSerial
++;
2962 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2964 pHardwareId
= &HardwareIdKeyboard
;
2965 DeviceIndex
= DeviceIndexKeyboard
++;
2967 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2969 pHardwareId
= &HardwareIdMouse
;
2970 DeviceIndex
= DeviceIndexMouse
++;
2972 else if (NT_SUCCESS(Status
))
2974 /* Try to also match the device identifier */
2975 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2977 pHardwareId
= &HardwareIdPci
;
2978 DeviceIndex
= DeviceIndexPci
++;
2980 /*else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0)
2982 pHardwareId = &HardwareIdAcpi;
2983 DeviceIndex = DeviceIndexAcpi++;
2987 /* Unknown device */
2988 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2994 /* Unknown key path */
2995 DPRINT("Unknown key path %wZ\n", RelativePath
);
2999 /* Add the detected device to Root key */
3000 InitializeObjectAttributes(&ObjectAttributes
, pHardwareId
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
3001 Status
= ZwCreateKey(
3007 REG_OPTION_NON_VOLATILE
,
3009 if (!NT_SUCCESS(Status
))
3011 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3014 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
3015 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
3016 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
3017 Status
= ZwCreateKey(
3019 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3023 REG_OPTION_NON_VOLATILE
,
3025 ZwClose(hLevel1Key
);
3026 if (!NT_SUCCESS(Status
))
3028 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3031 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, pHardwareId
);
3032 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
3033 if (!NT_SUCCESS(Status
))
3035 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3036 ZwDeleteKey(hLevel2Key
);
3039 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3040 if (!NT_SUCCESS(Status
))
3042 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3043 ZwDeleteKey(hLevel2Key
);
3046 if (BootResourcesLength
> 0)
3048 /* Save boot resources to 'LogConf\BootConfig' */
3049 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3050 Status
= ZwCreateKey(
3056 REG_OPTION_VOLATILE
,
3058 if (!NT_SUCCESS(Status
))
3060 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3061 ZwDeleteKey(hLevel2Key
);
3064 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
3066 if (!NT_SUCCESS(Status
))
3068 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3069 ZwDeleteKey(hLevel2Key
);
3075 if (BootResources
&& BootResources
!= ParentBootResources
)
3076 ExFreePool(BootResources
);
3079 ZwClose(hLevel2Key
);
3084 ZwClose(hDeviceKey
);
3089 Status
= STATUS_SUCCESS
;
3093 ZwClose(hDevicesKey
);
3095 ZwClose(hDeviceKey
);
3096 if (pDeviceInformation
)
3097 ExFreePool(pDeviceInformation
);
3098 if (pValueInformation
)
3099 ExFreePool(pValueInformation
);
3103 static BOOLEAN INIT_FUNCTION
3104 IopIsAcpiComputer(VOID
)
3108 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3109 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3110 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3111 OBJECT_ATTRIBUTES ObjectAttributes
;
3112 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3113 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3114 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3115 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3117 ULONG IndexDevice
= 0;
3118 UNICODE_STRING DeviceName
, ValueName
;
3119 HANDLE hDevicesKey
= NULL
;
3120 HANDLE hDeviceKey
= NULL
;
3122 BOOLEAN ret
= FALSE
;
3124 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3125 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3126 if (!NT_SUCCESS(Status
))
3128 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3132 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3133 if (!pDeviceInformation
)
3135 DPRINT("ExAllocatePool() failed\n");
3136 Status
= STATUS_NO_MEMORY
;
3140 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3141 if (!pDeviceInformation
)
3143 DPRINT("ExAllocatePool() failed\n");
3144 Status
= STATUS_NO_MEMORY
;
3150 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3151 if (Status
== STATUS_NO_MORE_ENTRIES
)
3153 else if (Status
== STATUS_BUFFER_OVERFLOW
)
3155 ExFreePool(pDeviceInformation
);
3156 DeviceInfoLength
= RequiredSize
;
3157 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3158 if (!pDeviceInformation
)
3160 DPRINT("ExAllocatePool() failed\n");
3161 Status
= STATUS_NO_MEMORY
;
3164 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3166 if (!NT_SUCCESS(Status
))
3168 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3173 /* Open device key */
3174 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3175 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3176 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3181 if (!NT_SUCCESS(Status
))
3183 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3187 /* Read identifier */
3188 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3189 if (Status
== STATUS_BUFFER_OVERFLOW
)
3191 ExFreePool(pValueInformation
);
3192 ValueInfoLength
= RequiredSize
;
3193 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3194 if (!pValueInformation
)
3196 DPRINT("ExAllocatePool() failed\n");
3197 Status
= STATUS_NO_MEMORY
;
3200 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3202 if (!NT_SUCCESS(Status
))
3204 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3207 else if (pValueInformation
->Type
!= REG_SZ
)
3209 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3213 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3214 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3215 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3216 ValueName
.Length
-= sizeof(WCHAR
);
3217 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3219 DPRINT("Found ACPI BIOS\n");
3225 ZwClose(hDeviceKey
);
3230 if (pDeviceInformation
)
3231 ExFreePool(pDeviceInformation
);
3232 if (pValueInformation
)
3233 ExFreePool(pValueInformation
);
3235 ZwClose(hDevicesKey
);
3237 ZwClose(hDeviceKey
);
3242 static NTSTATUS INIT_FUNCTION
3243 IopUpdateRootKey(VOID
)
3245 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum\\Root");
3246 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3247 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3248 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3249 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3250 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3251 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3252 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3253 OBJECT_ATTRIBUTES ObjectAttributes
;
3254 HANDLE hRoot
, hHalAcpiDevice
, hHalAcpiId
;
3257 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3258 Status
= ZwOpenKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
);
3259 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3261 /* We are probably in 1st stage */
3262 return STATUS_SUCCESS
;
3264 else if (!NT_SUCCESS(Status
))
3266 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3270 if (IopIsAcpiComputer())
3272 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3273 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3275 if (!NT_SUCCESS(Status
))
3277 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3278 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3279 ZwClose(hHalAcpiDevice
);
3280 if (!NT_SUCCESS(Status
))
3282 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3283 if (NT_SUCCESS(Status
))
3284 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3285 ZwClose(hHalAcpiId
);
3290 Status
= IopEnumerateDetectedDevices(
3307 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3308 Status
= IopUpdateRootKey();
3309 if (!NT_SUCCESS(Status
))
3311 CPRINT("IopUpdateRootKey() failed\n");
3312 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);