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
;
22 ERESOURCE PpRegistryDeviceResource
;
23 KGUARDED_MUTEX PpDeviceReferenceTableLock
;
24 RTL_AVL_TABLE PpDeviceReferenceTable
;
26 extern ULONG ExpInitializationPhase
;
28 /* DATA **********************************************************************/
30 PDRIVER_OBJECT IopRootDriverObject
;
31 PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList
= NULL
;
33 #if defined (ALLOC_PRAGMA)
34 #pragma alloc_text(INIT, PnpInit)
35 #pragma alloc_text(INIT, PnpInit2)
38 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
40 DEVICE_RELATION_TYPE Type
;
41 PIO_WORKITEM WorkItem
;
44 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
47 IopInvalidateDeviceRelations(
48 IN PDEVICE_OBJECT DeviceObject
,
49 IN PVOID InvalidateContext
);
53 IoSynchronousInvalidateDeviceRelations(
54 IN PDEVICE_OBJECT DeviceObject
,
55 IN DEVICE_RELATION_TYPE Type
);
58 /* FUNCTIONS *****************************************************************/
61 IopAssignDeviceResources(
62 IN PDEVICE_NODE DeviceNode
,
63 OUT ULONG
*pRequiredSize
);
65 IopTranslateDeviceResources(
66 IN PDEVICE_NODE DeviceNode
,
67 IN ULONG RequiredSize
);
71 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
73 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
78 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
79 PDRIVER_OBJECT DriverObject
)
83 BOOLEAN IsPnpDriver
= FALSE
;
85 if (DriverObject
->DriverExtension
->AddDevice
)
87 /* This is a Plug and Play driver */
88 DPRINT("Plug and Play driver found\n");
90 ASSERT(DeviceNode
->PhysicalDeviceObject
);
92 DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
93 DriverObject
->DriverExtension
->AddDevice
);
95 IsPnpDriver
= !IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
);
96 Status
= DriverObject
->DriverExtension
->AddDevice(
97 DriverObject
, IsPnpDriver
? DeviceNode
->PhysicalDeviceObject
: NULL
);
99 if (!NT_SUCCESS(Status
))
106 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
108 if (Fdo
== DeviceNode
->PhysicalDeviceObject
)
110 /* FIXME: What do we do? Unload the driver or just disable the device? */
111 DbgPrint("An FDO was not attached\n");
112 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
113 return STATUS_UNSUCCESSFUL
;
116 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
118 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
120 /* There can be only one system power device */
121 if (!SystemPowerDeviceNodeCreated
)
123 PopSystemPowerDeviceNode
= DeviceNode
;
124 SystemPowerDeviceNodeCreated
= TRUE
;
128 ObDereferenceObject(Fdo
);
131 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
132 IopDeviceNodeSetFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
135 return STATUS_SUCCESS
;
140 PDEVICE_NODE DeviceNode
)
142 IO_STATUS_BLOCK IoStatusBlock
;
143 IO_STACK_LOCATION Stack
;
144 ULONG RequiredLength
;
148 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
150 IopDeviceNodeSetFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
151 DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
152 Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
= DeviceNode
->ResourceRequirements
;
153 Status
= IopInitiatePnpIrp(
156 IRP_MN_FILTER_RESOURCE_REQUIREMENTS
,
158 /* FIXME: Take care of return code */
159 if (!NT_SUCCESS(Status
))
161 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
164 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
165 if (NT_SUCCESS(Status
))
167 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
168 if (NT_SUCCESS(Status
))
170 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
174 DPRINT("IopTranslateDeviceResources() failed (Status 0x08lx)\n", Status
);
179 DPRINT("IopAssignDeviceResources() failed (Status 0x08lx)\n", Status
);
181 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
183 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
184 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
185 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
188 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and
189 * actually _depend_ on this!. This is because NT will lock the Device Node
190 * with an ERESOURCE, which of course requires APCs to be disabled.
192 KeEnterCriticalRegion();
194 Status
= IopInitiatePnpIrp(
200 KeLeaveCriticalRegion();
202 if (!NT_SUCCESS(Status
))
204 DPRINT("IopInitiatePnpIrp() failed\n");
208 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
210 DPRINT("Device needs enumeration, invalidating bus relations\n");
211 /* Invalidate device relations synchronously
212 (otherwise there will be dirty read of DeviceNode) */
213 IoSynchronousInvalidateDeviceRelations(DeviceNode
->PhysicalDeviceObject
, BusRelations
);
214 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
218 ObDereferenceObject(Fdo
);
220 if (NT_SUCCESS(Status
))
221 DeviceNode
->Flags
|= DN_STARTED
;
228 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
229 PDEVICE_CAPABILITIES DeviceCaps
)
231 IO_STATUS_BLOCK StatusBlock
;
232 IO_STACK_LOCATION Stack
;
234 /* Set up the Header */
235 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
236 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
237 DeviceCaps
->Version
= 1;
238 DeviceCaps
->Address
= -1;
239 DeviceCaps
->UINumber
= -1;
241 /* Set up the Stack */
242 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
243 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
246 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
248 IRP_MN_QUERY_CAPABILITIES
,
257 IoInvalidateDeviceRelations(
258 IN PDEVICE_OBJECT DeviceObject
,
259 IN DEVICE_RELATION_TYPE Type
)
261 PIO_WORKITEM WorkItem
;
262 PINVALIDATE_DEVICE_RELATION_DATA Data
;
264 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
267 WorkItem
= IoAllocateWorkItem(DeviceObject
);
275 Data
->WorkItem
= WorkItem
;
280 IopInvalidateDeviceRelations
,
290 IoSynchronousInvalidateDeviceRelations(
291 IN PDEVICE_OBJECT DeviceObject
,
292 IN DEVICE_RELATION_TYPE Type
)
294 PIO_WORKITEM WorkItem
;
295 PINVALIDATE_DEVICE_RELATION_DATA Data
;
298 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
301 WorkItem
= IoAllocateWorkItem(DeviceObject
);
308 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
310 Data
->WorkItem
= WorkItem
;
311 Data
->Event
= &Event
;
315 IopInvalidateDeviceRelations
,
319 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
328 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
329 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
330 IN ULONG BufferLength
,
331 OUT PVOID PropertyBuffer
,
332 OUT PULONG ResultLength
)
334 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
335 DEVICE_CAPABILITIES DeviceCaps
;
341 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
343 if (DeviceNode
== NULL
)
344 return STATUS_INVALID_DEVICE_REQUEST
;
346 switch (DeviceProperty
)
348 case DevicePropertyBusNumber
:
349 Length
= sizeof(ULONG
);
350 Data
= &DeviceNode
->ChildBusNumber
;
353 /* Complete, untested */
354 case DevicePropertyBusTypeGuid
:
356 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
357 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
359 /* Return the GUID */
360 *ResultLength
= sizeof(GUID
);
362 /* Check if the buffer given was large enough */
363 if (BufferLength
< *ResultLength
)
365 return STATUS_BUFFER_TOO_SMALL
;
369 RtlCopyMemory(PropertyBuffer
,
370 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
372 return STATUS_SUCCESS
;
376 return STATUS_OBJECT_NAME_NOT_FOUND
;
380 case DevicePropertyLegacyBusType
:
381 Length
= sizeof(INTERFACE_TYPE
);
382 Data
= &DeviceNode
->ChildInterfaceType
;
385 case DevicePropertyAddress
:
386 /* Query the device caps */
387 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
388 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
391 *ResultLength
= sizeof(ULONG
);
393 /* Check if the buffer given was large enough */
394 if (BufferLength
< *ResultLength
)
396 return STATUS_BUFFER_TOO_SMALL
;
400 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
401 return STATUS_SUCCESS
;
405 return STATUS_OBJECT_NAME_NOT_FOUND
;
409 // case DevicePropertyUINumber:
410 // if (DeviceNode->CapabilityFlags == NULL)
411 // return STATUS_INVALID_DEVICE_REQUEST;
412 // Length = sizeof(ULONG);
413 // Data = &DeviceNode->CapabilityFlags->UINumber;
416 case DevicePropertyClassName
:
417 case DevicePropertyClassGuid
:
418 case DevicePropertyDriverKeyName
:
419 case DevicePropertyManufacturer
:
420 case DevicePropertyFriendlyName
:
421 case DevicePropertyHardwareID
:
422 case DevicePropertyCompatibleIDs
:
423 case DevicePropertyDeviceDescription
:
424 case DevicePropertyLocationInformation
:
425 case DevicePropertyUINumber
:
427 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
428 UNICODE_STRING KeyName
, ValueName
;
429 OBJECT_ATTRIBUTES ObjectAttributes
;
430 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
431 ULONG ValueInformationLength
;
435 switch (DeviceProperty
)
437 case DevicePropertyClassName
:
438 RegistryPropertyName
= L
"Class"; break;
439 case DevicePropertyClassGuid
:
440 RegistryPropertyName
= L
"ClassGuid"; break;
441 case DevicePropertyDriverKeyName
:
442 RegistryPropertyName
= L
"Driver"; break;
443 case DevicePropertyManufacturer
:
444 RegistryPropertyName
= L
"Mfg"; break;
445 case DevicePropertyFriendlyName
:
446 RegistryPropertyName
= L
"FriendlyName"; break;
447 case DevicePropertyHardwareID
:
448 RegistryPropertyName
= L
"HardwareID"; break;
449 case DevicePropertyCompatibleIDs
:
450 RegistryPropertyName
= L
"CompatibleIDs"; break;
451 case DevicePropertyDeviceDescription
:
452 RegistryPropertyName
= L
"DeviceDesc"; break;
453 case DevicePropertyLocationInformation
:
454 RegistryPropertyName
= L
"LocationInformation"; break;
455 case DevicePropertyUINumber
:
456 RegistryPropertyName
= L
"UINumber"; break;
458 RegistryPropertyName
= NULL
; break;
461 KeyNameBuffer
= ExAllocatePool(PagedPool
,
462 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
464 DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer
, RegistryPropertyName
);
466 if (KeyNameBuffer
== NULL
)
467 return STATUS_INSUFFICIENT_RESOURCES
;
469 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
470 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
471 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
472 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
473 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
475 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
476 ExFreePool(KeyNameBuffer
);
477 if (!NT_SUCCESS(Status
))
480 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
481 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
482 Data
[0]) + BufferLength
;
483 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
484 if (ValueInformation
== NULL
)
487 return STATUS_INSUFFICIENT_RESOURCES
;
490 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
491 KeyValuePartialInformation
, ValueInformation
,
492 ValueInformationLength
,
493 &ValueInformationLength
);
494 *ResultLength
= ValueInformation
->DataLength
;
497 if (!NT_SUCCESS(Status
))
499 ExFreePool(ValueInformation
);
500 if (Status
== STATUS_BUFFER_OVERFLOW
)
501 return STATUS_BUFFER_TOO_SMALL
;
506 /* FIXME: Verify the value (NULL-terminated, correct format). */
508 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
509 ValueInformation
->DataLength
);
510 ExFreePool(ValueInformation
);
512 return STATUS_SUCCESS
;
515 case DevicePropertyBootConfiguration
:
517 if (DeviceNode
->BootResources
->Count
!= 0)
519 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
521 Data
= &DeviceNode
->BootResources
;
524 /* FIXME: use a translated boot configuration instead */
525 case DevicePropertyBootConfigurationTranslated
:
527 if (DeviceNode
->BootResources
->Count
!= 0)
529 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
531 Data
= &DeviceNode
->BootResources
;
534 case DevicePropertyEnumeratorName
:
535 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
538 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
539 Data
= DeviceNode
->InstancePath
.Buffer
;
548 case DevicePropertyPhysicalDeviceObjectName
:
549 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
550 Data
= DeviceNode
->InstancePath
.Buffer
;
554 return STATUS_INVALID_PARAMETER_2
;
557 *ResultLength
= Length
;
558 if (BufferLength
< Length
)
559 return STATUS_BUFFER_TOO_SMALL
;
560 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
562 /* Terminate the string */
563 if (DeviceProperty
== DevicePropertyEnumeratorName
564 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
566 Ptr
= (PWSTR
)PropertyBuffer
;
567 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
570 return STATUS_SUCCESS
;
578 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
584 * @name IoOpenDeviceRegistryKey
586 * Open a registry key unique for a specified driver or device instance.
588 * @param DeviceObject Device to get the registry key for.
589 * @param DevInstKeyType Type of the key to return.
590 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
591 * @param DevInstRegKey Handle to the opened registry key on
600 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
601 IN ULONG DevInstKeyType
,
602 IN ACCESS_MASK DesiredAccess
,
603 OUT PHANDLE DevInstRegKey
)
605 static WCHAR RootKeyName
[] =
606 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
607 static WCHAR ProfileKeyName
[] =
608 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
609 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
610 static WCHAR EnumKeyName
[] = L
"Enum\\";
611 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
613 LPWSTR KeyNameBuffer
;
614 UNICODE_STRING KeyName
;
615 ULONG DriverKeyLength
;
616 OBJECT_ATTRIBUTES ObjectAttributes
;
617 PDEVICE_NODE DeviceNode
= NULL
;
620 DPRINT("IoOpenDeviceRegistryKey() called\n");
622 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
624 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
625 return STATUS_INVALID_PARAMETER
;
629 * Calculate the length of the base key name. This is the full
630 * name for driver key or the name excluding "Device Parameters"
631 * subkey for device key.
634 KeyNameLength
= sizeof(RootKeyName
);
635 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
636 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
637 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
639 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
640 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
641 0, NULL
, &DriverKeyLength
);
642 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
644 KeyNameLength
+= DriverKeyLength
;
648 DeviceNode
= IopGetDeviceNode(DeviceObject
);
649 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
650 DeviceNode
->InstancePath
.Length
;
654 * Now allocate the buffer for the key name...
657 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
658 if (KeyNameBuffer
== NULL
)
659 return STATUS_INSUFFICIENT_RESOURCES
;
662 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
663 KeyName
.Buffer
= KeyNameBuffer
;
666 * ...and build the key name.
669 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
670 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
672 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
673 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
675 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
677 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
678 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
679 DriverKeyLength
, KeyNameBuffer
+
680 (KeyName
.Length
/ sizeof(WCHAR
)),
682 if (!NT_SUCCESS(Status
))
684 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
685 ExFreePool(KeyNameBuffer
);
688 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
692 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
693 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
694 if (DeviceNode
->InstancePath
.Length
== 0)
696 ExFreePool(KeyNameBuffer
);
705 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
706 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
707 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
708 if (!NT_SUCCESS(Status
))
710 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
711 ExFreePool(KeyNameBuffer
);
714 ExFreePool(KeyNameBuffer
);
717 * For driver key we're done now.
720 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
724 * Let's go further. For device key we must open "Device Parameters"
725 * subkey and create it if it doesn't exist yet.
728 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
729 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
730 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
731 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
732 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
733 ZwClose(ObjectAttributes
.RootDirectory
);
743 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
750 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
754 if (PopSystemPowerDeviceNode
)
756 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
757 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
758 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
760 return STATUS_SUCCESS
;
763 return STATUS_UNSUCCESSFUL
;
768 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
770 USHORT i
= 0, FoundIndex
= 0xFFFF;
774 /* Acquire the lock */
775 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
777 /* Loop all entries */
778 while (i
< IopBusTypeGuidList
->GuidCount
)
780 /* Try to find a match */
781 if (RtlCompareMemory(BusTypeGuid
,
782 &IopBusTypeGuidList
->Guids
[i
],
783 sizeof(GUID
)) == sizeof(GUID
))
792 /* Check if we have to grow the list */
793 if (IopBusTypeGuidList
->GuidCount
)
795 /* Calculate the new size */
796 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
797 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
799 /* Allocate the new copy */
800 NewList
= ExAllocatePool(PagedPool
, NewSize
);
802 /* Now copy them, decrease the size too */
803 NewSize
-= sizeof(GUID
);
804 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
806 /* Free the old list */
807 ExFreePool(IopBusTypeGuidList
);
809 /* Use the new buffer */
810 IopBusTypeGuidList
= NewList
;
813 /* Copy the new GUID */
814 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
818 /* The new entry is the index */
819 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
820 IopBusTypeGuidList
->GuidCount
++;
823 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
829 * Creates a device node
832 * ParentNode = Pointer to parent device node
833 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
834 * to have the root device node create one
835 * (eg. for legacy drivers)
836 * DeviceNode = Pointer to storage for created device node
842 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
843 PDEVICE_OBJECT PhysicalDeviceObject
,
844 PUNICODE_STRING ServiceName
,
845 PDEVICE_NODE
*DeviceNode
)
851 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
852 ParentNode
, PhysicalDeviceObject
, ServiceName
);
854 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
857 return STATUS_INSUFFICIENT_RESOURCES
;
860 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
862 if (!PhysicalDeviceObject
)
864 Status
= PnpRootCreateDevice(ServiceName
, &PhysicalDeviceObject
);
865 if (!NT_SUCCESS(Status
))
871 /* This is for drivers passed on the command line to ntoskrnl.exe */
872 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
873 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
876 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
878 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
882 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
883 Node
->Parent
= ParentNode
;
884 Node
->NextSibling
= ParentNode
->Child
;
885 if (ParentNode
->Child
!= NULL
)
887 ParentNode
->Child
->PrevSibling
= Node
;
889 ParentNode
->Child
= Node
;
890 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
891 Node
->Level
= ParentNode
->Level
+ 1;
896 return STATUS_SUCCESS
;
900 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
904 /* All children must be deleted before a parent is deleted */
905 ASSERT(!DeviceNode
->Child
);
907 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
909 ASSERT(DeviceNode
->PhysicalDeviceObject
);
911 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
913 /* Unlink from parent if it exists */
915 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
917 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
920 /* Unlink from sibling list */
922 if (DeviceNode
->PrevSibling
)
924 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
927 if (DeviceNode
->NextSibling
)
929 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
932 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
934 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
936 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
938 if (DeviceNode
->ResourceList
)
940 ExFreePool(DeviceNode
->ResourceList
);
943 if (DeviceNode
->ResourceListTranslated
)
945 ExFreePool(DeviceNode
->ResourceListTranslated
);
948 if (DeviceNode
->ResourceRequirements
)
950 ExFreePool(DeviceNode
->ResourceRequirements
);
953 if (DeviceNode
->BootResources
)
955 ExFreePool(DeviceNode
->BootResources
);
958 ExFreePool(DeviceNode
);
960 return STATUS_SUCCESS
;
964 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
965 PIO_STATUS_BLOCK IoStatusBlock
,
967 PIO_STACK_LOCATION Stack OPTIONAL
)
969 PDEVICE_OBJECT TopDeviceObject
;
970 PIO_STACK_LOCATION IrpSp
;
975 /* Always call the top of the device stack */
976 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
983 Irp
= IoBuildSynchronousFsdRequest(
992 /* PNP IRPs are always initialized with a status code of
993 STATUS_NOT_IMPLEMENTED */
994 Irp
->IoStatus
.Status
= MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
? STATUS_SUCCESS
: STATUS_NOT_IMPLEMENTED
; // hpoussin's hack of doom
995 Irp
->IoStatus
.Information
= 0;
997 IrpSp
= IoGetNextIrpStackLocation(Irp
);
998 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
1002 RtlCopyMemory(&IrpSp
->Parameters
,
1004 sizeof(Stack
->Parameters
));
1007 Status
= IoCallDriver(TopDeviceObject
, Irp
);
1008 if (Status
== STATUS_PENDING
)
1010 KeWaitForSingleObject(&Event
,
1015 Status
= IoStatusBlock
->Status
;
1018 ObDereferenceObject(TopDeviceObject
);
1025 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1027 PDEVICE_NODE ParentDeviceNode
;
1028 PDEVICE_NODE ChildDeviceNode
;
1031 /* Copy context data so we don't overwrite it in subsequent calls to this function */
1032 ParentDeviceNode
= Context
->DeviceNode
;
1034 /* Call the action routine */
1035 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
1036 if (!NT_SUCCESS(Status
))
1041 /* Traversal of all children nodes */
1042 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
1043 ChildDeviceNode
!= NULL
;
1044 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
1046 /* Pass the current device node to the action routine */
1047 Context
->DeviceNode
= ChildDeviceNode
;
1049 Status
= IopTraverseDeviceTreeNode(Context
);
1050 if (!NT_SUCCESS(Status
))
1061 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1065 DPRINT("Context 0x%p\n", Context
);
1067 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1068 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1070 /* Start from the specified device node */
1071 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1073 /* Recursively traverse the device tree */
1074 Status
= IopTraverseDeviceTreeNode(Context
);
1075 if (Status
== STATUS_UNSUCCESSFUL
)
1077 /* The action routine just wanted to terminate the traversal with status
1078 code STATUS_SUCCESS */
1079 Status
= STATUS_SUCCESS
;
1088 IopCreateDeviceKeyPath(PWSTR Path
,
1091 OBJECT_ATTRIBUTES ObjectAttributes
;
1092 WCHAR KeyBuffer
[MAX_PATH
];
1093 UNICODE_STRING KeyName
;
1101 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
1103 return STATUS_INVALID_PARAMETER
;
1106 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
1108 /* Skip \\Registry\\ */
1109 Current
= KeyBuffer
;
1110 Current
= wcschr (Current
, L
'\\') + 1;
1111 Current
= wcschr (Current
, L
'\\') + 1;
1115 Next
= wcschr (Current
, L
'\\');
1125 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
1126 InitializeObjectAttributes (&ObjectAttributes
,
1128 OBJ_CASE_INSENSITIVE
,
1132 DPRINT("Create '%S'\n", KeyName
.Buffer
);
1134 Status
= ZwCreateKey (&KeyHandle
,
1141 if (!NT_SUCCESS (Status
))
1143 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
1149 *Handle
= KeyHandle
;
1150 return STATUS_SUCCESS
;
1154 ZwClose (KeyHandle
);
1161 return STATUS_UNSUCCESSFUL
;
1167 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1168 PDEVICE_NODE DeviceNode
)
1170 OBJECT_ATTRIBUTES ObjectAttributes
;
1171 UNICODE_STRING KeyName
;
1174 ULONG ListSize
, ResultLength
;
1177 DPRINT("IopSetDeviceInstanceData() called\n");
1179 /* Create the 'LogConf' key */
1180 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1181 InitializeObjectAttributes(&ObjectAttributes
,
1183 OBJ_CASE_INSENSITIVE
,
1186 Status
= ZwCreateKey(&LogConfKey
,
1193 if (NT_SUCCESS(Status
))
1195 /* Set 'BootConfig' value */
1196 if (DeviceNode
->BootResources
!= NULL
)
1198 ResCount
= DeviceNode
->BootResources
->Count
;
1201 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1203 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1204 Status
= ZwSetValueKey(LogConfKey
,
1208 &DeviceNode
->BootResources
,
1213 /* Set 'BasicConfigVector' value */
1214 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1215 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1217 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1218 Status
= ZwSetValueKey(LogConfKey
,
1221 REG_RESOURCE_REQUIREMENTS_LIST
,
1222 DeviceNode
->ResourceRequirements
,
1223 DeviceNode
->ResourceRequirements
->ListSize
);
1226 ZwClose(LogConfKey
);
1229 /* Set the 'ConfigFlags' value */
1230 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1231 Status
= ZwQueryValueKey(InstanceKey
,
1233 KeyValueBasicInformation
,
1237 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1239 /* Write the default value */
1240 ULONG DefaultConfigFlags
= 0;
1241 Status
= ZwSetValueKey(InstanceKey
,
1245 &DefaultConfigFlags
,
1246 sizeof(DefaultConfigFlags
));
1250 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1252 /* Create the 'Control' key */
1253 RtlInitUnicodeString(&KeyName
,
1255 InitializeObjectAttributes(&ObjectAttributes
,
1257 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1260 Status
= ZwCreateKey(&LogConfKey
,
1265 REG_OPTION_VOLATILE
,
1267 if (NT_SUCCESS(Status
))
1269 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1270 RtlInitUnicodeString(&KeyName
,
1271 L
"DeviceReference");
1272 Status
= ZwSetValueKey(LogConfKey
,
1279 ZwClose(LogConfKey
);
1284 DPRINT("IopSetDeviceInstanceData() done\n");
1286 return STATUS_SUCCESS
;
1291 IopAssignDeviceResources(
1292 IN PDEVICE_NODE DeviceNode
,
1293 OUT ULONG
*pRequiredSize
)
1295 PIO_RESOURCE_LIST ResourceList
;
1296 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1297 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
1298 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1299 ULONG NumberOfResources
= 0;
1304 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1306 /* No resource needed for this device */
1307 DeviceNode
->ResourceList
= NULL
;
1308 return STATUS_SUCCESS
;
1311 /* Fill DeviceNode->ResourceList
1312 * FIXME: the PnP arbiter should go there!
1313 * Actually, use the BootResources if provided, else the resource list #0
1316 if (DeviceNode
->BootResources
)
1318 /* Browse the boot resources to know if we have some custom structures */
1319 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1320 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1322 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1323 if (pPartialResourceList
->Version
!= 1 || pPartialResourceList
->Revision
!= 1)
1325 Status
= STATUS_REVISION_MISMATCH
;
1328 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1329 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1330 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1332 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1333 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1337 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1338 if (!DeviceNode
->ResourceList
)
1340 Status
= STATUS_NO_MEMORY
;
1343 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1345 *pRequiredSize
= Size
;
1346 return STATUS_SUCCESS
;
1349 /* Ok, here, we have to use the device requirement list */
1350 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1351 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1353 Status
= STATUS_REVISION_MISMATCH
;
1357 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1358 *pRequiredSize
= Size
;
1359 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1360 if (!DeviceNode
->ResourceList
)
1362 Status
= STATUS_NO_MEMORY
;
1366 DeviceNode
->ResourceList
->Count
= 1;
1367 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1368 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1369 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1370 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1372 for (i
= 0; i
< ResourceList
->Count
; i
++)
1374 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1376 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1378 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1379 NumberOfResources
++;
1381 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1382 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
1383 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1384 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
1385 switch (ResourceDescriptor
->Type
)
1387 case CmResourceTypePort
:
1389 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1390 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
1393 case CmResourceTypeInterrupt
:
1395 INTERFACE_TYPE BusType
;
1400 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1401 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1402 /* FIXME: HACK: if we have a PCI device, we try
1403 * to keep the IRQ assigned by the BIOS */
1404 if (NT_SUCCESS(IoGetDeviceProperty(
1405 DeviceNode
->PhysicalDeviceObject
,
1406 DevicePropertyLegacyBusType
,
1407 sizeof(INTERFACE_TYPE
),
1409 &ret
)) && BusType
== PCIBus
)
1411 /* We have a PCI bus */
1412 if (NT_SUCCESS(IoGetDeviceProperty(
1413 DeviceNode
->PhysicalDeviceObject
,
1414 DevicePropertyAddress
,
1417 &ret
)) && SlotNumber
> 0)
1419 /* We have a good slot number */
1420 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1421 DeviceNode
->ResourceRequirements
->BusNumber
,
1424 0x3c /* PCI_INTERRUPT_LINE */,
1426 if (ret
!= 0 && ret
!= 2
1427 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1428 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1430 /* The device already has an assigned IRQ */
1431 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1435 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1436 DescriptorRaw
->u
.Interrupt
.Vector
,
1437 &DeviceNode
->InstancePath
);
1438 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1439 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1440 DeviceNode
->ResourceRequirements
->BusNumber
,
1443 0x3c /* PCI_INTERRUPT_LINE */,
1445 if (ret
== 0 || ret
== 2)
1452 case CmResourceTypeMemory
:
1454 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1455 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
1458 case CmResourceTypeDma
:
1460 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1461 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
1462 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
1465 case CmResourceTypeBusNumber
:
1467 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1468 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
1469 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
1472 /*CmResourceTypeDevicePrivate:
1473 case CmResourceTypePcCardConfig:
1474 case CmResourceTypeMfCardConfig:
1477 &DescriptorRaw->u.DevicePrivate,
1478 &ResourceDescriptor->u.DevicePrivate,
1479 sizeof(ResourceDescriptor->u.DevicePrivate));
1481 &DescriptorTranslated->u.DevicePrivate,
1482 &ResourceDescriptor->u.DevicePrivate,
1483 sizeof(ResourceDescriptor->u.DevicePrivate));
1487 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1488 NumberOfResources
--;
1494 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1496 return STATUS_SUCCESS
;
1499 if (DeviceNode
->ResourceList
)
1501 ExFreePool(DeviceNode
->ResourceList
);
1502 DeviceNode
->ResourceList
= NULL
;
1509 IopTranslateDeviceResources(
1510 IN PDEVICE_NODE DeviceNode
,
1511 IN ULONG RequiredSize
)
1513 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1514 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1518 if (!DeviceNode
->ResourceList
)
1520 DeviceNode
->ResourceListTranslated
= NULL
;
1521 return STATUS_SUCCESS
;
1524 /* That's easy to translate a resource list. Just copy the
1525 * untranslated one and change few fields in the copy
1527 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1528 if (!DeviceNode
->ResourceListTranslated
)
1530 Status
=STATUS_NO_MEMORY
;
1533 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1535 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1537 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1538 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1540 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1541 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1542 switch (DescriptorRaw
->Type
)
1544 case CmResourceTypePort
:
1546 ULONG AddressSpace
= 0; /* IO space */
1547 if (!HalTranslateBusAddress(
1548 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1549 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1550 DescriptorRaw
->u
.Port
.Start
,
1552 &DescriptorTranslated
->u
.Port
.Start
))
1554 Status
= STATUS_UNSUCCESSFUL
;
1559 case CmResourceTypeInterrupt
:
1561 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1562 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1563 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1564 DescriptorRaw
->u
.Interrupt
.Level
,
1565 DescriptorRaw
->u
.Interrupt
.Vector
,
1566 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1567 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1570 case CmResourceTypeMemory
:
1572 ULONG AddressSpace
= 1; /* Memory space */
1573 if (!HalTranslateBusAddress(
1574 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1575 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1576 DescriptorRaw
->u
.Memory
.Start
,
1578 &DescriptorTranslated
->u
.Memory
.Start
))
1580 Status
= STATUS_UNSUCCESSFUL
;
1585 case CmResourceTypeDma
:
1586 case CmResourceTypeBusNumber
:
1587 case CmResourceTypeDeviceSpecific
:
1591 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1592 Status
= STATUS_NOT_IMPLEMENTED
;
1597 return STATUS_SUCCESS
;
1600 /* Yes! Also delete ResourceList because ResourceList and
1601 * ResourceListTranslated should be a pair! */
1602 ExFreePool(DeviceNode
->ResourceList
);
1603 DeviceNode
->ResourceList
= NULL
;
1604 if (DeviceNode
->ResourceListTranslated
)
1606 ExFreePool(DeviceNode
->ResourceListTranslated
);
1607 DeviceNode
->ResourceList
= NULL
;
1614 * IopGetParentIdPrefix
1616 * Retrieve (or create) a string which identifies a device.
1620 * Pointer to device node.
1622 * Pointer to the string where is returned the parent node identifier
1625 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1626 * valid and its Buffer field is NULL-terminated. The caller needs to
1627 * to free the string with RtlFreeUnicodeString when it is no longer
1632 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1633 PUNICODE_STRING ParentIdPrefix
)
1635 ULONG KeyNameBufferLength
;
1636 PWSTR KeyNameBuffer
= NULL
;
1637 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1638 UNICODE_STRING KeyName
;
1639 UNICODE_STRING KeyValue
;
1640 UNICODE_STRING ValueName
;
1641 OBJECT_ATTRIBUTES ObjectAttributes
;
1646 /* HACK: As long as some devices have a NULL device
1647 * instance path, the following test is required :(
1649 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1650 return STATUS_UNSUCCESSFUL
;
1652 /* 1. Try to retrieve ParentIdPrefix from registry */
1653 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1654 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1655 if (!ParentIdPrefixInformation
)
1657 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1660 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1663 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1666 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1667 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1668 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1669 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1670 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1671 if (!NT_SUCCESS(Status
))
1673 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1674 Status
= ZwQueryValueKey(
1676 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1677 KeyNameBufferLength
, &KeyNameBufferLength
);
1678 if (NT_SUCCESS(Status
))
1680 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1681 Status
= STATUS_UNSUCCESSFUL
;
1684 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1685 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1689 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1691 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1692 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1696 /* 2. Create the ParentIdPrefix value */
1697 crc32
= RtlComputeCrc32(0,
1698 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1699 DeviceNode
->Parent
->InstancePath
.Length
);
1701 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1702 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1704 /* 3. Try to write the ParentIdPrefix to registry */
1705 Status
= ZwSetValueKey(hKey
,
1709 (PVOID
)KeyValue
.Buffer
,
1710 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1713 if (NT_SUCCESS(Status
))
1715 /* Duplicate the string to return it */
1716 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1718 ExFreePool(ParentIdPrefixInformation
);
1719 ExFreePool(KeyNameBuffer
);
1727 * IopActionInterrogateDeviceStack
1729 * Retrieve information for all (direct) child nodes of a parent node.
1733 * Pointer to device node.
1735 * Pointer to parent node to retrieve child node information for.
1738 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1739 * when we reach a device node which is not a direct child of the device
1740 * node for which we retrieve information of child nodes for. Any errors
1741 * that occur is logged instead so that all child services have a chance
1742 * of being interrogated.
1746 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1749 IO_STATUS_BLOCK IoStatusBlock
;
1750 PDEVICE_NODE ParentDeviceNode
;
1751 WCHAR InstancePath
[MAX_PATH
];
1752 IO_STACK_LOCATION Stack
;
1758 ULONG RequiredLength
;
1760 HANDLE InstanceKey
= NULL
;
1761 UNICODE_STRING ValueName
;
1762 UNICODE_STRING ParentIdPrefix
= { 0 };
1763 DEVICE_CAPABILITIES DeviceCapabilities
;
1765 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1766 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1768 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1771 * We are called for the parent too, but we don't need to do special
1772 * handling for this node
1775 if (DeviceNode
== ParentDeviceNode
)
1777 DPRINT("Success\n");
1778 return STATUS_SUCCESS
;
1782 * Make sure this device node is a direct child of the parent device node
1783 * that is given as an argument
1786 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1788 /* Stop the traversal immediately and indicate successful operation */
1790 return STATUS_UNSUCCESSFUL
;
1794 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1795 if (!NT_SUCCESS(Status
))
1797 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1802 * FIXME: For critical errors, cleanup and disable device, but always
1803 * return STATUS_SUCCESS.
1806 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1808 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1809 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1813 if (NT_SUCCESS(Status
))
1815 /* Copy the device id string */
1816 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1819 * FIXME: Check for valid characters, if there is invalid characters
1825 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1828 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1830 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1831 if (!NT_SUCCESS(Status
))
1833 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1836 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1838 if (!DeviceCapabilities
.UniqueID
)
1840 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1841 DPRINT("Instance ID is not unique\n");
1842 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1843 if (!NT_SUCCESS(Status
))
1845 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1849 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1851 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1852 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1856 if (NT_SUCCESS(Status
))
1858 /* Append the instance id string */
1859 wcscat(InstancePath
, L
"\\");
1860 if (ParentIdPrefix
.Length
> 0)
1862 /* Add information from parent bus device to InstancePath */
1863 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1864 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1865 wcscat(InstancePath
, L
"&");
1867 if (IoStatusBlock
.Information
)
1868 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1871 * FIXME: Check for valid characters, if there is invalid characters
1877 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1879 RtlFreeUnicodeString(&ParentIdPrefix
);
1881 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1883 DPRINT("No resources\n");
1884 /* FIXME: Cleanup and disable device */
1887 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1890 * Create registry key for the instance id, if it doesn't exist yet
1892 KeyBuffer
= ExAllocatePool(
1894 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1895 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1896 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1897 Status
= IopCreateDeviceKeyPath(KeyBuffer
, &InstanceKey
);
1898 ExFreePool(KeyBuffer
);
1899 if (!NT_SUCCESS(Status
))
1901 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1906 /* Set 'Capabilities' value */
1907 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1908 Status
= ZwSetValueKey(InstanceKey
,
1912 (PVOID
)&DeviceNode
->CapabilityFlags
,
1915 /* Set 'UINumber' value */
1916 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1918 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1919 Status
= ZwSetValueKey(InstanceKey
,
1923 &DeviceCapabilities
.UINumber
,
1928 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1930 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1931 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1935 if (NT_SUCCESS(Status
))
1938 * FIXME: Check for valid characters, if there is invalid characters
1942 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1943 DPRINT("Hardware IDs:\n");
1946 DPRINT(" %S\n", Ptr
);
1947 Length
= wcslen(Ptr
) + 1;
1950 TotalLength
+= Length
;
1952 DPRINT("TotalLength: %hu\n", TotalLength
);
1955 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1956 Status
= ZwSetValueKey(InstanceKey
,
1960 (PVOID
)IoStatusBlock
.Information
,
1961 (TotalLength
+ 1) * sizeof(WCHAR
));
1962 if (!NT_SUCCESS(Status
))
1964 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1969 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1972 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1974 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1975 Status
= IopInitiatePnpIrp(
1976 DeviceNode
->PhysicalDeviceObject
,
1980 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1983 * FIXME: Check for valid characters, if there is invalid characters
1987 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1988 DPRINT("Compatible IDs:\n");
1991 DPRINT(" %S\n", Ptr
);
1992 Length
= wcslen(Ptr
) + 1;
1995 TotalLength
+= Length
;
1997 DPRINT("TotalLength: %hu\n", TotalLength
);
2000 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
2001 Status
= ZwSetValueKey(InstanceKey
,
2005 (PVOID
)IoStatusBlock
.Information
,
2006 (TotalLength
+ 1) * sizeof(WCHAR
));
2007 if (!NT_SUCCESS(Status
))
2009 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
2014 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2018 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2020 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2021 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2022 Status
= IopInitiatePnpIrp(
2023 DeviceNode
->PhysicalDeviceObject
,
2025 IRP_MN_QUERY_DEVICE_TEXT
,
2027 /* This key is mandatory, so even if the Irp fails, we still write it */
2028 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2029 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2031 if (NT_SUCCESS(Status
) &&
2032 IoStatusBlock
.Information
&&
2033 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2035 /* This key is overriden when a driver is installed. Don't write the
2036 * new description if another one already exists */
2037 Status
= ZwSetValueKey(InstanceKey
,
2041 (PVOID
)IoStatusBlock
.Information
,
2042 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2046 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2047 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2049 Status
= ZwSetValueKey(InstanceKey
,
2054 DeviceDesc
.MaximumLength
);
2056 if (!NT_SUCCESS(Status
))
2058 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2064 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2066 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2067 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2068 Status
= IopInitiatePnpIrp(
2069 DeviceNode
->PhysicalDeviceObject
,
2071 IRP_MN_QUERY_DEVICE_TEXT
,
2073 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2075 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2076 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2077 Status
= ZwSetValueKey(InstanceKey
,
2081 (PVOID
)IoStatusBlock
.Information
,
2082 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2083 if (!NT_SUCCESS(Status
))
2085 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2090 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2093 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2095 Status
= IopInitiatePnpIrp(
2096 DeviceNode
->PhysicalDeviceObject
,
2098 IRP_MN_QUERY_BUS_INFORMATION
,
2100 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2102 PPNP_BUS_INFORMATION BusInformation
=
2103 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2105 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2106 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2107 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2108 ExFreePool(BusInformation
);
2112 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2114 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2115 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2116 DeviceNode
->ChildBusTypeIndex
= -1;
2119 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2121 Status
= IopInitiatePnpIrp(
2122 DeviceNode
->PhysicalDeviceObject
,
2124 IRP_MN_QUERY_RESOURCES
,
2126 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2128 DeviceNode
->BootResources
=
2129 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2130 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2134 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2135 DeviceNode
->BootResources
= NULL
;
2138 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2140 Status
= IopInitiatePnpIrp(
2141 DeviceNode
->PhysicalDeviceObject
,
2143 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2145 if (NT_SUCCESS(Status
))
2147 DeviceNode
->ResourceRequirements
=
2148 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2149 if (IoStatusBlock
.Information
)
2150 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2152 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2156 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2157 DeviceNode
->ResourceRequirements
= NULL
;
2161 if (InstanceKey
!= NULL
)
2163 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2166 ZwClose(InstanceKey
);
2168 DeviceNode
->Flags
|= DNF_PROCESSED
;
2170 /* Report the device to the user-mode pnp manager */
2171 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2172 &DeviceNode
->InstancePath
);
2174 return STATUS_SUCCESS
;
2178 * IopActionConfigureChildServices
2180 * Retrieve configuration for all (direct) child nodes of a parent node.
2184 * Pointer to device node.
2186 * Pointer to parent node to retrieve child node configuration for.
2189 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2190 * when we reach a device node which is not a direct child of the device
2191 * node for which we configure child services for. Any errors that occur is
2192 * logged instead so that all child services have a chance of beeing
2197 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2200 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2201 PDEVICE_NODE ParentDeviceNode
;
2202 PUNICODE_STRING Service
;
2203 UNICODE_STRING ClassGUID
;
2204 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
2207 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2209 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2212 * We are called for the parent too, but we don't need to do special
2213 * handling for this node
2215 if (DeviceNode
== ParentDeviceNode
)
2217 DPRINT("Success\n");
2218 return STATUS_SUCCESS
;
2222 * Make sure this device node is a direct child of the parent device node
2223 * that is given as an argument
2225 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2227 /* Stop the traversal immediately and indicate successful operation */
2229 return STATUS_UNSUCCESSFUL
;
2232 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2234 WCHAR RegKeyBuffer
[MAX_PATH
];
2235 UNICODE_STRING RegKey
;
2238 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2239 RegKey
.Buffer
= RegKeyBuffer
;
2242 * Retrieve configuration from Enum key
2245 Service
= &DeviceNode
->ServiceName
;
2247 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2248 RtlInitUnicodeString(Service
, NULL
);
2249 RtlInitUnicodeString(&ClassGUID
, NULL
);
2251 QueryTable
[0].Name
= L
"Service";
2252 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2253 QueryTable
[0].EntryContext
= Service
;
2255 QueryTable
[1].Name
= L
"ClassGUID";
2256 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2257 QueryTable
[1].EntryContext
= &ClassGUID
;
2258 QueryTable
[1].DefaultType
= REG_SZ
;
2259 QueryTable
[1].DefaultData
= &NullString
;
2260 QueryTable
[1].DefaultLength
= 0;
2262 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2263 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2265 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2266 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2268 if (!NT_SUCCESS(Status
))
2270 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status
);
2271 /* FIXME: Log the error */
2272 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
2273 DeviceNode
->InstancePath
.Buffer
, Status
);
2274 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2275 return STATUS_SUCCESS
;
2278 if (Service
->Buffer
== NULL
)
2280 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2282 if (ClassGUID
.Length
!= 0)
2284 /* Device has a ClassGUID value, but no Service value.
2285 * Suppose it is using the NULL driver, so state the
2286 * device is started */
2287 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2288 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2289 DeviceNode
->Flags
|= DN_STARTED
;
2291 return STATUS_SUCCESS
;
2294 DPRINT("Got Service %S\n", Service
->Buffer
);
2297 return STATUS_SUCCESS
;
2301 * IopActionInitChildServices
2303 * Initialize the service for all (direct) child nodes of a parent node
2307 * Pointer to device node.
2309 * Pointer to parent node to initialize child node services for.
2311 * Load only driver marked as boot start.
2314 * If the driver image for a service is not loaded and initialized
2315 * it is done here too. We only return a status code indicating an
2316 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2317 * not a direct child of the device node for which we initialize
2318 * child services for. Any errors that occur is logged instead so
2319 * that all child services have a chance of being initialized.
2323 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2325 BOOLEAN BootDrivers
)
2327 PDEVICE_NODE ParentDeviceNode
;
2330 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2333 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2336 * We are called for the parent too, but we don't need to do special
2337 * handling for this node
2339 if (DeviceNode
== ParentDeviceNode
)
2341 DPRINT("Success\n");
2342 return STATUS_SUCCESS
;
2346 * Make sure this device node is a direct child of the parent device node
2347 * that is given as an argument
2350 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2353 * Stop the traversal immediately and indicate unsuccessful operation
2356 return STATUS_UNSUCCESSFUL
;
2360 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2361 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2362 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2364 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2365 PDRIVER_OBJECT DriverObject
;
2367 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2368 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2370 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2372 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2373 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2374 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2378 /* get existing DriverObject pointer */
2379 Status
= IopGetDriverObject(
2381 &DeviceNode
->ServiceName
,
2384 if (NT_SUCCESS(Status
))
2386 /* Attach lower level filter drivers. */
2387 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2388 /* Initialize the function driver for the device node */
2389 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2390 if (NT_SUCCESS(Status
))
2392 /* Attach upper level filter drivers. */
2393 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2394 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2396 Status
= IopStartDevice(DeviceNode
);
2403 * Don't disable when trying to load only boot drivers
2407 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2408 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2409 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2410 CPRINT("Initialization of service %S failed (Status %x)\n",
2411 DeviceNode
->ServiceName
.Buffer
, Status
);
2417 DPRINT("Service %S is disabled or already initialized\n",
2418 DeviceNode
->ServiceName
.Buffer
);
2421 return STATUS_SUCCESS
;
2425 * IopActionInitAllServices
2427 * Initialize the service for all (direct) child nodes of a parent node. This
2428 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2432 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2435 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2439 * IopActionInitBootServices
2441 * Initialize the boot start services for all (direct) child nodes of a
2442 * parent node. This function just calls IopActionInitChildServices with
2443 * BootDrivers = TRUE.
2446 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2449 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2453 * IopInitializePnpServices
2455 * Initialize services for discovered children
2459 * Top device node to start initializing services.
2462 * When set to TRUE, only drivers marked as boot start will
2463 * be loaded. Otherwise, all drivers will be loaded.
2469 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2470 IN BOOLEAN BootDrivers
)
2472 DEVICETREE_TRAVERSE_CONTEXT Context
;
2474 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2478 IopInitDeviceTreeTraverseContext(
2481 IopActionInitBootServices
,
2486 IopInitDeviceTreeTraverseContext(
2489 IopActionInitAllServices
,
2493 return IopTraverseDeviceTree(&Context
);
2496 /* Invalidate device list enumerated by a device node.
2497 * The call can be make synchronous by defining the Event field
2498 * of the INVALIDATE_DEVICE_RELATION_DATA structure
2501 IopInvalidateDeviceRelations(
2502 IN PDEVICE_OBJECT DeviceObject
,
2503 IN PVOID InvalidateContext
) /* PINVALIDATE_DEVICE_RELATION_DATA */
2505 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
2506 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2507 PKEVENT Event
= Data
->Event
;
2508 DEVICETREE_TRAVERSE_CONTEXT Context
;
2509 PDEVICE_RELATIONS DeviceRelations
;
2510 IO_STATUS_BLOCK IoStatusBlock
;
2511 PDEVICE_NODE ChildDeviceNode
;
2512 IO_STACK_LOCATION Stack
;
2513 BOOLEAN BootDrivers
;
2514 OBJECT_ATTRIBUTES ObjectAttributes
;
2515 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
2520 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2522 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2524 Stack
.Parameters
.QueryDeviceRelations
.Type
= Data
->Type
;
2526 Status
= IopInitiatePnpIrp(
2529 IRP_MN_QUERY_DEVICE_RELATIONS
,
2531 if (!NT_SUCCESS(Status
))
2533 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2537 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2539 if (!DeviceRelations
|| DeviceRelations
->Count
<= 0)
2541 DPRINT("No PDOs\n");
2542 if (DeviceRelations
)
2544 ExFreePool(DeviceRelations
);
2546 Status
= STATUS_SUCCESS
;
2550 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2553 * Create device nodes for all discovered devices
2555 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2557 Status
= IopCreateDeviceNode(
2559 DeviceRelations
->Objects
[i
],
2562 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2563 if (!NT_SUCCESS(Status
))
2565 DPRINT("No resources\n");
2566 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2567 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2568 ExFreePool(DeviceRelations
);
2569 Status
= STATUS_NO_MEMORY
;
2573 ExFreePool(DeviceRelations
);
2576 * Retrieve information about all discovered children from the bus driver
2578 IopInitDeviceTreeTraverseContext(
2581 IopActionInterrogateDeviceStack
,
2584 Status
= IopTraverseDeviceTree(&Context
);
2585 if (!NT_SUCCESS(Status
))
2587 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2592 * Retrieve configuration from the registry for discovered children
2594 IopInitDeviceTreeTraverseContext(
2597 IopActionConfigureChildServices
,
2600 Status
= IopTraverseDeviceTree(&Context
);
2601 if (!NT_SUCCESS(Status
))
2603 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2608 * Get the state of the system boot. If the \\SystemRoot link isn't
2609 * created yet, we will assume that it's possible to load only boot
2612 InitializeObjectAttributes(
2618 Status
= ZwOpenFile(
2625 if (NT_SUCCESS(Status
))
2627 BootDrivers
= FALSE
;
2634 * Initialize services for discovered children. Only boot drivers will
2635 * be loaded from boot driver!
2637 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2638 if (!NT_SUCCESS(Status
))
2640 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2644 DPRINT("IopInvalidateDeviceRelations() finished\n");
2645 Status
= STATUS_SUCCESS
;
2648 IoFreeWorkItem(Data
->WorkItem
);
2651 Data
->Status
= Status
;
2652 KeSetEvent(Event
, 0, FALSE
);
2658 static NTSTATUS INIT_FUNCTION
2659 IopEnumerateDetectedDevices(
2661 IN PUNICODE_STRING RelativePath
,
2663 IN BOOLEAN EnumerateSubKeys
,
2664 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2665 IN ULONG ParentBootResourcesLength
)
2667 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2668 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2669 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2670 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2671 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2672 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2673 OBJECT_ATTRIBUTES ObjectAttributes
;
2674 HANDLE hDevicesKey
= NULL
;
2675 HANDLE hDeviceKey
= NULL
;
2676 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2677 UNICODE_STRING Level2NameU
;
2678 WCHAR Level2Name
[5];
2679 ULONG IndexDevice
= 0;
2681 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2682 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2683 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2684 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2685 UNICODE_STRING DeviceName
, ValueName
;
2687 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2688 ULONG BootResourcesLength
;
2691 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI BIOS");
2692 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2693 static ULONG DeviceIndexPci
= 0;
2694 /*const UNICODE_STRING IdentifierAcpi = RTL_CONSTANT_STRING(L"ACPI BIOS");
2695 UNICODE_STRING HardwareIdAcpi = RTL_CONSTANT_STRING(L"*PNP0C08\0");
2696 static ULONG DeviceIndexAcpi = 0;*/
2697 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2698 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2699 static ULONG DeviceIndexSerial
= 0;
2700 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2701 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2702 static ULONG DeviceIndexKeyboard
= 0;
2703 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2704 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2705 static ULONG DeviceIndexMouse
= 0;
2706 PUNICODE_STRING pHardwareId
;
2707 ULONG DeviceIndex
= 0;
2709 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2710 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2711 if (!NT_SUCCESS(Status
))
2713 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2717 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2718 if (!pDeviceInformation
)
2720 DPRINT("ExAllocatePool() failed\n");
2721 Status
= STATUS_NO_MEMORY
;
2725 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2726 if (!pValueInformation
)
2728 DPRINT("ExAllocatePool() failed\n");
2729 Status
= STATUS_NO_MEMORY
;
2735 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2736 if (Status
== STATUS_NO_MORE_ENTRIES
)
2738 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2740 ExFreePool(pDeviceInformation
);
2741 DeviceInfoLength
= RequiredSize
;
2742 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2743 if (!pDeviceInformation
)
2745 DPRINT("ExAllocatePool() failed\n");
2746 Status
= STATUS_NO_MEMORY
;
2749 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2751 if (!NT_SUCCESS(Status
))
2753 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2758 /* Open device key */
2759 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2760 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2761 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2764 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0),
2766 if (!NT_SUCCESS(Status
))
2768 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2772 /* Read boot resources, and add then to parent ones */
2773 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2774 if (Status
== STATUS_BUFFER_OVERFLOW
)
2776 ExFreePool(pValueInformation
);
2777 ValueInfoLength
= RequiredSize
;
2778 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2779 if (!pValueInformation
)
2781 DPRINT("ExAllocatePool() failed\n");
2782 ZwDeleteKey(hLevel2Key
);
2783 Status
= STATUS_NO_MEMORY
;
2786 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2788 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2790 BootResources
= ParentBootResources
;
2791 BootResourcesLength
= ParentBootResourcesLength
;
2793 else if (!NT_SUCCESS(Status
))
2795 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2798 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2800 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2803 else if (((PCM_FULL_RESOURCE_DESCRIPTOR
)pValueInformation
->Data
)->PartialResourceList
.Count
== 0)
2805 BootResources
= ParentBootResources
;
2806 BootResourcesLength
= ParentBootResourcesLength
;
2810 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2812 /* Concatenate current resources and parent ones */
2813 if (ParentBootResourcesLength
== 0)
2814 BootResourcesLength
= pValueInformation
->DataLength
;
2816 BootResourcesLength
= ParentBootResourcesLength
2817 + pValueInformation
->DataLength
2819 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2822 DPRINT("ExAllocatePool() failed\n");
2825 if (ParentBootResourcesLength
== 0)
2827 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2829 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2831 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2833 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2834 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2835 ParentBootResourcesLength
- Header
);
2836 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2840 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2842 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2843 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2844 ParentBootResourcesLength
- Header
);
2846 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2847 pValueInformation
->Data
+ Header
,
2848 pValueInformation
->DataLength
- Header
);
2849 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2853 if (EnumerateSubKeys
)
2858 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2859 if (Status
== STATUS_NO_MORE_ENTRIES
)
2861 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2863 ExFreePool(pDeviceInformation
);
2864 DeviceInfoLength
= RequiredSize
;
2865 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2866 if (!pDeviceInformation
)
2868 DPRINT("ExAllocatePool() failed\n");
2869 Status
= STATUS_NO_MEMORY
;
2872 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2874 if (!NT_SUCCESS(Status
))
2876 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2880 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2881 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2883 Status
= IopEnumerateDetectedDevices(
2889 BootResourcesLength
);
2890 if (!NT_SUCCESS(Status
))
2895 /* Read identifier */
2896 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2897 if (Status
== STATUS_BUFFER_OVERFLOW
)
2899 ExFreePool(pValueInformation
);
2900 ValueInfoLength
= RequiredSize
;
2901 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2902 if (!pValueInformation
)
2904 DPRINT("ExAllocatePool() failed\n");
2905 Status
= STATUS_NO_MEMORY
;
2908 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2910 if (!NT_SUCCESS(Status
))
2912 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2914 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2917 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2919 else if (pValueInformation
->Type
!= REG_SZ
)
2921 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2926 /* Assign hardware id to this device */
2927 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2928 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2929 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2930 ValueName
.Length
-= sizeof(WCHAR
);
2933 if (RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2935 pHardwareId
= &HardwareIdSerial
;
2936 DeviceIndex
= DeviceIndexSerial
++;
2938 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2940 pHardwareId
= &HardwareIdKeyboard
;
2941 DeviceIndex
= DeviceIndexKeyboard
++;
2943 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2945 pHardwareId
= &HardwareIdMouse
;
2946 DeviceIndex
= DeviceIndexMouse
++;
2948 else if (NT_SUCCESS(Status
))
2950 /* Try to also match the device identifier */
2951 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2953 pHardwareId
= &HardwareIdPci
;
2954 DeviceIndex
= DeviceIndexPci
++;
2956 /*else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0)
2958 pHardwareId = &HardwareIdAcpi;
2959 DeviceIndex = DeviceIndexAcpi++;
2963 /* Unknown device */
2964 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2970 /* Unknown key path */
2971 DPRINT("Unknown key path %wZ\n", RelativePath
);
2975 /* Add the detected device to Root key */
2976 InitializeObjectAttributes(&ObjectAttributes
, pHardwareId
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2977 Status
= ZwCreateKey(
2983 REG_OPTION_NON_VOLATILE
,
2985 if (!NT_SUCCESS(Status
))
2987 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2990 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2991 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2992 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2993 Status
= ZwCreateKey(
2995 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
2999 REG_OPTION_NON_VOLATILE
,
3001 ZwClose(hLevel1Key
);
3002 if (!NT_SUCCESS(Status
))
3004 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3007 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, pHardwareId
);
3008 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
3009 if (!NT_SUCCESS(Status
))
3011 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3012 ZwDeleteKey(hLevel2Key
);
3015 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3016 if (!NT_SUCCESS(Status
))
3018 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3019 ZwDeleteKey(hLevel2Key
);
3022 if (BootResourcesLength
> 0)
3024 /* Save boot resources to 'LogConf\BootConfig' */
3025 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3026 Status
= ZwCreateKey(
3032 REG_OPTION_VOLATILE
,
3034 if (!NT_SUCCESS(Status
))
3036 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3037 ZwDeleteKey(hLevel2Key
);
3040 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
3042 if (!NT_SUCCESS(Status
))
3044 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3045 ZwDeleteKey(hLevel2Key
);
3051 if (BootResources
&& BootResources
!= ParentBootResources
)
3052 ExFreePool(BootResources
);
3055 ZwClose(hLevel2Key
);
3060 ZwClose(hDeviceKey
);
3065 Status
= STATUS_SUCCESS
;
3069 ZwClose(hDevicesKey
);
3071 ZwClose(hDeviceKey
);
3072 if (pDeviceInformation
)
3073 ExFreePool(pDeviceInformation
);
3074 if (pValueInformation
)
3075 ExFreePool(pValueInformation
);
3079 static BOOLEAN INIT_FUNCTION
3080 IopIsAcpiComputer(VOID
)
3084 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3085 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3086 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3087 OBJECT_ATTRIBUTES ObjectAttributes
;
3088 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3089 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3090 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3091 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3093 ULONG IndexDevice
= 0;
3094 UNICODE_STRING DeviceName
, ValueName
;
3095 HANDLE hDevicesKey
= NULL
;
3096 HANDLE hDeviceKey
= NULL
;
3098 BOOLEAN ret
= FALSE
;
3100 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3101 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3102 if (!NT_SUCCESS(Status
))
3104 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3108 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3109 if (!pDeviceInformation
)
3111 DPRINT("ExAllocatePool() failed\n");
3112 Status
= STATUS_NO_MEMORY
;
3116 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3117 if (!pDeviceInformation
)
3119 DPRINT("ExAllocatePool() failed\n");
3120 Status
= STATUS_NO_MEMORY
;
3126 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3127 if (Status
== STATUS_NO_MORE_ENTRIES
)
3129 else if (Status
== STATUS_BUFFER_OVERFLOW
)
3131 ExFreePool(pDeviceInformation
);
3132 DeviceInfoLength
= RequiredSize
;
3133 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3134 if (!pDeviceInformation
)
3136 DPRINT("ExAllocatePool() failed\n");
3137 Status
= STATUS_NO_MEMORY
;
3140 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3142 if (!NT_SUCCESS(Status
))
3144 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3149 /* Open device key */
3150 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3151 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3152 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3157 if (!NT_SUCCESS(Status
))
3159 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3163 /* Read identifier */
3164 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3165 if (Status
== STATUS_BUFFER_OVERFLOW
)
3167 ExFreePool(pValueInformation
);
3168 ValueInfoLength
= RequiredSize
;
3169 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3170 if (!pValueInformation
)
3172 DPRINT("ExAllocatePool() failed\n");
3173 Status
= STATUS_NO_MEMORY
;
3176 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3178 if (!NT_SUCCESS(Status
))
3180 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3183 else if (pValueInformation
->Type
!= REG_SZ
)
3185 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3189 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3190 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3191 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3192 ValueName
.Length
-= sizeof(WCHAR
);
3193 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3195 DPRINT("Found ACPI BIOS\n");
3201 ZwClose(hDeviceKey
);
3206 if (pDeviceInformation
)
3207 ExFreePool(pDeviceInformation
);
3208 if (pValueInformation
)
3209 ExFreePool(pValueInformation
);
3211 ZwClose(hDevicesKey
);
3213 ZwClose(hDeviceKey
);
3218 static NTSTATUS INIT_FUNCTION
3219 IopUpdateRootKey(VOID
)
3221 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum\\Root");
3222 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3223 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3224 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3225 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3226 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3227 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3228 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3229 OBJECT_ATTRIBUTES ObjectAttributes
;
3230 HANDLE hRoot
, hHalAcpiDevice
, hHalAcpiId
;
3233 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3234 Status
= ZwOpenKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
);
3235 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3237 /* We are probably in 1st stage */
3238 return STATUS_SUCCESS
;
3240 else if (!NT_SUCCESS(Status
))
3242 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3246 if (IopIsAcpiComputer())
3248 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3249 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3251 if (!NT_SUCCESS(Status
))
3253 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3254 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3255 ZwClose(hHalAcpiDevice
);
3256 if (!NT_SUCCESS(Status
))
3258 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3259 if (NT_SUCCESS(Status
))
3260 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3261 ZwClose(hHalAcpiId
);
3266 Status
= IopEnumerateDetectedDevices(
3278 static NTSTATUS INIT_FUNCTION
3280 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
3282 return STATUS_SUCCESS
;
3291 DPRINT("PnpInit()\n");
3293 KeInitializeSpinLock(&IopDeviceTreeLock
);
3295 /* Initialize the Bus Type GUID List */
3296 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3297 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3298 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3300 /* Initialize PnP-Event notification support */
3301 Status
= IopInitPlugPlayEvents();
3302 if (!NT_SUCCESS(Status
))
3304 CPRINT("IopInitPlugPlayEvents() failed\n");
3305 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3309 * Create root device node
3312 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, &IopRootDriverObject
);
3313 if (!NT_SUCCESS(Status
))
3315 CPRINT("IoCreateDriverObject() failed\n");
3316 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3319 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3321 if (!NT_SUCCESS(Status
))
3323 CPRINT("IoCreateDevice() failed\n");
3324 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3327 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
3328 if (!NT_SUCCESS(Status
))
3330 CPRINT("Insufficient resources\n");
3331 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3334 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3337 CPRINT("Failed to create the instance path!\n");
3338 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3341 /* Report the device to the user-mode pnp manager */
3342 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3343 &IopRootDeviceNode
->InstancePath
);
3345 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3346 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3347 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3348 IopRootDriverObject
->DriverExtension
->AddDevice(
3349 IopRootDriverObject
,
3350 IopRootDeviceNode
->PhysicalDeviceObject
);
3352 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3353 Status
= IopUpdateRootKey();
3354 if (!NT_SUCCESS(Status
))
3356 CPRINT("IopUpdateRootKey() failed\n");
3357 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3361 RTL_GENERIC_COMPARE_RESULTS
3363 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3364 IN PVOID FirstStruct
,
3365 IN PVOID SecondStruct
)
3373 // The allocation function is called by the generic table package whenever
3374 // it needs to allocate memory for the table.
3379 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3389 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3398 PpInitializeDeviceReferenceTable(VOID
)
3400 /* Setup the guarded mutex and AVL table */
3401 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3402 RtlInitializeGenericTableAvl(
3403 &PpDeviceReferenceTable
,
3404 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3405 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3406 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3414 /* Initialize the resource when accessing device registry data */
3415 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3417 /* Setup the device reference AVL table */
3418 PpInitializeDeviceReferenceTable();
3426 /* Check the initialization phase */
3427 switch (ExpInitializationPhase
)
3432 return PiInitPhase0();
3438 //return PiInitPhase1();
3442 /* Don't know any other phase! Bugcheck! */
3443 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);