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 if (!NT_SUCCESS(Status
))
160 DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
163 DeviceNode
->ResourceRequirements
= Stack
.Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
165 Status
= IopAssignDeviceResources(DeviceNode
, &RequiredLength
);
166 if (NT_SUCCESS(Status
))
168 Status
= IopTranslateDeviceResources(DeviceNode
, RequiredLength
);
169 if (NT_SUCCESS(Status
))
171 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_ASSIGNED
);
175 DPRINT("IopTranslateDeviceResources() failed (Status 0x08lx)\n", Status
);
180 DPRINT("IopAssignDeviceResources() failed (Status 0x08lx)\n", Status
);
182 IopDeviceNodeClearFlag(DeviceNode
, DNF_ASSIGNING_RESOURCES
);
184 DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
185 Stack
.Parameters
.StartDevice
.AllocatedResources
= DeviceNode
->ResourceList
;
186 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
= DeviceNode
->ResourceListTranslated
;
189 * Windows NT Drivers receive IRP_MN_START_DEVICE in a critical region and
190 * actually _depend_ on this!. This is because NT will lock the Device Node
191 * with an ERESOURCE, which of course requires APCs to be disabled.
193 KeEnterCriticalRegion();
195 Status
= IopInitiatePnpIrp(
201 KeLeaveCriticalRegion();
203 if (!NT_SUCCESS(Status
))
205 DPRINT("IopInitiatePnpIrp() failed\n");
209 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
))
211 DPRINT("Device needs enumeration, invalidating bus relations\n");
212 /* Invalidate device relations synchronously
213 (otherwise there will be dirty read of DeviceNode) */
214 IoSynchronousInvalidateDeviceRelations(DeviceNode
->PhysicalDeviceObject
, BusRelations
);
215 IopDeviceNodeClearFlag(DeviceNode
, DNF_NEED_ENUMERATION_ONLY
);
219 ObDereferenceObject(Fdo
);
221 if (NT_SUCCESS(Status
))
222 DeviceNode
->Flags
|= DN_STARTED
;
229 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
230 PDEVICE_CAPABILITIES DeviceCaps
)
232 IO_STATUS_BLOCK StatusBlock
;
233 IO_STACK_LOCATION Stack
;
235 /* Set up the Header */
236 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
237 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
238 DeviceCaps
->Version
= 1;
239 DeviceCaps
->Address
= -1;
240 DeviceCaps
->UINumber
= -1;
242 /* Set up the Stack */
243 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
244 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
247 return IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
249 IRP_MN_QUERY_CAPABILITIES
,
258 IoInvalidateDeviceRelations(
259 IN PDEVICE_OBJECT DeviceObject
,
260 IN DEVICE_RELATION_TYPE Type
)
262 PIO_WORKITEM WorkItem
;
263 PINVALIDATE_DEVICE_RELATION_DATA Data
;
265 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
268 WorkItem
= IoAllocateWorkItem(DeviceObject
);
276 Data
->WorkItem
= WorkItem
;
281 IopInvalidateDeviceRelations
,
291 IoSynchronousInvalidateDeviceRelations(
292 IN PDEVICE_OBJECT DeviceObject
,
293 IN DEVICE_RELATION_TYPE Type
)
295 PIO_WORKITEM WorkItem
;
296 PINVALIDATE_DEVICE_RELATION_DATA Data
;
299 Data
= ExAllocatePool(PagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
302 WorkItem
= IoAllocateWorkItem(DeviceObject
);
309 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
311 Data
->WorkItem
= WorkItem
;
312 Data
->Event
= &Event
;
316 IopInvalidateDeviceRelations
,
320 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
329 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
330 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
331 IN ULONG BufferLength
,
332 OUT PVOID PropertyBuffer
,
333 OUT PULONG ResultLength
)
335 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
336 DEVICE_CAPABILITIES DeviceCaps
;
342 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
344 if (DeviceNode
== NULL
)
345 return STATUS_INVALID_DEVICE_REQUEST
;
347 switch (DeviceProperty
)
349 case DevicePropertyBusNumber
:
350 Length
= sizeof(ULONG
);
351 Data
= &DeviceNode
->ChildBusNumber
;
354 /* Complete, untested */
355 case DevicePropertyBusTypeGuid
:
357 if ((DeviceNode
->ChildBusTypeIndex
!= 0xFFFF) &&
358 (DeviceNode
->ChildBusTypeIndex
< IopBusTypeGuidList
->GuidCount
))
360 /* Return the GUID */
361 *ResultLength
= sizeof(GUID
);
363 /* Check if the buffer given was large enough */
364 if (BufferLength
< *ResultLength
)
366 return STATUS_BUFFER_TOO_SMALL
;
370 RtlCopyMemory(PropertyBuffer
,
371 &(IopBusTypeGuidList
->Guids
[DeviceNode
->ChildBusTypeIndex
]),
373 return STATUS_SUCCESS
;
377 return STATUS_OBJECT_NAME_NOT_FOUND
;
381 case DevicePropertyLegacyBusType
:
382 Length
= sizeof(INTERFACE_TYPE
);
383 Data
= &DeviceNode
->ChildInterfaceType
;
386 case DevicePropertyAddress
:
387 /* Query the device caps */
388 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
389 if (NT_SUCCESS(Status
) && (DeviceCaps
.Address
!= (ULONG
)-1))
392 *ResultLength
= sizeof(ULONG
);
394 /* Check if the buffer given was large enough */
395 if (BufferLength
< *ResultLength
)
397 return STATUS_BUFFER_TOO_SMALL
;
401 *(PULONG
)PropertyBuffer
= DeviceCaps
.Address
;
402 return STATUS_SUCCESS
;
406 return STATUS_OBJECT_NAME_NOT_FOUND
;
410 // case DevicePropertyUINumber:
411 // if (DeviceNode->CapabilityFlags == NULL)
412 // return STATUS_INVALID_DEVICE_REQUEST;
413 // Length = sizeof(ULONG);
414 // Data = &DeviceNode->CapabilityFlags->UINumber;
417 case DevicePropertyClassName
:
418 case DevicePropertyClassGuid
:
419 case DevicePropertyDriverKeyName
:
420 case DevicePropertyManufacturer
:
421 case DevicePropertyFriendlyName
:
422 case DevicePropertyHardwareID
:
423 case DevicePropertyCompatibleIDs
:
424 case DevicePropertyDeviceDescription
:
425 case DevicePropertyLocationInformation
:
426 case DevicePropertyUINumber
:
428 LPWSTR RegistryPropertyName
, KeyNameBuffer
;
429 UNICODE_STRING KeyName
, ValueName
;
430 OBJECT_ATTRIBUTES ObjectAttributes
;
431 KEY_VALUE_PARTIAL_INFORMATION
*ValueInformation
;
432 ULONG ValueInformationLength
;
436 switch (DeviceProperty
)
438 case DevicePropertyClassName
:
439 RegistryPropertyName
= L
"Class"; break;
440 case DevicePropertyClassGuid
:
441 RegistryPropertyName
= L
"ClassGuid"; break;
442 case DevicePropertyDriverKeyName
:
443 RegistryPropertyName
= L
"Driver"; break;
444 case DevicePropertyManufacturer
:
445 RegistryPropertyName
= L
"Mfg"; break;
446 case DevicePropertyFriendlyName
:
447 RegistryPropertyName
= L
"FriendlyName"; break;
448 case DevicePropertyHardwareID
:
449 RegistryPropertyName
= L
"HardwareID"; break;
450 case DevicePropertyCompatibleIDs
:
451 RegistryPropertyName
= L
"CompatibleIDs"; break;
452 case DevicePropertyDeviceDescription
:
453 RegistryPropertyName
= L
"DeviceDesc"; break;
454 case DevicePropertyLocationInformation
:
455 RegistryPropertyName
= L
"LocationInformation"; break;
456 case DevicePropertyUINumber
:
457 RegistryPropertyName
= L
"UINumber"; break;
459 RegistryPropertyName
= NULL
; break;
462 KeyNameBuffer
= ExAllocatePool(PagedPool
,
463 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
465 DPRINT("KeyNameBuffer: 0x%p, value %S\n", KeyNameBuffer
, RegistryPropertyName
);
467 if (KeyNameBuffer
== NULL
)
468 return STATUS_INSUFFICIENT_RESOURCES
;
470 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
471 wcscat(KeyNameBuffer
, DeviceNode
->InstancePath
.Buffer
);
472 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
473 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
474 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
476 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
477 ExFreePool(KeyNameBuffer
);
478 if (!NT_SUCCESS(Status
))
481 RtlInitUnicodeString(&ValueName
, RegistryPropertyName
);
482 ValueInformationLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
,
483 Data
[0]) + BufferLength
;
484 ValueInformation
= ExAllocatePool(PagedPool
, ValueInformationLength
);
485 if (ValueInformation
== NULL
)
488 return STATUS_INSUFFICIENT_RESOURCES
;
491 Status
= ZwQueryValueKey(KeyHandle
, &ValueName
,
492 KeyValuePartialInformation
, ValueInformation
,
493 ValueInformationLength
,
494 &ValueInformationLength
);
495 *ResultLength
= ValueInformation
->DataLength
;
498 if (!NT_SUCCESS(Status
))
500 ExFreePool(ValueInformation
);
501 if (Status
== STATUS_BUFFER_OVERFLOW
)
502 return STATUS_BUFFER_TOO_SMALL
;
507 /* FIXME: Verify the value (NULL-terminated, correct format). */
509 RtlCopyMemory(PropertyBuffer
, ValueInformation
->Data
,
510 ValueInformation
->DataLength
);
511 ExFreePool(ValueInformation
);
513 return STATUS_SUCCESS
;
516 case DevicePropertyBootConfiguration
:
518 if (DeviceNode
->BootResources
->Count
!= 0)
520 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
522 Data
= &DeviceNode
->BootResources
;
525 /* FIXME: use a translated boot configuration instead */
526 case DevicePropertyBootConfigurationTranslated
:
528 if (DeviceNode
->BootResources
->Count
!= 0)
530 Length
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
532 Data
= &DeviceNode
->BootResources
;
535 case DevicePropertyEnumeratorName
:
536 Ptr
= wcschr(DeviceNode
->InstancePath
.Buffer
, L
'\\');
539 Length
= (ULONG
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)DeviceNode
->InstancePath
.Buffer
) + sizeof(WCHAR
);
540 Data
= DeviceNode
->InstancePath
.Buffer
;
549 case DevicePropertyPhysicalDeviceObjectName
:
550 Length
= DeviceNode
->InstancePath
.Length
+ sizeof(WCHAR
);
551 Data
= DeviceNode
->InstancePath
.Buffer
;
555 return STATUS_INVALID_PARAMETER_2
;
558 *ResultLength
= Length
;
559 if (BufferLength
< Length
)
560 return STATUS_BUFFER_TOO_SMALL
;
561 RtlCopyMemory(PropertyBuffer
, Data
, Length
);
563 /* Terminate the string */
564 if (DeviceProperty
== DevicePropertyEnumeratorName
565 || DeviceProperty
== DevicePropertyPhysicalDeviceObjectName
)
567 Ptr
= (PWSTR
)PropertyBuffer
;
568 Ptr
[(Length
/ sizeof(WCHAR
)) - 1] = 0;
571 return STATUS_SUCCESS
;
579 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
585 * @name IoOpenDeviceRegistryKey
587 * Open a registry key unique for a specified driver or device instance.
589 * @param DeviceObject Device to get the registry key for.
590 * @param DevInstKeyType Type of the key to return.
591 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
592 * @param DevInstRegKey Handle to the opened registry key on
601 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
602 IN ULONG DevInstKeyType
,
603 IN ACCESS_MASK DesiredAccess
,
604 OUT PHANDLE DevInstRegKey
)
606 static WCHAR RootKeyName
[] =
607 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
608 static WCHAR ProfileKeyName
[] =
609 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
610 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
611 static WCHAR EnumKeyName
[] = L
"Enum\\";
612 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
614 LPWSTR KeyNameBuffer
;
615 UNICODE_STRING KeyName
;
616 ULONG DriverKeyLength
;
617 OBJECT_ATTRIBUTES ObjectAttributes
;
618 PDEVICE_NODE DeviceNode
= NULL
;
621 DPRINT("IoOpenDeviceRegistryKey() called\n");
623 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
625 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
626 return STATUS_INVALID_PARAMETER
;
630 * Calculate the length of the base key name. This is the full
631 * name for driver key or the name excluding "Device Parameters"
632 * subkey for device key.
635 KeyNameLength
= sizeof(RootKeyName
);
636 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
637 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
638 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
640 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
641 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
642 0, NULL
, &DriverKeyLength
);
643 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
645 KeyNameLength
+= DriverKeyLength
;
649 DeviceNode
= IopGetDeviceNode(DeviceObject
);
650 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
651 DeviceNode
->InstancePath
.Length
;
655 * Now allocate the buffer for the key name...
658 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
659 if (KeyNameBuffer
== NULL
)
660 return STATUS_INSUFFICIENT_RESOURCES
;
663 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
664 KeyName
.Buffer
= KeyNameBuffer
;
667 * ...and build the key name.
670 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
671 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
673 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
674 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
676 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
678 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
679 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
680 DriverKeyLength
, KeyNameBuffer
+
681 (KeyName
.Length
/ sizeof(WCHAR
)),
683 if (!NT_SUCCESS(Status
))
685 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
686 ExFreePool(KeyNameBuffer
);
689 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
693 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
694 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
695 if (DeviceNode
->InstancePath
.Length
== 0)
697 ExFreePool(KeyNameBuffer
);
706 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
707 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
708 Status
= ZwOpenKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
);
709 if (!NT_SUCCESS(Status
))
711 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
712 ExFreePool(KeyNameBuffer
);
715 ExFreePool(KeyNameBuffer
);
718 * For driver key we're done now.
721 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
725 * Let's go further. For device key we must open "Device Parameters"
726 * subkey and create it if it doesn't exist yet.
729 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
730 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
731 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
732 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
733 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
734 ZwClose(ObjectAttributes
.RootDirectory
);
744 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
751 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
755 if (PopSystemPowerDeviceNode
)
757 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
758 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
759 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
761 return STATUS_SUCCESS
;
764 return STATUS_UNSUCCESSFUL
;
769 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
771 USHORT i
= 0, FoundIndex
= 0xFFFF;
775 /* Acquire the lock */
776 ExAcquireFastMutex(&IopBusTypeGuidList
->Lock
);
778 /* Loop all entries */
779 while (i
< IopBusTypeGuidList
->GuidCount
)
781 /* Try to find a match */
782 if (RtlCompareMemory(BusTypeGuid
,
783 &IopBusTypeGuidList
->Guids
[i
],
784 sizeof(GUID
)) == sizeof(GUID
))
793 /* Check if we have to grow the list */
794 if (IopBusTypeGuidList
->GuidCount
)
796 /* Calculate the new size */
797 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
798 (sizeof(GUID
) * IopBusTypeGuidList
->GuidCount
);
800 /* Allocate the new copy */
801 NewList
= ExAllocatePool(PagedPool
, NewSize
);
803 /* Now copy them, decrease the size too */
804 NewSize
-= sizeof(GUID
);
805 RtlCopyMemory(NewList
, IopBusTypeGuidList
, NewSize
);
807 /* Free the old list */
808 ExFreePool(IopBusTypeGuidList
);
810 /* Use the new buffer */
811 IopBusTypeGuidList
= NewList
;
814 /* Copy the new GUID */
815 RtlCopyMemory(&IopBusTypeGuidList
->Guids
[IopBusTypeGuidList
->GuidCount
],
819 /* The new entry is the index */
820 FoundIndex
= (USHORT
)IopBusTypeGuidList
->GuidCount
;
821 IopBusTypeGuidList
->GuidCount
++;
824 ExReleaseFastMutex(&IopBusTypeGuidList
->Lock
);
830 * Creates a device node
833 * ParentNode = Pointer to parent device node
834 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
835 * to have the root device node create one
836 * (eg. for legacy drivers)
837 * DeviceNode = Pointer to storage for created device node
843 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
844 PDEVICE_OBJECT PhysicalDeviceObject
,
845 PUNICODE_STRING ServiceName
,
846 PDEVICE_NODE
*DeviceNode
)
852 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
853 ParentNode
, PhysicalDeviceObject
, ServiceName
);
855 Node
= (PDEVICE_NODE
)ExAllocatePool(NonPagedPool
, sizeof(DEVICE_NODE
));
858 return STATUS_INSUFFICIENT_RESOURCES
;
861 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
863 if (!PhysicalDeviceObject
)
865 Status
= PnpRootCreateDevice(ServiceName
, &PhysicalDeviceObject
);
866 if (!NT_SUCCESS(Status
))
872 /* This is for drivers passed on the command line to ntoskrnl.exe */
873 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
874 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
877 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
879 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
883 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
884 Node
->Parent
= ParentNode
;
885 Node
->NextSibling
= ParentNode
->Child
;
886 if (ParentNode
->Child
!= NULL
)
888 ParentNode
->Child
->PrevSibling
= Node
;
890 ParentNode
->Child
= Node
;
891 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
892 Node
->Level
= ParentNode
->Level
+ 1;
897 return STATUS_SUCCESS
;
901 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
905 /* All children must be deleted before a parent is deleted */
906 ASSERT(!DeviceNode
->Child
);
908 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
910 ASSERT(DeviceNode
->PhysicalDeviceObject
);
912 ObDereferenceObject(DeviceNode
->PhysicalDeviceObject
);
914 /* Unlink from parent if it exists */
916 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
918 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
921 /* Unlink from sibling list */
923 if (DeviceNode
->PrevSibling
)
925 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
928 if (DeviceNode
->NextSibling
)
930 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
933 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
935 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
937 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
939 if (DeviceNode
->ResourceList
)
941 ExFreePool(DeviceNode
->ResourceList
);
944 if (DeviceNode
->ResourceListTranslated
)
946 ExFreePool(DeviceNode
->ResourceListTranslated
);
949 if (DeviceNode
->ResourceRequirements
)
951 ExFreePool(DeviceNode
->ResourceRequirements
);
954 if (DeviceNode
->BootResources
)
956 ExFreePool(DeviceNode
->BootResources
);
959 ExFreePool(DeviceNode
);
961 return STATUS_SUCCESS
;
965 IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject
,
966 PIO_STATUS_BLOCK IoStatusBlock
,
968 PIO_STACK_LOCATION Stack OPTIONAL
)
970 PDEVICE_OBJECT TopDeviceObject
;
971 PIO_STACK_LOCATION IrpSp
;
976 /* Always call the top of the device stack */
977 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
984 Irp
= IoBuildSynchronousFsdRequest(
993 /* Most of PNP IRPs are initialized with a status code of
994 STATUS_NOT_IMPLEMENTED */
995 if (MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
996 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
998 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
999 Irp
->IoStatus
.Information
= 0;
1001 IrpSp
= IoGetNextIrpStackLocation(Irp
);
1002 IrpSp
->MinorFunction
= (UCHAR
)MinorFunction
;
1006 RtlCopyMemory(&IrpSp
->Parameters
,
1008 sizeof(Stack
->Parameters
));
1011 Status
= IoCallDriver(TopDeviceObject
, Irp
);
1012 if (Status
== STATUS_PENDING
)
1014 KeWaitForSingleObject(&Event
,
1019 Status
= IoStatusBlock
->Status
;
1022 ObDereferenceObject(TopDeviceObject
);
1029 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1031 PDEVICE_NODE ParentDeviceNode
;
1032 PDEVICE_NODE ChildDeviceNode
;
1035 /* Copy context data so we don't overwrite it in subsequent calls to this function */
1036 ParentDeviceNode
= Context
->DeviceNode
;
1038 /* Call the action routine */
1039 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
1040 if (!NT_SUCCESS(Status
))
1045 /* Traversal of all children nodes */
1046 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
1047 ChildDeviceNode
!= NULL
;
1048 ChildDeviceNode
= ChildDeviceNode
->NextSibling
)
1050 /* Pass the current device node to the action routine */
1051 Context
->DeviceNode
= ChildDeviceNode
;
1053 Status
= IopTraverseDeviceTreeNode(Context
);
1054 if (!NT_SUCCESS(Status
))
1065 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1069 DPRINT("Context 0x%p\n", Context
);
1071 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %x Context 0x%p)\n",
1072 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1074 /* Start from the specified device node */
1075 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1077 /* Recursively traverse the device tree */
1078 Status
= IopTraverseDeviceTreeNode(Context
);
1079 if (Status
== STATUS_UNSUCCESSFUL
)
1081 /* The action routine just wanted to terminate the traversal with status
1082 code STATUS_SUCCESS */
1083 Status
= STATUS_SUCCESS
;
1092 IopCreateDeviceKeyPath(PWSTR Path
,
1095 OBJECT_ATTRIBUTES ObjectAttributes
;
1096 WCHAR KeyBuffer
[MAX_PATH
];
1097 UNICODE_STRING KeyName
;
1105 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
1107 return STATUS_INVALID_PARAMETER
;
1110 wcsncpy (KeyBuffer
, Path
, MAX_PATH
-1);
1112 /* Skip \\Registry\\ */
1113 Current
= KeyBuffer
;
1114 Current
= wcschr (Current
, L
'\\') + 1;
1115 Current
= wcschr (Current
, L
'\\') + 1;
1119 Next
= wcschr (Current
, L
'\\');
1129 RtlInitUnicodeString (&KeyName
, KeyBuffer
);
1130 InitializeObjectAttributes (&ObjectAttributes
,
1132 OBJ_CASE_INSENSITIVE
,
1136 DPRINT("Create '%S'\n", KeyName
.Buffer
);
1138 Status
= ZwCreateKey (&KeyHandle
,
1145 if (!NT_SUCCESS (Status
))
1147 DPRINT ("ZwCreateKey() failed with status %x\n", Status
);
1153 *Handle
= KeyHandle
;
1154 return STATUS_SUCCESS
;
1158 ZwClose (KeyHandle
);
1165 return STATUS_UNSUCCESSFUL
;
1171 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1172 PDEVICE_NODE DeviceNode
)
1174 OBJECT_ATTRIBUTES ObjectAttributes
;
1175 UNICODE_STRING KeyName
;
1178 ULONG ListSize
, ResultLength
;
1181 DPRINT("IopSetDeviceInstanceData() called\n");
1183 /* Create the 'LogConf' key */
1184 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1185 InitializeObjectAttributes(&ObjectAttributes
,
1187 OBJ_CASE_INSENSITIVE
,
1190 Status
= ZwCreateKey(&LogConfKey
,
1197 if (NT_SUCCESS(Status
))
1199 /* Set 'BootConfig' value */
1200 if (DeviceNode
->BootResources
!= NULL
)
1202 ResCount
= DeviceNode
->BootResources
->Count
;
1205 ListSize
= CM_RESOURCE_LIST_SIZE(DeviceNode
->BootResources
);
1207 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1208 Status
= ZwSetValueKey(LogConfKey
,
1212 &DeviceNode
->BootResources
,
1217 /* Set 'BasicConfigVector' value */
1218 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1219 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1221 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1222 Status
= ZwSetValueKey(LogConfKey
,
1225 REG_RESOURCE_REQUIREMENTS_LIST
,
1226 DeviceNode
->ResourceRequirements
,
1227 DeviceNode
->ResourceRequirements
->ListSize
);
1230 ZwClose(LogConfKey
);
1233 /* Set the 'ConfigFlags' value */
1234 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1235 Status
= ZwQueryValueKey(InstanceKey
,
1237 KeyValueBasicInformation
,
1241 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1243 /* Write the default value */
1244 ULONG DefaultConfigFlags
= 0;
1245 Status
= ZwSetValueKey(InstanceKey
,
1249 &DefaultConfigFlags
,
1250 sizeof(DefaultConfigFlags
));
1254 if (DeviceNode
->PhysicalDeviceObject
!= NULL
)
1256 /* Create the 'Control' key */
1257 RtlInitUnicodeString(&KeyName
,
1259 InitializeObjectAttributes(&ObjectAttributes
,
1261 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1264 Status
= ZwCreateKey(&LogConfKey
,
1269 REG_OPTION_VOLATILE
,
1271 if (NT_SUCCESS(Status
))
1273 ULONG Reference
= (ULONG
)DeviceNode
->PhysicalDeviceObject
;
1274 RtlInitUnicodeString(&KeyName
,
1275 L
"DeviceReference");
1276 Status
= ZwSetValueKey(LogConfKey
,
1283 ZwClose(LogConfKey
);
1288 DPRINT("IopSetDeviceInstanceData() done\n");
1290 return STATUS_SUCCESS
;
1295 IopAssignDeviceResources(
1296 IN PDEVICE_NODE DeviceNode
,
1297 OUT ULONG
*pRequiredSize
)
1299 PIO_RESOURCE_LIST ResourceList
;
1300 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor
;
1301 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
;
1302 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1303 ULONG NumberOfResources
= 0;
1308 if (!DeviceNode
->BootResources
&& !DeviceNode
->ResourceRequirements
)
1310 /* No resource needed for this device */
1311 DeviceNode
->ResourceList
= NULL
;
1312 return STATUS_SUCCESS
;
1315 /* Fill DeviceNode->ResourceList
1316 * FIXME: the PnP arbiter should go there!
1317 * Actually, use the BootResources if provided, else the resource list #0
1320 if (DeviceNode
->BootResources
)
1322 /* Browse the boot resources to know if we have some custom structures */
1323 Size
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1324 for (i
= 0; i
< DeviceNode
->BootResources
->Count
; i
++)
1326 pPartialResourceList
= &DeviceNode
->BootResources
->List
[i
].PartialResourceList
;
1327 if (pPartialResourceList
->Version
!= 1 || pPartialResourceList
->Revision
!= 1)
1329 Status
= STATUS_REVISION_MISMATCH
;
1332 Size
+= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
)
1333 + pPartialResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1334 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1336 if (pPartialResourceList
->PartialDescriptors
[j
].Type
== CmResourceTypeDeviceSpecific
)
1337 Size
+= pPartialResourceList
->PartialDescriptors
[j
].u
.DeviceSpecificData
.DataSize
;
1341 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1342 if (!DeviceNode
->ResourceList
)
1344 Status
= STATUS_NO_MEMORY
;
1347 RtlCopyMemory(DeviceNode
->ResourceList
, DeviceNode
->BootResources
, Size
);
1349 *pRequiredSize
= Size
;
1350 return STATUS_SUCCESS
;
1353 /* Ok, here, we have to use the device requirement list */
1354 ResourceList
= &DeviceNode
->ResourceRequirements
->List
[0];
1355 if (ResourceList
->Version
!= 1 || ResourceList
->Revision
!= 1)
1357 Status
= STATUS_REVISION_MISMATCH
;
1361 Size
= sizeof(CM_RESOURCE_LIST
) + ResourceList
->Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1362 *pRequiredSize
= Size
;
1363 DeviceNode
->ResourceList
= ExAllocatePool(PagedPool
, Size
);
1364 if (!DeviceNode
->ResourceList
)
1366 Status
= STATUS_NO_MEMORY
;
1370 DeviceNode
->ResourceList
->Count
= 1;
1371 DeviceNode
->ResourceList
->List
[0].InterfaceType
= DeviceNode
->ResourceRequirements
->InterfaceType
;
1372 DeviceNode
->ResourceList
->List
[0].BusNumber
= DeviceNode
->ResourceRequirements
->BusNumber
;
1373 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Version
= 1;
1374 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Revision
= 1;
1376 for (i
= 0; i
< ResourceList
->Count
; i
++)
1378 ResourceDescriptor
= &ResourceList
->Descriptors
[i
];
1380 if (ResourceDescriptor
->Option
== 0 || ResourceDescriptor
->Option
== IO_RESOURCE_PREFERRED
)
1382 DescriptorRaw
= &DeviceNode
->ResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[NumberOfResources
];
1383 NumberOfResources
++;
1385 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1386 DescriptorRaw
->Type
= ResourceDescriptor
->Type
;
1387 DescriptorRaw
->ShareDisposition
= ResourceDescriptor
->ShareDisposition
;
1388 DescriptorRaw
->Flags
= ResourceDescriptor
->Flags
;
1389 switch (ResourceDescriptor
->Type
)
1391 case CmResourceTypePort
:
1393 DescriptorRaw
->u
.Port
.Start
= ResourceDescriptor
->u
.Port
.MinimumAddress
;
1394 DescriptorRaw
->u
.Port
.Length
= ResourceDescriptor
->u
.Port
.Length
;
1397 case CmResourceTypeInterrupt
:
1399 INTERFACE_TYPE BusType
;
1404 DescriptorRaw
->u
.Interrupt
.Level
= 0;
1405 DescriptorRaw
->u
.Interrupt
.Vector
= ResourceDescriptor
->u
.Interrupt
.MinimumVector
;
1406 /* FIXME: HACK: if we have a PCI device, we try
1407 * to keep the IRQ assigned by the BIOS */
1408 if (NT_SUCCESS(IoGetDeviceProperty(
1409 DeviceNode
->PhysicalDeviceObject
,
1410 DevicePropertyLegacyBusType
,
1411 sizeof(INTERFACE_TYPE
),
1413 &ret
)) && BusType
== PCIBus
)
1415 /* We have a PCI bus */
1416 if (NT_SUCCESS(IoGetDeviceProperty(
1417 DeviceNode
->PhysicalDeviceObject
,
1418 DevicePropertyAddress
,
1421 &ret
)) && SlotNumber
> 0)
1423 /* We have a good slot number */
1424 ret
= HalGetBusDataByOffset(PCIConfiguration
,
1425 DeviceNode
->ResourceRequirements
->BusNumber
,
1428 0x3c /* PCI_INTERRUPT_LINE */,
1430 if (ret
!= 0 && ret
!= 2
1431 && ResourceDescriptor
->u
.Interrupt
.MinimumVector
<= Irq
1432 && ResourceDescriptor
->u
.Interrupt
.MaximumVector
>= Irq
)
1434 /* The device already has an assigned IRQ */
1435 DescriptorRaw
->u
.Interrupt
.Vector
= Irq
;
1439 DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n",
1440 DescriptorRaw
->u
.Interrupt
.Vector
,
1441 &DeviceNode
->InstancePath
);
1442 Irq
= (UCHAR
)DescriptorRaw
->u
.Interrupt
.Vector
;
1443 ret
= HalSetBusDataByOffset(PCIConfiguration
,
1444 DeviceNode
->ResourceRequirements
->BusNumber
,
1447 0x3c /* PCI_INTERRUPT_LINE */,
1449 if (ret
== 0 || ret
== 2)
1456 case CmResourceTypeMemory
:
1458 DescriptorRaw
->u
.Memory
.Start
= ResourceDescriptor
->u
.Memory
.MinimumAddress
;
1459 DescriptorRaw
->u
.Memory
.Length
= ResourceDescriptor
->u
.Memory
.Length
;
1462 case CmResourceTypeDma
:
1464 DescriptorRaw
->u
.Dma
.Channel
= ResourceDescriptor
->u
.Dma
.MinimumChannel
;
1465 DescriptorRaw
->u
.Dma
.Port
= 0; /* FIXME */
1466 DescriptorRaw
->u
.Dma
.Reserved1
= 0;
1469 case CmResourceTypeBusNumber
:
1471 DescriptorRaw
->u
.BusNumber
.Start
= ResourceDescriptor
->u
.BusNumber
.MinBusNumber
;
1472 DescriptorRaw
->u
.BusNumber
.Length
= ResourceDescriptor
->u
.BusNumber
.Length
;
1473 DescriptorRaw
->u
.BusNumber
.Reserved
= ResourceDescriptor
->u
.BusNumber
.Reserved
;
1476 /*CmResourceTypeDevicePrivate:
1477 case CmResourceTypePcCardConfig:
1478 case CmResourceTypeMfCardConfig:
1481 &DescriptorRaw->u.DevicePrivate,
1482 &ResourceDescriptor->u.DevicePrivate,
1483 sizeof(ResourceDescriptor->u.DevicePrivate));
1485 &DescriptorTranslated->u.DevicePrivate,
1486 &ResourceDescriptor->u.DevicePrivate,
1487 sizeof(ResourceDescriptor->u.DevicePrivate));
1491 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor
->Type
);
1492 NumberOfResources
--;
1498 DeviceNode
->ResourceList
->List
[0].PartialResourceList
.Count
= NumberOfResources
;
1500 return STATUS_SUCCESS
;
1503 if (DeviceNode
->ResourceList
)
1505 ExFreePool(DeviceNode
->ResourceList
);
1506 DeviceNode
->ResourceList
= NULL
;
1513 IopTranslateDeviceResources(
1514 IN PDEVICE_NODE DeviceNode
,
1515 IN ULONG RequiredSize
)
1517 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList
;
1518 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw
, DescriptorTranslated
;
1522 if (!DeviceNode
->ResourceList
)
1524 DeviceNode
->ResourceListTranslated
= NULL
;
1525 return STATUS_SUCCESS
;
1528 /* That's easy to translate a resource list. Just copy the
1529 * untranslated one and change few fields in the copy
1531 DeviceNode
->ResourceListTranslated
= ExAllocatePool(PagedPool
, RequiredSize
);
1532 if (!DeviceNode
->ResourceListTranslated
)
1534 Status
=STATUS_NO_MEMORY
;
1537 RtlCopyMemory(DeviceNode
->ResourceListTranslated
, DeviceNode
->ResourceList
, RequiredSize
);
1539 for (i
= 0; i
< DeviceNode
->ResourceList
->Count
; i
++)
1541 pPartialResourceList
= &DeviceNode
->ResourceList
->List
[i
].PartialResourceList
;
1542 for (j
= 0; j
< pPartialResourceList
->Count
; j
++)
1544 DescriptorRaw
= &pPartialResourceList
->PartialDescriptors
[j
];
1545 DescriptorTranslated
= &DeviceNode
->ResourceListTranslated
->List
[i
].PartialResourceList
.PartialDescriptors
[j
];
1546 switch (DescriptorRaw
->Type
)
1548 case CmResourceTypePort
:
1550 ULONG AddressSpace
= 0; /* IO space */
1551 if (!HalTranslateBusAddress(
1552 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1553 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1554 DescriptorRaw
->u
.Port
.Start
,
1556 &DescriptorTranslated
->u
.Port
.Start
))
1558 Status
= STATUS_UNSUCCESSFUL
;
1563 case CmResourceTypeInterrupt
:
1565 DescriptorTranslated
->u
.Interrupt
.Vector
= HalGetInterruptVector(
1566 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1567 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1568 DescriptorRaw
->u
.Interrupt
.Level
,
1569 DescriptorRaw
->u
.Interrupt
.Vector
,
1570 (PKIRQL
)&DescriptorTranslated
->u
.Interrupt
.Level
,
1571 &DescriptorRaw
->u
.Interrupt
.Affinity
);
1574 case CmResourceTypeMemory
:
1576 ULONG AddressSpace
= 1; /* Memory space */
1577 if (!HalTranslateBusAddress(
1578 DeviceNode
->ResourceList
->List
[i
].InterfaceType
,
1579 DeviceNode
->ResourceList
->List
[i
].BusNumber
,
1580 DescriptorRaw
->u
.Memory
.Start
,
1582 &DescriptorTranslated
->u
.Memory
.Start
))
1584 Status
= STATUS_UNSUCCESSFUL
;
1589 case CmResourceTypeDma
:
1590 case CmResourceTypeBusNumber
:
1591 case CmResourceTypeDeviceSpecific
:
1595 DPRINT1("Unknown resource descriptor type 0x%x\n", DescriptorRaw
->Type
);
1596 Status
= STATUS_NOT_IMPLEMENTED
;
1601 return STATUS_SUCCESS
;
1604 /* Yes! Also delete ResourceList because ResourceList and
1605 * ResourceListTranslated should be a pair! */
1606 ExFreePool(DeviceNode
->ResourceList
);
1607 DeviceNode
->ResourceList
= NULL
;
1608 if (DeviceNode
->ResourceListTranslated
)
1610 ExFreePool(DeviceNode
->ResourceListTranslated
);
1611 DeviceNode
->ResourceList
= NULL
;
1618 * IopGetParentIdPrefix
1620 * Retrieve (or create) a string which identifies a device.
1624 * Pointer to device node.
1626 * Pointer to the string where is returned the parent node identifier
1629 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1630 * valid and its Buffer field is NULL-terminated. The caller needs to
1631 * to free the string with RtlFreeUnicodeString when it is no longer
1636 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1637 PUNICODE_STRING ParentIdPrefix
)
1639 ULONG KeyNameBufferLength
;
1640 PWSTR KeyNameBuffer
= NULL
;
1641 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1642 UNICODE_STRING KeyName
;
1643 UNICODE_STRING KeyValue
;
1644 UNICODE_STRING ValueName
;
1645 OBJECT_ATTRIBUTES ObjectAttributes
;
1650 /* HACK: As long as some devices have a NULL device
1651 * instance path, the following test is required :(
1653 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1655 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1656 &DeviceNode
->InstancePath
);
1657 return STATUS_UNSUCCESSFUL
;
1660 /* 1. Try to retrieve ParentIdPrefix from registry */
1661 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1662 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1663 if (!ParentIdPrefixInformation
)
1665 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1668 KeyNameBuffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1671 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1674 wcscpy(KeyNameBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1675 wcscat(KeyNameBuffer
, DeviceNode
->Parent
->InstancePath
.Buffer
);
1676 RtlInitUnicodeString(&KeyName
, KeyNameBuffer
);
1677 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
, NULL
, NULL
);
1678 Status
= ZwOpenKey(&hKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
1679 if (!NT_SUCCESS(Status
))
1681 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1682 Status
= ZwQueryValueKey(
1684 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1685 KeyNameBufferLength
, &KeyNameBufferLength
);
1686 if (NT_SUCCESS(Status
))
1688 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1689 Status
= STATUS_UNSUCCESSFUL
;
1692 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1693 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1697 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1699 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1700 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1704 /* 2. Create the ParentIdPrefix value */
1705 crc32
= RtlComputeCrc32(0,
1706 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1707 DeviceNode
->Parent
->InstancePath
.Length
);
1709 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1710 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1712 /* 3. Try to write the ParentIdPrefix to registry */
1713 Status
= ZwSetValueKey(hKey
,
1717 (PVOID
)KeyValue
.Buffer
,
1718 (wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1721 if (NT_SUCCESS(Status
))
1723 /* Duplicate the string to return it */
1724 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1726 ExFreePool(ParentIdPrefixInformation
);
1727 ExFreePool(KeyNameBuffer
);
1735 * IopActionInterrogateDeviceStack
1737 * Retrieve information for all (direct) child nodes of a parent node.
1741 * Pointer to device node.
1743 * Pointer to parent node to retrieve child node information for.
1746 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1747 * when we reach a device node which is not a direct child of the device
1748 * node for which we retrieve information of child nodes for. Any errors
1749 * that occur is logged instead so that all child services have a chance
1750 * of being interrogated.
1754 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1757 IO_STATUS_BLOCK IoStatusBlock
;
1758 PDEVICE_NODE ParentDeviceNode
;
1759 WCHAR InstancePath
[MAX_PATH
];
1760 IO_STACK_LOCATION Stack
;
1766 ULONG RequiredLength
;
1768 HANDLE InstanceKey
= NULL
;
1769 UNICODE_STRING ValueName
;
1770 UNICODE_STRING ParentIdPrefix
= { 0 };
1771 DEVICE_CAPABILITIES DeviceCapabilities
;
1773 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1774 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1776 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1779 * We are called for the parent too, but we don't need to do special
1780 * handling for this node
1783 if (DeviceNode
== ParentDeviceNode
)
1785 DPRINT("Success\n");
1786 return STATUS_SUCCESS
;
1790 * Make sure this device node is a direct child of the parent device node
1791 * that is given as an argument
1794 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1796 /* Stop the traversal immediately and indicate successful operation */
1798 return STATUS_UNSUCCESSFUL
;
1802 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1803 if (!NT_SUCCESS(Status
))
1805 DPRINT("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1810 * FIXME: For critical errors, cleanup and disable device, but always
1811 * return STATUS_SUCCESS.
1814 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1816 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1817 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1821 if (NT_SUCCESS(Status
))
1823 /* Copy the device id string */
1824 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1827 * FIXME: Check for valid characters, if there is invalid characters
1833 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1836 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n");
1838 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1839 if (!NT_SUCCESS(Status
))
1841 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1844 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCapabilities
+ 4);
1846 if (!DeviceCapabilities
.UniqueID
)
1848 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1849 DPRINT("Instance ID is not unique\n");
1850 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1851 if (!NT_SUCCESS(Status
))
1853 DPRINT("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1857 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1859 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1860 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1864 if (NT_SUCCESS(Status
))
1866 /* Append the instance id string */
1867 wcscat(InstancePath
, L
"\\");
1868 if (ParentIdPrefix
.Length
> 0)
1870 /* Add information from parent bus device to InstancePath */
1871 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1872 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1873 wcscat(InstancePath
, L
"&");
1875 if (IoStatusBlock
.Information
)
1876 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1879 * FIXME: Check for valid characters, if there is invalid characters
1885 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1887 RtlFreeUnicodeString(&ParentIdPrefix
);
1889 if (!RtlCreateUnicodeString(&DeviceNode
->InstancePath
, InstancePath
))
1891 DPRINT("No resources\n");
1892 /* FIXME: Cleanup and disable device */
1895 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
1898 * Create registry key for the instance id, if it doesn't exist yet
1900 KeyBuffer
= ExAllocatePool(
1902 (49 * sizeof(WCHAR
)) + DeviceNode
->InstancePath
.Length
);
1903 wcscpy(KeyBuffer
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1904 wcscat(KeyBuffer
, DeviceNode
->InstancePath
.Buffer
);
1905 Status
= IopCreateDeviceKeyPath(KeyBuffer
, &InstanceKey
);
1906 ExFreePool(KeyBuffer
);
1907 if (!NT_SUCCESS(Status
))
1909 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
1914 /* Set 'Capabilities' value */
1915 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
1916 Status
= ZwSetValueKey(InstanceKey
,
1920 (PVOID
)&DeviceNode
->CapabilityFlags
,
1923 /* Set 'UINumber' value */
1924 if (DeviceCapabilities
.UINumber
!= (ULONG
)-1)
1926 RtlInitUnicodeString(&ValueName
, L
"UINumber");
1927 Status
= ZwSetValueKey(InstanceKey
,
1931 &DeviceCapabilities
.UINumber
,
1936 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1938 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1939 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1943 if (NT_SUCCESS(Status
))
1946 * FIXME: Check for valid characters, if there is invalid characters
1950 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1951 DPRINT("Hardware IDs:\n");
1954 DPRINT(" %S\n", Ptr
);
1955 Length
= wcslen(Ptr
) + 1;
1958 TotalLength
+= Length
;
1960 DPRINT("TotalLength: %hu\n", TotalLength
);
1963 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1964 Status
= ZwSetValueKey(InstanceKey
,
1968 (PVOID
)IoStatusBlock
.Information
,
1969 (TotalLength
+ 1) * sizeof(WCHAR
));
1970 if (!NT_SUCCESS(Status
))
1972 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1977 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1980 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1982 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1983 Status
= IopInitiatePnpIrp(
1984 DeviceNode
->PhysicalDeviceObject
,
1988 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1991 * FIXME: Check for valid characters, if there is invalid characters
1995 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1996 DPRINT("Compatible IDs:\n");
1999 DPRINT(" %S\n", Ptr
);
2000 Length
= wcslen(Ptr
) + 1;
2003 TotalLength
+= Length
;
2005 DPRINT("TotalLength: %hu\n", TotalLength
);
2008 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
2009 Status
= ZwSetValueKey(InstanceKey
,
2013 (PVOID
)IoStatusBlock
.Information
,
2014 (TotalLength
+ 1) * sizeof(WCHAR
));
2015 if (!NT_SUCCESS(Status
))
2017 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
2022 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2025 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2027 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2028 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2029 Status
= IopInitiatePnpIrp(
2030 DeviceNode
->PhysicalDeviceObject
,
2032 IRP_MN_QUERY_DEVICE_TEXT
,
2034 /* This key is mandatory, so even if the Irp fails, we still write it */
2035 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2036 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2038 if (NT_SUCCESS(Status
) &&
2039 IoStatusBlock
.Information
&&
2040 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2042 /* This key is overriden when a driver is installed. Don't write the
2043 * new description if another one already exists */
2044 Status
= ZwSetValueKey(InstanceKey
,
2048 (PVOID
)IoStatusBlock
.Information
,
2049 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2053 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2054 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2056 Status
= ZwSetValueKey(InstanceKey
,
2061 DeviceDesc
.MaximumLength
);
2063 if (!NT_SUCCESS(Status
))
2065 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2071 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2073 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2074 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2075 Status
= IopInitiatePnpIrp(
2076 DeviceNode
->PhysicalDeviceObject
,
2078 IRP_MN_QUERY_DEVICE_TEXT
,
2080 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2082 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2083 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2084 Status
= ZwSetValueKey(InstanceKey
,
2088 (PVOID
)IoStatusBlock
.Information
,
2089 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2090 if (!NT_SUCCESS(Status
))
2092 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2097 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2100 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2102 Status
= IopInitiatePnpIrp(
2103 DeviceNode
->PhysicalDeviceObject
,
2105 IRP_MN_QUERY_BUS_INFORMATION
,
2107 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2109 PPNP_BUS_INFORMATION BusInformation
=
2110 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2112 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2113 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2114 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2115 ExFreePool(BusInformation
);
2119 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2121 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2122 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2123 DeviceNode
->ChildBusTypeIndex
= -1;
2126 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2128 Status
= IopInitiatePnpIrp(
2129 DeviceNode
->PhysicalDeviceObject
,
2131 IRP_MN_QUERY_RESOURCES
,
2133 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2135 DeviceNode
->BootResources
=
2136 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2137 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2141 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2142 DeviceNode
->BootResources
= NULL
;
2145 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2147 Status
= IopInitiatePnpIrp(
2148 DeviceNode
->PhysicalDeviceObject
,
2150 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2152 if (NT_SUCCESS(Status
))
2154 DeviceNode
->ResourceRequirements
=
2155 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2156 if (IoStatusBlock
.Information
)
2157 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2159 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2163 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2164 DeviceNode
->ResourceRequirements
= NULL
;
2168 if (InstanceKey
!= NULL
)
2170 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2173 ZwClose(InstanceKey
);
2175 DeviceNode
->Flags
|= DNF_PROCESSED
;
2177 /* Report the device to the user-mode pnp manager */
2178 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2179 &DeviceNode
->InstancePath
);
2181 return STATUS_SUCCESS
;
2185 * IopActionConfigureChildServices
2187 * Retrieve configuration for all (direct) child nodes of a parent node.
2191 * Pointer to device node.
2193 * Pointer to parent node to retrieve child node configuration for.
2196 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2197 * when we reach a device node which is not a direct child of the device
2198 * node for which we configure child services for. Any errors that occur is
2199 * logged instead so that all child services have a chance of beeing
2204 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2207 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2208 PDEVICE_NODE ParentDeviceNode
;
2209 PUNICODE_STRING Service
;
2210 UNICODE_STRING ClassGUID
;
2213 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2215 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2218 * We are called for the parent too, but we don't need to do special
2219 * handling for this node
2221 if (DeviceNode
== ParentDeviceNode
)
2223 DPRINT("Success\n");
2224 return STATUS_SUCCESS
;
2228 * Make sure this device node is a direct child of the parent device node
2229 * that is given as an argument
2231 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2233 /* Stop the traversal immediately and indicate successful operation */
2235 return STATUS_UNSUCCESSFUL
;
2238 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2240 WCHAR RegKeyBuffer
[MAX_PATH
];
2241 UNICODE_STRING RegKey
;
2244 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2245 RegKey
.Buffer
= RegKeyBuffer
;
2248 * Retrieve configuration from Enum key
2251 Service
= &DeviceNode
->ServiceName
;
2253 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2254 RtlInitUnicodeString(Service
, NULL
);
2255 RtlInitUnicodeString(&ClassGUID
, NULL
);
2257 QueryTable
[0].Name
= L
"Service";
2258 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
2259 QueryTable
[0].EntryContext
= Service
;
2261 QueryTable
[1].Name
= L
"ClassGUID";
2262 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2263 QueryTable
[1].EntryContext
= &ClassGUID
;
2264 QueryTable
[1].DefaultType
= REG_SZ
;
2265 QueryTable
[1].DefaultData
= L
"";
2266 QueryTable
[1].DefaultLength
= 0;
2268 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2269 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2271 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2272 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2274 if (!NT_SUCCESS(Status
))
2276 /* FIXME: Log the error */
2277 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2278 &DeviceNode
->InstancePath
, Status
);
2279 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2280 return STATUS_SUCCESS
;
2283 if (Service
->Buffer
== NULL
)
2285 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2287 if (ClassGUID
.Length
!= 0)
2289 /* Device has a ClassGUID value, but no Service value.
2290 * Suppose it is using the NULL driver, so state the
2291 * device is started */
2292 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2293 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2294 DeviceNode
->Flags
|= DN_STARTED
;
2296 return STATUS_SUCCESS
;
2299 DPRINT("Got Service %S\n", Service
->Buffer
);
2302 return STATUS_SUCCESS
;
2306 * IopActionInitChildServices
2308 * Initialize the service for all (direct) child nodes of a parent node
2312 * Pointer to device node.
2314 * Pointer to parent node to initialize child node services for.
2316 * Load only driver marked as boot start.
2319 * If the driver image for a service is not loaded and initialized
2320 * it is done here too. We only return a status code indicating an
2321 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2322 * not a direct child of the device node for which we initialize
2323 * child services for. Any errors that occur is logged instead so
2324 * that all child services have a chance of being initialized.
2328 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2330 BOOLEAN BootDrivers
)
2332 PDEVICE_NODE ParentDeviceNode
;
2335 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2338 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2341 * We are called for the parent too, but we don't need to do special
2342 * handling for this node
2344 if (DeviceNode
== ParentDeviceNode
)
2346 DPRINT("Success\n");
2347 return STATUS_SUCCESS
;
2351 * Make sure this device node is a direct child of the parent device node
2352 * that is given as an argument
2355 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2358 * Stop the traversal immediately and indicate unsuccessful operation
2361 return STATUS_UNSUCCESSFUL
;
2365 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2366 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2367 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2369 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2370 PDRIVER_OBJECT DriverObject
;
2372 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2373 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2375 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2377 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2378 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2379 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2383 /* get existing DriverObject pointer */
2384 Status
= IopGetDriverObject(
2386 &DeviceNode
->ServiceName
,
2389 if (NT_SUCCESS(Status
))
2391 /* Attach lower level filter drivers. */
2392 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2393 /* Initialize the function driver for the device node */
2394 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2395 if (NT_SUCCESS(Status
))
2397 /* Attach upper level filter drivers. */
2398 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2399 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2401 Status
= IopStartDevice(DeviceNode
);
2408 * Don't disable when trying to load only boot drivers
2412 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2413 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2414 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2415 CPRINT("Initialization of service %S failed (Status %x)\n",
2416 DeviceNode
->ServiceName
.Buffer
, Status
);
2422 DPRINT("Device %wZ is disabled or already initialized\n",
2423 &DeviceNode
->InstancePath
);
2426 return STATUS_SUCCESS
;
2430 * IopActionInitAllServices
2432 * Initialize the service for all (direct) child nodes of a parent node. This
2433 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2437 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2440 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2444 * IopActionInitBootServices
2446 * Initialize the boot start services for all (direct) child nodes of a
2447 * parent node. This function just calls IopActionInitChildServices with
2448 * BootDrivers = TRUE.
2451 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2454 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2458 * IopInitializePnpServices
2460 * Initialize services for discovered children
2464 * Top device node to start initializing services.
2467 * When set to TRUE, only drivers marked as boot start will
2468 * be loaded. Otherwise, all drivers will be loaded.
2474 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2475 IN BOOLEAN BootDrivers
)
2477 DEVICETREE_TRAVERSE_CONTEXT Context
;
2479 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2483 IopInitDeviceTreeTraverseContext(
2486 IopActionInitBootServices
,
2491 IopInitDeviceTreeTraverseContext(
2494 IopActionInitAllServices
,
2498 return IopTraverseDeviceTree(&Context
);
2501 /* Invalidate device list enumerated by a device node.
2502 * The call can be make synchronous by defining the Event field
2503 * of the INVALIDATE_DEVICE_RELATION_DATA structure
2506 IopInvalidateDeviceRelations(
2507 IN PDEVICE_OBJECT DeviceObject
,
2508 IN PVOID InvalidateContext
) /* PINVALIDATE_DEVICE_RELATION_DATA */
2510 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
2511 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2512 PKEVENT Event
= Data
->Event
;
2513 DEVICETREE_TRAVERSE_CONTEXT Context
;
2514 PDEVICE_RELATIONS DeviceRelations
;
2515 IO_STATUS_BLOCK IoStatusBlock
;
2516 PDEVICE_NODE ChildDeviceNode
;
2517 IO_STACK_LOCATION Stack
;
2518 BOOLEAN BootDrivers
;
2519 OBJECT_ATTRIBUTES ObjectAttributes
;
2520 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
2525 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2527 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2529 Stack
.Parameters
.QueryDeviceRelations
.Type
= Data
->Type
;
2531 Status
= IopInitiatePnpIrp(
2534 IRP_MN_QUERY_DEVICE_RELATIONS
,
2536 if (!NT_SUCCESS(Status
))
2538 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2542 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2544 if (!DeviceRelations
|| DeviceRelations
->Count
<= 0)
2546 DPRINT("No PDOs\n");
2547 if (DeviceRelations
)
2549 ExFreePool(DeviceRelations
);
2551 Status
= STATUS_SUCCESS
;
2555 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2558 * Create device nodes for all discovered devices
2560 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2562 Status
= IopCreateDeviceNode(
2564 DeviceRelations
->Objects
[i
],
2567 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2568 if (!NT_SUCCESS(Status
))
2570 DPRINT("No resources\n");
2571 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2572 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2573 ExFreePool(DeviceRelations
);
2574 Status
= STATUS_NO_MEMORY
;
2578 ExFreePool(DeviceRelations
);
2581 * Retrieve information about all discovered children from the bus driver
2583 IopInitDeviceTreeTraverseContext(
2586 IopActionInterrogateDeviceStack
,
2589 Status
= IopTraverseDeviceTree(&Context
);
2590 if (!NT_SUCCESS(Status
))
2592 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2597 * Retrieve configuration from the registry for discovered children
2599 IopInitDeviceTreeTraverseContext(
2602 IopActionConfigureChildServices
,
2605 Status
= IopTraverseDeviceTree(&Context
);
2606 if (!NT_SUCCESS(Status
))
2608 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2613 * Get the state of the system boot. If the \\SystemRoot link isn't
2614 * created yet, we will assume that it's possible to load only boot
2617 InitializeObjectAttributes(
2623 Status
= ZwOpenFile(
2630 if (NT_SUCCESS(Status
))
2632 BootDrivers
= FALSE
;
2639 * Initialize services for discovered children. Only boot drivers will
2640 * be loaded from boot driver!
2642 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2643 if (!NT_SUCCESS(Status
))
2645 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2649 DPRINT("IopInvalidateDeviceRelations() finished\n");
2650 Status
= STATUS_SUCCESS
;
2653 IoFreeWorkItem(Data
->WorkItem
);
2656 Data
->Status
= Status
;
2657 KeSetEvent(Event
, 0, FALSE
);
2663 static NTSTATUS INIT_FUNCTION
2664 IopEnumerateDetectedDevices(
2666 IN PUNICODE_STRING RelativePath
,
2668 IN BOOLEAN EnumerateSubKeys
,
2669 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2670 IN ULONG ParentBootResourcesLength
)
2672 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2673 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2674 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2675 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2676 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2677 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2678 OBJECT_ATTRIBUTES ObjectAttributes
;
2679 HANDLE hDevicesKey
= NULL
;
2680 HANDLE hDeviceKey
= NULL
;
2681 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2682 UNICODE_STRING Level2NameU
;
2683 WCHAR Level2Name
[5];
2684 ULONG IndexDevice
= 0;
2686 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2687 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2688 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2689 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2690 UNICODE_STRING DeviceName
, ValueName
;
2692 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2693 ULONG BootResourcesLength
;
2696 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI BIOS");
2697 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2698 static ULONG DeviceIndexPci
= 0;
2699 /*const UNICODE_STRING IdentifierAcpi = RTL_CONSTANT_STRING(L"ACPI BIOS");
2700 UNICODE_STRING HardwareIdAcpi = RTL_CONSTANT_STRING(L"*PNP0C08\0");
2701 static ULONG DeviceIndexAcpi = 0;*/
2702 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2703 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2704 static ULONG DeviceIndexSerial
= 0;
2705 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2706 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2707 static ULONG DeviceIndexKeyboard
= 0;
2708 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2709 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2710 static ULONG DeviceIndexMouse
= 0;
2711 PUNICODE_STRING pHardwareId
;
2712 ULONG DeviceIndex
= 0;
2714 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2715 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2716 if (!NT_SUCCESS(Status
))
2718 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2722 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2723 if (!pDeviceInformation
)
2725 DPRINT("ExAllocatePool() failed\n");
2726 Status
= STATUS_NO_MEMORY
;
2730 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2731 if (!pValueInformation
)
2733 DPRINT("ExAllocatePool() failed\n");
2734 Status
= STATUS_NO_MEMORY
;
2740 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2741 if (Status
== STATUS_NO_MORE_ENTRIES
)
2743 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2745 ExFreePool(pDeviceInformation
);
2746 DeviceInfoLength
= RequiredSize
;
2747 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2748 if (!pDeviceInformation
)
2750 DPRINT("ExAllocatePool() failed\n");
2751 Status
= STATUS_NO_MEMORY
;
2754 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2756 if (!NT_SUCCESS(Status
))
2758 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2763 /* Open device key */
2764 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2765 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2766 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2769 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0),
2771 if (!NT_SUCCESS(Status
))
2773 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2777 /* Read boot resources, and add then to parent ones */
2778 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2779 if (Status
== STATUS_BUFFER_OVERFLOW
)
2781 ExFreePool(pValueInformation
);
2782 ValueInfoLength
= RequiredSize
;
2783 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2784 if (!pValueInformation
)
2786 DPRINT("ExAllocatePool() failed\n");
2787 ZwDeleteKey(hLevel2Key
);
2788 Status
= STATUS_NO_MEMORY
;
2791 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2793 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2795 BootResources
= ParentBootResources
;
2796 BootResourcesLength
= ParentBootResourcesLength
;
2798 else if (!NT_SUCCESS(Status
))
2800 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2803 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2805 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2808 else if (((PCM_FULL_RESOURCE_DESCRIPTOR
)pValueInformation
->Data
)->PartialResourceList
.Count
== 0)
2810 BootResources
= ParentBootResources
;
2811 BootResourcesLength
= ParentBootResourcesLength
;
2815 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2817 /* Concatenate current resources and parent ones */
2818 if (ParentBootResourcesLength
== 0)
2819 BootResourcesLength
= pValueInformation
->DataLength
;
2821 BootResourcesLength
= ParentBootResourcesLength
2822 + pValueInformation
->DataLength
2824 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2827 DPRINT("ExAllocatePool() failed\n");
2830 if (ParentBootResourcesLength
== 0)
2832 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2834 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2836 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2838 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2839 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2840 ParentBootResourcesLength
- Header
);
2841 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2845 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2847 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2848 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2849 ParentBootResourcesLength
- Header
);
2851 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2852 pValueInformation
->Data
+ Header
,
2853 pValueInformation
->DataLength
- Header
);
2854 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2858 if (EnumerateSubKeys
)
2863 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2864 if (Status
== STATUS_NO_MORE_ENTRIES
)
2866 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2868 ExFreePool(pDeviceInformation
);
2869 DeviceInfoLength
= RequiredSize
;
2870 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2871 if (!pDeviceInformation
)
2873 DPRINT("ExAllocatePool() failed\n");
2874 Status
= STATUS_NO_MEMORY
;
2877 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2879 if (!NT_SUCCESS(Status
))
2881 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2885 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2886 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2888 Status
= IopEnumerateDetectedDevices(
2894 BootResourcesLength
);
2895 if (!NT_SUCCESS(Status
))
2900 /* Read identifier */
2901 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2902 if (Status
== STATUS_BUFFER_OVERFLOW
)
2904 ExFreePool(pValueInformation
);
2905 ValueInfoLength
= RequiredSize
;
2906 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2907 if (!pValueInformation
)
2909 DPRINT("ExAllocatePool() failed\n");
2910 Status
= STATUS_NO_MEMORY
;
2913 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2915 if (!NT_SUCCESS(Status
))
2917 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2919 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2922 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2924 else if (pValueInformation
->Type
!= REG_SZ
)
2926 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2931 /* Assign hardware id to this device */
2932 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2933 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2934 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2935 ValueName
.Length
-= sizeof(WCHAR
);
2938 if (RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2940 pHardwareId
= &HardwareIdSerial
;
2941 DeviceIndex
= DeviceIndexSerial
++;
2943 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2945 pHardwareId
= &HardwareIdKeyboard
;
2946 DeviceIndex
= DeviceIndexKeyboard
++;
2948 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2950 pHardwareId
= &HardwareIdMouse
;
2951 DeviceIndex
= DeviceIndexMouse
++;
2953 else if (NT_SUCCESS(Status
))
2955 /* Try to also match the device identifier */
2956 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2958 pHardwareId
= &HardwareIdPci
;
2959 DeviceIndex
= DeviceIndexPci
++;
2961 /*else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0)
2963 pHardwareId = &HardwareIdAcpi;
2964 DeviceIndex = DeviceIndexAcpi++;
2968 /* Unknown device */
2969 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2975 /* Unknown key path */
2976 DPRINT("Unknown key path %wZ\n", RelativePath
);
2980 /* Add the detected device to Root key */
2981 InitializeObjectAttributes(&ObjectAttributes
, pHardwareId
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2982 Status
= ZwCreateKey(
2988 REG_OPTION_NON_VOLATILE
,
2990 if (!NT_SUCCESS(Status
))
2992 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2995 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2996 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2997 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2998 Status
= ZwCreateKey(
3000 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3004 REG_OPTION_NON_VOLATILE
,
3006 ZwClose(hLevel1Key
);
3007 if (!NT_SUCCESS(Status
))
3009 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3012 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, pHardwareId
);
3013 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
3014 if (!NT_SUCCESS(Status
))
3016 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3017 ZwDeleteKey(hLevel2Key
);
3020 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3021 if (!NT_SUCCESS(Status
))
3023 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3024 ZwDeleteKey(hLevel2Key
);
3027 if (BootResourcesLength
> 0)
3029 /* Save boot resources to 'LogConf\BootConfig' */
3030 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3031 Status
= ZwCreateKey(
3037 REG_OPTION_VOLATILE
,
3039 if (!NT_SUCCESS(Status
))
3041 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3042 ZwDeleteKey(hLevel2Key
);
3045 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
3047 if (!NT_SUCCESS(Status
))
3049 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3050 ZwDeleteKey(hLevel2Key
);
3056 if (BootResources
&& BootResources
!= ParentBootResources
)
3057 ExFreePool(BootResources
);
3060 ZwClose(hLevel2Key
);
3065 ZwClose(hDeviceKey
);
3070 Status
= STATUS_SUCCESS
;
3074 ZwClose(hDevicesKey
);
3076 ZwClose(hDeviceKey
);
3077 if (pDeviceInformation
)
3078 ExFreePool(pDeviceInformation
);
3079 if (pValueInformation
)
3080 ExFreePool(pValueInformation
);
3084 static BOOLEAN INIT_FUNCTION
3085 IopIsAcpiComputer(VOID
)
3089 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3090 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3091 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3092 OBJECT_ATTRIBUTES ObjectAttributes
;
3093 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3094 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3095 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3096 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3098 ULONG IndexDevice
= 0;
3099 UNICODE_STRING DeviceName
, ValueName
;
3100 HANDLE hDevicesKey
= NULL
;
3101 HANDLE hDeviceKey
= NULL
;
3103 BOOLEAN ret
= FALSE
;
3105 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3106 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3107 if (!NT_SUCCESS(Status
))
3109 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3113 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3114 if (!pDeviceInformation
)
3116 DPRINT("ExAllocatePool() failed\n");
3117 Status
= STATUS_NO_MEMORY
;
3121 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3122 if (!pDeviceInformation
)
3124 DPRINT("ExAllocatePool() failed\n");
3125 Status
= STATUS_NO_MEMORY
;
3131 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3132 if (Status
== STATUS_NO_MORE_ENTRIES
)
3134 else if (Status
== STATUS_BUFFER_OVERFLOW
)
3136 ExFreePool(pDeviceInformation
);
3137 DeviceInfoLength
= RequiredSize
;
3138 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3139 if (!pDeviceInformation
)
3141 DPRINT("ExAllocatePool() failed\n");
3142 Status
= STATUS_NO_MEMORY
;
3145 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3147 if (!NT_SUCCESS(Status
))
3149 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3154 /* Open device key */
3155 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3156 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3157 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3162 if (!NT_SUCCESS(Status
))
3164 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3168 /* Read identifier */
3169 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3170 if (Status
== STATUS_BUFFER_OVERFLOW
)
3172 ExFreePool(pValueInformation
);
3173 ValueInfoLength
= RequiredSize
;
3174 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3175 if (!pValueInformation
)
3177 DPRINT("ExAllocatePool() failed\n");
3178 Status
= STATUS_NO_MEMORY
;
3181 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3183 if (!NT_SUCCESS(Status
))
3185 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3188 else if (pValueInformation
->Type
!= REG_SZ
)
3190 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3194 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3195 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3196 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3197 ValueName
.Length
-= sizeof(WCHAR
);
3198 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3200 DPRINT("Found ACPI BIOS\n");
3206 ZwClose(hDeviceKey
);
3211 if (pDeviceInformation
)
3212 ExFreePool(pDeviceInformation
);
3213 if (pValueInformation
)
3214 ExFreePool(pValueInformation
);
3216 ZwClose(hDevicesKey
);
3218 ZwClose(hDeviceKey
);
3223 static NTSTATUS INIT_FUNCTION
3224 IopUpdateRootKey(VOID
)
3226 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum\\Root");
3227 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3228 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3229 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3230 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3231 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3232 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3233 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3234 OBJECT_ATTRIBUTES ObjectAttributes
;
3235 HANDLE hRoot
, hHalAcpiDevice
, hHalAcpiId
;
3238 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3239 Status
= ZwOpenKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
);
3240 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3242 /* We are probably in 1st stage */
3243 return STATUS_SUCCESS
;
3245 else if (!NT_SUCCESS(Status
))
3247 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3251 if (IopIsAcpiComputer())
3253 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3254 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3256 if (!NT_SUCCESS(Status
))
3258 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3259 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3260 ZwClose(hHalAcpiDevice
);
3261 if (!NT_SUCCESS(Status
))
3263 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3264 if (NT_SUCCESS(Status
))
3265 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3266 ZwClose(hHalAcpiId
);
3271 Status
= IopEnumerateDetectedDevices(
3283 static NTSTATUS INIT_FUNCTION
3285 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
3287 return STATUS_SUCCESS
;
3296 DPRINT("PnpInit()\n");
3298 KeInitializeSpinLock(&IopDeviceTreeLock
);
3300 /* Initialize the Bus Type GUID List */
3301 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3302 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3303 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3305 /* Initialize PnP-Event notification support */
3306 Status
= IopInitPlugPlayEvents();
3307 if (!NT_SUCCESS(Status
))
3309 CPRINT("IopInitPlugPlayEvents() failed\n");
3310 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3314 * Create root device node
3317 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, 0, 0, &IopRootDriverObject
);
3318 if (!NT_SUCCESS(Status
))
3320 CPRINT("IoCreateDriverObject() failed\n");
3321 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3324 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3326 if (!NT_SUCCESS(Status
))
3328 CPRINT("IoCreateDevice() failed\n");
3329 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3332 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
3333 if (!NT_SUCCESS(Status
))
3335 CPRINT("Insufficient resources\n");
3336 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3339 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3342 CPRINT("Failed to create the instance path!\n");
3343 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3346 /* Report the device to the user-mode pnp manager */
3347 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3348 &IopRootDeviceNode
->InstancePath
);
3350 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3351 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3352 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3353 IopRootDriverObject
->DriverExtension
->AddDevice(
3354 IopRootDriverObject
,
3355 IopRootDeviceNode
->PhysicalDeviceObject
);
3357 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3358 Status
= IopUpdateRootKey();
3359 if (!NT_SUCCESS(Status
))
3361 CPRINT("IopUpdateRootKey() failed\n");
3362 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3366 RTL_GENERIC_COMPARE_RESULTS
3368 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3369 IN PVOID FirstStruct
,
3370 IN PVOID SecondStruct
)
3378 // The allocation function is called by the generic table package whenever
3379 // it needs to allocate memory for the table.
3384 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3394 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3403 PpInitializeDeviceReferenceTable(VOID
)
3405 /* Setup the guarded mutex and AVL table */
3406 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3407 RtlInitializeGenericTableAvl(
3408 &PpDeviceReferenceTable
,
3409 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3410 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3411 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3419 /* Initialize the resource when accessing device registry data */
3420 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3422 /* Setup the device reference AVL table */
3423 PpInitializeDeviceReferenceTable();
3431 /* Check the initialization phase */
3432 switch (ExpInitializationPhase
)
3437 return PiInitPhase0();
3443 //return PiInitPhase1();
3447 /* Don't know any other phase! Bugcheck! */
3448 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);