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)
33 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
35 DEVICE_RELATION_TYPE Type
;
36 PIO_WORKITEM WorkItem
;
39 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
42 IopInvalidateDeviceRelations(
43 IN PDEVICE_OBJECT DeviceObject
,
44 IN PVOID InvalidateContext
);
46 /* FUNCTIONS *****************************************************************/
50 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
52 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
57 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
58 PDRIVER_OBJECT DriverObject
)
62 BOOLEAN IsPnpDriver
= FALSE
;
64 if (DriverObject
->DriverExtension
->AddDevice
)
66 /* This is a Plug and Play driver */
67 DPRINT("Plug and Play driver found\n");
69 ASSERT(DeviceNode
->PhysicalDeviceObject
);
71 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
72 DriverObject
->DriverExtension
->AddDevice
);
74 IsPnpDriver
= !IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
75 Status
= DriverObject
->DriverExtension
->AddDevice(
76 DriverObject
, IsPnpDriver
? DeviceNode
->PhysicalDeviceObject
: NULL
);
78 if (!NT_SUCCESS(Status
))
85 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
87 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
89 /* FIXME: What do we do? Unload the driver or just disable the device? */
90 DbgPrint("An FDO was not attached\n");
91 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
92 return STATUS_UNSUCCESSFUL
;
95 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
97 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
99 /* There can be only one system power device */
100 if (!SystemPowerDeviceNodeCreated
)
102 PopSystemPowerDeviceNode
= DeviceNode
;
103 SystemPowerDeviceNodeCreated
= TRUE
;
107 ObDereferenceObject(Fdo
);
110 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
111 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
114 return STATUS_SUCCESS
;
119 PDEVICE_NODE DeviceNode
)
121 IO_STATUS_BLOCK IoStatusBlock
;
122 IO_STACK_LOCATION Stack
;
126 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
128 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
129 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
130 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
132 Status
= IopInitiatePnpIrp(
138 if (!NT_SUCCESS(Status
))
140 DPRINT("IopInitiatePnpIrp() failed\n");
144 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
146 DPRINT("Device needs enumeration, invalidating bus relations\n");
147 IoInvalidateDeviceRelations(DeviceNode
->PhysicalDeviceObject
, BusRelations
);
148 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
152 ObDereferenceObject(Fdo
);
154 if (NT_SUCCESS(Status
))
155 DeviceNode
->Flags
|= DN_STARTED
;
162 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
163 PDEVICE_CAPABILITIES DeviceCaps
)
165 IO_STATUS_BLOCK StatusBlock
;
166 IO_STACK_LOCATION Stack
;
168 /* Set up the Header */
169 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
170 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
171 DeviceCaps
->Version
= 1;
172 DeviceCaps
->Address
= -1;
173 DeviceCaps
->UINumber
= -1;
175 /* Set up the Stack */
176 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
177 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
180 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
182 IRP_MN_QUERY_CAPABILITIES
,
191 IoInvalidateDeviceRelations(
192 IN PDEVICE_OBJECT DeviceObject
,
193 IN DEVICE_RELATION_TYPE Type
)
195 PIO_WORKITEM WorkItem
;
196 PINVALIDATE_DEVICE_RELATION_DATA Data
;
198 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
201 WorkItem
= IoAllocateWorkItem(DeviceObject
);
209 Data
->WorkItem
= WorkItem
;
214 IopInvalidateDeviceRelations
,
224 IoSynchronousInvalidateDeviceRelations(
225 IN PDEVICE_OBJECT DeviceObject
,
226 IN DEVICE_RELATION_TYPE Type
)
228 PIO_WORKITEM WorkItem
;
229 PINVALIDATE_DEVICE_RELATION_DATA Data
;
232 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
235 WorkItem
= IoAllocateWorkItem(DeviceObject
);
242 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
244 Data
->WorkItem
= WorkItem
;
245 Data
->Event
= &Event
;
249 IopInvalidateDeviceRelations
,
253 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
262 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
263 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
264 IN ULONG BufferLength
,
265 OUT PVOID PropertyBuffer
,
266 OUT PULONG ResultLength
)
268 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
269 DEVICE_CAPABILITIES DeviceCaps
;
275 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
277 if (DeviceNode
== NULL
)
278 return STATUS_INVALID_DEVICE_REQUEST
;
280 switch (DeviceProperty
)
282 case DevicePropertyBusNumber
:
283 Length
= sizeof(ULONG
);
284 Data
= &DeviceNode
->ChildBusNumber
;
287 /* Complete, untested */
288 case DevicePropertyBusTypeGuid
:
290 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
291 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
293 /* Return the GUID */
294 *ResultLength
= sizeof(GUID
);
296 /* Check if the buffer given was large enough */
297 if (BufferLength
< *ResultLength
)
299 return STATUS_BUFFER_TOO_SMALL
;
303 RtlCopyMemory(PropertyBuffer
,
304 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
306 return STATUS_SUCCESS
;
310 return STATUS_OBJECT_NAME_NOT_FOUND
;
314 case DevicePropertyLegacyBusType
:
315 Length
= sizeof(INTERFACE_TYPE
);
316 Data
= &DeviceNode
->ChildInterfaceType
;
319 case DevicePropertyAddress
:
320 /* Query the device caps */
321 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
322 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
325 *ResultLength
= sizeof(ULONG
);
327 /* Check if the buffer given was large enough */
328 if (BufferLength
< *ResultLength
)
330 return STATUS_BUFFER_TOO_SMALL
;
334 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
335 return STATUS_SUCCESS
;
339 return STATUS_OBJECT_NAME_NOT_FOUND
;
343 // case DevicePropertyUINumber:
344 // if (DeviceNode->CapabilityFlags == NULL)
345 // return STATUS_INVALID_DEVICE_REQUEST;
346 // Length = sizeof(ULONG);
347 // Data = &DeviceNode->CapabilityFlags->UINumber;
350 case DevicePropertyClassName
:
351 case DevicePropertyClassGuid
:
352 case DevicePropertyDriverKeyName
:
353 case DevicePropertyManufacturer
:
354 case DevicePropertyFriendlyName
:
355 case DevicePropertyHardwareID
:
356 case DevicePropertyCompatibleIDs
:
357 case DevicePropertyDeviceDescription
:
358 case DevicePropertyLocationInformation
:
359 case DevicePropertyUINumber
:
361 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
362 UNICODE_STRING KeyName
, ValueName
;
363 OBJECT_ATTRIBUTES ObjectAttributes
;
364 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
365 ULONG ValueInformationLength
;
369 switch (DeviceProperty
)
371 case DevicePropertyClassName
:
372 RegistryPropertyName
= L
"Class"; break;
373 case DevicePropertyClassGuid
:
374 RegistryPropertyName
= L
"ClassGuid"; break;
375 case DevicePropertyDriverKeyName
:
376 RegistryPropertyName
= L
"Driver"; break;
377 case DevicePropertyManufacturer
:
378 RegistryPropertyName
= L
"Mfg"; break;
379 case DevicePropertyFriendlyName
:
380 RegistryPropertyName
= L
"FriendlyName"; break;
381 case DevicePropertyHardwareID
:
382 RegistryPropertyName
= L
"HardwareID"; break;
383 case DevicePropertyCompatibleIDs
:
384 RegistryPropertyName
= L
"CompatibleIDs"; break;
385 case DevicePropertyDeviceDescription
:
386 RegistryPropertyName
= L
"DeviceDesc"; break;
387 case DevicePropertyLocationInformation
:
388 RegistryPropertyName
= L
"LocationInformation"; break;
389 case DevicePropertyUINumber
:
390 RegistryPropertyName
= L
"UINumber"; break;
392 RegistryPropertyName
= NULL
; break;
395 KeyNameBuffer
= ExAllocatePool(PagedPool
,
396 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
398 DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer
, RegistryPropertyName
);
400 if (KeyNameBuffer
== NULL
)
401 return STATUS_INSUFFICIENT_RESOURCES
;
403 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
404 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
405 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
406 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
407 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
409 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
410 ExFreePool(KeyNameBuffer
);
411 if (!NT_SUCCESS(Status
))
414 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
415 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
416 Data
[0]) + BufferLength
;
417 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
418 if (ValueInformation
== NULL
)
421 return STATUS_INSUFFICIENT_RESOURCES
;
424 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
425 KeyValuePartialInformation
, ValueInformation
,
426 ValueInformationLength
,
427 &ValueInformationLength
);
428 *ResultLength
= ValueInformation
->DataLength
;
431 if (!NT_SUCCESS(Status
))
433 ExFreePool(ValueInformation
);
434 if (Status
== STATUS_BUFFER_OVERFLOW
)
435 return STATUS_BUFFER_TOO_SMALL
;
440 /* FIXME: Verify the value (NULL-terminated, correct format). */
442 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
443 ValueInformation
->DataLength
);
444 ExFreePool(ValueInformation
);
446 return STATUS_SUCCESS
;
449 case DevicePropertyBootConfiguration
:
451 if (DeviceNode
->BootResources
->Count
!= 0)
453 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
455 Data
= &DeviceNode
->BootResources
;
458 /* FIXME: use a translated boot configuration instead */
459 case DevicePropertyBootConfigurationTranslated
:
461 if (DeviceNode
->BootResources
->Count
!= 0)
463 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
465 Data
= &DeviceNode
->BootResources
;
468 case DevicePropertyEnumeratorName
:
469 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
472 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
473 Data
= DeviceNode
->InstancePath
.Buffer
;
482 case DevicePropertyPhysicalDeviceObjectName
:
483 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
484 Data
= DeviceNode
->InstancePath
.Buffer
;
488 return STATUS_INVALID_PARAMETER_2
;
491 *ResultLength
= Length
;
492 if (BufferLength
< Length
)
493 return STATUS_BUFFER_TOO_SMALL
;
494 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
496 /* Terminate the string */
497 if (DeviceProperty
== DevicePropertyEnumeratorName
498 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
500 Ptr
= (PWSTR
)PropertyBuffer
;
501 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
504 return STATUS_SUCCESS
;
512 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
518 * @name IoOpenDeviceRegistryKey
520 * Open a registry key unique for a specified driver or device instance.
522 * @param DeviceObject Device to get the registry key for.
523 * @param DevInstKeyType Type of the key to return.
524 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
525 * @param DevInstRegKey Handle to the opened registry key on
534 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
535 IN ULONG DevInstKeyType
,
536 IN ACCESS_MASK DesiredAccess
,
537 OUT PHANDLE DevInstRegKey
)
539 static WCHAR RootKeyName
[] =
540 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
541 static WCHAR ProfileKeyName
[] =
542 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
543 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
544 static WCHAR EnumKeyName
[] = L
"Enum\\";
545 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
547 LPWSTR KeyNameBuffer
;
548 UNICODE_STRING KeyName
;
549 ULONG DriverKeyLength
;
550 OBJECT_ATTRIBUTES ObjectAttributes
;
551 PDEVICE_NODE DeviceNode
= NULL
;
554 DPRINT("IoOpenDeviceRegistryKey() called\n");
556 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
558 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
559 return STATUS_INVALID_PARAMETER
;
563 * Calculate the length of the base key name. This is the full
564 * name for driver key or the name excluding "Device Parameters"
565 * subkey for device key.
568 KeyNameLength
= sizeof(RootKeyName
);
569 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
570 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
571 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
573 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
574 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
575 0, NULL
, &DriverKeyLength
);
576 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
578 KeyNameLength
+= DriverKeyLength
;
582 DeviceNode
= IopGetDeviceNode(DeviceObject
);
583 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
584 DeviceNode
->InstancePath
.Length
;
588 * Now allocate the buffer for the key name...
591 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
592 if (KeyNameBuffer
== NULL
)
593 return STATUS_INSUFFICIENT_RESOURCES
;
596 KeyName
.MaximumLength
= KeyNameLength
;
597 KeyName
.Buffer
= KeyNameBuffer
;
600 * ...and build the key name.
603 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
604 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
606 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
607 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
609 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
611 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
612 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
613 DriverKeyLength
, KeyNameBuffer
+
614 (KeyName
.Length
/ sizeof(WCHAR
)),
616 if (!NT_SUCCESS(Status
))
618 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
619 ExFreePool(KeyNameBuffer
);
622 KeyName
.Length
+= DriverKeyLength
- sizeof(UNICODE_NULL
);
626 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
627 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
628 if (DeviceNode
->InstancePath
.Length
== 0)
630 ExFreePool(KeyNameBuffer
);
639 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
640 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
641 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
642 if (!NT_SUCCESS(Status
))
644 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
645 ExFreePool(KeyNameBuffer
);
648 ExFreePool(KeyNameBuffer
);
651 * For driver key we're done now.
654 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
658 * Let's go further. For device key we must open "Device Parameters"
659 * subkey and create it if it doesn't exist yet.
662 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
663 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
664 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
665 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
666 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
667 ZwClose(ObjectAttributes
.RootDirectory
);
677 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
684 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
688 if (PopSystemPowerDeviceNode
)
690 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
691 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
692 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
694 return STATUS_SUCCESS
;
697 return STATUS_UNSUCCESSFUL
;
702 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
704 USHORT i
= 0, FoundIndex
= 0xFFFF;
708 /* Acquire the lock */
709 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
711 /* Loop all entries */
712 while (i
< IopBusTypeGuidList
->GuidCount
)
714 /* Try to find a match */
715 if (RtlCompareMemory(BusTypeGuid
,
716 &IopBusTypeGuidList
->Guids
[i
],
717 sizeof(GUID
)) == sizeof(GUID
))
726 /* Check if we have to grow the list */
727 if (IopBusTypeGuidList
->GuidCount
)
729 /* Calculate the new size */
730 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
731 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
733 /* Allocate the new copy */
734 NewList
= ExAllocatePool(PagedPool
, NewSize
);
736 /* Now copy them, decrease the size too */
737 NewSize
-= sizeof(GUID
);
738 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
740 /* Free the old list */
741 ExFreePool(IopBusTypeGuidList
);
743 /* Use the new buffer */
744 IopBusTypeGuidList
= NewList
;
747 /* Copy the new GUID */
748 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
752 /* The new entry is the index */
753 FoundIndex
= IopBusTypeGuidList
->GuidCount
;
754 IopBusTypeGuidList
->GuidCount
++;
757 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
763 * Creates a device node
766 * ParentNode = Pointer to parent device node
767 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
768 * to have the root device node create one
769 * (eg. for legacy drivers)
770 * DeviceNode = Pointer to storage for created device node
776 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
777 PDEVICE_OBJECT PhysicalDeviceObject
,
778 PDEVICE_NODE
*DeviceNode
)
784 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
785 ParentNode
, PhysicalDeviceObject
);
787 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
790 return STATUS_INSUFFICIENT_RESOURCES
;
793 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
795 if (!PhysicalDeviceObject
)
797 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
798 if (!NT_SUCCESS(Status
))
804 /* This is for drivers passed on the command line to ntoskrnl.exe */
805 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
806 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
809 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
811 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
815 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
816 Node
->Parent
= ParentNode
;
817 Node
->NextSibling
= ParentNode
->Child
;
818 if (ParentNode
->Child
!= NULL
)
820 ParentNode
->Child
->PrevSibling
= Node
;
822 ParentNode
->Child
= Node
;
823 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
824 Node
->Level
= ParentNode
->Level
+ 1;
829 return STATUS_SUCCESS
;
833 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
837 /* All children must be deleted before a parent is deleted */
838 ASSERT(!DeviceNode
->Child
);
840 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
842 ASSERT(DeviceNode
->PhysicalDeviceObject
);
844 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
846 /* Unlink from parent if it exists */
848 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
850 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
853 /* Unlink from sibling list */
855 if (DeviceNode
->PrevSibling
)
857 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
860 if (DeviceNode
->NextSibling
)
862 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
865 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
867 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
869 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
871 if (DeviceNode
->ResourceList
)
873 ExFreePool(DeviceNode
->ResourceList
);
876 if (DeviceNode
->ResourceListTranslated
)
878 ExFreePool(DeviceNode
->ResourceListTranslated
);
881 if (DeviceNode
->ResourceRequirements
)
883 ExFreePool(DeviceNode
->ResourceRequirements
);
886 if (DeviceNode
->BootResources
)
888 ExFreePool(DeviceNode
->BootResources
);
891 ExFreePool(DeviceNode
);
893 return STATUS_SUCCESS
;
897 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
898 PIO_STATUS_BLOCK IoStatusBlock
,
900 PIO_STACK_LOCATION Stack OPTIONAL
)
902 PDEVICE_OBJECT TopDeviceObject
;
903 PIO_STACK_LOCATION IrpSp
;
908 /* Always call the top of the device stack */
909 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
916 Irp
= IoBuildSynchronousFsdRequest(
925 /* PNP IRPs are always initialized with a status code of
926 STATUS_NOT_IMPLEMENTED */
927 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
928 Irp
->IoStatus
.Information
= 0;
930 IrpSp
= IoGetNextIrpStackLocation(Irp
);
931 IrpSp
->MinorFunction
= MinorFunction
;
935 RtlMoveMemory(&IrpSp
->Parameters
,
937 sizeof(Stack
->Parameters
));
940 Status
= IoCallDriver(TopDeviceObject
, Irp
);
941 if (Status
== STATUS_PENDING
)
943 KeWaitForSingleObject(&Event
,
948 Status
= IoStatusBlock
->Status
;
951 ObDereferenceObject(TopDeviceObject
);
958 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
960 PDEVICE_NODE ParentDeviceNode
;
961 PDEVICE_NODE ChildDeviceNode
;
964 /* Copy context data so we don't overwrite it in subsequent calls to this function */
965 ParentDeviceNode
= Context
->DeviceNode
;
967 /* Call the action routine */
968 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
969 if (!NT_SUCCESS(Status
))
974 /* Traversal of all children nodes */
975 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
976 ChildDeviceNode
!= NULL
;
977 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
979 /* Pass the current device node to the action routine */
980 Context
->DeviceNode
= ChildDeviceNode
;
982 Status
= IopTraverseDeviceTreeNode(Context
);
983 if (!NT_SUCCESS(Status
))
994 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
998 DPRINT("Context 0x%p\n", Context
);
1000 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1001 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1003 /* Start from the specified device node */
1004 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1006 /* Recursively traverse the device tree */
1007 Status
= IopTraverseDeviceTreeNode(Context
);
1008 if (Status
== STATUS_UNSUCCESSFUL
)
1010 /* The action routine just wanted to terminate the traversal with status
1011 code STATUS_SUCCESS */
1012 Status
= STATUS_SUCCESS
;
1021 IopCreateDeviceKeyPath(PWSTR Path
,
1024 OBJECT_ATTRIBUTES ObjectAttributes
;
1025 WCHAR KeyBuffer
[MAX_PATH
];
1026 UNICODE_STRING KeyName
;
1034 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
1036 return STATUS_INVALID_PARAMETER
;
1039 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
1041 /* Skip \\Registry\\ */
1042 Current
= KeyBuffer
;
1043 Current
= wcschr (Current
, L
'\\') + 1;
1044 Current
= wcschr (Current
, L
'\\') + 1;
1048 Next
= wcschr (Current
, L
'\\');
1058 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
1059 InitializeObjectAttributes (&ObjectAttributes
,
1061 OBJ_CASE_INSENSITIVE
,
1065 DPRINT("Create '%S'\n", KeyName
.Buffer
);
1067 Status
= ZwCreateKey (&KeyHandle
,
1074 if (!NT_SUCCESS (Status
))
1076 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
1082 *Handle
= KeyHandle
;
1083 return STATUS_SUCCESS
;
1087 ZwClose (KeyHandle
);
1094 return STATUS_UNSUCCESSFUL
;
1100 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1101 PDEVICE_NODE DeviceNode
)
1103 OBJECT_ATTRIBUTES ObjectAttributes
;
1104 UNICODE_STRING KeyName
;
1107 ULONG ListSize
, ResultLength
;
1110 DPRINT("IopSetDeviceInstanceData() called\n");
1112 /* Create the 'LogConf' key */
1113 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1114 InitializeObjectAttributes(&ObjectAttributes
,
1116 OBJ_CASE_INSENSITIVE
,
1119 Status
= ZwCreateKey(&LogConfKey
,
1126 if (NT_SUCCESS(Status
))
1128 /* Set 'BootConfig' value */
1129 if (DeviceNode
->BootResources
!= NULL
)
1131 ResCount
= DeviceNode
->BootResources
->Count
;
1134 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1136 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1137 Status
= ZwSetValueKey(LogConfKey
,
1141 &DeviceNode
->BootResources
,
1146 /* Set 'BasicConfigVector' value */
1147 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1148 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1150 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1151 Status
= ZwSetValueKey(LogConfKey
,
1154 REG_RESOURCE_REQUIREMENTS_LIST
,
1155 DeviceNode
->ResourceRequirements
,
1156 DeviceNode
->ResourceRequirements
->ListSize
);
1159 ZwClose(LogConfKey
);
1162 /* Set the 'ConfigFlags' value */
1163 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1164 Status
= ZwQueryValueKey(InstanceKey
,
1166 KeyValueBasicInformation
,
1170 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1172 /* Write the default value */
1173 ULONG DefaultConfigFlags
= 0;
1174 Status
= ZwSetValueKey(InstanceKey
,
1178 &DefaultConfigFlags
,
1179 sizeof(DefaultConfigFlags
));
1183 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1185 /* Create the 'Control' key */
1186 RtlInitUnicodeString(&KeyName
,
1188 InitializeObjectAttributes(&ObjectAttributes
,
1190 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1193 Status
= ZwCreateKey(&LogConfKey
,
1198 REG_OPTION_VOLATILE
,
1200 if (NT_SUCCESS(Status
))
1202 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1203 RtlInitUnicodeString(&KeyName
,
1204 L
"DeviceReference");
1205 Status
= ZwSetValueKey(LogConfKey
,
1212 ZwClose(LogConfKey
);
1217 DPRINT("IopSetDeviceInstanceData() done\n");
1219 return STATUS_SUCCESS
;
1224 IopAssignDeviceResources(
1225 IN PDEVICE_NODE DeviceNode
,
1226 OUT ULONG
*pRequiredSize
)
1228 PIO_RESOURCE_LIST ResourceList
;
1229 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1230 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
1231 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1232 ULONG NumberOfResources
= 0;
1237 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1239 /* No resource needed for this device */
1240 DeviceNode
->ResourceList
= NULL
;
1241 return STATUS_SUCCESS
;
1244 /* Fill DeviceNode->ResourceList
1245 * FIXME: the PnP arbiter should go there!
1246 * Actually, use the BootResources if provided, else the resource list #0
1249 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1251 if (DeviceNode
->BootResources
)
1253 /* Browse the boot resources to know if we have some custom structures */
1254 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1255 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1257 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1258 if (pPartialResourceList
->Version
!= 1 || pPartialResourceList
->Revision
!= 1)
1260 Status
= STATUS_REVISION_MISMATCH
;
1263 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1264 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1265 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1267 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1268 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1272 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1273 if (!DeviceNode
->ResourceList
)
1275 Status
= STATUS_NO_MEMORY
;
1278 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1280 *pRequiredSize
= Size
;
1281 return STATUS_SUCCESS
;
1284 /* Ok, here, we have to use the device requirement list */
1285 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1287 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1288 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1290 Status
= STATUS_REVISION_MISMATCH
;
1294 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1295 *pRequiredSize
= Size
;
1296 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1297 if (!DeviceNode
->ResourceList
)
1299 Status
= STATUS_NO_MEMORY
;
1303 DeviceNode
->ResourceList
->Count
= 1;
1304 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1305 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1306 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1307 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1309 for (i
= 0; i
< ResourceList
->Count
; i
++)
1311 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1313 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1315 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1316 NumberOfResources
++;
1318 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1319 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
1320 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1321 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
1322 switch (ResourceDescriptor
->Type
)
1324 case CmResourceTypePort
:
1326 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1327 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
1330 case CmResourceTypeInterrupt
:
1332 INTERFACE_TYPE BusType
;
1337 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1338 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1339 /* FIXME: HACK: if we have a PCI device, we try
1340 * to keep the IRQ assigned by the BIOS */
1341 if (NT_SUCCESS(IoGetDeviceProperty(
1342 DeviceNode
->PhysicalDeviceObject
,
1343 DevicePropertyLegacyBusType
,
1344 sizeof(INTERFACE_TYPE
),
1346 &ret
)) && BusType
== PCIBus
)
1348 /* We have a PCI bus */
1349 if (NT_SUCCESS(IoGetDeviceProperty(
1350 DeviceNode
->PhysicalDeviceObject
,
1351 DevicePropertyAddress
,
1354 &ret
)) && SlotNumber
> 0)
1356 /* We have a good slot number */
1357 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1358 DeviceNode
->ResourceRequirements
->BusNumber
,
1361 0x3c /* PCI_INTERRUPT_LINE */,
1363 if (ret
!= 0 && ret
!= 2
1364 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1365 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1367 /* The device already has an assigned IRQ */
1368 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1372 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1373 DescriptorRaw
->u
.Interrupt
.Vector
,
1374 &DeviceNode
->InstancePath
);
1375 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1376 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1377 DeviceNode
->ResourceRequirements
->BusNumber
,
1380 0x3c /* PCI_INTERRUPT_LINE */,
1382 if (ret
== 0 || ret
== 2)
1389 case CmResourceTypeMemory
:
1391 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1392 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
1395 case CmResourceTypeDma
:
1397 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1398 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
1399 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
1402 case CmResourceTypeBusNumber
:
1404 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1405 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
1406 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
1409 /*CmResourceTypeDevicePrivate:
1410 case CmResourceTypePcCardConfig:
1411 case CmResourceTypeMfCardConfig:
1414 &DescriptorRaw->u.DevicePrivate,
1415 &ResourceDescriptor->u.DevicePrivate,
1416 sizeof(ResourceDescriptor->u.DevicePrivate));
1418 &DescriptorTranslated->u.DevicePrivate,
1419 &ResourceDescriptor->u.DevicePrivate,
1420 sizeof(ResourceDescriptor->u.DevicePrivate));
1424 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1425 NumberOfResources
--;
1431 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1433 return STATUS_SUCCESS
;
1436 if (DeviceNode
->ResourceList
)
1438 ExFreePool(DeviceNode
->ResourceList
);
1439 DeviceNode
->ResourceList
= NULL
;
1446 IopTranslateDeviceResources(
1447 IN PDEVICE_NODE DeviceNode
,
1448 IN ULONG RequiredSize
)
1450 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1451 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1455 if (!DeviceNode
->ResourceList
)
1457 DeviceNode
->ResourceListTranslated
= NULL
;
1458 return STATUS_SUCCESS
;
1461 /* That's easy to translate a resource list. Just copy the
1462 * untranslated one and change few fields in the copy
1464 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1465 if (!DeviceNode
->ResourceListTranslated
)
1467 Status
=STATUS_NO_MEMORY
;
1470 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1472 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1474 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1475 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1477 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1478 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1479 switch (DescriptorRaw
->Type
)
1481 case CmResourceTypePort
:
1483 ULONG AddressSpace
= 0; /* IO space */
1484 if (!HalTranslateBusAddress(
1485 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1486 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1487 DescriptorRaw
->u
.Port
.Start
,
1489 &DescriptorTranslated
->u
.Port
.Start
))
1491 Status
= STATUS_UNSUCCESSFUL
;
1496 case CmResourceTypeInterrupt
:
1498 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1499 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1500 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1501 DescriptorRaw
->u
.Interrupt
.Level
,
1502 DescriptorRaw
->u
.Interrupt
.Vector
,
1503 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1504 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1507 case CmResourceTypeMemory
:
1509 ULONG AddressSpace
= 1; /* Memory space */
1510 if (!HalTranslateBusAddress(
1511 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1512 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1513 DescriptorRaw
->u
.Memory
.Start
,
1515 &DescriptorTranslated
->u
.Memory
.Start
))
1517 Status
= STATUS_UNSUCCESSFUL
;
1522 case CmResourceTypeDma
:
1523 case CmResourceTypeBusNumber
:
1524 case CmResourceTypeDeviceSpecific
:
1528 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1529 Status
= STATUS_NOT_IMPLEMENTED
;
1534 return STATUS_SUCCESS
;
1537 /* Yes! Also delete ResourceList because ResourceList and
1538 * ResourceListTranslated should be a pair! */
1539 ExFreePool(DeviceNode
->ResourceList
);
1540 DeviceNode
->ResourceList
= NULL
;
1541 if (DeviceNode
->ResourceListTranslated
)
1543 ExFreePool(DeviceNode
->ResourceListTranslated
);
1544 DeviceNode
->ResourceList
= NULL
;
1551 * IopGetParentIdPrefix
1553 * Retrieve (or create) a string which identifies a device.
1557 * Pointer to device node.
1559 * Pointer to the string where is returned the parent node identifier
1562 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1563 * valid and its Buffer field is NULL-terminated. The caller needs to
1564 * to free the string with RtlFreeUnicodeString when it is no longer
1569 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1570 PUNICODE_STRING ParentIdPrefix
)
1572 ULONG KeyNameBufferLength
;
1573 PWSTR KeyNameBuffer
= NULL
;
1574 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1575 UNICODE_STRING KeyName
;
1576 UNICODE_STRING KeyValue
;
1577 UNICODE_STRING ValueName
;
1578 OBJECT_ATTRIBUTES ObjectAttributes
;
1583 /* HACK: As long as some devices have a NULL device
1584 * instance path, the following test is required :(
1586 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1587 return STATUS_UNSUCCESSFUL
;
1589 /* 1. Try to retrieve ParentIdPrefix from registry */
1590 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1591 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1592 if (!ParentIdPrefixInformation
)
1594 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1597 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1600 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1603 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1604 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1605 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1606 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1607 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1608 if (!NT_SUCCESS(Status
))
1610 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1611 Status
= ZwQueryValueKey(
1613 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1614 KeyNameBufferLength
, &KeyNameBufferLength
);
1615 if (NT_SUCCESS(Status
))
1617 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1618 Status
= STATUS_UNSUCCESSFUL
;
1621 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1622 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1626 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1628 KeyValue
.Length
= KeyValue
.MaximumLength
= ParentIdPrefixInformation
->DataLength
;
1629 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1633 /* 2. Create the ParentIdPrefix value */
1634 crc32
= RtlComputeCrc32(0,
1635 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1636 DeviceNode
->Parent
->InstancePath
.Length
);
1638 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1639 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1641 /* 3. Try to write the ParentIdPrefix to registry */
1642 Status
= ZwSetValueKey(hKey
,
1646 (PVOID
)KeyValue
.Buffer
,
1647 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1650 if (NT_SUCCESS(Status
))
1652 /* Duplicate the string to return it */
1653 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1655 ExFreePool(ParentIdPrefixInformation
);
1656 ExFreePool(KeyNameBuffer
);
1664 * IopActionInterrogateDeviceStack
1666 * Retrieve information for all (direct) child nodes of a parent node.
1670 * Pointer to device node.
1672 * Pointer to parent node to retrieve child node information for.
1675 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1676 * when we reach a device node which is not a direct child of the device
1677 * node for which we retrieve information of child nodes for. Any errors
1678 * that occur is logged instead so that all child services have a chance
1679 * of being interrogated.
1683 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1686 IO_STATUS_BLOCK IoStatusBlock
;
1687 PDEVICE_NODE ParentDeviceNode
;
1688 WCHAR InstancePath
[MAX_PATH
];
1689 IO_STACK_LOCATION Stack
;
1695 ULONG RequiredLength
;
1697 HANDLE InstanceKey
= NULL
;
1698 UNICODE_STRING ValueName
;
1699 UNICODE_STRING ParentIdPrefix
= { 0 };
1700 DEVICE_CAPABILITIES DeviceCapabilities
;
1702 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1703 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1705 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1708 * We are called for the parent too, but we don't need to do special
1709 * handling for this node
1712 if (DeviceNode
== ParentDeviceNode
)
1714 DPRINT("Success\n");
1715 return STATUS_SUCCESS
;
1719 * Make sure this device node is a direct child of the parent device node
1720 * that is given as an argument
1723 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1725 /* Stop the traversal immediately and indicate successful operation */
1727 return STATUS_UNSUCCESSFUL
;
1731 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1732 if (!NT_SUCCESS(Status
))
1734 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1739 * FIXME: For critical errors, cleanup and disable device, but always
1740 * return STATUS_SUCCESS.
1743 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1745 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1746 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1750 if (NT_SUCCESS(Status
))
1752 /* Copy the device id string */
1753 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1756 * FIXME: Check for valid characters, if there is invalid characters
1762 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1765 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1767 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1768 if (!NT_SUCCESS(Status
))
1770 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1773 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1775 if (!DeviceCapabilities
.UniqueID
)
1777 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1778 DPRINT("Instance ID is not unique\n");
1779 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1780 if (!NT_SUCCESS(Status
))
1782 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1786 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1788 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1789 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1793 if (NT_SUCCESS(Status
))
1795 /* Append the instance id string */
1796 wcscat(InstancePath
, L
"\\");
1797 if (ParentIdPrefix
.Length
> 0)
1799 /* Add information from parent bus device to InstancePath */
1800 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1801 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1802 wcscat(InstancePath
, L
"&");
1804 if (IoStatusBlock
.Information
)
1805 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1808 * FIXME: Check for valid characters, if there is invalid characters
1814 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1816 RtlFreeUnicodeString(&ParentIdPrefix
);
1818 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1820 DPRINT("No resources\n");
1821 /* FIXME: Cleanup and disable device */
1824 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1827 * Create registry key for the instance id, if it doesn't exist yet
1829 KeyBuffer
= ExAllocatePool(
1831 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1832 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1833 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1834 Status
= IopCreateDeviceKeyPath(KeyBuffer
, &InstanceKey
);
1835 ExFreePool(KeyBuffer
);
1836 if (!NT_SUCCESS(Status
))
1838 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1843 /* Set 'Capabilities' value */
1844 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1845 Status
= ZwSetValueKey(InstanceKey
,
1849 (PVOID
)&DeviceNode
->CapabilityFlags
,
1852 /* Set 'UINumber' value */
1853 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1855 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1856 Status
= ZwSetValueKey(InstanceKey
,
1860 &DeviceCapabilities
.UINumber
,
1865 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1867 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1868 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1872 if (NT_SUCCESS(Status
))
1875 * FIXME: Check for valid characters, if there is invalid characters
1879 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1880 DPRINT("Hardware IDs:\n");
1883 DPRINT(" %S\n", Ptr
);
1884 Length
= wcslen(Ptr
) + 1;
1887 TotalLength
+= Length
;
1889 DPRINT("TotalLength: %hu\n", TotalLength
);
1892 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1893 Status
= ZwSetValueKey(InstanceKey
,
1897 (PVOID
)IoStatusBlock
.Information
,
1898 (TotalLength
+ 1) * sizeof(WCHAR
));
1899 if (!NT_SUCCESS(Status
))
1901 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1906 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1909 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1911 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1912 Status
= IopInitiatePnpIrp(
1913 DeviceNode
->PhysicalDeviceObject
,
1917 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1920 * FIXME: Check for valid characters, if there is invalid characters
1924 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1925 DPRINT("Compatible IDs:\n");
1928 DPRINT(" %S\n", Ptr
);
1929 Length
= wcslen(Ptr
) + 1;
1932 TotalLength
+= Length
;
1934 DPRINT("TotalLength: %hu\n", TotalLength
);
1937 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1938 Status
= ZwSetValueKey(InstanceKey
,
1942 (PVOID
)IoStatusBlock
.Information
,
1943 (TotalLength
+ 1) * sizeof(WCHAR
));
1944 if (!NT_SUCCESS(Status
))
1946 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1951 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1955 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1957 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1958 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1959 Status
= IopInitiatePnpIrp(
1960 DeviceNode
->PhysicalDeviceObject
,
1962 IRP_MN_QUERY_DEVICE_TEXT
,
1964 /* This key is mandatory, so even if the Irp fails, we still write it */
1965 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1966 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1968 if (NT_SUCCESS(Status
) &&
1969 IoStatusBlock
.Information
&&
1970 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1972 /* This key is overriden when a driver is installed. Don't write the
1973 * new description if another one already exists */
1974 Status
= ZwSetValueKey(InstanceKey
,
1978 (PVOID
)IoStatusBlock
.Information
,
1979 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1983 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1984 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1986 Status
= ZwSetValueKey(InstanceKey
,
1991 DeviceDesc
.MaximumLength
);
1993 if (!NT_SUCCESS(Status
))
1995 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2001 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2003 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2004 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2005 Status
= IopInitiatePnpIrp(
2006 DeviceNode
->PhysicalDeviceObject
,
2008 IRP_MN_QUERY_DEVICE_TEXT
,
2010 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2012 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2013 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2014 Status
= ZwSetValueKey(InstanceKey
,
2018 (PVOID
)IoStatusBlock
.Information
,
2019 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2020 if (!NT_SUCCESS(Status
))
2022 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2027 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2030 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2032 Status
= IopInitiatePnpIrp(
2033 DeviceNode
->PhysicalDeviceObject
,
2035 IRP_MN_QUERY_BUS_INFORMATION
,
2037 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2039 PPNP_BUS_INFORMATION BusInformation
=
2040 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2042 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2043 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2044 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2045 ExFreePool(BusInformation
);
2049 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2051 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2052 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2053 DeviceNode
->ChildBusTypeIndex
= -1;
2056 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2058 Status
= IopInitiatePnpIrp(
2059 DeviceNode
->PhysicalDeviceObject
,
2061 IRP_MN_QUERY_RESOURCES
,
2063 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2065 DeviceNode
->BootResources
=
2066 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2067 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2071 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2072 DeviceNode
->BootResources
= NULL
;
2075 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2077 Status
= IopInitiatePnpIrp(
2078 DeviceNode
->PhysicalDeviceObject
,
2080 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2082 if (NT_SUCCESS(Status
))
2084 DeviceNode
->ResourceRequirements
=
2085 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2086 if (IoStatusBlock
.Information
)
2087 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2089 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2093 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2094 DeviceNode
->ResourceRequirements
= NULL
;
2098 if (InstanceKey
!= NULL
)
2100 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2103 ZwClose(InstanceKey
);
2105 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
2106 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
2107 if (NT_SUCCESS(Status
))
2109 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
2110 if (NT_SUCCESS(Status
))
2112 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
2116 DPRINT("IopTranslateDeviceResources() failed (Status 0x08lx)\n", Status
);
2121 DPRINT("IopAssignDeviceResources() failed (Status 0x08lx)\n", Status
);
2123 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
2125 DeviceNode
->Flags
|= DNF_PROCESSED
;
2127 /* Report the device to the user-mode pnp manager */
2128 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2129 &DeviceNode
->InstancePath
);
2131 return STATUS_SUCCESS
;
2135 * IopActionConfigureChildServices
2137 * Retrieve configuration for all (direct) child nodes of a parent node.
2141 * Pointer to device node.
2143 * Pointer to parent node to retrieve child node configuration for.
2146 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2147 * when we reach a device node which is not a direct child of the device
2148 * node for which we configure child services for. Any errors that occur is
2149 * logged instead so that all child services have a chance of beeing
2154 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2157 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2158 PDEVICE_NODE ParentDeviceNode
;
2159 PUNICODE_STRING Service
;
2160 UNICODE_STRING ClassGUID
;
2161 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
2164 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2166 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2169 * We are called for the parent too, but we don't need to do special
2170 * handling for this node
2172 if (DeviceNode
== ParentDeviceNode
)
2174 DPRINT("Success\n");
2175 return STATUS_SUCCESS
;
2179 * Make sure this device node is a direct child of the parent device node
2180 * that is given as an argument
2182 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2184 /* Stop the traversal immediately and indicate successful operation */
2186 return STATUS_UNSUCCESSFUL
;
2189 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2191 WCHAR RegKeyBuffer
[MAX_PATH
];
2192 UNICODE_STRING RegKey
;
2195 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2196 RegKey
.Buffer
= RegKeyBuffer
;
2199 * Retrieve configuration from Enum key
2202 Service
= &DeviceNode
->ServiceName
;
2204 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2205 RtlInitUnicodeString(Service
, NULL
);
2206 RtlInitUnicodeString(&ClassGUID
, NULL
);
2208 QueryTable
[0].Name
= L
"Service";
2209 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2210 QueryTable
[0].EntryContext
= Service
;
2212 QueryTable
[1].Name
= L
"ClassGUID";
2213 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2214 QueryTable
[1].EntryContext
= &ClassGUID
;
2215 QueryTable
[1].DefaultType
= REG_SZ
;
2216 QueryTable
[1].DefaultData
= &NullString
;
2217 QueryTable
[1].DefaultLength
= 0;
2219 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2220 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2222 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2223 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2225 if (!NT_SUCCESS(Status
))
2227 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
2228 /* FIXME: Log the error */
2229 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
2230 DeviceNode
->InstancePath
.Buffer
, Status
);
2231 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2232 return STATUS_SUCCESS
;
2235 if (Service
->Buffer
== NULL
)
2237 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2239 if (ClassGUID
.Length
!= 0)
2241 /* Device has a ClassGUID value, but no Service value.
2242 * Suppose it is using the NULL driver, so state the
2243 * device is started */
2244 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2245 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2246 DeviceNode
->Flags
|= DN_STARTED
;
2248 return STATUS_SUCCESS
;
2251 DPRINT("Got Service %S\n", Service
->Buffer
);
2254 return STATUS_SUCCESS
;
2258 * IopActionInitChildServices
2260 * Initialize the service for all (direct) child nodes of a parent node
2264 * Pointer to device node.
2266 * Pointer to parent node to initialize child node services for.
2268 * Load only driver marked as boot start.
2271 * If the driver image for a service is not loaded and initialized
2272 * it is done here too. We only return a status code indicating an
2273 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2274 * not a direct child of the device node for which we initialize
2275 * child services for. Any errors that occur is logged instead so
2276 * that all child services have a chance of being initialized.
2280 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2282 BOOLEAN BootDrivers
)
2284 PDEVICE_NODE ParentDeviceNode
;
2287 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2290 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2293 * We are called for the parent too, but we don't need to do special
2294 * handling for this node
2296 if (DeviceNode
== ParentDeviceNode
)
2298 DPRINT("Success\n");
2299 return STATUS_SUCCESS
;
2303 * Make sure this device node is a direct child of the parent device node
2304 * that is given as an argument
2307 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2310 * Stop the traversal immediately and indicate unsuccessful operation
2313 return STATUS_UNSUCCESSFUL
;
2317 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2318 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2319 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2321 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2322 PDRIVER_OBJECT DriverObject
;
2324 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2325 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2327 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2329 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2330 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2331 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2335 /* get existing DriverObject pointer */
2336 Status
= IopGetDriverObject(
2338 &DeviceNode
->ServiceName
,
2341 if (NT_SUCCESS(Status
))
2343 /* Attach lower level filter drivers. */
2344 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2345 /* Initialize the function driver for the device node */
2346 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2347 if (NT_SUCCESS(Status
))
2349 /* Attach upper level filter drivers. */
2350 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2351 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2353 Status
= IopStartDevice(DeviceNode
);
2360 * Don't disable when trying to load only boot drivers
2364 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2365 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2366 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2367 CPRINT("Initialization of service %S failed (Status %x)\n",
2368 DeviceNode
->ServiceName
.Buffer
, Status
);
2373 DPRINT("Service %S is disabled or already initialized\n",
2374 DeviceNode
->ServiceName
.Buffer
);
2377 return STATUS_SUCCESS
;
2381 * IopActionInitAllServices
2383 * Initialize the service for all (direct) child nodes of a parent node. This
2384 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2388 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2391 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2395 * IopActionInitBootServices
2397 * Initialize the boot start services for all (direct) child nodes of a
2398 * parent node. This function just calls IopActionInitChildServices with
2399 * BootDrivers = TRUE.
2402 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2405 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2409 * IopInitializePnpServices
2411 * Initialize services for discovered children
2415 * Top device node to start initializing services.
2418 * When set to TRUE, only drivers marked as boot start will
2419 * be loaded. Otherwise, all drivers will be loaded.
2425 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2426 IN BOOLEAN BootDrivers
)
2428 DEVICETREE_TRAVERSE_CONTEXT Context
;
2430 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2434 IopInitDeviceTreeTraverseContext(
2437 IopActionInitBootServices
,
2442 IopInitDeviceTreeTraverseContext(
2445 IopActionInitAllServices
,
2449 return IopTraverseDeviceTree(&Context
);
2452 /* Invalidate device list enumerated by a device node.
2453 * The call can be make synchronous by defining the Event field
2454 * of the INVALIDATE_DEVICE_RELATION_DATA structure
2457 IopInvalidateDeviceRelations(
2458 IN PDEVICE_OBJECT DeviceObject
,
2459 IN PVOID InvalidateContext
) /* PINVALIDATE_DEVICE_RELATION_DATA */
2461 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
2462 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2463 PKEVENT Event
= Data
->Event
;
2464 DEVICETREE_TRAVERSE_CONTEXT Context
;
2465 PDEVICE_RELATIONS DeviceRelations
;
2466 IO_STATUS_BLOCK IoStatusBlock
;
2467 PDEVICE_NODE ChildDeviceNode
;
2468 IO_STACK_LOCATION Stack
;
2469 BOOLEAN BootDrivers
;
2470 OBJECT_ATTRIBUTES ObjectAttributes
;
2471 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
2476 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2478 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2480 Stack
.Parameters
.QueryDeviceRelations
.Type
= Data
->Type
;
2482 Status
= IopInitiatePnpIrp(
2485 IRP_MN_QUERY_DEVICE_RELATIONS
,
2487 if (!NT_SUCCESS(Status
))
2489 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2493 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2495 if (!DeviceRelations
|| DeviceRelations
->Count
<= 0)
2497 DPRINT("No PDOs\n");
2498 if (DeviceRelations
)
2500 ExFreePool(DeviceRelations
);
2502 Status
= STATUS_SUCCESS
;
2506 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2509 * Create device nodes for all discovered devices
2511 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2513 Status
= IopCreateDeviceNode(
2515 DeviceRelations
->Objects
[i
],
2517 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2518 if (!NT_SUCCESS(Status
))
2520 DPRINT("No resources\n");
2521 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2522 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2523 ExFreePool(DeviceRelations
);
2524 Status
= STATUS_NO_MEMORY
;
2528 ExFreePool(DeviceRelations
);
2531 * Retrieve information about all discovered children from the bus driver
2533 IopInitDeviceTreeTraverseContext(
2536 IopActionInterrogateDeviceStack
,
2539 Status
= IopTraverseDeviceTree(&Context
);
2540 if (!NT_SUCCESS(Status
))
2542 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2547 * Retrieve configuration from the registry for discovered children
2549 IopInitDeviceTreeTraverseContext(
2552 IopActionConfigureChildServices
,
2555 Status
= IopTraverseDeviceTree(&Context
);
2556 if (!NT_SUCCESS(Status
))
2558 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2563 * Get the state of the system boot. If the \\SystemRoot link isn't
2564 * created yet, we will assume that it's possible to load only boot
2567 InitializeObjectAttributes(
2573 Status
= ZwOpenFile(
2580 if (NT_SUCCESS(Status
))
2582 BootDrivers
= FALSE
;
2589 * Initialize services for discovered children. Only boot drivers will
2590 * be loaded from boot driver!
2592 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2593 if (!NT_SUCCESS(Status
))
2595 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2599 DPRINT("IopInvalidateDeviceRelations() finished\n");
2600 Status
= STATUS_SUCCESS
;
2603 IoFreeWorkItem(Data
->WorkItem
);
2606 Data
->Status
= Status
;
2607 KeSetEvent(Event
, 0, FALSE
);
2613 static NTSTATUS INIT_FUNCTION
2614 IopEnumerateDetectedDevices(
2616 IN PUNICODE_STRING RelativePath
,
2618 IN BOOLEAN EnumerateSubKeys
,
2619 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2620 IN ULONG ParentBootResourcesLength
)
2622 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2623 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2624 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2625 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2626 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2627 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2628 OBJECT_ATTRIBUTES ObjectAttributes
;
2629 HANDLE hDevicesKey
= NULL
;
2630 HANDLE hDeviceKey
= NULL
;
2631 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2632 UNICODE_STRING Level2NameU
;
2633 WCHAR Level2Name
[5];
2634 ULONG IndexDevice
= 0;
2636 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2637 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2638 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2639 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2640 UNICODE_STRING DeviceName
, ValueName
;
2642 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2643 ULONG BootResourcesLength
;
2646 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI BIOS");
2647 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2648 static ULONG DeviceIndexPci
= 0;
2649 /*const UNICODE_STRING IdentifierAcpi = RTL_CONSTANT_STRING(L"ACPI BIOS");
2650 UNICODE_STRING HardwareIdAcpi = RTL_CONSTANT_STRING(L"*PNP0C08\0");
2651 static ULONG DeviceIndexAcpi = 0;*/
2652 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2653 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2654 static ULONG DeviceIndexSerial
= 0;
2655 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2656 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2657 static ULONG DeviceIndexKeyboard
= 0;
2658 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2659 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2660 static ULONG DeviceIndexMouse
= 0;
2661 PUNICODE_STRING pHardwareId
;
2662 ULONG DeviceIndex
= 0;
2664 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2665 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2666 if (!NT_SUCCESS(Status
))
2668 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2672 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2673 if (!pDeviceInformation
)
2675 DPRINT("ExAllocatePool() failed\n");
2676 Status
= STATUS_NO_MEMORY
;
2680 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2681 if (!pValueInformation
)
2683 DPRINT("ExAllocatePool() failed\n");
2684 Status
= STATUS_NO_MEMORY
;
2690 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2691 if (Status
== STATUS_NO_MORE_ENTRIES
)
2693 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2695 ExFreePool(pDeviceInformation
);
2696 DeviceInfoLength
= RequiredSize
;
2697 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2698 if (!pDeviceInformation
)
2700 DPRINT("ExAllocatePool() failed\n");
2701 Status
= STATUS_NO_MEMORY
;
2704 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2706 if (!NT_SUCCESS(Status
))
2708 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2713 /* Open device key */
2714 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2715 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2716 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2719 KEY_QUERY_VALUE
+ EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0,
2721 if (!NT_SUCCESS(Status
))
2723 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2727 /* Read boot resources, and add then to parent ones */
2728 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2729 if (Status
== STATUS_BUFFER_OVERFLOW
)
2731 ExFreePool(pValueInformation
);
2732 ValueInfoLength
= RequiredSize
;
2733 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2734 if (!pValueInformation
)
2736 DPRINT("ExAllocatePool() failed\n");
2737 ZwDeleteKey(hLevel2Key
);
2738 Status
= STATUS_NO_MEMORY
;
2741 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2743 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2745 BootResources
= ParentBootResources
;
2746 BootResourcesLength
= ParentBootResourcesLength
;
2748 else if (!NT_SUCCESS(Status
))
2750 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2753 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2755 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2758 else if (((PCM_FULL_RESOURCE_DESCRIPTOR
)pValueInformation
->Data
)->PartialResourceList
.Count
== 0)
2760 BootResources
= ParentBootResources
;
2761 BootResourcesLength
= ParentBootResourcesLength
;
2765 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2767 /* Concatenate current resources and parent ones */
2768 if (ParentBootResourcesLength
== 0)
2769 BootResourcesLength
= pValueInformation
->DataLength
;
2771 BootResourcesLength
= ParentBootResourcesLength
2772 + pValueInformation
->DataLength
2774 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2777 DPRINT("ExAllocatePool() failed\n");
2780 if (ParentBootResourcesLength
== 0)
2782 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2784 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2786 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2788 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2789 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2790 ParentBootResourcesLength
- Header
);
2791 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2795 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2797 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2798 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2799 ParentBootResourcesLength
- Header
);
2801 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2802 pValueInformation
->Data
+ Header
,
2803 pValueInformation
->DataLength
- Header
);
2804 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2808 if (EnumerateSubKeys
)
2813 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2814 if (Status
== STATUS_NO_MORE_ENTRIES
)
2816 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2818 ExFreePool(pDeviceInformation
);
2819 DeviceInfoLength
= RequiredSize
;
2820 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2821 if (!pDeviceInformation
)
2823 DPRINT("ExAllocatePool() failed\n");
2824 Status
= STATUS_NO_MEMORY
;
2827 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2829 if (!NT_SUCCESS(Status
))
2831 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2835 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
2836 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2838 Status
= IopEnumerateDetectedDevices(
2844 BootResourcesLength
);
2845 if (!NT_SUCCESS(Status
))
2850 /* Read identifier */
2851 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, 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 Status
= STATUS_NO_MEMORY
;
2863 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2865 if (!NT_SUCCESS(Status
))
2867 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2869 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2873 else if (pValueInformation
->Type
!= REG_SZ
)
2875 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2880 /* Assign hardware id to this device */
2881 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
2882 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2883 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2884 ValueName
.Length
-= sizeof(WCHAR
);
2887 if (RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2889 pHardwareId
= &HardwareIdSerial
;
2890 DeviceIndex
= DeviceIndexSerial
++;
2892 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2894 pHardwareId
= &HardwareIdKeyboard
;
2895 DeviceIndex
= DeviceIndexKeyboard
++;
2897 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2899 pHardwareId
= &HardwareIdMouse
;
2900 DeviceIndex
= DeviceIndexMouse
++;
2902 else if (NT_SUCCESS(Status
))
2904 /* Try to also match the device identifier */
2905 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2907 pHardwareId
= &HardwareIdPci
;
2908 DeviceIndex
= DeviceIndexPci
++;
2910 /*else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0)
2912 pHardwareId = &HardwareIdAcpi;
2913 DeviceIndex = DeviceIndexAcpi++;
2917 /* Unknown device */
2918 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2924 /* Unknown key path */
2925 DPRINT("Unknown key path %wZ\n", RelativePath
);
2929 /* Add the detected device to Root key */
2930 InitializeObjectAttributes(&ObjectAttributes
, pHardwareId
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2931 Status
= ZwCreateKey(
2937 REG_OPTION_NON_VOLATILE
,
2939 if (!NT_SUCCESS(Status
))
2941 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2944 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2945 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2946 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2947 Status
= ZwCreateKey(
2949 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2953 REG_OPTION_NON_VOLATILE
,
2955 ZwClose(hLevel1Key
);
2956 if (!NT_SUCCESS(Status
))
2958 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2961 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, pHardwareId
);
2962 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
2963 if (!NT_SUCCESS(Status
))
2965 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2966 ZwDeleteKey(hLevel2Key
);
2969 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2970 if (!NT_SUCCESS(Status
))
2972 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2973 ZwDeleteKey(hLevel2Key
);
2976 if (BootResourcesLength
> 0)
2978 /* Save boot resources to 'LogConf\BootConfig' */
2979 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2980 Status
= ZwCreateKey(
2986 REG_OPTION_VOLATILE
,
2988 if (!NT_SUCCESS(Status
))
2990 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2991 ZwDeleteKey(hLevel2Key
);
2994 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
2996 if (!NT_SUCCESS(Status
))
2998 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2999 ZwDeleteKey(hLevel2Key
);
3005 if (BootResources
&& BootResources
!= ParentBootResources
)
3006 ExFreePool(BootResources
);
3009 ZwClose(hLevel2Key
);
3014 ZwClose(hDeviceKey
);
3019 Status
= STATUS_SUCCESS
;
3023 ZwClose(hDevicesKey
);
3025 ZwClose(hDeviceKey
);
3026 if (pDeviceInformation
)
3027 ExFreePool(pDeviceInformation
);
3028 if (pValueInformation
)
3029 ExFreePool(pValueInformation
);
3033 static BOOLEAN INIT_FUNCTION
3034 IopIsAcpiComputer(VOID
)
3038 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3039 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3040 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3041 OBJECT_ATTRIBUTES ObjectAttributes
;
3042 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3043 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3044 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3045 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3047 ULONG IndexDevice
= 0;
3048 UNICODE_STRING DeviceName
, ValueName
;
3049 HANDLE hDevicesKey
= NULL
;
3050 HANDLE hDeviceKey
= NULL
;
3052 BOOLEAN ret
= FALSE
;
3054 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3055 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3056 if (!NT_SUCCESS(Status
))
3058 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3062 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3063 if (!pDeviceInformation
)
3065 DPRINT("ExAllocatePool() failed\n");
3066 Status
= STATUS_NO_MEMORY
;
3070 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3071 if (!pDeviceInformation
)
3073 DPRINT("ExAllocatePool() failed\n");
3074 Status
= STATUS_NO_MEMORY
;
3080 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3081 if (Status
== STATUS_NO_MORE_ENTRIES
)
3083 else if (Status
== STATUS_BUFFER_OVERFLOW
)
3085 ExFreePool(pDeviceInformation
);
3086 DeviceInfoLength
= RequiredSize
;
3087 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3088 if (!pDeviceInformation
)
3090 DPRINT("ExAllocatePool() failed\n");
3091 Status
= STATUS_NO_MEMORY
;
3094 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3096 if (!NT_SUCCESS(Status
))
3098 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3103 /* Open device key */
3104 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3105 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3106 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3111 if (!NT_SUCCESS(Status
))
3113 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3117 /* Read identifier */
3118 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3119 if (Status
== STATUS_BUFFER_OVERFLOW
)
3121 ExFreePool(pValueInformation
);
3122 ValueInfoLength
= RequiredSize
;
3123 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3124 if (!pValueInformation
)
3126 DPRINT("ExAllocatePool() failed\n");
3127 Status
= STATUS_NO_MEMORY
;
3130 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3132 if (!NT_SUCCESS(Status
))
3134 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3137 else if (pValueInformation
->Type
!= REG_SZ
)
3139 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3143 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3144 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3145 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3146 ValueName
.Length
-= sizeof(WCHAR
);
3147 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3149 DPRINT("Found ACPI BIOS\n");
3155 ZwClose(hDeviceKey
);
3160 if (pDeviceInformation
)
3161 ExFreePool(pDeviceInformation
);
3162 if (pValueInformation
)
3163 ExFreePool(pValueInformation
);
3165 ZwClose(hDevicesKey
);
3167 ZwClose(hDeviceKey
);
3172 static NTSTATUS INIT_FUNCTION
3173 IopUpdateRootKey(VOID
)
3175 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum\\Root");
3176 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3177 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3178 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3179 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3180 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3181 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3182 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3183 OBJECT_ATTRIBUTES ObjectAttributes
;
3184 HANDLE hRoot
, hHalAcpiDevice
, hHalAcpiId
;
3187 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3188 Status
= ZwOpenKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
);
3189 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3191 /* We are probably in 1st stage */
3192 return STATUS_SUCCESS
;
3194 else if (!NT_SUCCESS(Status
))
3196 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3200 if (IopIsAcpiComputer())
3202 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3203 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3205 if (!NT_SUCCESS(Status
))
3207 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3208 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3209 ZwClose(hHalAcpiDevice
);
3210 if (!NT_SUCCESS(Status
))
3212 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3213 if (NT_SUCCESS(Status
))
3214 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3215 ZwClose(hHalAcpiId
);
3220 Status
= IopEnumerateDetectedDevices(
3238 DPRINT("PnpInit()\n");
3240 KeInitializeSpinLock(&IopDeviceTreeLock
);
3242 /* Initialize the Bus Type GUID List */
3243 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3244 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3245 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3247 /* Initialize PnP-Event notification support */
3248 Status
= IopInitPlugPlayEvents();
3249 if (!NT_SUCCESS(Status
))
3251 CPRINT("IopInitPlugPlayEvents() failed\n");
3252 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3256 * Create root device node
3259 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
3260 if (!NT_SUCCESS(Status
))
3262 CPRINT("IoCreateDriverObject() failed\n");
3263 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3266 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3268 if (!NT_SUCCESS(Status
))
3270 CPRINT("IoCreateDevice() failed\n");
3271 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3274 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
3275 if (!NT_SUCCESS(Status
))
3277 CPRINT("Insufficient resources\n");
3278 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3281 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3284 CPRINT("Failed to create the instance path!\n");
3285 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3288 /* Report the device to the user-mode pnp manager */
3289 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3290 &IopRootDeviceNode
->InstancePath
);
3292 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3293 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3294 IopRootDriverObject
->DriverExtension
->AddDevice(
3295 IopRootDriverObject
,
3296 IopRootDeviceNode
->PhysicalDeviceObject
);
3298 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3299 Status
= IopUpdateRootKey();
3300 if (!NT_SUCCESS(Status
))
3302 CPRINT("IopUpdateRootKey() failed\n");
3303 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);