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
);
48 IoSynchronousInvalidateDeviceRelations(
49 IN PDEVICE_OBJECT DeviceObject
,
50 IN DEVICE_RELATION_TYPE Type
);
53 /* FUNCTIONS *****************************************************************/
57 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
59 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
64 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
65 PDRIVER_OBJECT DriverObject
)
69 BOOLEAN IsPnpDriver
= FALSE
;
71 if (DriverObject
->DriverExtension
->AddDevice
)
73 /* This is a Plug and Play driver */
74 DPRINT("Plug and Play driver found\n");
76 ASSERT(DeviceNode
->PhysicalDeviceObject
);
78 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
79 DriverObject
->DriverExtension
->AddDevice
);
81 IsPnpDriver
= !IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
82 Status
= DriverObject
->DriverExtension
->AddDevice(
83 DriverObject
, IsPnpDriver
? DeviceNode
->PhysicalDeviceObject
: NULL
);
85 if (!NT_SUCCESS(Status
))
92 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
94 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
96 /* FIXME: What do we do? Unload the driver or just disable the device? */
97 DbgPrint("An FDO was not attached\n");
98 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
99 return STATUS_UNSUCCESSFUL
;
102 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
104 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
106 /* There can be only one system power device */
107 if (!SystemPowerDeviceNodeCreated
)
109 PopSystemPowerDeviceNode
= DeviceNode
;
110 SystemPowerDeviceNodeCreated
= TRUE
;
114 ObDereferenceObject(Fdo
);
117 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
118 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
121 return STATUS_SUCCESS
;
126 PDEVICE_NODE DeviceNode
)
128 IO_STATUS_BLOCK IoStatusBlock
;
129 IO_STACK_LOCATION Stack
;
133 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
135 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
136 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
137 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
139 Status
= IopInitiatePnpIrp(
145 if (!NT_SUCCESS(Status
))
147 DPRINT("IopInitiatePnpIrp() failed\n");
151 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
153 DPRINT("Device needs enumeration, invalidating bus relations\n");
154 /* Invalidate device relations synchronously
155 (otherwise there will be dirty read of DeviceNode) */
156 IoSynchronousInvalidateDeviceRelations(DeviceNode
->PhysicalDeviceObject
, BusRelations
);
157 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
161 ObDereferenceObject(Fdo
);
163 if (NT_SUCCESS(Status
))
164 DeviceNode
->Flags
|= DN_STARTED
;
171 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
172 PDEVICE_CAPABILITIES DeviceCaps
)
174 IO_STATUS_BLOCK StatusBlock
;
175 IO_STACK_LOCATION Stack
;
177 /* Set up the Header */
178 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
179 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
180 DeviceCaps
->Version
= 1;
181 DeviceCaps
->Address
= -1;
182 DeviceCaps
->UINumber
= -1;
184 /* Set up the Stack */
185 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
186 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
189 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
191 IRP_MN_QUERY_CAPABILITIES
,
200 IoInvalidateDeviceRelations(
201 IN PDEVICE_OBJECT DeviceObject
,
202 IN DEVICE_RELATION_TYPE Type
)
204 PIO_WORKITEM WorkItem
;
205 PINVALIDATE_DEVICE_RELATION_DATA Data
;
207 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
210 WorkItem
= IoAllocateWorkItem(DeviceObject
);
218 Data
->WorkItem
= WorkItem
;
223 IopInvalidateDeviceRelations
,
233 IoSynchronousInvalidateDeviceRelations(
234 IN PDEVICE_OBJECT DeviceObject
,
235 IN DEVICE_RELATION_TYPE Type
)
237 PIO_WORKITEM WorkItem
;
238 PINVALIDATE_DEVICE_RELATION_DATA Data
;
241 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
244 WorkItem
= IoAllocateWorkItem(DeviceObject
);
251 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
253 Data
->WorkItem
= WorkItem
;
254 Data
->Event
= &Event
;
258 IopInvalidateDeviceRelations
,
262 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
271 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
272 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
273 IN ULONG BufferLength
,
274 OUT PVOID PropertyBuffer
,
275 OUT PULONG ResultLength
)
277 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
278 DEVICE_CAPABILITIES DeviceCaps
;
284 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
286 if (DeviceNode
== NULL
)
287 return STATUS_INVALID_DEVICE_REQUEST
;
289 switch (DeviceProperty
)
291 case DevicePropertyBusNumber
:
292 Length
= sizeof(ULONG
);
293 Data
= &DeviceNode
->ChildBusNumber
;
296 /* Complete, untested */
297 case DevicePropertyBusTypeGuid
:
299 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
300 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
302 /* Return the GUID */
303 *ResultLength
= sizeof(GUID
);
305 /* Check if the buffer given was large enough */
306 if (BufferLength
< *ResultLength
)
308 return STATUS_BUFFER_TOO_SMALL
;
312 RtlCopyMemory(PropertyBuffer
,
313 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
315 return STATUS_SUCCESS
;
319 return STATUS_OBJECT_NAME_NOT_FOUND
;
323 case DevicePropertyLegacyBusType
:
324 Length
= sizeof(INTERFACE_TYPE
);
325 Data
= &DeviceNode
->ChildInterfaceType
;
328 case DevicePropertyAddress
:
329 /* Query the device caps */
330 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
331 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
334 *ResultLength
= sizeof(ULONG
);
336 /* Check if the buffer given was large enough */
337 if (BufferLength
< *ResultLength
)
339 return STATUS_BUFFER_TOO_SMALL
;
343 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
344 return STATUS_SUCCESS
;
348 return STATUS_OBJECT_NAME_NOT_FOUND
;
352 // case DevicePropertyUINumber:
353 // if (DeviceNode->CapabilityFlags == NULL)
354 // return STATUS_INVALID_DEVICE_REQUEST;
355 // Length = sizeof(ULONG);
356 // Data = &DeviceNode->CapabilityFlags->UINumber;
359 case DevicePropertyClassName
:
360 case DevicePropertyClassGuid
:
361 case DevicePropertyDriverKeyName
:
362 case DevicePropertyManufacturer
:
363 case DevicePropertyFriendlyName
:
364 case DevicePropertyHardwareID
:
365 case DevicePropertyCompatibleIDs
:
366 case DevicePropertyDeviceDescription
:
367 case DevicePropertyLocationInformation
:
368 case DevicePropertyUINumber
:
370 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
371 UNICODE_STRING KeyName
, ValueName
;
372 OBJECT_ATTRIBUTES ObjectAttributes
;
373 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
374 ULONG ValueInformationLength
;
378 switch (DeviceProperty
)
380 case DevicePropertyClassName
:
381 RegistryPropertyName
= L
"Class"; break;
382 case DevicePropertyClassGuid
:
383 RegistryPropertyName
= L
"ClassGuid"; break;
384 case DevicePropertyDriverKeyName
:
385 RegistryPropertyName
= L
"Driver"; break;
386 case DevicePropertyManufacturer
:
387 RegistryPropertyName
= L
"Mfg"; break;
388 case DevicePropertyFriendlyName
:
389 RegistryPropertyName
= L
"FriendlyName"; break;
390 case DevicePropertyHardwareID
:
391 RegistryPropertyName
= L
"HardwareID"; break;
392 case DevicePropertyCompatibleIDs
:
393 RegistryPropertyName
= L
"CompatibleIDs"; break;
394 case DevicePropertyDeviceDescription
:
395 RegistryPropertyName
= L
"DeviceDesc"; break;
396 case DevicePropertyLocationInformation
:
397 RegistryPropertyName
= L
"LocationInformation"; break;
398 case DevicePropertyUINumber
:
399 RegistryPropertyName
= L
"UINumber"; break;
401 RegistryPropertyName
= NULL
; break;
404 KeyNameBuffer
= ExAllocatePool(PagedPool
,
405 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
407 DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer
, RegistryPropertyName
);
409 if (KeyNameBuffer
== NULL
)
410 return STATUS_INSUFFICIENT_RESOURCES
;
412 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
413 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
414 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
415 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
416 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
418 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
419 ExFreePool(KeyNameBuffer
);
420 if (!NT_SUCCESS(Status
))
423 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
424 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
425 Data
[0]) + BufferLength
;
426 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
427 if (ValueInformation
== NULL
)
430 return STATUS_INSUFFICIENT_RESOURCES
;
433 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
434 KeyValuePartialInformation
, ValueInformation
,
435 ValueInformationLength
,
436 &ValueInformationLength
);
437 *ResultLength
= ValueInformation
->DataLength
;
440 if (!NT_SUCCESS(Status
))
442 ExFreePool(ValueInformation
);
443 if (Status
== STATUS_BUFFER_OVERFLOW
)
444 return STATUS_BUFFER_TOO_SMALL
;
449 /* FIXME: Verify the value (NULL-terminated, correct format). */
451 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
452 ValueInformation
->DataLength
);
453 ExFreePool(ValueInformation
);
455 return STATUS_SUCCESS
;
458 case DevicePropertyBootConfiguration
:
460 if (DeviceNode
->BootResources
->Count
!= 0)
462 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
464 Data
= &DeviceNode
->BootResources
;
467 /* FIXME: use a translated boot configuration instead */
468 case DevicePropertyBootConfigurationTranslated
:
470 if (DeviceNode
->BootResources
->Count
!= 0)
472 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
474 Data
= &DeviceNode
->BootResources
;
477 case DevicePropertyEnumeratorName
:
478 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
481 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
482 Data
= DeviceNode
->InstancePath
.Buffer
;
491 case DevicePropertyPhysicalDeviceObjectName
:
492 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
493 Data
= DeviceNode
->InstancePath
.Buffer
;
497 return STATUS_INVALID_PARAMETER_2
;
500 *ResultLength
= Length
;
501 if (BufferLength
< Length
)
502 return STATUS_BUFFER_TOO_SMALL
;
503 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
505 /* Terminate the string */
506 if (DeviceProperty
== DevicePropertyEnumeratorName
507 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
509 Ptr
= (PWSTR
)PropertyBuffer
;
510 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
513 return STATUS_SUCCESS
;
521 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
527 * @name IoOpenDeviceRegistryKey
529 * Open a registry key unique for a specified driver or device instance.
531 * @param DeviceObject Device to get the registry key for.
532 * @param DevInstKeyType Type of the key to return.
533 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
534 * @param DevInstRegKey Handle to the opened registry key on
543 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
544 IN ULONG DevInstKeyType
,
545 IN ACCESS_MASK DesiredAccess
,
546 OUT PHANDLE DevInstRegKey
)
548 static WCHAR RootKeyName
[] =
549 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
550 static WCHAR ProfileKeyName
[] =
551 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
552 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
553 static WCHAR EnumKeyName
[] = L
"Enum\\";
554 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
556 LPWSTR KeyNameBuffer
;
557 UNICODE_STRING KeyName
;
558 ULONG DriverKeyLength
;
559 OBJECT_ATTRIBUTES ObjectAttributes
;
560 PDEVICE_NODE DeviceNode
= NULL
;
563 DPRINT("IoOpenDeviceRegistryKey() called\n");
565 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
567 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
568 return STATUS_INVALID_PARAMETER
;
572 * Calculate the length of the base key name. This is the full
573 * name for driver key or the name excluding "Device Parameters"
574 * subkey for device key.
577 KeyNameLength
= sizeof(RootKeyName
);
578 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
579 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
580 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
582 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
583 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
584 0, NULL
, &DriverKeyLength
);
585 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
587 KeyNameLength
+= DriverKeyLength
;
591 DeviceNode
= IopGetDeviceNode(DeviceObject
);
592 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
593 DeviceNode
->InstancePath
.Length
;
597 * Now allocate the buffer for the key name...
600 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
601 if (KeyNameBuffer
== NULL
)
602 return STATUS_INSUFFICIENT_RESOURCES
;
605 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
606 KeyName
.Buffer
= KeyNameBuffer
;
609 * ...and build the key name.
612 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
613 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
615 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
616 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
618 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
620 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
621 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
622 DriverKeyLength
, KeyNameBuffer
+
623 (KeyName
.Length
/ sizeof(WCHAR
)),
625 if (!NT_SUCCESS(Status
))
627 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
628 ExFreePool(KeyNameBuffer
);
631 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
635 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
636 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
637 if (DeviceNode
->InstancePath
.Length
== 0)
639 ExFreePool(KeyNameBuffer
);
648 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
649 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
650 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
651 if (!NT_SUCCESS(Status
))
653 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
654 ExFreePool(KeyNameBuffer
);
657 ExFreePool(KeyNameBuffer
);
660 * For driver key we're done now.
663 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
667 * Let's go further. For device key we must open "Device Parameters"
668 * subkey and create it if it doesn't exist yet.
671 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
672 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
673 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
674 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
675 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
676 ZwClose(ObjectAttributes
.RootDirectory
);
686 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
693 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
697 if (PopSystemPowerDeviceNode
)
699 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
700 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
701 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
703 return STATUS_SUCCESS
;
706 return STATUS_UNSUCCESSFUL
;
711 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
713 USHORT i
= 0, FoundIndex
= 0xFFFF;
717 /* Acquire the lock */
718 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
720 /* Loop all entries */
721 while (i
< IopBusTypeGuidList
->GuidCount
)
723 /* Try to find a match */
724 if (RtlCompareMemory(BusTypeGuid
,
725 &IopBusTypeGuidList
->Guids
[i
],
726 sizeof(GUID
)) == sizeof(GUID
))
735 /* Check if we have to grow the list */
736 if (IopBusTypeGuidList
->GuidCount
)
738 /* Calculate the new size */
739 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
740 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
742 /* Allocate the new copy */
743 NewList
= ExAllocatePool(PagedPool
, NewSize
);
745 /* Now copy them, decrease the size too */
746 NewSize
-= sizeof(GUID
);
747 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
749 /* Free the old list */
750 ExFreePool(IopBusTypeGuidList
);
752 /* Use the new buffer */
753 IopBusTypeGuidList
= NewList
;
756 /* Copy the new GUID */
757 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
761 /* The new entry is the index */
762 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
763 IopBusTypeGuidList
->GuidCount
++;
766 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
772 * Creates a device node
775 * ParentNode = Pointer to parent device node
776 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
777 * to have the root device node create one
778 * (eg. for legacy drivers)
779 * DeviceNode = Pointer to storage for created device node
785 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
786 PDEVICE_OBJECT PhysicalDeviceObject
,
787 PDEVICE_NODE
*DeviceNode
)
793 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p\n",
794 ParentNode
, PhysicalDeviceObject
);
796 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
799 return STATUS_INSUFFICIENT_RESOURCES
;
802 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
804 if (!PhysicalDeviceObject
)
806 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
807 if (!NT_SUCCESS(Status
))
813 /* This is for drivers passed on the command line to ntoskrnl.exe */
814 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
815 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
818 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
820 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
824 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
825 Node
->Parent
= ParentNode
;
826 Node
->NextSibling
= ParentNode
->Child
;
827 if (ParentNode
->Child
!= NULL
)
829 ParentNode
->Child
->PrevSibling
= Node
;
831 ParentNode
->Child
= Node
;
832 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
833 Node
->Level
= ParentNode
->Level
+ 1;
838 return STATUS_SUCCESS
;
842 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
846 /* All children must be deleted before a parent is deleted */
847 ASSERT(!DeviceNode
->Child
);
849 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
851 ASSERT(DeviceNode
->PhysicalDeviceObject
);
853 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
855 /* Unlink from parent if it exists */
857 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
859 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
862 /* Unlink from sibling list */
864 if (DeviceNode
->PrevSibling
)
866 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
869 if (DeviceNode
->NextSibling
)
871 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
874 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
876 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
878 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
880 if (DeviceNode
->ResourceList
)
882 ExFreePool(DeviceNode
->ResourceList
);
885 if (DeviceNode
->ResourceListTranslated
)
887 ExFreePool(DeviceNode
->ResourceListTranslated
);
890 if (DeviceNode
->ResourceRequirements
)
892 ExFreePool(DeviceNode
->ResourceRequirements
);
895 if (DeviceNode
->BootResources
)
897 ExFreePool(DeviceNode
->BootResources
);
900 ExFreePool(DeviceNode
);
902 return STATUS_SUCCESS
;
906 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
907 PIO_STATUS_BLOCK IoStatusBlock
,
909 PIO_STACK_LOCATION Stack OPTIONAL
)
911 PDEVICE_OBJECT TopDeviceObject
;
912 PIO_STACK_LOCATION IrpSp
;
917 /* Always call the top of the device stack */
918 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
925 Irp
= IoBuildSynchronousFsdRequest(
934 /* PNP IRPs are always initialized with a status code of
935 STATUS_NOT_IMPLEMENTED */
936 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
937 Irp
->IoStatus
.Information
= 0;
939 IrpSp
= IoGetNextIrpStackLocation(Irp
);
940 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
944 RtlCopyMemory(&IrpSp
->Parameters
,
946 sizeof(Stack
->Parameters
));
949 Status
= IoCallDriver(TopDeviceObject
, Irp
);
950 if (Status
== STATUS_PENDING
)
952 KeWaitForSingleObject(&Event
,
957 Status
= IoStatusBlock
->Status
;
960 ObDereferenceObject(TopDeviceObject
);
967 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
969 PDEVICE_NODE ParentDeviceNode
;
970 PDEVICE_NODE ChildDeviceNode
;
973 /* Copy context data so we don't overwrite it in subsequent calls to this function */
974 ParentDeviceNode
= Context
->DeviceNode
;
976 /* Call the action routine */
977 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
978 if (!NT_SUCCESS(Status
))
983 /* Traversal of all children nodes */
984 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
985 ChildDeviceNode
!= NULL
;
986 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
988 /* Pass the current device node to the action routine */
989 Context
->DeviceNode
= ChildDeviceNode
;
991 Status
= IopTraverseDeviceTreeNode(Context
);
992 if (!NT_SUCCESS(Status
))
1003 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1007 DPRINT("Context 0x%p\n", Context
);
1009 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1010 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1012 /* Start from the specified device node */
1013 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1015 /* Recursively traverse the device tree */
1016 Status
= IopTraverseDeviceTreeNode(Context
);
1017 if (Status
== STATUS_UNSUCCESSFUL
)
1019 /* The action routine just wanted to terminate the traversal with status
1020 code STATUS_SUCCESS */
1021 Status
= STATUS_SUCCESS
;
1030 IopCreateDeviceKeyPath(PWSTR Path
,
1033 OBJECT_ATTRIBUTES ObjectAttributes
;
1034 WCHAR KeyBuffer
[MAX_PATH
];
1035 UNICODE_STRING KeyName
;
1043 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
1045 return STATUS_INVALID_PARAMETER
;
1048 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
1050 /* Skip \\Registry\\ */
1051 Current
= KeyBuffer
;
1052 Current
= wcschr (Current
, L
'\\') + 1;
1053 Current
= wcschr (Current
, L
'\\') + 1;
1057 Next
= wcschr (Current
, L
'\\');
1067 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
1068 InitializeObjectAttributes (&ObjectAttributes
,
1070 OBJ_CASE_INSENSITIVE
,
1074 DPRINT("Create '%S'\n", KeyName
.Buffer
);
1076 Status
= ZwCreateKey (&KeyHandle
,
1083 if (!NT_SUCCESS (Status
))
1085 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
1091 *Handle
= KeyHandle
;
1092 return STATUS_SUCCESS
;
1096 ZwClose (KeyHandle
);
1103 return STATUS_UNSUCCESSFUL
;
1109 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1110 PDEVICE_NODE DeviceNode
)
1112 OBJECT_ATTRIBUTES ObjectAttributes
;
1113 UNICODE_STRING KeyName
;
1116 ULONG ListSize
, ResultLength
;
1119 DPRINT("IopSetDeviceInstanceData() called\n");
1121 /* Create the 'LogConf' key */
1122 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1123 InitializeObjectAttributes(&ObjectAttributes
,
1125 OBJ_CASE_INSENSITIVE
,
1128 Status
= ZwCreateKey(&LogConfKey
,
1135 if (NT_SUCCESS(Status
))
1137 /* Set 'BootConfig' value */
1138 if (DeviceNode
->BootResources
!= NULL
)
1140 ResCount
= DeviceNode
->BootResources
->Count
;
1143 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1145 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1146 Status
= ZwSetValueKey(LogConfKey
,
1150 &DeviceNode
->BootResources
,
1155 /* Set 'BasicConfigVector' value */
1156 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1157 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1159 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1160 Status
= ZwSetValueKey(LogConfKey
,
1163 REG_RESOURCE_REQUIREMENTS_LIST
,
1164 DeviceNode
->ResourceRequirements
,
1165 DeviceNode
->ResourceRequirements
->ListSize
);
1168 ZwClose(LogConfKey
);
1171 /* Set the 'ConfigFlags' value */
1172 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1173 Status
= ZwQueryValueKey(InstanceKey
,
1175 KeyValueBasicInformation
,
1179 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1181 /* Write the default value */
1182 ULONG DefaultConfigFlags
= 0;
1183 Status
= ZwSetValueKey(InstanceKey
,
1187 &DefaultConfigFlags
,
1188 sizeof(DefaultConfigFlags
));
1192 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1194 /* Create the 'Control' key */
1195 RtlInitUnicodeString(&KeyName
,
1197 InitializeObjectAttributes(&ObjectAttributes
,
1199 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1202 Status
= ZwCreateKey(&LogConfKey
,
1207 REG_OPTION_VOLATILE
,
1209 if (NT_SUCCESS(Status
))
1211 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1212 RtlInitUnicodeString(&KeyName
,
1213 L
"DeviceReference");
1214 Status
= ZwSetValueKey(LogConfKey
,
1221 ZwClose(LogConfKey
);
1226 DPRINT("IopSetDeviceInstanceData() done\n");
1228 return STATUS_SUCCESS
;
1233 IopAssignDeviceResources(
1234 IN PDEVICE_NODE DeviceNode
,
1235 OUT ULONG
*pRequiredSize
)
1237 PIO_RESOURCE_LIST ResourceList
;
1238 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1239 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
1240 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1241 ULONG NumberOfResources
= 0;
1246 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1248 /* No resource needed for this device */
1249 DeviceNode
->ResourceList
= NULL
;
1250 return STATUS_SUCCESS
;
1253 /* Fill DeviceNode->ResourceList
1254 * FIXME: the PnP arbiter should go there!
1255 * Actually, use the BootResources if provided, else the resource list #0
1258 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1260 if (DeviceNode
->BootResources
)
1262 /* Browse the boot resources to know if we have some custom structures */
1263 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1264 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1266 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1267 if (pPartialResourceList
->Version
!= 1 || pPartialResourceList
->Revision
!= 1)
1269 Status
= STATUS_REVISION_MISMATCH
;
1272 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1273 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1274 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1276 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1277 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1281 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1282 if (!DeviceNode
->ResourceList
)
1284 Status
= STATUS_NO_MEMORY
;
1287 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1289 *pRequiredSize
= Size
;
1290 return STATUS_SUCCESS
;
1293 /* Ok, here, we have to use the device requirement list */
1294 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
1296 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1297 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1299 Status
= STATUS_REVISION_MISMATCH
;
1303 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1304 *pRequiredSize
= Size
;
1305 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1306 if (!DeviceNode
->ResourceList
)
1308 Status
= STATUS_NO_MEMORY
;
1312 DeviceNode
->ResourceList
->Count
= 1;
1313 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1314 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1315 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1316 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1318 for (i
= 0; i
< ResourceList
->Count
; i
++)
1320 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1322 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1324 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1325 NumberOfResources
++;
1327 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1328 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
1329 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1330 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
1331 switch (ResourceDescriptor
->Type
)
1333 case CmResourceTypePort
:
1335 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1336 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
1339 case CmResourceTypeInterrupt
:
1341 INTERFACE_TYPE BusType
;
1346 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1347 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1348 /* FIXME: HACK: if we have a PCI device, we try
1349 * to keep the IRQ assigned by the BIOS */
1350 if (NT_SUCCESS(IoGetDeviceProperty(
1351 DeviceNode
->PhysicalDeviceObject
,
1352 DevicePropertyLegacyBusType
,
1353 sizeof(INTERFACE_TYPE
),
1355 &ret
)) && BusType
== PCIBus
)
1357 /* We have a PCI bus */
1358 if (NT_SUCCESS(IoGetDeviceProperty(
1359 DeviceNode
->PhysicalDeviceObject
,
1360 DevicePropertyAddress
,
1363 &ret
)) && SlotNumber
> 0)
1365 /* We have a good slot number */
1366 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1367 DeviceNode
->ResourceRequirements
->BusNumber
,
1370 0x3c /* PCI_INTERRUPT_LINE */,
1372 if (ret
!= 0 && ret
!= 2
1373 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1374 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1376 /* The device already has an assigned IRQ */
1377 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1381 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1382 DescriptorRaw
->u
.Interrupt
.Vector
,
1383 &DeviceNode
->InstancePath
);
1384 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1385 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1386 DeviceNode
->ResourceRequirements
->BusNumber
,
1389 0x3c /* PCI_INTERRUPT_LINE */,
1391 if (ret
== 0 || ret
== 2)
1398 case CmResourceTypeMemory
:
1400 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1401 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
1404 case CmResourceTypeDma
:
1406 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1407 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
1408 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
1411 case CmResourceTypeBusNumber
:
1413 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1414 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
1415 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
1418 /*CmResourceTypeDevicePrivate:
1419 case CmResourceTypePcCardConfig:
1420 case CmResourceTypeMfCardConfig:
1423 &DescriptorRaw->u.DevicePrivate,
1424 &ResourceDescriptor->u.DevicePrivate,
1425 sizeof(ResourceDescriptor->u.DevicePrivate));
1427 &DescriptorTranslated->u.DevicePrivate,
1428 &ResourceDescriptor->u.DevicePrivate,
1429 sizeof(ResourceDescriptor->u.DevicePrivate));
1433 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1434 NumberOfResources
--;
1440 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1442 return STATUS_SUCCESS
;
1445 if (DeviceNode
->ResourceList
)
1447 ExFreePool(DeviceNode
->ResourceList
);
1448 DeviceNode
->ResourceList
= NULL
;
1455 IopTranslateDeviceResources(
1456 IN PDEVICE_NODE DeviceNode
,
1457 IN ULONG RequiredSize
)
1459 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1460 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1464 if (!DeviceNode
->ResourceList
)
1466 DeviceNode
->ResourceListTranslated
= NULL
;
1467 return STATUS_SUCCESS
;
1470 /* That's easy to translate a resource list. Just copy the
1471 * untranslated one and change few fields in the copy
1473 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1474 if (!DeviceNode
->ResourceListTranslated
)
1476 Status
=STATUS_NO_MEMORY
;
1479 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1481 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1483 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1484 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1486 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1487 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1488 switch (DescriptorRaw
->Type
)
1490 case CmResourceTypePort
:
1492 ULONG AddressSpace
= 0; /* IO space */
1493 if (!HalTranslateBusAddress(
1494 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1495 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1496 DescriptorRaw
->u
.Port
.Start
,
1498 &DescriptorTranslated
->u
.Port
.Start
))
1500 Status
= STATUS_UNSUCCESSFUL
;
1505 case CmResourceTypeInterrupt
:
1507 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1508 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1509 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1510 DescriptorRaw
->u
.Interrupt
.Level
,
1511 DescriptorRaw
->u
.Interrupt
.Vector
,
1512 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1513 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1516 case CmResourceTypeMemory
:
1518 ULONG AddressSpace
= 1; /* Memory space */
1519 if (!HalTranslateBusAddress(
1520 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1521 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1522 DescriptorRaw
->u
.Memory
.Start
,
1524 &DescriptorTranslated
->u
.Memory
.Start
))
1526 Status
= STATUS_UNSUCCESSFUL
;
1531 case CmResourceTypeDma
:
1532 case CmResourceTypeBusNumber
:
1533 case CmResourceTypeDeviceSpecific
:
1537 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1538 Status
= STATUS_NOT_IMPLEMENTED
;
1543 return STATUS_SUCCESS
;
1546 /* Yes! Also delete ResourceList because ResourceList and
1547 * ResourceListTranslated should be a pair! */
1548 ExFreePool(DeviceNode
->ResourceList
);
1549 DeviceNode
->ResourceList
= NULL
;
1550 if (DeviceNode
->ResourceListTranslated
)
1552 ExFreePool(DeviceNode
->ResourceListTranslated
);
1553 DeviceNode
->ResourceList
= NULL
;
1560 * IopGetParentIdPrefix
1562 * Retrieve (or create) a string which identifies a device.
1566 * Pointer to device node.
1568 * Pointer to the string where is returned the parent node identifier
1571 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1572 * valid and its Buffer field is NULL-terminated. The caller needs to
1573 * to free the string with RtlFreeUnicodeString when it is no longer
1578 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1579 PUNICODE_STRING ParentIdPrefix
)
1581 ULONG KeyNameBufferLength
;
1582 PWSTR KeyNameBuffer
= NULL
;
1583 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1584 UNICODE_STRING KeyName
;
1585 UNICODE_STRING KeyValue
;
1586 UNICODE_STRING ValueName
;
1587 OBJECT_ATTRIBUTES ObjectAttributes
;
1592 /* HACK: As long as some devices have a NULL device
1593 * instance path, the following test is required :(
1595 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1596 return STATUS_UNSUCCESSFUL
;
1598 /* 1. Try to retrieve ParentIdPrefix from registry */
1599 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1600 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1601 if (!ParentIdPrefixInformation
)
1603 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1606 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1609 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1612 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1613 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1614 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1615 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1616 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1617 if (!NT_SUCCESS(Status
))
1619 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1620 Status
= ZwQueryValueKey(
1622 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1623 KeyNameBufferLength
, &KeyNameBufferLength
);
1624 if (NT_SUCCESS(Status
))
1626 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1627 Status
= STATUS_UNSUCCESSFUL
;
1630 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1631 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1635 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1637 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1638 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1642 /* 2. Create the ParentIdPrefix value */
1643 crc32
= RtlComputeCrc32(0,
1644 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1645 DeviceNode
->Parent
->InstancePath
.Length
);
1647 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1648 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1650 /* 3. Try to write the ParentIdPrefix to registry */
1651 Status
= ZwSetValueKey(hKey
,
1655 (PVOID
)KeyValue
.Buffer
,
1656 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1659 if (NT_SUCCESS(Status
))
1661 /* Duplicate the string to return it */
1662 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1664 ExFreePool(ParentIdPrefixInformation
);
1665 ExFreePool(KeyNameBuffer
);
1673 * IopActionInterrogateDeviceStack
1675 * Retrieve information for all (direct) child nodes of a parent node.
1679 * Pointer to device node.
1681 * Pointer to parent node to retrieve child node information for.
1684 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1685 * when we reach a device node which is not a direct child of the device
1686 * node for which we retrieve information of child nodes for. Any errors
1687 * that occur is logged instead so that all child services have a chance
1688 * of being interrogated.
1692 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1695 IO_STATUS_BLOCK IoStatusBlock
;
1696 PDEVICE_NODE ParentDeviceNode
;
1697 WCHAR InstancePath
[MAX_PATH
];
1698 IO_STACK_LOCATION Stack
;
1704 ULONG RequiredLength
;
1706 HANDLE InstanceKey
= NULL
;
1707 UNICODE_STRING ValueName
;
1708 UNICODE_STRING ParentIdPrefix
= { 0 };
1709 DEVICE_CAPABILITIES DeviceCapabilities
;
1711 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1712 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1714 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1717 * We are called for the parent too, but we don't need to do special
1718 * handling for this node
1721 if (DeviceNode
== ParentDeviceNode
)
1723 DPRINT("Success\n");
1724 return STATUS_SUCCESS
;
1728 * Make sure this device node is a direct child of the parent device node
1729 * that is given as an argument
1732 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1734 /* Stop the traversal immediately and indicate successful operation */
1736 return STATUS_UNSUCCESSFUL
;
1740 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1741 if (!NT_SUCCESS(Status
))
1743 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1748 * FIXME: For critical errors, cleanup and disable device, but always
1749 * return STATUS_SUCCESS.
1752 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1754 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1755 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1759 if (NT_SUCCESS(Status
))
1761 /* Copy the device id string */
1762 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1765 * FIXME: Check for valid characters, if there is invalid characters
1771 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1774 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1776 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1777 if (!NT_SUCCESS(Status
))
1779 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1782 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1784 if (!DeviceCapabilities
.UniqueID
)
1786 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1787 DPRINT("Instance ID is not unique\n");
1788 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1789 if (!NT_SUCCESS(Status
))
1791 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1795 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1797 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1798 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1802 if (NT_SUCCESS(Status
))
1804 /* Append the instance id string */
1805 wcscat(InstancePath
, L
"\\");
1806 if (ParentIdPrefix
.Length
> 0)
1808 /* Add information from parent bus device to InstancePath */
1809 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1810 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1811 wcscat(InstancePath
, L
"&");
1813 if (IoStatusBlock
.Information
)
1814 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1817 * FIXME: Check for valid characters, if there is invalid characters
1823 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1825 RtlFreeUnicodeString(&ParentIdPrefix
);
1827 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1829 DPRINT("No resources\n");
1830 /* FIXME: Cleanup and disable device */
1833 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1836 * Create registry key for the instance id, if it doesn't exist yet
1838 KeyBuffer
= ExAllocatePool(
1840 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1841 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1842 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1843 Status
= IopCreateDeviceKeyPath(KeyBuffer
, &InstanceKey
);
1844 ExFreePool(KeyBuffer
);
1845 if (!NT_SUCCESS(Status
))
1847 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1852 /* Set 'Capabilities' value */
1853 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1854 Status
= ZwSetValueKey(InstanceKey
,
1858 (PVOID
)&DeviceNode
->CapabilityFlags
,
1861 /* Set 'UINumber' value */
1862 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1864 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1865 Status
= ZwSetValueKey(InstanceKey
,
1869 &DeviceCapabilities
.UINumber
,
1874 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1876 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1877 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1881 if (NT_SUCCESS(Status
))
1884 * FIXME: Check for valid characters, if there is invalid characters
1888 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1889 DPRINT("Hardware IDs:\n");
1892 DPRINT(" %S\n", Ptr
);
1893 Length
= wcslen(Ptr
) + 1;
1896 TotalLength
+= Length
;
1898 DPRINT("TotalLength: %hu\n", TotalLength
);
1901 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1902 Status
= ZwSetValueKey(InstanceKey
,
1906 (PVOID
)IoStatusBlock
.Information
,
1907 (TotalLength
+ 1) * sizeof(WCHAR
));
1908 if (!NT_SUCCESS(Status
))
1910 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1915 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1918 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1920 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1921 Status
= IopInitiatePnpIrp(
1922 DeviceNode
->PhysicalDeviceObject
,
1926 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1929 * FIXME: Check for valid characters, if there is invalid characters
1933 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1934 DPRINT("Compatible IDs:\n");
1937 DPRINT(" %S\n", Ptr
);
1938 Length
= wcslen(Ptr
) + 1;
1941 TotalLength
+= Length
;
1943 DPRINT("TotalLength: %hu\n", TotalLength
);
1946 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1947 Status
= ZwSetValueKey(InstanceKey
,
1951 (PVOID
)IoStatusBlock
.Information
,
1952 (TotalLength
+ 1) * sizeof(WCHAR
));
1953 if (!NT_SUCCESS(Status
))
1955 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1960 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1964 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1966 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
1967 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
1968 Status
= IopInitiatePnpIrp(
1969 DeviceNode
->PhysicalDeviceObject
,
1971 IRP_MN_QUERY_DEVICE_TEXT
,
1973 /* This key is mandatory, so even if the Irp fails, we still write it */
1974 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
1975 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
1977 if (NT_SUCCESS(Status
) &&
1978 IoStatusBlock
.Information
&&
1979 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
1981 /* This key is overriden when a driver is installed. Don't write the
1982 * new description if another one already exists */
1983 Status
= ZwSetValueKey(InstanceKey
,
1987 (PVOID
)IoStatusBlock
.Information
,
1988 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
1992 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
1993 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
1995 Status
= ZwSetValueKey(InstanceKey
,
2000 DeviceDesc
.MaximumLength
);
2002 if (!NT_SUCCESS(Status
))
2004 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2010 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2012 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2013 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2014 Status
= IopInitiatePnpIrp(
2015 DeviceNode
->PhysicalDeviceObject
,
2017 IRP_MN_QUERY_DEVICE_TEXT
,
2019 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2021 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2022 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2023 Status
= ZwSetValueKey(InstanceKey
,
2027 (PVOID
)IoStatusBlock
.Information
,
2028 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2029 if (!NT_SUCCESS(Status
))
2031 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2036 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2039 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2041 Status
= IopInitiatePnpIrp(
2042 DeviceNode
->PhysicalDeviceObject
,
2044 IRP_MN_QUERY_BUS_INFORMATION
,
2046 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2048 PPNP_BUS_INFORMATION BusInformation
=
2049 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2051 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2052 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2053 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2054 ExFreePool(BusInformation
);
2058 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2060 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2061 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2062 DeviceNode
->ChildBusTypeIndex
= -1;
2065 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2067 Status
= IopInitiatePnpIrp(
2068 DeviceNode
->PhysicalDeviceObject
,
2070 IRP_MN_QUERY_RESOURCES
,
2072 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2074 DeviceNode
->BootResources
=
2075 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2076 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2080 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2081 DeviceNode
->BootResources
= NULL
;
2084 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2086 Status
= IopInitiatePnpIrp(
2087 DeviceNode
->PhysicalDeviceObject
,
2089 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2091 if (NT_SUCCESS(Status
))
2093 DeviceNode
->ResourceRequirements
=
2094 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2095 if (IoStatusBlock
.Information
)
2096 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2098 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2102 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2103 DeviceNode
->ResourceRequirements
= NULL
;
2107 if (InstanceKey
!= NULL
)
2109 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2112 ZwClose(InstanceKey
);
2114 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
2115 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
2116 if (NT_SUCCESS(Status
))
2118 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
2119 if (NT_SUCCESS(Status
))
2121 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
2125 DPRINT("IopTranslateDeviceResources() failed (Status 0x08lx)\n", Status
);
2130 DPRINT("IopAssignDeviceResources() failed (Status 0x08lx)\n", Status
);
2132 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
2134 DeviceNode
->Flags
|= DNF_PROCESSED
;
2136 /* Report the device to the user-mode pnp manager */
2137 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2138 &DeviceNode
->InstancePath
);
2140 return STATUS_SUCCESS
;
2144 * IopActionConfigureChildServices
2146 * Retrieve configuration for all (direct) child nodes of a parent node.
2150 * Pointer to device node.
2152 * Pointer to parent node to retrieve child node configuration for.
2155 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2156 * when we reach a device node which is not a direct child of the device
2157 * node for which we configure child services for. Any errors that occur is
2158 * logged instead so that all child services have a chance of beeing
2163 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2166 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2167 PDEVICE_NODE ParentDeviceNode
;
2168 PUNICODE_STRING Service
;
2169 UNICODE_STRING ClassGUID
;
2170 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
2173 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2175 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2178 * We are called for the parent too, but we don't need to do special
2179 * handling for this node
2181 if (DeviceNode
== ParentDeviceNode
)
2183 DPRINT("Success\n");
2184 return STATUS_SUCCESS
;
2188 * Make sure this device node is a direct child of the parent device node
2189 * that is given as an argument
2191 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2193 /* Stop the traversal immediately and indicate successful operation */
2195 return STATUS_UNSUCCESSFUL
;
2198 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2200 WCHAR RegKeyBuffer
[MAX_PATH
];
2201 UNICODE_STRING RegKey
;
2204 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2205 RegKey
.Buffer
= RegKeyBuffer
;
2208 * Retrieve configuration from Enum key
2211 Service
= &DeviceNode
->ServiceName
;
2213 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2214 RtlInitUnicodeString(Service
, NULL
);
2215 RtlInitUnicodeString(&ClassGUID
, NULL
);
2217 QueryTable
[0].Name
= L
"Service";
2218 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2219 QueryTable
[0].EntryContext
= Service
;
2221 QueryTable
[1].Name
= L
"ClassGUID";
2222 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2223 QueryTable
[1].EntryContext
= &ClassGUID
;
2224 QueryTable
[1].DefaultType
= REG_SZ
;
2225 QueryTable
[1].DefaultData
= &NullString
;
2226 QueryTable
[1].DefaultLength
= 0;
2228 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2229 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2231 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2232 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2234 if (!NT_SUCCESS(Status
))
2236 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
2237 /* FIXME: Log the error */
2238 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
2239 DeviceNode
->InstancePath
.Buffer
, Status
);
2240 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2241 return STATUS_SUCCESS
;
2244 if (Service
->Buffer
== NULL
)
2246 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2248 if (ClassGUID
.Length
!= 0)
2250 /* Device has a ClassGUID value, but no Service value.
2251 * Suppose it is using the NULL driver, so state the
2252 * device is started */
2253 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2254 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2255 DeviceNode
->Flags
|= DN_STARTED
;
2257 return STATUS_SUCCESS
;
2260 DPRINT("Got Service %S\n", Service
->Buffer
);
2263 return STATUS_SUCCESS
;
2267 * IopActionInitChildServices
2269 * Initialize the service for all (direct) child nodes of a parent node
2273 * Pointer to device node.
2275 * Pointer to parent node to initialize child node services for.
2277 * Load only driver marked as boot start.
2280 * If the driver image for a service is not loaded and initialized
2281 * it is done here too. We only return a status code indicating an
2282 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2283 * not a direct child of the device node for which we initialize
2284 * child services for. Any errors that occur is logged instead so
2285 * that all child services have a chance of being initialized.
2289 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2291 BOOLEAN BootDrivers
)
2293 PDEVICE_NODE ParentDeviceNode
;
2296 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2299 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2302 * We are called for the parent too, but we don't need to do special
2303 * handling for this node
2305 if (DeviceNode
== ParentDeviceNode
)
2307 DPRINT("Success\n");
2308 return STATUS_SUCCESS
;
2312 * Make sure this device node is a direct child of the parent device node
2313 * that is given as an argument
2316 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2319 * Stop the traversal immediately and indicate unsuccessful operation
2322 return STATUS_UNSUCCESSFUL
;
2326 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2327 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2328 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2330 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2331 PDRIVER_OBJECT DriverObject
;
2333 /* FIXME: Remove this once the bug is fixed */
2334 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
2335 DPRINT1("Weird DeviceNode %p having ServiceName->Buffer==NULL. Probable stack corruption or memory overwrite.\n", DeviceNode
);
2337 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2338 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2340 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2342 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2343 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2344 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2348 /* get existing DriverObject pointer */
2349 Status
= IopGetDriverObject(
2351 &DeviceNode
->ServiceName
,
2354 if (NT_SUCCESS(Status
))
2356 /* Attach lower level filter drivers. */
2357 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2358 /* Initialize the function driver for the device node */
2359 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2360 if (NT_SUCCESS(Status
))
2362 /* Attach upper level filter drivers. */
2363 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2364 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2366 Status
= IopStartDevice(DeviceNode
);
2373 * Don't disable when trying to load only boot drivers
2377 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2378 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2379 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2380 CPRINT("Initialization of service %S failed (Status %x)\n",
2381 DeviceNode
->ServiceName
.Buffer
, Status
);
2386 DPRINT("Service %S is disabled or already initialized\n",
2387 DeviceNode
->ServiceName
.Buffer
);
2390 return STATUS_SUCCESS
;
2394 * IopActionInitAllServices
2396 * Initialize the service for all (direct) child nodes of a parent node. This
2397 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2401 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2404 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2408 * IopActionInitBootServices
2410 * Initialize the boot start services for all (direct) child nodes of a
2411 * parent node. This function just calls IopActionInitChildServices with
2412 * BootDrivers = TRUE.
2415 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2418 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2422 * IopInitializePnpServices
2424 * Initialize services for discovered children
2428 * Top device node to start initializing services.
2431 * When set to TRUE, only drivers marked as boot start will
2432 * be loaded. Otherwise, all drivers will be loaded.
2438 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2439 IN BOOLEAN BootDrivers
)
2441 DEVICETREE_TRAVERSE_CONTEXT Context
;
2443 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2447 IopInitDeviceTreeTraverseContext(
2450 IopActionInitBootServices
,
2455 IopInitDeviceTreeTraverseContext(
2458 IopActionInitAllServices
,
2462 return IopTraverseDeviceTree(&Context
);
2465 /* Invalidate device list enumerated by a device node.
2466 * The call can be make synchronous by defining the Event field
2467 * of the INVALIDATE_DEVICE_RELATION_DATA structure
2470 IopInvalidateDeviceRelations(
2471 IN PDEVICE_OBJECT DeviceObject
,
2472 IN PVOID InvalidateContext
) /* PINVALIDATE_DEVICE_RELATION_DATA */
2474 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
2475 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2476 PKEVENT Event
= Data
->Event
;
2477 DEVICETREE_TRAVERSE_CONTEXT Context
;
2478 PDEVICE_RELATIONS DeviceRelations
;
2479 IO_STATUS_BLOCK IoStatusBlock
;
2480 PDEVICE_NODE ChildDeviceNode
;
2481 IO_STACK_LOCATION Stack
;
2482 BOOLEAN BootDrivers
;
2483 OBJECT_ATTRIBUTES ObjectAttributes
;
2484 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
2489 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2491 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2493 Stack
.Parameters
.QueryDeviceRelations
.Type
= Data
->Type
;
2495 Status
= IopInitiatePnpIrp(
2498 IRP_MN_QUERY_DEVICE_RELATIONS
,
2500 if (!NT_SUCCESS(Status
))
2502 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2506 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2508 if (!DeviceRelations
|| DeviceRelations
->Count
<= 0)
2510 DPRINT("No PDOs\n");
2511 if (DeviceRelations
)
2513 ExFreePool(DeviceRelations
);
2515 Status
= STATUS_SUCCESS
;
2519 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2522 * Create device nodes for all discovered devices
2524 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2526 Status
= IopCreateDeviceNode(
2528 DeviceRelations
->Objects
[i
],
2530 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2531 if (!NT_SUCCESS(Status
))
2533 DPRINT("No resources\n");
2534 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2535 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2536 ExFreePool(DeviceRelations
);
2537 Status
= STATUS_NO_MEMORY
;
2541 ExFreePool(DeviceRelations
);
2544 * Retrieve information about all discovered children from the bus driver
2546 IopInitDeviceTreeTraverseContext(
2549 IopActionInterrogateDeviceStack
,
2552 Status
= IopTraverseDeviceTree(&Context
);
2553 if (!NT_SUCCESS(Status
))
2555 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2560 * Retrieve configuration from the registry for discovered children
2562 IopInitDeviceTreeTraverseContext(
2565 IopActionConfigureChildServices
,
2568 Status
= IopTraverseDeviceTree(&Context
);
2569 if (!NT_SUCCESS(Status
))
2571 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2576 * Get the state of the system boot. If the \\SystemRoot link isn't
2577 * created yet, we will assume that it's possible to load only boot
2580 InitializeObjectAttributes(
2586 Status
= ZwOpenFile(
2593 if (NT_SUCCESS(Status
))
2595 BootDrivers
= FALSE
;
2602 * Initialize services for discovered children. Only boot drivers will
2603 * be loaded from boot driver!
2605 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2606 if (!NT_SUCCESS(Status
))
2608 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2612 DPRINT("IopInvalidateDeviceRelations() finished\n");
2613 Status
= STATUS_SUCCESS
;
2616 IoFreeWorkItem(Data
->WorkItem
);
2619 Data
->Status
= Status
;
2620 KeSetEvent(Event
, 0, FALSE
);
2626 static NTSTATUS INIT_FUNCTION
2627 IopEnumerateDetectedDevices(
2629 IN PUNICODE_STRING RelativePath
,
2631 IN BOOLEAN EnumerateSubKeys
,
2632 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2633 IN ULONG ParentBootResourcesLength
)
2635 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2636 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2637 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2638 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2639 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2640 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2641 OBJECT_ATTRIBUTES ObjectAttributes
;
2642 HANDLE hDevicesKey
= NULL
;
2643 HANDLE hDeviceKey
= NULL
;
2644 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2645 UNICODE_STRING Level2NameU
;
2646 WCHAR Level2Name
[5];
2647 ULONG IndexDevice
= 0;
2649 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2650 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2651 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2652 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2653 UNICODE_STRING DeviceName
, ValueName
;
2655 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2656 ULONG BootResourcesLength
;
2659 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI BIOS");
2660 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2661 static ULONG DeviceIndexPci
= 0;
2662 /*const UNICODE_STRING IdentifierAcpi = RTL_CONSTANT_STRING(L"ACPI BIOS");
2663 UNICODE_STRING HardwareIdAcpi = RTL_CONSTANT_STRING(L"*PNP0C08\0");
2664 static ULONG DeviceIndexAcpi = 0;*/
2665 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2666 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2667 static ULONG DeviceIndexSerial
= 0;
2668 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2669 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2670 static ULONG DeviceIndexKeyboard
= 0;
2671 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2672 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2673 static ULONG DeviceIndexMouse
= 0;
2674 PUNICODE_STRING pHardwareId
;
2675 ULONG DeviceIndex
= 0;
2677 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2678 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2679 if (!NT_SUCCESS(Status
))
2681 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2685 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2686 if (!pDeviceInformation
)
2688 DPRINT("ExAllocatePool() failed\n");
2689 Status
= STATUS_NO_MEMORY
;
2693 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2694 if (!pValueInformation
)
2696 DPRINT("ExAllocatePool() failed\n");
2697 Status
= STATUS_NO_MEMORY
;
2703 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2704 if (Status
== STATUS_NO_MORE_ENTRIES
)
2706 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2708 ExFreePool(pDeviceInformation
);
2709 DeviceInfoLength
= RequiredSize
;
2710 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2711 if (!pDeviceInformation
)
2713 DPRINT("ExAllocatePool() failed\n");
2714 Status
= STATUS_NO_MEMORY
;
2717 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2719 if (!NT_SUCCESS(Status
))
2721 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2726 /* Open device key */
2727 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2728 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2729 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2732 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0),
2734 if (!NT_SUCCESS(Status
))
2736 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2740 /* Read boot resources, and add then to parent ones */
2741 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, 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 ZwDeleteKey(hLevel2Key
);
2751 Status
= STATUS_NO_MEMORY
;
2754 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2756 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2758 BootResources
= ParentBootResources
;
2759 BootResourcesLength
= ParentBootResourcesLength
;
2761 else if (!NT_SUCCESS(Status
))
2763 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2766 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2768 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2771 else if (((PCM_FULL_RESOURCE_DESCRIPTOR
)pValueInformation
->Data
)->PartialResourceList
.Count
== 0)
2773 BootResources
= ParentBootResources
;
2774 BootResourcesLength
= ParentBootResourcesLength
;
2778 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2780 /* Concatenate current resources and parent ones */
2781 if (ParentBootResourcesLength
== 0)
2782 BootResourcesLength
= pValueInformation
->DataLength
;
2784 BootResourcesLength
= ParentBootResourcesLength
2785 + pValueInformation
->DataLength
2787 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2790 DPRINT("ExAllocatePool() failed\n");
2793 if (ParentBootResourcesLength
== 0)
2795 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2797 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2799 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2801 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2802 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2803 ParentBootResourcesLength
- Header
);
2804 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2808 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2810 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2811 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2812 ParentBootResourcesLength
- Header
);
2814 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2815 pValueInformation
->Data
+ Header
,
2816 pValueInformation
->DataLength
- Header
);
2817 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2821 if (EnumerateSubKeys
)
2826 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2827 if (Status
== STATUS_NO_MORE_ENTRIES
)
2829 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2831 ExFreePool(pDeviceInformation
);
2832 DeviceInfoLength
= RequiredSize
;
2833 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2834 if (!pDeviceInformation
)
2836 DPRINT("ExAllocatePool() failed\n");
2837 Status
= STATUS_NO_MEMORY
;
2840 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2842 if (!NT_SUCCESS(Status
))
2844 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2848 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2849 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2851 Status
= IopEnumerateDetectedDevices(
2857 BootResourcesLength
);
2858 if (!NT_SUCCESS(Status
))
2863 /* Read identifier */
2864 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2865 if (Status
== STATUS_BUFFER_OVERFLOW
)
2867 ExFreePool(pValueInformation
);
2868 ValueInfoLength
= RequiredSize
;
2869 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2870 if (!pValueInformation
)
2872 DPRINT("ExAllocatePool() failed\n");
2873 Status
= STATUS_NO_MEMORY
;
2876 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2878 if (!NT_SUCCESS(Status
))
2880 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2882 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2886 else if (pValueInformation
->Type
!= REG_SZ
)
2888 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2893 /* Assign hardware id to this device */
2894 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2895 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2896 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2897 ValueName
.Length
-= sizeof(WCHAR
);
2900 if (RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2902 pHardwareId
= &HardwareIdSerial
;
2903 DeviceIndex
= DeviceIndexSerial
++;
2905 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2907 pHardwareId
= &HardwareIdKeyboard
;
2908 DeviceIndex
= DeviceIndexKeyboard
++;
2910 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2912 pHardwareId
= &HardwareIdMouse
;
2913 DeviceIndex
= DeviceIndexMouse
++;
2915 else if (NT_SUCCESS(Status
))
2917 /* Try to also match the device identifier */
2918 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2920 pHardwareId
= &HardwareIdPci
;
2921 DeviceIndex
= DeviceIndexPci
++;
2923 /*else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0)
2925 pHardwareId = &HardwareIdAcpi;
2926 DeviceIndex = DeviceIndexAcpi++;
2930 /* Unknown device */
2931 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2937 /* Unknown key path */
2938 DPRINT("Unknown key path %wZ\n", RelativePath
);
2942 /* Add the detected device to Root key */
2943 InitializeObjectAttributes(&ObjectAttributes
, pHardwareId
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2944 Status
= ZwCreateKey(
2950 REG_OPTION_NON_VOLATILE
,
2952 if (!NT_SUCCESS(Status
))
2954 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2957 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2958 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2959 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2960 Status
= ZwCreateKey(
2962 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2966 REG_OPTION_NON_VOLATILE
,
2968 ZwClose(hLevel1Key
);
2969 if (!NT_SUCCESS(Status
))
2971 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2974 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, pHardwareId
);
2975 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
2976 if (!NT_SUCCESS(Status
))
2978 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2979 ZwDeleteKey(hLevel2Key
);
2982 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
2983 if (!NT_SUCCESS(Status
))
2985 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
2986 ZwDeleteKey(hLevel2Key
);
2989 if (BootResourcesLength
> 0)
2991 /* Save boot resources to 'LogConf\BootConfig' */
2992 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
2993 Status
= ZwCreateKey(
2999 REG_OPTION_VOLATILE
,
3001 if (!NT_SUCCESS(Status
))
3003 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3004 ZwDeleteKey(hLevel2Key
);
3007 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
3009 if (!NT_SUCCESS(Status
))
3011 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3012 ZwDeleteKey(hLevel2Key
);
3018 if (BootResources
&& BootResources
!= ParentBootResources
)
3019 ExFreePool(BootResources
);
3022 ZwClose(hLevel2Key
);
3027 ZwClose(hDeviceKey
);
3032 Status
= STATUS_SUCCESS
;
3036 ZwClose(hDevicesKey
);
3038 ZwClose(hDeviceKey
);
3039 if (pDeviceInformation
)
3040 ExFreePool(pDeviceInformation
);
3041 if (pValueInformation
)
3042 ExFreePool(pValueInformation
);
3046 static BOOLEAN INIT_FUNCTION
3047 IopIsAcpiComputer(VOID
)
3051 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3052 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3053 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3054 OBJECT_ATTRIBUTES ObjectAttributes
;
3055 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3056 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3057 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3058 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3060 ULONG IndexDevice
= 0;
3061 UNICODE_STRING DeviceName
, ValueName
;
3062 HANDLE hDevicesKey
= NULL
;
3063 HANDLE hDeviceKey
= NULL
;
3065 BOOLEAN ret
= FALSE
;
3067 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3068 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3069 if (!NT_SUCCESS(Status
))
3071 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3075 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3076 if (!pDeviceInformation
)
3078 DPRINT("ExAllocatePool() failed\n");
3079 Status
= STATUS_NO_MEMORY
;
3083 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3084 if (!pDeviceInformation
)
3086 DPRINT("ExAllocatePool() failed\n");
3087 Status
= STATUS_NO_MEMORY
;
3093 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3094 if (Status
== STATUS_NO_MORE_ENTRIES
)
3096 else if (Status
== STATUS_BUFFER_OVERFLOW
)
3098 ExFreePool(pDeviceInformation
);
3099 DeviceInfoLength
= RequiredSize
;
3100 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3101 if (!pDeviceInformation
)
3103 DPRINT("ExAllocatePool() failed\n");
3104 Status
= STATUS_NO_MEMORY
;
3107 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3109 if (!NT_SUCCESS(Status
))
3111 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3116 /* Open device key */
3117 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3118 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3119 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3124 if (!NT_SUCCESS(Status
))
3126 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3130 /* Read identifier */
3131 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3132 if (Status
== STATUS_BUFFER_OVERFLOW
)
3134 ExFreePool(pValueInformation
);
3135 ValueInfoLength
= RequiredSize
;
3136 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3137 if (!pValueInformation
)
3139 DPRINT("ExAllocatePool() failed\n");
3140 Status
= STATUS_NO_MEMORY
;
3143 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3145 if (!NT_SUCCESS(Status
))
3147 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3150 else if (pValueInformation
->Type
!= REG_SZ
)
3152 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3156 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3157 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3158 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3159 ValueName
.Length
-= sizeof(WCHAR
);
3160 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3162 DPRINT("Found ACPI BIOS\n");
3168 ZwClose(hDeviceKey
);
3173 if (pDeviceInformation
)
3174 ExFreePool(pDeviceInformation
);
3175 if (pValueInformation
)
3176 ExFreePool(pValueInformation
);
3178 ZwClose(hDevicesKey
);
3180 ZwClose(hDeviceKey
);
3185 static NTSTATUS INIT_FUNCTION
3186 IopUpdateRootKey(VOID
)
3188 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum\\Root");
3189 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3190 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3191 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3192 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3193 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3194 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3195 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3196 OBJECT_ATTRIBUTES ObjectAttributes
;
3197 HANDLE hRoot
, hHalAcpiDevice
, hHalAcpiId
;
3200 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3201 Status
= ZwOpenKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
);
3202 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3204 /* We are probably in 1st stage */
3205 return STATUS_SUCCESS
;
3207 else if (!NT_SUCCESS(Status
))
3209 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3213 if (IopIsAcpiComputer())
3215 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3216 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3218 if (!NT_SUCCESS(Status
))
3220 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3221 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3222 ZwClose(hHalAcpiDevice
);
3223 if (!NT_SUCCESS(Status
))
3225 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3226 if (NT_SUCCESS(Status
))
3227 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3228 ZwClose(hHalAcpiId
);
3233 Status
= IopEnumerateDetectedDevices(
3251 DPRINT("PnpInit()\n");
3253 KeInitializeSpinLock(&IopDeviceTreeLock
);
3255 /* Initialize the Bus Type GUID List */
3256 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3257 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3258 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3260 /* Initialize PnP-Event notification support */
3261 Status
= IopInitPlugPlayEvents();
3262 if (!NT_SUCCESS(Status
))
3264 CPRINT("IopInitPlugPlayEvents() failed\n");
3265 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3269 * Create root device node
3272 Status
= IopCreateDriverObject(&IopRootDriverObject
, NULL
, 0, FALSE
, NULL
, 0);
3273 if (!NT_SUCCESS(Status
))
3275 CPRINT("IoCreateDriverObject() failed\n");
3276 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3279 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3281 if (!NT_SUCCESS(Status
))
3283 CPRINT("IoCreateDevice() failed\n");
3284 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3287 Status
= IopCreateDeviceNode(NULL
, Pdo
, &IopRootDeviceNode
);
3288 if (!NT_SUCCESS(Status
))
3290 CPRINT("Insufficient resources\n");
3291 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3294 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3297 CPRINT("Failed to create the instance path!\n");
3298 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3301 /* Report the device to the user-mode pnp manager */
3302 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3303 &IopRootDeviceNode
->InstancePath
);
3305 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3306 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3307 IopRootDriverObject
->DriverExtension
->AddDevice(
3308 IopRootDriverObject
,
3309 IopRootDeviceNode
->PhysicalDeviceObject
);
3311 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3312 Status
= IopUpdateRootKey();
3313 if (!NT_SUCCESS(Status
))
3315 CPRINT("IopUpdateRootKey() failed\n");
3316 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);