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 static NTSTATUS INIT_FUNCTION
29 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
);
31 #if defined (ALLOC_PRAGMA)
32 #pragma alloc_text(INIT, IopSetRootDeviceInstanceData)
33 #pragma alloc_text(INIT, PnpInit)
34 #pragma alloc_text(INIT, PnpInit2)
35 #pragma alloc_text(INIT, IopUpdateRootKey)
36 #pragma alloc_text(INIT, IopEnumerateDetectedDevices)
37 #pragma alloc_text(INIT, IopIsAcpiComputer)
41 /* FUNCTIONS *****************************************************************/
45 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
47 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
52 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
53 PDRIVER_OBJECT DriverObject
)
57 BOOLEAN IsPnpDriver
= FALSE
;
59 if (DriverObject
->DriverExtension
->AddDevice
)
61 /* This is a Plug and Play driver */
62 DPRINT("Plug and Play driver found\n");
64 ASSERT(DeviceNode
->PhysicalDeviceObject
);
66 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
67 DriverObject
->DriverExtension
->AddDevice
);
69 IsPnpDriver
= !IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
70 Status
= DriverObject
->DriverExtension
->AddDevice(
71 DriverObject
, IsPnpDriver
? DeviceNode
->PhysicalDeviceObject
: NULL
);
73 if (!NT_SUCCESS(Status
))
80 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
82 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
84 /* FIXME: What do we do? Unload the driver or just disable the device? */
85 DbgPrint("An FDO was not attached\n");
86 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
87 return STATUS_UNSUCCESSFUL
;
90 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
92 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
94 /* There can be only one system power device */
95 if (!SystemPowerDeviceNodeCreated
)
97 PopSystemPowerDeviceNode
= DeviceNode
;
98 SystemPowerDeviceNodeCreated
= TRUE
;
102 ObDereferenceObject(Fdo
);
105 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
106 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
109 return STATUS_SUCCESS
;
114 PDEVICE_NODE DeviceNode
)
116 IO_STATUS_BLOCK IoStatusBlock
;
117 IO_STACK_LOCATION Stack
;
121 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
123 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
124 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
125 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
127 Status
= IopInitiatePnpIrp(
133 if (!NT_SUCCESS(Status
))
135 DPRINT("IopInitiatePnpIrp() failed\n");
139 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
141 DPRINT("Device needs enumeration, invalidating bus relations\n");
142 Status
= IopInvalidateDeviceRelations(DeviceNode
, BusRelations
);
143 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
147 ObDereferenceObject(Fdo
);
149 if (NT_SUCCESS(Status
))
150 DeviceNode
->Flags
|= DN_STARTED
;
157 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
158 PDEVICE_CAPABILITIES DeviceCaps
)
160 IO_STATUS_BLOCK StatusBlock
;
161 IO_STACK_LOCATION Stack
;
163 /* Set up the Header */
164 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
165 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
166 DeviceCaps
->Version
= 1;
167 DeviceCaps
->Address
= -1;
168 DeviceCaps
->UINumber
= -1;
170 /* Set up the Stack */
171 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
172 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
175 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
177 IRP_MN_QUERY_CAPABILITIES
,
181 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
183 DEVICE_RELATION_TYPE Type
;
184 PIO_WORKITEM WorkItem
;
185 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
189 IoInvalidateDeviceRelationsWorker(
190 IN PDEVICE_OBJECT DeviceObject
,
193 PINVALIDATE_DEVICE_RELATION_DATA Data
= Context
;
195 IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject
), Data
->Type
);
196 IoFreeWorkItem(Data
->WorkItem
);
205 IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject
,
206 IN DEVICE_RELATION_TYPE Type
)
208 PIO_WORKITEM WorkItem
;
209 PINVALIDATE_DEVICE_RELATION_DATA Data
;
211 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
214 WorkItem
= IoAllocateWorkItem(DeviceObject
);
222 Data
->WorkItem
= WorkItem
;
226 IoInvalidateDeviceRelationsWorker
,
236 IoSynchronousInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject
,
237 IN DEVICE_RELATION_TYPE Type
)
247 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
248 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
249 IN ULONG BufferLength
,
250 OUT PVOID PropertyBuffer
,
251 OUT PULONG ResultLength
)
253 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
254 DEVICE_CAPABILITIES DeviceCaps
;
260 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
262 if (DeviceNode
== NULL
)
263 return STATUS_INVALID_DEVICE_REQUEST
;
265 switch (DeviceProperty
)
267 case DevicePropertyBusNumber
:
268 Length
= sizeof(ULONG
);
269 Data
= &DeviceNode
->ChildBusNumber
;
272 /* Complete, untested */
273 case DevicePropertyBusTypeGuid
:
275 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
276 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
278 /* Return the GUID */
279 *ResultLength
= sizeof(GUID
);
281 /* Check if the buffer given was large enough */
282 if (BufferLength
< *ResultLength
)
284 return STATUS_BUFFER_TOO_SMALL
;
288 RtlCopyMemory(PropertyBuffer
,
289 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
291 return STATUS_SUCCESS
;
295 return STATUS_OBJECT_NAME_NOT_FOUND
;
299 case DevicePropertyLegacyBusType
:
300 Length
= sizeof(INTERFACE_TYPE
);
301 Data
= &DeviceNode
->ChildInterfaceType
;
304 case DevicePropertyAddress
:
305 /* Query the device caps */
306 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
307 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
310 *ResultLength
= sizeof(ULONG
);
312 /* Check if the buffer given was large enough */
313 if (BufferLength
< *ResultLength
)
315 return STATUS_BUFFER_TOO_SMALL
;
319 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
320 return STATUS_SUCCESS
;
324 return STATUS_OBJECT_NAME_NOT_FOUND
;
328 // case DevicePropertyUINumber:
329 // if (DeviceNode->CapabilityFlags == NULL)
330 // return STATUS_INVALID_DEVICE_REQUEST;
331 // Length = sizeof(ULONG);
332 // Data = &DeviceNode->CapabilityFlags->UINumber;
335 case DevicePropertyClassName
:
336 case DevicePropertyClassGuid
:
337 case DevicePropertyDriverKeyName
:
338 case DevicePropertyManufacturer
:
339 case DevicePropertyFriendlyName
:
340 case DevicePropertyHardwareID
:
341 case DevicePropertyCompatibleIDs
:
342 case DevicePropertyDeviceDescription
:
343 case DevicePropertyLocationInformation
:
344 case DevicePropertyUINumber
:
346 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
347 UNICODE_STRING KeyName
, ValueName
;
348 OBJECT_ATTRIBUTES ObjectAttributes
;
349 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
350 ULONG ValueInformationLength
;
354 switch (DeviceProperty
)
356 case DevicePropertyClassName
:
357 RegistryPropertyName
= L
"Class"; break;
358 case DevicePropertyClassGuid
:
359 RegistryPropertyName
= L
"ClassGuid"; break;
360 case DevicePropertyDriverKeyName
:
361 RegistryPropertyName
= L
"Driver"; break;
362 case DevicePropertyManufacturer
:
363 RegistryPropertyName
= L
"Mfg"; break;
364 case DevicePropertyFriendlyName
:
365 RegistryPropertyName
= L
"FriendlyName"; break;
366 case DevicePropertyHardwareID
:
367 RegistryPropertyName
= L
"HardwareID"; break;
368 case DevicePropertyCompatibleIDs
:
369 RegistryPropertyName
= L
"CompatibleIDs"; break;
370 case DevicePropertyDeviceDescription
:
371 RegistryPropertyName
= L
"DeviceDesc"; break;
372 case DevicePropertyLocationInformation
:
373 RegistryPropertyName
= L
"LocationInformation"; break;
374 case DevicePropertyUINumber
:
375 RegistryPropertyName
= L
"UINumber"; break;
377 RegistryPropertyName
= NULL
; break;
380 KeyNameBuffer
= ExAllocatePool(PagedPool
,
381 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
383 DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer
, RegistryPropertyName
);
385 if (KeyNameBuffer
== NULL
)
386 return STATUS_INSUFFICIENT_RESOURCES
;
388 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
389 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
390 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
391 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
392 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
394 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
395 ExFreePool(KeyNameBuffer
);
396 if (!NT_SUCCESS(Status
))
399 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
400 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
401 Data
[0]) + BufferLength
;
402 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
403 if (ValueInformation
== NULL
)
406 return STATUS_INSUFFICIENT_RESOURCES
;
409 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
410 KeyValuePartialInformation
, ValueInformation
,
411 ValueInformationLength
,
412 &ValueInformationLength
);
413 *ResultLength
= ValueInformation
->DataLength
;
416 if (!NT_SUCCESS(Status
))
418 ExFreePool(ValueInformation
);
419 if (Status
== STATUS_BUFFER_OVERFLOW
)
420 return STATUS_BUFFER_TOO_SMALL
;
425 /* FIXME: Verify the value (NULL-terminated, correct format). */
427 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
428 ValueInformation
->DataLength
);
429 ExFreePool(ValueInformation
);
431 return STATUS_SUCCESS
;
434 case DevicePropertyBootConfiguration
:
436 if (DeviceNode
->BootResources
->Count
!= 0)
438 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
440 Data
= &DeviceNode
->BootResources
;
443 /* FIXME: use a translated boot configuration instead */
444 case DevicePropertyBootConfigurationTranslated
:
446 if (DeviceNode
->BootResources
->Count
!= 0)
448 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
450 Data
= &DeviceNode
->BootResources
;
453 case DevicePropertyEnumeratorName
:
454 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
457 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
458 Data
= DeviceNode
->InstancePath
.Buffer
;
467 case DevicePropertyPhysicalDeviceObjectName
:
468 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
469 Data
= DeviceNode
->InstancePath
.Buffer
;
473 return STATUS_INVALID_PARAMETER_2
;
476 *ResultLength
= Length
;
477 if (BufferLength
< Length
)
478 return STATUS_BUFFER_TOO_SMALL
;
479 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
481 /* Terminate the string */
482 if (DeviceProperty
== DevicePropertyEnumeratorName
483 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
485 Ptr
= (PWSTR
)PropertyBuffer
;
486 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
489 return STATUS_SUCCESS
;
497 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
503 * @name IoOpenDeviceRegistryKey
505 * Open a registry key unique for a specified driver or device instance.
507 * @param DeviceObject Device to get the registry key for.
508 * @param DevInstKeyType Type of the key to return.
509 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
510 * @param DevInstRegKey Handle to the opened registry key on
519 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
520 IN ULONG DevInstKeyType
,
521 IN ACCESS_MASK DesiredAccess
,
522 OUT PHANDLE DevInstRegKey
)
524 static WCHAR RootKeyName
[] =
525 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
526 static WCHAR ProfileKeyName
[] =
527 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
528 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
529 static WCHAR EnumKeyName
[] = L
"Enum\\";
530 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
532 LPWSTR KeyNameBuffer
;
533 UNICODE_STRING KeyName
;
534 ULONG DriverKeyLength
;
535 OBJECT_ATTRIBUTES ObjectAttributes
;
536 PDEVICE_NODE DeviceNode
= NULL
;
539 DPRINT("IoOpenDeviceRegistryKey() called\n");
541 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
543 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
544 return STATUS_INVALID_PARAMETER
;
548 * Calculate the length of the base key name. This is the full
549 * name for driver key or the name excluding "Device Parameters"
550 * subkey for device key.
553 KeyNameLength
= sizeof(RootKeyName
);
554 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
555 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
556 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
558 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
559 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
560 0, NULL
, &DriverKeyLength
);
561 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
563 KeyNameLength
+= DriverKeyLength
;
567 DeviceNode
= IopGetDeviceNode(DeviceObject
);
568 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
569 DeviceNode
->InstancePath
.Length
;
573 * Now allocate the buffer for the key name...
576 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
577 if (KeyNameBuffer
== NULL
)
578 return STATUS_INSUFFICIENT_RESOURCES
;
581 KeyName
.MaximumLength
= KeyNameLength
;
582 KeyName
.Buffer
= KeyNameBuffer
;
585 * ...and build the key name.
588 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
589 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
591 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
592 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
594 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
596 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
597 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
598 DriverKeyLength
, KeyNameBuffer
+
599 (KeyName
.Length
/ sizeof(WCHAR
)),
601 if (!NT_SUCCESS(Status
))
603 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
604 ExFreePool(KeyNameBuffer
);
607 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
611 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
612 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
613 if (DeviceNode
->InstancePath
.Length
== 0)
615 ExFreePool(KeyNameBuffer
);
624 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
625 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
626 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
627 if (!NT_SUCCESS(Status
))
629 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
630 ExFreePool(KeyNameBuffer
);
633 ExFreePool(KeyNameBuffer
);
636 * For driver key we're done now.
639 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
643 * Let's go further. For device key we must open "Device Parameters"
644 * subkey and create it if it doesn't exist yet.
647 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
648 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
649 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
650 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
651 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
652 ZwClose(ObjectAttributes
.RootDirectory
);
662 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
669 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
673 if (PopSystemPowerDeviceNode
)
675 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
676 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
677 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
679 return STATUS_SUCCESS
;
682 return STATUS_UNSUCCESSFUL
;
687 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
689 USHORT i
= 0, FoundIndex
= 0xFFFF;
693 /* Acquire the lock */
694 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
696 /* Loop all entries */
697 while (i
< IopBusTypeGuidList
->GuidCount
)
699 /* Try to find a match */
700 if (RtlCompareMemory(BusTypeGuid
,
701 &IopBusTypeGuidList
->Guids
[i
],
702 sizeof(GUID
)) == sizeof(GUID
))
711 /* Check if we have to grow the list */
712 if (IopBusTypeGuidList
->GuidCount
)
714 /* Calculate the new size */
715 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
716 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
718 /* Allocate the new copy */
719 NewList
= ExAllocatePool(PagedPool
, NewSize
);
721 /* Now copy them, decrease the size too */
722 NewSize
-= sizeof(GUID
);
723 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
725 /* Free the old list */
726 ExFreePool(IopBusTypeGuidList
);
728 /* Use the new buffer */
729 IopBusTypeGuidList
= NewList
;
732 /* Copy the new GUID */
733 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
737 /* The new entry is the index */
738 FoundIndex
= IopBusTypeGuidList
->GuidCount
;
739 IopBusTypeGuidList
->GuidCount
++;
742 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
748 * Creates a device node
751 * ParentNode = Pointer to parent device node
752 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
753 * to have the root device node create one
754 * (eg. for legacy drivers)
755 * DeviceNode = Pointer to storage for created device node
761 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
762 PDEVICE_OBJECT PhysicalDeviceObject
,
763 PDEVICE_NODE
*DeviceNode
)
769 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
770 ParentNode
, PhysicalDeviceObject
);
772 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
775 return STATUS_INSUFFICIENT_RESOURCES
;
778 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
780 if (!PhysicalDeviceObject
)
782 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
783 if (!NT_SUCCESS(Status
))
789 /* This is for drivers passed on the command line to ntoskrnl.exe */
790 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
791 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
794 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
796 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
800 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
801 Node
->Parent
= ParentNode
;
802 Node
->NextSibling
= ParentNode
->Child
;
803 if (ParentNode
->Child
!= NULL
)
805 ParentNode
->Child
->PrevSibling
= Node
;
807 ParentNode
->Child
= Node
;
808 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
809 Node
->Level
= ParentNode
->Level
+ 1;
814 return STATUS_SUCCESS
;
818 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
822 /* All children must be deleted before a parent is deleted */
823 ASSERT(!DeviceNode
->Child
);
825 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
827 ASSERT(DeviceNode
->PhysicalDeviceObject
);
829 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
831 /* Unlink from parent if it exists */
833 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
835 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
838 /* Unlink from sibling list */
840 if (DeviceNode
->PrevSibling
)
842 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
845 if (DeviceNode
->NextSibling
)
847 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
850 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
852 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
854 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
856 if (DeviceNode
->ResourceList
)
858 ExFreePool(DeviceNode
->ResourceList
);
861 if (DeviceNode
->ResourceListTranslated
)
863 ExFreePool(DeviceNode
->ResourceListTranslated
);
866 if (DeviceNode
->ResourceRequirements
)
868 ExFreePool(DeviceNode
->ResourceRequirements
);
871 if (DeviceNode
->BootResources
)
873 ExFreePool(DeviceNode
->BootResources
);
876 ExFreePool(DeviceNode
);
878 return STATUS_SUCCESS
;
882 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
883 PIO_STATUS_BLOCK IoStatusBlock
,
885 PIO_STACK_LOCATION Stack OPTIONAL
)
887 PDEVICE_OBJECT TopDeviceObject
;
888 PIO_STACK_LOCATION IrpSp
;
893 /* Always call the top of the device stack */
894 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
901 Irp
= IoBuildSynchronousFsdRequest(
910 /* PNP IRPs are always initialized with a status code of
911 STATUS_NOT_IMPLEMENTED */
912 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
913 Irp
->IoStatus
.Information
= 0;
915 IrpSp
= IoGetNextIrpStackLocation(Irp
);
916 IrpSp
->MinorFunction
= MinorFunction
;
920 RtlMoveMemory(&IrpSp
->Parameters
,
922 sizeof(Stack
->Parameters
));
925 Status
= IoCallDriver(TopDeviceObject
, Irp
);
926 if (Status
== STATUS_PENDING
)
928 KeWaitForSingleObject(&Event
,
933 Status
= IoStatusBlock
->Status
;
936 ObDereferenceObject(TopDeviceObject
);
943 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
945 PDEVICE_NODE ParentDeviceNode
;
946 PDEVICE_NODE ChildDeviceNode
;
949 /* Copy context data so we don't overwrite it in subsequent calls to this function */
950 ParentDeviceNode
= Context
->DeviceNode
;
952 /* Call the action routine */
953 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
954 if (!NT_SUCCESS(Status
))
959 /* Traversal of all children nodes */
960 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
961 ChildDeviceNode
!= NULL
;
962 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
964 /* Pass the current device node to the action routine */
965 Context
->DeviceNode
= ChildDeviceNode
;
967 Status
= IopTraverseDeviceTreeNode(Context
);
968 if (!NT_SUCCESS(Status
))
979 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
983 DPRINT("Context 0x%p\n", Context
);
985 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
986 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
988 /* Start from the specified device node */
989 Context
->DeviceNode
= Context
->FirstDeviceNode
;
991 /* Recursively traverse the device tree */
992 Status
= IopTraverseDeviceTreeNode(Context
);
993 if (Status
== STATUS_UNSUCCESSFUL
)
995 /* The action routine just wanted to terminate the traversal with status
996 code STATUS_SUCCESS */
997 Status
= STATUS_SUCCESS
;
1006 IopCreateDeviceKeyPath(PWSTR Path
,
1009 OBJECT_ATTRIBUTES ObjectAttributes
;
1010 WCHAR KeyBuffer
[MAX_PATH
];
1011 UNICODE_STRING KeyName
;
1019 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
1021 return STATUS_INVALID_PARAMETER
;
1024 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
1026 /* Skip \\Registry\\ */
1027 Current
= KeyBuffer
;
1028 Current
= wcschr (Current
, L
'\\') + 1;
1029 Current
= wcschr (Current
, L
'\\') + 1;
1033 Next
= wcschr (Current
, L
'\\');
1043 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
1044 InitializeObjectAttributes (&ObjectAttributes
,
1046 OBJ_CASE_INSENSITIVE
,
1050 DPRINT("Create '%S'\n", KeyName
.Buffer
);
1052 Status
= ZwCreateKey (&KeyHandle
,
1059 if (!NT_SUCCESS (Status
))
1061 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
1067 *Handle
= KeyHandle
;
1068 return STATUS_SUCCESS
;
1072 ZwClose (KeyHandle
);
1079 return STATUS_UNSUCCESSFUL
;
1085 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1086 PDEVICE_NODE DeviceNode
)
1088 OBJECT_ATTRIBUTES ObjectAttributes
;
1089 UNICODE_STRING KeyName
;
1092 ULONG ListSize
, ResultLength
;
1095 DPRINT("IopSetDeviceInstanceData() called\n");
1097 /* Create the 'LogConf' key */
1098 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1099 InitializeObjectAttributes(&ObjectAttributes
,
1101 OBJ_CASE_INSENSITIVE
,
1104 Status
= ZwCreateKey(&LogConfKey
,
1111 if (NT_SUCCESS(Status
))
1113 /* Set 'BootConfig' value */
1114 if (DeviceNode
->BootResources
!= NULL
)
1116 ResCount
= DeviceNode
->BootResources
->Count
;
1119 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1121 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1122 Status
= ZwSetValueKey(LogConfKey
,
1126 &DeviceNode
->BootResources
,
1131 /* Set 'BasicConfigVector' value */
1132 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1133 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1135 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1136 Status
= ZwSetValueKey(LogConfKey
,
1139 REG_RESOURCE_REQUIREMENTS_LIST
,
1140 DeviceNode
->ResourceRequirements
,
1141 DeviceNode
->ResourceRequirements
->ListSize
);
1144 ZwClose(LogConfKey
);
1147 /* Set the 'ConfigFlags' value */
1148 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1149 Status
= ZwQueryValueKey(InstanceKey
,
1151 KeyValueBasicInformation
,
1155 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1157 /* Write the default value */
1158 ULONG DefaultConfigFlags
= 0;
1159 Status
= ZwSetValueKey(InstanceKey
,
1163 &DefaultConfigFlags
,
1164 sizeof(DefaultConfigFlags
));
1168 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1170 /* Create the 'Control' key */
1171 RtlInitUnicodeString(&KeyName
,
1173 InitializeObjectAttributes(&ObjectAttributes
,
1175 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1178 Status
= ZwCreateKey(&LogConfKey
,
1183 REG_OPTION_VOLATILE
,
1185 if (NT_SUCCESS(Status
))
1187 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1188 RtlInitUnicodeString(&KeyName
,
1189 L
"DeviceReference");
1190 Status
= ZwSetValueKey(LogConfKey
,
1197 ZwClose(LogConfKey
);
1202 DPRINT("IopSetDeviceInstanceData() done\n");
1204 return STATUS_SUCCESS
;
1209 IopAssignDeviceResources(PDEVICE_NODE DeviceNode
)
1211 PIO_RESOURCE_LIST ResourceList
;
1212 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1213 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1214 ULONG NumberOfResources
= 0;
1218 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
1219 * by using DeviceNode->ResourceRequirements */
1221 if (!DeviceNode
->ResourceRequirements
1222 || DeviceNode
->ResourceRequirements
->AlternativeLists
== 0)
1224 DeviceNode
->ResourceList
= DeviceNode
->ResourceListTranslated
= NULL
;
1225 return STATUS_SUCCESS
;
1228 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1230 /* FIXME: that's here that PnP arbiter should go */
1231 /* Actually, simply use resource list #0 as assigned resource list */
1232 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1233 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1235 Status
= STATUS_REVISION_MISMATCH
;
1239 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
,
1240 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1241 if (!DeviceNode
->ResourceList
)
1243 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1247 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
,
1248 sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
1249 if (!DeviceNode
->ResourceListTranslated
)
1251 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1255 DeviceNode
->ResourceList
->Count
= 1;
1256 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1257 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1258 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1259 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1261 DeviceNode
->ResourceListTranslated
->Count
= 1;
1262 DeviceNode
->ResourceListTranslated
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1263 DeviceNode
->ResourceListTranslated
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1264 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Version
= 1;
1265 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Revision
= 1;
1267 for (i
= 0; i
< ResourceList
->Count
; i
++)
1269 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1271 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1273 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1274 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1275 NumberOfResources
++;
1277 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1278 DescriptorRaw
->Type
= DescriptorTranslated
->Type
= ResourceDescriptor
->Type
;
1279 DescriptorRaw
->ShareDisposition
= DescriptorTranslated
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1280 DescriptorRaw
->Flags
= DescriptorTranslated
->Flags
= ResourceDescriptor
->Flags
;
1281 switch (ResourceDescriptor
->Type
)
1283 case CmResourceTypePort
:
1285 ULONG AddressSpace
= 0; /* IO space */
1286 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1287 DescriptorRaw
->u
.Port
.Length
= DescriptorTranslated
->u
.Port
.Length
1288 = ResourceDescriptor
->u
.Port
.Length
;
1289 if (!HalTranslateBusAddress(
1290 DeviceNode
->ResourceRequirements
->InterfaceType
,
1291 DeviceNode
->ResourceRequirements
->BusNumber
,
1292 DescriptorRaw
->u
.Port
.Start
,
1294 &DescriptorTranslated
->u
.Port
.Start
))
1296 Status
= STATUS_UNSUCCESSFUL
;
1301 case CmResourceTypeInterrupt
:
1303 INTERFACE_TYPE BusType
;
1308 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1309 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1310 /* FIXME: HACK: if we have a PCI device, we try
1311 * to keep the IRQ assigned by the BIOS */
1312 if (NT_SUCCESS(IoGetDeviceProperty(
1313 DeviceNode
->PhysicalDeviceObject
,
1314 DevicePropertyLegacyBusType
,
1315 sizeof(INTERFACE_TYPE
),
1317 &ret
)) && BusType
== PCIBus
)
1319 /* We have a PCI bus */
1320 if (NT_SUCCESS(IoGetDeviceProperty(
1321 DeviceNode
->PhysicalDeviceObject
,
1322 DevicePropertyAddress
,
1325 &ret
)) && SlotNumber
> 0)
1327 /* We have a good slot number */
1328 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1329 DeviceNode
->ResourceRequirements
->BusNumber
,
1332 0x3c /* PCI_INTERRUPT_LINE */,
1334 if (ret
!= 0 && ret
!= 2
1335 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1336 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1338 /* The device already has an assigned IRQ */
1339 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1343 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1344 DescriptorRaw
->u
.Interrupt
.Vector
,
1345 &DeviceNode
->InstancePath
);
1346 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1347 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1348 DeviceNode
->ResourceRequirements
->BusNumber
,
1351 0x3c /* PCI_INTERRUPT_LINE */,
1353 if (ret
== 0 || ret
== 2)
1359 DescriptorTranslated
->u
.Interrupt
.Level
= 0;
1360 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1361 DeviceNode
->ResourceRequirements
->InterfaceType
,
1362 DeviceNode
->ResourceRequirements
->BusNumber
,
1363 DescriptorRaw
->u
.Interrupt
.Level
,
1364 DescriptorRaw
->u
.Interrupt
.Vector
,
1365 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1366 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1367 DescriptorTranslated
->u
.Interrupt
.Affinity
= DescriptorRaw
->u
.Interrupt
.Affinity
;
1370 case CmResourceTypeMemory
:
1372 ULONG AddressSpace
= 1; /* Memory space */
1373 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1374 DescriptorRaw
->u
.Memory
.Length
= DescriptorTranslated
->u
.Memory
.Length
1375 = ResourceDescriptor
->u
.Memory
.Length
;
1376 if (!HalTranslateBusAddress(
1377 DeviceNode
->ResourceRequirements
->InterfaceType
,
1378 DeviceNode
->ResourceRequirements
->BusNumber
,
1379 DescriptorRaw
->u
.Memory
.Start
,
1381 &DescriptorTranslated
->u
.Memory
.Start
))
1383 Status
= STATUS_UNSUCCESSFUL
;
1388 case CmResourceTypeDma
:
1390 DescriptorRaw
->u
.Dma
.Channel
= DescriptorTranslated
->u
.Dma
.Channel
1391 = ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1392 DescriptorRaw
->u
.Dma
.Port
= DescriptorTranslated
->u
.Dma
.Port
1394 DescriptorRaw
->u
.Dma
.Reserved1
= DescriptorTranslated
->u
.Dma
.Reserved1
1398 case CmResourceTypeBusNumber
:
1400 DescriptorRaw
->u
.BusNumber
.Start
= DescriptorTranslated
->u
.BusNumber
.Start
1401 = ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1402 DescriptorRaw
->u
.BusNumber
.Length
= DescriptorTranslated
->u
.BusNumber
.Length
1403 = ResourceDescriptor
->u
.BusNumber
.Length
;
1404 DescriptorRaw
->u
.BusNumber
.Reserved
= DescriptorTranslated
->u
.BusNumber
.Reserved
1405 = ResourceDescriptor
->u
.BusNumber
.Reserved
;
1408 /*CmResourceTypeDevicePrivate:
1409 case CmResourceTypePcCardConfig:
1410 case CmResourceTypeMfCardConfig:
1413 &DescriptorRaw->u.DevicePrivate,
1414 &ResourceDescriptor->u.DevicePrivate,
1415 sizeof(ResourceDescriptor->u.DevicePrivate));
1417 &DescriptorTranslated->u.DevicePrivate,
1418 &ResourceDescriptor->u.DevicePrivate,
1419 sizeof(ResourceDescriptor->u.DevicePrivate));
1423 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1424 NumberOfResources
--;
1430 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1431 DeviceNode
->ResourceListTranslated
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1433 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1434 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
1435 return STATUS_SUCCESS
;
1438 if (DeviceNode
->ResourceList
)
1440 ExFreePool(DeviceNode
->ResourceList
);
1441 DeviceNode
->ResourceList
= NULL
;
1443 if (DeviceNode
->ResourceListTranslated
)
1445 ExFreePool(DeviceNode
->ResourceListTranslated
);
1446 DeviceNode
->ResourceListTranslated
= NULL
;
1449 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1455 * IopGetParentIdPrefix
1457 * Retrieve (or create) a string which identifies a device.
1461 * Pointer to device node.
1463 * Pointer to the string where is returned the parent node identifier
1466 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1467 * valid and its Buffer field is NULL-terminated. The caller needs to
1468 * to free the string with RtlFreeUnicodeString when it is no longer
1473 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1474 PUNICODE_STRING ParentIdPrefix
)
1476 ULONG KeyNameBufferLength
;
1477 PWSTR KeyNameBuffer
= NULL
;
1478 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1479 UNICODE_STRING KeyName
;
1480 UNICODE_STRING KeyValue
;
1481 UNICODE_STRING ValueName
;
1482 OBJECT_ATTRIBUTES ObjectAttributes
;
1487 /* HACK: As long as some devices have a NULL device
1488 * instance path, the following test is required :(
1490 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1491 return STATUS_UNSUCCESSFUL
;
1493 /* 1. Try to retrieve ParentIdPrefix from registry */
1494 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1495 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1496 if (!ParentIdPrefixInformation
)
1498 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1501 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1504 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1507 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1508 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1509 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1510 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1511 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1512 if (!NT_SUCCESS(Status
))
1514 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1515 Status
= ZwQueryValueKey(
1517 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1518 KeyNameBufferLength
, &KeyNameBufferLength
);
1519 if (NT_SUCCESS(Status
))
1521 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1522 Status
= STATUS_UNSUCCESSFUL
;
1525 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1526 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1530 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1532 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1533 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1537 /* 2. Create the ParentIdPrefix value */
1538 crc32
= RtlComputeCrc32(0,
1539 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1540 DeviceNode
->Parent
->InstancePath
.Length
);
1542 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1543 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1545 /* 3. Try to write the ParentIdPrefix to registry */
1546 Status
= ZwSetValueKey(hKey
,
1550 (PVOID
)KeyValue
.Buffer
,
1551 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1554 if (NT_SUCCESS(Status
))
1556 /* Duplicate the string to return it */
1557 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1559 ExFreePool(ParentIdPrefixInformation
);
1560 ExFreePool(KeyNameBuffer
);
1568 * IopActionInterrogateDeviceStack
1570 * Retrieve information for all (direct) child nodes of a parent node.
1574 * Pointer to device node.
1576 * Pointer to parent node to retrieve child node information for.
1579 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1580 * when we reach a device node which is not a direct child of the device
1581 * node for which we retrieve information of child nodes for. Any errors
1582 * that occur is logged instead so that all child services have a chance
1583 * of being interrogated.
1587 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1590 IO_STATUS_BLOCK IoStatusBlock
;
1591 PDEVICE_NODE ParentDeviceNode
;
1592 WCHAR InstancePath
[MAX_PATH
];
1593 IO_STACK_LOCATION Stack
;
1599 ULONG RequiredLength
;
1601 HANDLE InstanceKey
= NULL
;
1602 UNICODE_STRING ValueName
;
1603 UNICODE_STRING ParentIdPrefix
= { 0 };
1604 DEVICE_CAPABILITIES DeviceCapabilities
;
1606 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1607 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1609 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1612 * We are called for the parent too, but we don't need to do special
1613 * handling for this node
1616 if (DeviceNode
== ParentDeviceNode
)
1618 DPRINT("Success\n");
1619 return STATUS_SUCCESS
;
1623 * Make sure this device node is a direct child of the parent device node
1624 * that is given as an argument
1627 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1629 /* Stop the traversal immediately and indicate successful operation */
1631 return STATUS_UNSUCCESSFUL
;
1635 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1636 if (!NT_SUCCESS(Status
))
1638 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1643 * FIXME: For critical errors, cleanup and disable device, but always
1644 * return STATUS_SUCCESS.
1647 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1649 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1650 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1654 if (NT_SUCCESS(Status
))
1656 /* Copy the device id string */
1657 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1660 * FIXME: Check for valid characters, if there is invalid characters
1666 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1669 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1671 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1672 if (!NT_SUCCESS(Status
))
1674 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1677 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1679 if (!DeviceCapabilities
.UniqueID
)
1681 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1682 DPRINT("Instance ID is not unique\n");
1683 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1684 if (!NT_SUCCESS(Status
))
1686 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1690 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1692 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1693 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1697 if (NT_SUCCESS(Status
))
1699 /* Append the instance id string */
1700 wcscat(InstancePath
, L
"\\");
1701 if (ParentIdPrefix
.Length
> 0)
1703 /* Add information from parent bus device to InstancePath */
1704 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1705 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1706 wcscat(InstancePath
, L
"&");
1708 if (IoStatusBlock
.Information
)
1709 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1712 * FIXME: Check for valid characters, if there is invalid characters
1718 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1720 RtlFreeUnicodeString(&ParentIdPrefix
);
1722 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1724 DPRINT("No resources\n");
1725 /* FIXME: Cleanup and disable device */
1728 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1731 * Create registry key for the instance id, if it doesn't exist yet
1733 KeyBuffer
= ExAllocatePool(
1735 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1736 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1737 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1738 Status
= IopCreateDeviceKeyPath(KeyBuffer
, &InstanceKey
);
1739 ExFreePool(KeyBuffer
);
1740 if (!NT_SUCCESS(Status
))
1742 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1747 /* Set 'Capabilities' value */
1748 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1749 Status
= ZwSetValueKey(InstanceKey
,
1753 (PVOID
)&DeviceNode
->CapabilityFlags
,
1756 /* Set 'UINumber' value */
1757 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1759 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1760 Status
= ZwSetValueKey(InstanceKey
,
1764 &DeviceCapabilities
.UINumber
,
1769 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1771 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1772 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1776 if (NT_SUCCESS(Status
))
1779 * FIXME: Check for valid characters, if there is invalid characters
1783 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1784 DPRINT("Hardware IDs:\n");
1787 DPRINT(" %S\n", Ptr
);
1788 Length
= wcslen(Ptr
) + 1;
1791 TotalLength
+= Length
;
1793 DPRINT("TotalLength: %hu\n", TotalLength
);
1796 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1797 Status
= ZwSetValueKey(InstanceKey
,
1801 (PVOID
)IoStatusBlock
.Information
,
1802 (TotalLength
+ 1) * sizeof(WCHAR
));
1803 if (!NT_SUCCESS(Status
))
1805 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1810 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1813 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1815 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1816 Status
= IopInitiatePnpIrp(
1817 DeviceNode
->PhysicalDeviceObject
,
1821 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1824 * FIXME: Check for valid characters, if there is invalid characters
1828 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1829 DPRINT("Compatible IDs:\n");
1832 DPRINT(" %S\n", Ptr
);
1833 Length
= wcslen(Ptr
) + 1;
1836 TotalLength
+= Length
;
1838 DPRINT("TotalLength: %hu\n", TotalLength
);
1841 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1842 Status
= ZwSetValueKey(InstanceKey
,
1846 (PVOID
)IoStatusBlock
.Information
,
1847 (TotalLength
+ 1) * sizeof(WCHAR
));
1848 if (!NT_SUCCESS(Status
))
1850 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1855 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1859 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1861 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1862 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1863 Status
= IopInitiatePnpIrp(
1864 DeviceNode
->PhysicalDeviceObject
,
1866 IRP_MN_QUERY_DEVICE_TEXT
,
1868 /* This key is mandatory, so even if the Irp fails, we still write it */
1869 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1870 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1872 if (NT_SUCCESS(Status
) &&
1873 IoStatusBlock
.Information
&&
1874 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1876 /* This key is overriden when a driver is installed. Don't write the
1877 * new description if another one already exists */
1878 Status
= ZwSetValueKey(InstanceKey
,
1882 (PVOID
)IoStatusBlock
.Information
,
1883 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1887 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1888 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1890 Status
= ZwSetValueKey(InstanceKey
,
1895 DeviceDesc
.MaximumLength
);
1897 if (!NT_SUCCESS(Status
))
1899 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
1905 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1907 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
1908 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1909 Status
= IopInitiatePnpIrp(
1910 DeviceNode
->PhysicalDeviceObject
,
1912 IRP_MN_QUERY_DEVICE_TEXT
,
1914 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1916 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
1917 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
1918 Status
= ZwSetValueKey(InstanceKey
,
1922 (PVOID
)IoStatusBlock
.Information
,
1923 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1924 if (!NT_SUCCESS(Status
))
1926 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1931 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1934 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1936 Status
= IopInitiatePnpIrp(
1937 DeviceNode
->PhysicalDeviceObject
,
1939 IRP_MN_QUERY_BUS_INFORMATION
,
1941 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1943 PPNP_BUS_INFORMATION BusInformation
=
1944 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
1946 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
1947 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
1948 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
1949 ExFreePool(BusInformation
);
1953 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1955 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
1956 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
1957 DeviceNode
->ChildBusTypeIndex
= -1;
1960 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1962 Status
= IopInitiatePnpIrp(
1963 DeviceNode
->PhysicalDeviceObject
,
1965 IRP_MN_QUERY_RESOURCES
,
1967 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1969 DeviceNode
->BootResources
=
1970 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
1971 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
1975 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
1976 DeviceNode
->BootResources
= NULL
;
1979 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1981 Status
= IopInitiatePnpIrp(
1982 DeviceNode
->PhysicalDeviceObject
,
1984 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
1986 if (NT_SUCCESS(Status
))
1988 DeviceNode
->ResourceRequirements
=
1989 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
1990 if (IoStatusBlock
.Information
)
1991 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
1993 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
1997 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
1998 DeviceNode
->ResourceRequirements
= NULL
;
2002 if (InstanceKey
!= NULL
)
2004 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2007 ZwClose(InstanceKey
);
2009 Status
= IopAssignDeviceResources(DeviceNode
);
2010 if (!NT_SUCCESS(Status
))
2012 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status
);
2015 DeviceNode
->Flags
|= DNF_PROCESSED
;
2017 /* Report the device to the user-mode pnp manager */
2018 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2019 &DeviceNode
->InstancePath
);
2021 return STATUS_SUCCESS
;
2025 * IopActionConfigureChildServices
2027 * Retrieve configuration for all (direct) child nodes of a parent node.
2031 * Pointer to device node.
2033 * Pointer to parent node to retrieve child node configuration for.
2036 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2037 * when we reach a device node which is not a direct child of the device
2038 * node for which we configure child services for. Any errors that occur is
2039 * logged instead so that all child services have a chance of beeing
2044 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2047 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2048 PDEVICE_NODE ParentDeviceNode
;
2049 PUNICODE_STRING Service
;
2050 UNICODE_STRING ClassGUID
;
2051 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
2054 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2056 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2059 * We are called for the parent too, but we don't need to do special
2060 * handling for this node
2062 if (DeviceNode
== ParentDeviceNode
)
2064 DPRINT("Success\n");
2065 return STATUS_SUCCESS
;
2069 * Make sure this device node is a direct child of the parent device node
2070 * that is given as an argument
2072 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2074 /* Stop the traversal immediately and indicate successful operation */
2076 return STATUS_UNSUCCESSFUL
;
2079 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2081 WCHAR RegKeyBuffer
[MAX_PATH
];
2082 UNICODE_STRING RegKey
;
2085 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2086 RegKey
.Buffer
= RegKeyBuffer
;
2089 * Retrieve configuration from Enum key
2092 Service
= &DeviceNode
->ServiceName
;
2094 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2095 RtlInitUnicodeString(Service
, NULL
);
2096 RtlInitUnicodeString(&ClassGUID
, NULL
);
2098 QueryTable
[0].Name
= L
"Service";
2099 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2100 QueryTable
[0].EntryContext
= Service
;
2102 QueryTable
[1].Name
= L
"ClassGUID";
2103 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2104 QueryTable
[1].EntryContext
= &ClassGUID
;
2105 QueryTable
[1].DefaultType
= REG_SZ
;
2106 QueryTable
[1].DefaultData
= &NullString
;
2107 QueryTable
[1].DefaultLength
= 0;
2109 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2110 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2112 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2113 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2115 if (!NT_SUCCESS(Status
))
2117 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
2118 /* FIXME: Log the error */
2119 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
2120 DeviceNode
->InstancePath
.Buffer
, Status
);
2121 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2122 return STATUS_SUCCESS
;
2125 if (Service
->Buffer
== NULL
)
2127 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2129 if (ClassGUID
.Length
!= 0)
2131 /* Device has a ClassGUID value, but no Service value.
2132 * Suppose it is using the NULL driver, so state the
2133 * device is started */
2134 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2135 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2136 DeviceNode
->Flags
|= DN_STARTED
;
2138 return STATUS_SUCCESS
;
2141 DPRINT("Got Service %S\n", Service
->Buffer
);
2144 return STATUS_SUCCESS
;
2148 * IopActionInitChildServices
2150 * Initialize the service for all (direct) child nodes of a parent node
2154 * Pointer to device node.
2156 * Pointer to parent node to initialize child node services for.
2158 * Load only driver marked as boot start.
2161 * If the driver image for a service is not loaded and initialized
2162 * it is done here too. We only return a status code indicating an
2163 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2164 * not a direct child of the device node for which we initialize
2165 * child services for. Any errors that occur is logged instead so
2166 * that all child services have a chance of being initialized.
2170 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2172 BOOLEAN BootDrivers
)
2174 PDEVICE_NODE ParentDeviceNode
;
2177 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2180 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2183 * We are called for the parent too, but we don't need to do special
2184 * handling for this node
2186 if (DeviceNode
== ParentDeviceNode
)
2188 DPRINT("Success\n");
2189 return STATUS_SUCCESS
;
2193 * Make sure this device node is a direct child of the parent device node
2194 * that is given as an argument
2197 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2200 * Stop the traversal immediately and indicate unsuccessful operation
2203 return STATUS_UNSUCCESSFUL
;
2207 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2208 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2209 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2211 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2212 PDRIVER_OBJECT DriverObject
;
2214 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2215 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2217 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2219 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2220 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2221 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2225 /* get existing DriverObject pointer */
2226 Status
= IopGetDriverObject(
2228 &DeviceNode
->ServiceName
,
2231 if (NT_SUCCESS(Status
))
2233 /* Attach lower level filter drivers. */
2234 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2235 /* Initialize the function driver for the device node */
2236 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2237 if (NT_SUCCESS(Status
))
2239 /* Attach upper level filter drivers. */
2240 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2241 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2243 Status
= IopStartDevice(DeviceNode
);
2250 * Don't disable when trying to load only boot drivers
2254 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2255 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2256 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2257 CPRINT("Initialization of service %S failed (Status %x)\n",
2258 DeviceNode
->ServiceName
.Buffer
, Status
);
2263 DPRINT("Service %S is disabled or already initialized\n",
2264 DeviceNode
->ServiceName
.Buffer
);
2267 return STATUS_SUCCESS
;
2271 * IopActionInitAllServices
2273 * Initialize the service for all (direct) child nodes of a parent node. This
2274 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2278 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2281 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2285 * IopActionInitBootServices
2287 * Initialize the boot start services for all (direct) child nodes of a
2288 * parent node. This function just calls IopActionInitChildServices with
2289 * BootDrivers = TRUE.
2292 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2295 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2299 * IopInitializePnpServices
2301 * Initialize services for discovered children
2305 * Top device node to start initializing services.
2308 * When set to TRUE, only drivers marked as boot start will
2309 * be loaded. Otherwise, all drivers will be loaded.
2315 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2316 IN BOOLEAN BootDrivers
)
2318 DEVICETREE_TRAVERSE_CONTEXT Context
;
2320 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2324 IopInitDeviceTreeTraverseContext(
2327 IopActionInitBootServices
,
2332 IopInitDeviceTreeTraverseContext(
2335 IopActionInitAllServices
,
2339 return IopTraverseDeviceTree(&Context
);
2344 IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode
,
2345 IN DEVICE_RELATION_TYPE Type
)
2347 DEVICETREE_TRAVERSE_CONTEXT Context
;
2348 PDEVICE_RELATIONS DeviceRelations
;
2349 IO_STATUS_BLOCK IoStatusBlock
;
2350 PDEVICE_NODE ChildDeviceNode
;
2351 IO_STACK_LOCATION Stack
;
2352 BOOLEAN BootDrivers
;
2353 OBJECT_ATTRIBUTES ObjectAttributes
;
2354 UNICODE_STRING LinkName
;
2359 DPRINT("DeviceNode 0x%p, Type %d\n", DeviceNode
, Type
);
2361 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2363 Stack
.Parameters
.QueryDeviceRelations
.Type
= Type
/*BusRelations*/;
2365 Status
= IopInitiatePnpIrp(
2366 DeviceNode
->PhysicalDeviceObject
,
2368 IRP_MN_QUERY_DEVICE_RELATIONS
,
2370 if (!NT_SUCCESS(Status
))
2372 DPRINT("IopInitiatePnpIrp() failed\n");
2376 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2378 if ((!DeviceRelations
) || (DeviceRelations
->Count
<= 0))
2380 DPRINT("No PDOs\n");
2381 if (DeviceRelations
)
2383 ExFreePool(DeviceRelations
);
2385 return STATUS_SUCCESS
;
2388 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2391 * Create device nodes for all discovered devices
2394 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2396 Status
= IopCreateDeviceNode(
2398 DeviceRelations
->Objects
[i
],
2400 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2401 if (!NT_SUCCESS(Status
))
2403 DPRINT("No resources\n");
2404 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2405 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2406 ExFreePool(DeviceRelations
);
2407 return STATUS_INSUFFICIENT_RESOURCES
;
2410 ExFreePool(DeviceRelations
);
2413 * Retrieve information about all discovered children from the bus driver
2416 IopInitDeviceTreeTraverseContext(
2419 IopActionInterrogateDeviceStack
,
2422 Status
= IopTraverseDeviceTree(&Context
);
2423 if (!NT_SUCCESS(Status
))
2425 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2430 * Retrieve configuration from the registry for discovered children
2433 IopInitDeviceTreeTraverseContext(
2436 IopActionConfigureChildServices
,
2439 Status
= IopTraverseDeviceTree(&Context
);
2440 if (!NT_SUCCESS(Status
))
2442 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status
);
2447 * Get the state of the system boot. If the \\SystemRoot link isn't
2448 * created yet, we will assume that it's possible to load only boot
2452 RtlInitUnicodeString(&LinkName
, L
"\\SystemRoot");
2454 InitializeObjectAttributes(
2461 Status
= ZwOpenFile(
2468 if(NT_SUCCESS(Status
))
2470 BootDrivers
= FALSE
;
2477 * Initialize services for discovered children. Only boot drivers will
2478 * be loaded from boot driver!
2481 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2482 if (!NT_SUCCESS(Status
))
2484 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status
);
2488 DPRINT("IopInvalidateDeviceRelations() finished\n");
2489 return STATUS_SUCCESS
;
2496 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode
)
2500 HANDLE InstanceKey
= NULL
;
2503 /* Create registry key for the instance id, if it doesn't exist yet */
2504 KeyBuffer
= ExAllocatePool(PagedPool
,
2505 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
2506 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2507 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
2508 Status
= IopCreateDeviceKeyPath(KeyBuffer
,
2510 ExFreePool(KeyBuffer
);
2511 if (!NT_SUCCESS(Status
))
2513 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2517 /* FIXME: Set 'ConfigFlags' value */
2519 ZwClose(InstanceKey
);
2523 return STATUS_SUCCESS
;
2533 DPRINT("PnpInit()\n");
2535 KeInitializeSpinLock(&IopDeviceTreeLock
);
2537 /* Initialize the Bus Type GUID List */
2538 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2539 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
2540 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
2542 /* Initialize PnP-Event notification support */
2543 Status
= IopInitPlugPlayEvents();
2544 if (!NT_SUCCESS(Status
))
2546 CPRINT("IopInitPlugPlayEvents() failed\n");
2547 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2551 * Create root device node
2554 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
2555 if (!NT_SUCCESS(Status
))
2557 CPRINT("IoCreateDriverObject() failed\n");
2558 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2561 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
2563 if (!NT_SUCCESS(Status
))
2565 CPRINT("IoCreateDevice() failed\n");
2566 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2569 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
2570 if (!NT_SUCCESS(Status
))
2572 CPRINT("Insufficient resources\n");
2573 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
2576 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
2579 CPRINT("Failed to create the instance path!\n");
2580 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_UNSUCCESSFUL
, 0, 0, 0);
2583 /* Report the device to the user-mode pnp manager */
2584 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2585 &IopRootDeviceNode
->InstancePath
);
2587 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2588 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
2589 IopRootDriverObject
->DriverExtension
->AddDevice(
2590 IopRootDriverObject
,
2591 IopRootDeviceNode
->PhysicalDeviceObject
);
2594 static NTSTATUS INIT_FUNCTION
2595 IopEnumerateDetectedDevices(
2597 IN PUNICODE_STRING RelativePath
,
2599 IN BOOLEAN EnumerateSubKeys
)
2601 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2602 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2603 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2604 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2605 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2606 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2607 OBJECT_ATTRIBUTES ObjectAttributes
;
2608 HANDLE hDevicesKey
= NULL
;
2609 HANDLE hDeviceKey
= NULL
;
2610 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2611 UNICODE_STRING Level2NameU
;
2612 WCHAR Level2Name
[5];
2613 ULONG IndexDevice
= 0;
2615 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2616 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2617 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2618 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2619 UNICODE_STRING DeviceName
, ValueName
;
2623 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI BIOS");
2624 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2625 static ULONG DeviceIndexPci
= 0;
2626 const UNICODE_STRING IdentifierAcpi
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2627 UNICODE_STRING HardwareIdAcpi
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
2628 static ULONG DeviceIndexAcpi
= 0;
2629 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2630 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2631 static ULONG DeviceIndexSerial
= 0;
2632 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardPeripheral");
2633 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2634 static ULONG DeviceIndexKeyboard
= 0;
2635 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerPeripheral");
2636 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2637 static ULONG DeviceIndexMouse
= 0;
2638 PUNICODE_STRING pHardwareId
;
2639 ULONG DeviceIndex
= 0;
2641 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2642 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2643 if (!NT_SUCCESS(Status
))
2645 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2649 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2650 if (!pDeviceInformation
)
2652 DPRINT("ExAllocatePool() failed\n");
2653 Status
= STATUS_NO_MEMORY
;
2657 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2658 if (!pValueInformation
)
2660 DPRINT("ExAllocatePool() failed\n");
2661 Status
= STATUS_NO_MEMORY
;
2667 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2668 if (Status
== STATUS_NO_MORE_ENTRIES
)
2670 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2672 ExFreePool(pDeviceInformation
);
2673 DeviceInfoLength
= RequiredSize
;
2674 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2675 if (!pDeviceInformation
)
2677 DPRINT("ExAllocatePool() failed\n");
2678 Status
= STATUS_NO_MEMORY
;
2681 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2683 if (!NT_SUCCESS(Status
))
2685 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2690 /* Open device key */
2691 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2692 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2693 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2696 KEY_QUERY_VALUE
+ EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0,
2698 if (!NT_SUCCESS(Status
))
2700 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2704 if (EnumerateSubKeys
)
2709 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2710 if (Status
== STATUS_NO_MORE_ENTRIES
)
2712 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2714 ExFreePool(pDeviceInformation
);
2715 DeviceInfoLength
= RequiredSize
;
2716 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2717 if (!pDeviceInformation
)
2719 DPRINT("ExAllocatePool() failed\n");
2720 Status
= STATUS_NO_MEMORY
;
2723 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2725 if (!NT_SUCCESS(Status
))
2727 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2731 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2732 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2734 Status
= IopEnumerateDetectedDevices(hDeviceKey
, &DeviceName
, hRootKey
, TRUE
);
2735 if (!NT_SUCCESS(Status
))
2740 /* Read identifier */
2741 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2742 if (Status
== STATUS_BUFFER_OVERFLOW
)
2744 ExFreePool(pValueInformation
);
2745 ValueInfoLength
= RequiredSize
;
2746 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2747 if (!pValueInformation
)
2749 DPRINT("ExAllocatePool() failed\n");
2750 Status
= STATUS_NO_MEMORY
;
2753 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2755 if (!NT_SUCCESS(Status
))
2757 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2760 else if (pValueInformation
->Type
!= REG_SZ
)
2762 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2766 /* Assign hardware id to this device */
2767 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2768 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2769 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2770 ValueName
.Length
-= sizeof(WCHAR
);
2771 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2773 pHardwareId
= &HardwareIdPci
;
2774 DeviceIndex
= DeviceIndexPci
++;
2776 else if (RtlCompareUnicodeString(&ValueName
, &IdentifierAcpi
, FALSE
) == 0)
2778 pHardwareId
= &HardwareIdAcpi
;
2779 DeviceIndex
= DeviceIndexAcpi
++;
2781 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2783 pHardwareId
= &HardwareIdSerial
;
2784 DeviceIndex
= DeviceIndexSerial
++;
2786 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2788 pHardwareId
= &HardwareIdKeyboard
;
2789 DeviceIndex
= DeviceIndexKeyboard
++;
2791 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2793 pHardwareId
= &HardwareIdMouse
;
2794 DeviceIndex
= DeviceIndexMouse
++;
2798 /* Unknown device */
2799 DPRINT("Unknown device %wZ in %wZ\n", &ValueName
, RelativePath
);
2803 /* Add the detected device to Root key */
2804 InitializeObjectAttributes(&ObjectAttributes
, pHardwareId
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2805 Status
= ZwCreateKey(
2811 REG_OPTION_VOLATILE
,
2813 if (!NT_SUCCESS(Status
))
2815 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2818 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2819 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2820 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2821 Status
= ZwCreateKey(
2823 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2827 REG_OPTION_VOLATILE
,
2829 ZwClose(hLevel1Key
);
2830 if (!NT_SUCCESS(Status
))
2832 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2835 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, pHardwareId
);
2836 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
2837 if (!NT_SUCCESS(Status
))
2839 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2840 ZwDeleteKey(hLevel2Key
);
2843 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
+ sizeof(WCHAR
));
2844 if (!NT_SUCCESS(Status
))
2846 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2847 ZwDeleteKey(hLevel2Key
);
2850 /* Copy 'Configuration Data' to 'LogConf\BootConfig' */
2851 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2852 if (Status
== STATUS_BUFFER_OVERFLOW
)
2854 ExFreePool(pValueInformation
);
2855 ValueInfoLength
= RequiredSize
;
2856 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2857 if (!pValueInformation
)
2859 DPRINT("ExAllocatePool() failed\n");
2860 ZwDeleteKey(hLevel2Key
);
2861 Status
= STATUS_NO_MEMORY
;
2864 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2866 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2868 else if (!NT_SUCCESS(Status
))
2870 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2871 ZwDeleteKey(hLevel2Key
);
2874 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2876 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2877 ZwDeleteKey(hLevel2Key
);
2880 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2881 Status
= ZwCreateKey(
2887 REG_OPTION_VOLATILE
,
2889 if (!NT_SUCCESS(Status
))
2891 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2892 ZwDeleteKey(hLevel2Key
);
2895 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, pValueInformation
->Type
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2897 if (!NT_SUCCESS(Status
))
2899 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2900 ZwDeleteKey(hLevel2Key
);
2907 ZwClose(hLevel2Key
);
2912 ZwClose(hDeviceKey
);
2917 Status
= STATUS_SUCCESS
;
2921 ZwClose(hDevicesKey
);
2923 ZwClose(hDeviceKey
);
2924 if (pDeviceInformation
)
2925 ExFreePool(pDeviceInformation
);
2926 if (pValueInformation
)
2927 ExFreePool(pValueInformation
);
2931 static BOOLEAN INIT_FUNCTION
2932 IopIsAcpiComputer(VOID
)
2934 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
2935 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2936 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
2937 OBJECT_ATTRIBUTES ObjectAttributes
;
2938 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2939 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2940 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2941 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2943 ULONG IndexDevice
= 0;
2944 UNICODE_STRING DeviceName
, ValueName
;
2945 HANDLE hDevicesKey
= NULL
;
2946 HANDLE hDeviceKey
= NULL
;
2948 BOOLEAN ret
= FALSE
;
2950 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
2951 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2952 if (!NT_SUCCESS(Status
))
2954 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2958 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2959 if (!pDeviceInformation
)
2961 DPRINT("ExAllocatePool() failed\n");
2962 Status
= STATUS_NO_MEMORY
;
2966 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2967 if (!pDeviceInformation
)
2969 DPRINT("ExAllocatePool() failed\n");
2970 Status
= STATUS_NO_MEMORY
;
2976 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2977 if (Status
== STATUS_NO_MORE_ENTRIES
)
2979 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2981 ExFreePool(pDeviceInformation
);
2982 DeviceInfoLength
= RequiredSize
;
2983 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2984 if (!pDeviceInformation
)
2986 DPRINT("ExAllocatePool() failed\n");
2987 Status
= STATUS_NO_MEMORY
;
2990 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2992 if (!NT_SUCCESS(Status
))
2994 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2999 /* Open device key */
3000 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3001 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3002 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3007 if (!NT_SUCCESS(Status
))
3009 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3013 /* Read identifier */
3014 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3015 if (Status
== STATUS_BUFFER_OVERFLOW
)
3017 ExFreePool(pValueInformation
);
3018 ValueInfoLength
= RequiredSize
;
3019 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3020 if (!pValueInformation
)
3022 DPRINT("ExAllocatePool() failed\n");
3023 Status
= STATUS_NO_MEMORY
;
3026 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3028 if (!NT_SUCCESS(Status
))
3030 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3033 else if (pValueInformation
->Type
!= REG_SZ
)
3035 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3039 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3040 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3041 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3042 ValueName
.Length
-= sizeof(WCHAR
);
3043 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3045 DPRINT("Found ACPI BIOS\n");
3051 ZwClose(hDeviceKey
);
3056 if (pDeviceInformation
)
3057 ExFreePool(pDeviceInformation
);
3058 if (pValueInformation
)
3059 ExFreePool(pValueInformation
);
3061 ZwClose(hDevicesKey
);
3063 ZwClose(hDeviceKey
);
3067 static NTSTATUS INIT_FUNCTION
3068 IopUpdateRootKey(VOID
)
3070 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum\\Root");
3071 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3072 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3073 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3074 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3075 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3076 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3077 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3078 OBJECT_ATTRIBUTES ObjectAttributes
;
3079 HANDLE hRoot
, hHalAcpiDevice
, hHalAcpiId
;
3082 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3083 Status
= ZwOpenKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
);
3084 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3086 /* We are probably in 1st stage */
3087 return STATUS_SUCCESS
;
3089 else if (!NT_SUCCESS(Status
))
3091 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3095 if (IopIsAcpiComputer())
3097 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3098 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3100 if (!NT_SUCCESS(Status
))
3102 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3103 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3104 ZwClose(hHalAcpiDevice
);
3105 if (!NT_SUCCESS(Status
))
3107 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3108 if (NT_SUCCESS(Status
))
3109 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
+ sizeof(WCHAR
));
3110 ZwClose(hHalAcpiId
);
3115 Status
= IopEnumerateDetectedDevices(
3130 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3131 Status
= IopUpdateRootKey();
3132 if (!NT_SUCCESS(Status
))
3134 CPRINT("IopUpdateRootKey() failed\n");
3135 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3138 /* Set root device instance data */
3139 Status
= IopSetRootDeviceInstanceData(IopRootDeviceNode
);
3140 if (!NT_SUCCESS(Status
))
3142 CPRINT("Failed to set instance data\n");
3143 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);