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
);
2026 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2028 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2029 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2030 Status
= IopInitiatePnpIrp(
2031 DeviceNode
->PhysicalDeviceObject
,
2033 IRP_MN_QUERY_DEVICE_TEXT
,
2035 /* This key is mandatory, so even if the Irp fails, we still write it */
2036 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2037 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2039 if (NT_SUCCESS(Status
) &&
2040 IoStatusBlock
.Information
&&
2041 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2043 /* This key is overriden when a driver is installed. Don't write the
2044 * new description if another one already exists */
2045 Status
= ZwSetValueKey(InstanceKey
,
2049 (PVOID
)IoStatusBlock
.Information
,
2050 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2054 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2055 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2057 Status
= ZwSetValueKey(InstanceKey
,
2062 DeviceDesc
.MaximumLength
);
2064 if (!NT_SUCCESS(Status
))
2066 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2072 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2074 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2075 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2076 Status
= IopInitiatePnpIrp(
2077 DeviceNode
->PhysicalDeviceObject
,
2079 IRP_MN_QUERY_DEVICE_TEXT
,
2081 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2083 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2084 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2085 Status
= ZwSetValueKey(InstanceKey
,
2089 (PVOID
)IoStatusBlock
.Information
,
2090 (wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2091 if (!NT_SUCCESS(Status
))
2093 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2098 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2101 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2103 Status
= IopInitiatePnpIrp(
2104 DeviceNode
->PhysicalDeviceObject
,
2106 IRP_MN_QUERY_BUS_INFORMATION
,
2108 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2110 PPNP_BUS_INFORMATION BusInformation
=
2111 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2113 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2114 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2115 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2116 ExFreePool(BusInformation
);
2120 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2122 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2123 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2124 DeviceNode
->ChildBusTypeIndex
= -1;
2127 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2129 Status
= IopInitiatePnpIrp(
2130 DeviceNode
->PhysicalDeviceObject
,
2132 IRP_MN_QUERY_RESOURCES
,
2134 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2136 DeviceNode
->BootResources
=
2137 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2138 DeviceNode
->Flags
|= DNF_HAS_BOOT_CONFIG
;
2142 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2143 DeviceNode
->BootResources
= NULL
;
2146 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2148 Status
= IopInitiatePnpIrp(
2149 DeviceNode
->PhysicalDeviceObject
,
2151 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2153 if (NT_SUCCESS(Status
))
2155 DeviceNode
->ResourceRequirements
=
2156 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2157 if (IoStatusBlock
.Information
)
2158 IopDeviceNodeSetFlag(DeviceNode
, DNF_RESOURCE_REPORTED
);
2160 IopDeviceNodeSetFlag(DeviceNode
, DNF_NO_RESOURCE_REQUIRED
);
2164 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2165 DeviceNode
->ResourceRequirements
= NULL
;
2169 if (InstanceKey
!= NULL
)
2171 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2174 ZwClose(InstanceKey
);
2176 DeviceNode
->Flags
|= DNF_PROCESSED
;
2178 /* Report the device to the user-mode pnp manager */
2179 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2180 &DeviceNode
->InstancePath
);
2182 return STATUS_SUCCESS
;
2186 * IopActionConfigureChildServices
2188 * Retrieve configuration for all (direct) child nodes of a parent node.
2192 * Pointer to device node.
2194 * Pointer to parent node to retrieve child node configuration for.
2197 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
2198 * when we reach a device node which is not a direct child of the device
2199 * node for which we configure child services for. Any errors that occur is
2200 * logged instead so that all child services have a chance of beeing
2205 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2208 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2209 PDEVICE_NODE ParentDeviceNode
;
2210 PUNICODE_STRING Service
;
2211 UNICODE_STRING ClassGUID
;
2214 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2216 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2219 * We are called for the parent too, but we don't need to do special
2220 * handling for this node
2222 if (DeviceNode
== ParentDeviceNode
)
2224 DPRINT("Success\n");
2225 return STATUS_SUCCESS
;
2229 * Make sure this device node is a direct child of the parent device node
2230 * that is given as an argument
2232 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2234 /* Stop the traversal immediately and indicate successful operation */
2236 return STATUS_UNSUCCESSFUL
;
2239 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2241 WCHAR RegKeyBuffer
[MAX_PATH
];
2242 UNICODE_STRING RegKey
;
2245 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2246 RegKey
.Buffer
= RegKeyBuffer
;
2249 * Retrieve configuration from Enum key
2252 Service
= &DeviceNode
->ServiceName
;
2254 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2255 RtlInitUnicodeString(Service
, NULL
);
2256 RtlInitUnicodeString(&ClassGUID
, NULL
);
2258 QueryTable
[0].Name
= L
"Service";
2259 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
2260 QueryTable
[0].EntryContext
= Service
;
2262 QueryTable
[1].Name
= L
"ClassGUID";
2263 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2264 QueryTable
[1].EntryContext
= &ClassGUID
;
2265 QueryTable
[1].DefaultType
= REG_SZ
;
2266 QueryTable
[1].DefaultData
= L
"";
2267 QueryTable
[1].DefaultLength
= 0;
2269 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2270 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2272 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2273 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2275 if (!NT_SUCCESS(Status
))
2277 /* FIXME: Log the error */
2278 DPRINT1("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2279 &DeviceNode
->InstancePath
, Status
);
2280 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2281 return STATUS_SUCCESS
;
2284 if (Service
->Buffer
== NULL
)
2286 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2288 if (ClassGUID
.Length
!= 0)
2290 /* Device has a ClassGUID value, but no Service value.
2291 * Suppose it is using the NULL driver, so state the
2292 * device is started */
2293 DPRINT1("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2294 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2295 DeviceNode
->Flags
|= DN_STARTED
;
2297 return STATUS_SUCCESS
;
2300 DPRINT1("Got Service %S\n", Service
->Buffer
);
2303 return STATUS_SUCCESS
;
2307 * IopActionInitChildServices
2309 * Initialize the service for all (direct) child nodes of a parent node
2313 * Pointer to device node.
2315 * Pointer to parent node to initialize child node services for.
2317 * Load only driver marked as boot start.
2320 * If the driver image for a service is not loaded and initialized
2321 * it is done here too. We only return a status code indicating an
2322 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
2323 * not a direct child of the device node for which we initialize
2324 * child services for. Any errors that occur is logged instead so
2325 * that all child services have a chance of being initialized.
2329 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2331 BOOLEAN BootDrivers
)
2333 PDEVICE_NODE ParentDeviceNode
;
2336 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode
, Context
,
2339 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2342 * We are called for the parent too, but we don't need to do special
2343 * handling for this node
2345 if (DeviceNode
== ParentDeviceNode
)
2347 DPRINT("Success\n");
2348 return STATUS_SUCCESS
;
2352 * Make sure this device node is a direct child of the parent device node
2353 * that is given as an argument
2356 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2359 * Stop the traversal immediately and indicate unsuccessful operation
2362 return STATUS_UNSUCCESSFUL
;
2366 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
) &&
2367 !IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) &&
2368 !IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
))
2370 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2371 PDRIVER_OBJECT DriverObject
;
2373 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2374 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2376 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
2378 DeviceNode
->Flags
|= DN_DRIVER_LOADED
;
2379 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2380 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2384 /* get existing DriverObject pointer */
2385 Status
= IopGetDriverObject(
2387 &DeviceNode
->ServiceName
,
2390 if (NT_SUCCESS(Status
))
2392 /* Attach lower level filter drivers. */
2393 IopAttachFilterDrivers(DeviceNode
, TRUE
);
2394 /* Initialize the function driver for the device node */
2395 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
2396 if (NT_SUCCESS(Status
))
2398 /* Attach upper level filter drivers. */
2399 IopAttachFilterDrivers(DeviceNode
, FALSE
);
2400 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2402 Status
= IopStartDevice(DeviceNode
);
2409 * Don't disable when trying to load only boot drivers
2413 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2414 IopDeviceNodeSetFlag(DeviceNode
, DNF_START_FAILED
);
2415 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
2416 CPRINT("Initialization of service %S failed (Status %x)\n",
2417 DeviceNode
->ServiceName
.Buffer
, Status
);
2423 DPRINT("Device %wZ is disabled or already initialized\n",
2424 &DeviceNode
->InstancePath
);
2427 return STATUS_SUCCESS
;
2431 * IopActionInitAllServices
2433 * Initialize the service for all (direct) child nodes of a parent node. This
2434 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
2438 IopActionInitAllServices(PDEVICE_NODE DeviceNode
,
2441 return IopActionInitChildServices(DeviceNode
, Context
, FALSE
);
2445 * IopActionInitBootServices
2447 * Initialize the boot start services for all (direct) child nodes of a
2448 * parent node. This function just calls IopActionInitChildServices with
2449 * BootDrivers = TRUE.
2452 IopActionInitBootServices(PDEVICE_NODE DeviceNode
,
2455 return IopActionInitChildServices(DeviceNode
, Context
, TRUE
);
2459 * IopInitializePnpServices
2461 * Initialize services for discovered children
2465 * Top device node to start initializing services.
2468 * When set to TRUE, only drivers marked as boot start will
2469 * be loaded. Otherwise, all drivers will be loaded.
2475 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
,
2476 IN BOOLEAN BootDrivers
)
2478 DEVICETREE_TRAVERSE_CONTEXT Context
;
2480 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode
, BootDrivers
);
2484 IopInitDeviceTreeTraverseContext(
2487 IopActionInitBootServices
,
2492 IopInitDeviceTreeTraverseContext(
2495 IopActionInitAllServices
,
2499 return IopTraverseDeviceTree(&Context
);
2502 /* Invalidate device list enumerated by a device node.
2503 * The call can be make synchronous by defining the Event field
2504 * of the INVALIDATE_DEVICE_RELATION_DATA structure
2507 IopInvalidateDeviceRelations(
2508 IN PDEVICE_OBJECT DeviceObject
,
2509 IN PVOID InvalidateContext
) /* PINVALIDATE_DEVICE_RELATION_DATA */
2511 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
2512 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2513 PKEVENT Event
= Data
->Event
;
2514 DEVICETREE_TRAVERSE_CONTEXT Context
;
2515 PDEVICE_RELATIONS DeviceRelations
;
2516 IO_STATUS_BLOCK IoStatusBlock
;
2517 PDEVICE_NODE ChildDeviceNode
;
2518 IO_STACK_LOCATION Stack
;
2519 BOOLEAN BootDrivers
;
2520 OBJECT_ATTRIBUTES ObjectAttributes
;
2521 UNICODE_STRING LinkName
= RTL_CONSTANT_STRING(L
"\\SystemRoot");
2526 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2528 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2530 Stack
.Parameters
.QueryDeviceRelations
.Type
= Data
->Type
;
2532 Status
= IopInitiatePnpIrp(
2535 IRP_MN_QUERY_DEVICE_RELATIONS
,
2537 if (!NT_SUCCESS(Status
))
2539 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2543 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2545 if (!DeviceRelations
|| DeviceRelations
->Count
<= 0)
2547 DPRINT("No PDOs\n");
2548 if (DeviceRelations
)
2550 ExFreePool(DeviceRelations
);
2552 Status
= STATUS_SUCCESS
;
2556 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
2559 * Create device nodes for all discovered devices
2561 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2563 Status
= IopCreateDeviceNode(
2565 DeviceRelations
->Objects
[i
],
2568 DeviceNode
->Flags
|= DNF_ENUMERATED
;
2569 if (!NT_SUCCESS(Status
))
2571 DPRINT("No resources\n");
2572 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2573 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
2574 ExFreePool(DeviceRelations
);
2575 Status
= STATUS_NO_MEMORY
;
2579 ExFreePool(DeviceRelations
);
2582 * Retrieve information about all discovered children from the bus driver
2584 IopInitDeviceTreeTraverseContext(
2587 IopActionInterrogateDeviceStack
,
2590 Status
= IopTraverseDeviceTree(&Context
);
2591 if (!NT_SUCCESS(Status
))
2593 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2598 * Retrieve configuration from the registry for discovered children
2600 IopInitDeviceTreeTraverseContext(
2603 IopActionConfigureChildServices
,
2606 Status
= IopTraverseDeviceTree(&Context
);
2607 if (!NT_SUCCESS(Status
))
2609 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2614 * Get the state of the system boot. If the \\SystemRoot link isn't
2615 * created yet, we will assume that it's possible to load only boot
2618 InitializeObjectAttributes(
2624 Status
= ZwOpenFile(
2631 if (NT_SUCCESS(Status
))
2633 BootDrivers
= FALSE
;
2640 * Initialize services for discovered children. Only boot drivers will
2641 * be loaded from boot driver!
2643 Status
= IopInitializePnpServices(DeviceNode
, BootDrivers
);
2644 if (!NT_SUCCESS(Status
))
2646 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2650 DPRINT("IopInvalidateDeviceRelations() finished\n");
2651 Status
= STATUS_SUCCESS
;
2654 IoFreeWorkItem(Data
->WorkItem
);
2657 Data
->Status
= Status
;
2658 KeSetEvent(Event
, 0, FALSE
);
2664 static NTSTATUS INIT_FUNCTION
2665 IopEnumerateDetectedDevices(
2667 IN PUNICODE_STRING RelativePath
,
2669 IN BOOLEAN EnumerateSubKeys
,
2670 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2671 IN ULONG ParentBootResourcesLength
)
2673 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2674 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
2675 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2676 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2677 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2678 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2679 OBJECT_ATTRIBUTES ObjectAttributes
;
2680 HANDLE hDevicesKey
= NULL
;
2681 HANDLE hDeviceKey
= NULL
;
2682 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2683 UNICODE_STRING Level2NameU
;
2684 WCHAR Level2Name
[5];
2685 ULONG IndexDevice
= 0;
2687 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2688 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2689 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2690 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2691 UNICODE_STRING DeviceName
, ValueName
;
2693 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2694 ULONG BootResourcesLength
;
2697 const UNICODE_STRING IdentifierPci
= RTL_CONSTANT_STRING(L
"PCI BIOS");
2698 UNICODE_STRING HardwareIdPci
= RTL_CONSTANT_STRING(L
"*PNP0A03\0");
2699 static ULONG DeviceIndexPci
= 0;
2700 /*const UNICODE_STRING IdentifierAcpi = RTL_CONSTANT_STRING(L"ACPI BIOS");
2701 UNICODE_STRING HardwareIdAcpi = RTL_CONSTANT_STRING(L"*PNP0C08\0");
2702 static ULONG DeviceIndexAcpi = 0;*/
2703 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2704 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2705 static ULONG DeviceIndexSerial
= 0;
2706 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2707 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2708 static ULONG DeviceIndexKeyboard
= 0;
2709 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2710 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2711 static ULONG DeviceIndexMouse
= 0;
2712 PUNICODE_STRING pHardwareId
;
2713 ULONG DeviceIndex
= 0;
2715 InitializeObjectAttributes(&ObjectAttributes
, RelativePath
, OBJ_KERNEL_HANDLE
, hBaseKey
, NULL
);
2716 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
2717 if (!NT_SUCCESS(Status
))
2719 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2723 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2724 if (!pDeviceInformation
)
2726 DPRINT("ExAllocatePool() failed\n");
2727 Status
= STATUS_NO_MEMORY
;
2731 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2732 if (!pValueInformation
)
2734 DPRINT("ExAllocatePool() failed\n");
2735 Status
= STATUS_NO_MEMORY
;
2741 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2742 if (Status
== STATUS_NO_MORE_ENTRIES
)
2744 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2746 ExFreePool(pDeviceInformation
);
2747 DeviceInfoLength
= RequiredSize
;
2748 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2749 if (!pDeviceInformation
)
2751 DPRINT("ExAllocatePool() failed\n");
2752 Status
= STATUS_NO_MEMORY
;
2755 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2757 if (!NT_SUCCESS(Status
))
2759 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2764 /* Open device key */
2765 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2766 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2767 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
2770 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0),
2772 if (!NT_SUCCESS(Status
))
2774 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2778 /* Read boot resources, and add then to parent ones */
2779 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2780 if (Status
== STATUS_BUFFER_OVERFLOW
)
2782 ExFreePool(pValueInformation
);
2783 ValueInfoLength
= RequiredSize
;
2784 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2785 if (!pValueInformation
)
2787 DPRINT("ExAllocatePool() failed\n");
2788 ZwDeleteKey(hLevel2Key
);
2789 Status
= STATUS_NO_MEMORY
;
2792 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2794 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2796 BootResources
= ParentBootResources
;
2797 BootResourcesLength
= ParentBootResourcesLength
;
2799 else if (!NT_SUCCESS(Status
))
2801 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2804 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2806 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2809 else if (((PCM_FULL_RESOURCE_DESCRIPTOR
)pValueInformation
->Data
)->PartialResourceList
.Count
== 0)
2811 BootResources
= ParentBootResources
;
2812 BootResourcesLength
= ParentBootResourcesLength
;
2816 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2818 /* Concatenate current resources and parent ones */
2819 if (ParentBootResourcesLength
== 0)
2820 BootResourcesLength
= pValueInformation
->DataLength
;
2822 BootResourcesLength
= ParentBootResourcesLength
2823 + pValueInformation
->DataLength
2825 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2828 DPRINT("ExAllocatePool() failed\n");
2831 if (ParentBootResourcesLength
== 0)
2833 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2835 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2837 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2839 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2840 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2841 ParentBootResourcesLength
- Header
);
2842 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2846 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2848 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2849 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2850 ParentBootResourcesLength
- Header
);
2852 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2853 pValueInformation
->Data
+ Header
,
2854 pValueInformation
->DataLength
- Header
);
2855 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2859 if (EnumerateSubKeys
)
2864 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2865 if (Status
== STATUS_NO_MORE_ENTRIES
)
2867 else if (Status
== STATUS_BUFFER_OVERFLOW
)
2869 ExFreePool(pDeviceInformation
);
2870 DeviceInfoLength
= RequiredSize
;
2871 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2872 if (!pDeviceInformation
)
2874 DPRINT("ExAllocatePool() failed\n");
2875 Status
= STATUS_NO_MEMORY
;
2878 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2880 if (!NT_SUCCESS(Status
))
2882 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2886 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2887 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2889 Status
= IopEnumerateDetectedDevices(
2895 BootResourcesLength
);
2896 if (!NT_SUCCESS(Status
))
2901 /* Read identifier */
2902 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2903 if (Status
== STATUS_BUFFER_OVERFLOW
)
2905 ExFreePool(pValueInformation
);
2906 ValueInfoLength
= RequiredSize
;
2907 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2908 if (!pValueInformation
)
2910 DPRINT("ExAllocatePool() failed\n");
2911 Status
= STATUS_NO_MEMORY
;
2914 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2916 if (!NT_SUCCESS(Status
))
2918 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2920 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2923 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2925 else if (pValueInformation
->Type
!= REG_SZ
)
2927 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2932 /* Assign hardware id to this device */
2933 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2934 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2935 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2936 ValueName
.Length
-= sizeof(WCHAR
);
2939 if (RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2941 pHardwareId
= &HardwareIdSerial
;
2942 DeviceIndex
= DeviceIndexSerial
++;
2944 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2946 pHardwareId
= &HardwareIdKeyboard
;
2947 DeviceIndex
= DeviceIndexKeyboard
++;
2949 else if (RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2951 pHardwareId
= &HardwareIdMouse
;
2952 DeviceIndex
= DeviceIndexMouse
++;
2954 else if (NT_SUCCESS(Status
))
2956 /* Try to also match the device identifier */
2957 if (RtlCompareUnicodeString(&ValueName
, &IdentifierPci
, FALSE
) == 0)
2959 pHardwareId
= &HardwareIdPci
;
2960 DeviceIndex
= DeviceIndexPci
++;
2962 /*else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0)
2964 pHardwareId = &HardwareIdAcpi;
2965 DeviceIndex = DeviceIndexAcpi++;
2969 /* Unknown device */
2970 DPRINT("Unknown device '%wZ'\n", &ValueName
);
2976 /* Unknown key path */
2977 DPRINT("Unknown key path %wZ\n", RelativePath
);
2981 /* Add the detected device to Root key */
2982 InitializeObjectAttributes(&ObjectAttributes
, pHardwareId
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
2983 Status
= ZwCreateKey(
2989 REG_OPTION_NON_VOLATILE
,
2991 if (!NT_SUCCESS(Status
))
2993 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
2996 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
2997 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
2998 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
2999 Status
= ZwCreateKey(
3001 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3005 REG_OPTION_NON_VOLATILE
,
3007 ZwClose(hLevel1Key
);
3008 if (!NT_SUCCESS(Status
))
3010 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3013 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, pHardwareId
);
3014 Status
= ZwSetValueKey(hLevel2Key
, &DeviceDescU
, 0, REG_SZ
, ValueName
.Buffer
, ValueName
.MaximumLength
);
3015 if (!NT_SUCCESS(Status
))
3017 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3018 ZwDeleteKey(hLevel2Key
);
3021 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3022 if (!NT_SUCCESS(Status
))
3024 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3025 ZwDeleteKey(hLevel2Key
);
3028 if (BootResourcesLength
> 0)
3030 /* Save boot resources to 'LogConf\BootConfig' */
3031 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3032 Status
= ZwCreateKey(
3038 REG_OPTION_VOLATILE
,
3040 if (!NT_SUCCESS(Status
))
3042 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3043 ZwDeleteKey(hLevel2Key
);
3046 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_FULL_RESOURCE_DESCRIPTOR
, BootResources
, BootResourcesLength
);
3048 if (!NT_SUCCESS(Status
))
3050 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3051 ZwDeleteKey(hLevel2Key
);
3057 if (BootResources
&& BootResources
!= ParentBootResources
)
3058 ExFreePool(BootResources
);
3061 ZwClose(hLevel2Key
);
3066 ZwClose(hDeviceKey
);
3071 Status
= STATUS_SUCCESS
;
3075 ZwClose(hDevicesKey
);
3077 ZwClose(hDeviceKey
);
3078 if (pDeviceInformation
)
3079 ExFreePool(pDeviceInformation
);
3080 if (pValueInformation
)
3081 ExFreePool(pValueInformation
);
3085 static BOOLEAN INIT_FUNCTION
3086 IopIsAcpiComputer(VOID
)
3090 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3091 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
3092 UNICODE_STRING AcpiBiosIdentifier
= RTL_CONSTANT_STRING(L
"ACPI BIOS");
3093 OBJECT_ATTRIBUTES ObjectAttributes
;
3094 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
3095 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
3096 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
3097 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
3099 ULONG IndexDevice
= 0;
3100 UNICODE_STRING DeviceName
, ValueName
;
3101 HANDLE hDevicesKey
= NULL
;
3102 HANDLE hDeviceKey
= NULL
;
3104 BOOLEAN ret
= FALSE
;
3106 InitializeObjectAttributes(&ObjectAttributes
, &MultiKeyPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3107 Status
= ZwOpenKey(&hDevicesKey
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
3108 if (!NT_SUCCESS(Status
))
3110 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3114 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3115 if (!pDeviceInformation
)
3117 DPRINT("ExAllocatePool() failed\n");
3118 Status
= STATUS_NO_MEMORY
;
3122 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3123 if (!pDeviceInformation
)
3125 DPRINT("ExAllocatePool() failed\n");
3126 Status
= STATUS_NO_MEMORY
;
3132 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3133 if (Status
== STATUS_NO_MORE_ENTRIES
)
3135 else if (Status
== STATUS_BUFFER_OVERFLOW
)
3137 ExFreePool(pDeviceInformation
);
3138 DeviceInfoLength
= RequiredSize
;
3139 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3140 if (!pDeviceInformation
)
3142 DPRINT("ExAllocatePool() failed\n");
3143 Status
= STATUS_NO_MEMORY
;
3146 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3148 if (!NT_SUCCESS(Status
))
3150 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3155 /* Open device key */
3156 DeviceName
.Length
= DeviceName
.MaximumLength
= pDeviceInformation
->NameLength
;
3157 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3158 InitializeObjectAttributes(&ObjectAttributes
, &DeviceName
, OBJ_KERNEL_HANDLE
, hDevicesKey
, NULL
);
3163 if (!NT_SUCCESS(Status
))
3165 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3169 /* Read identifier */
3170 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3171 if (Status
== STATUS_BUFFER_OVERFLOW
)
3173 ExFreePool(pValueInformation
);
3174 ValueInfoLength
= RequiredSize
;
3175 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3176 if (!pValueInformation
)
3178 DPRINT("ExAllocatePool() failed\n");
3179 Status
= STATUS_NO_MEMORY
;
3182 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3184 if (!NT_SUCCESS(Status
))
3186 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3189 else if (pValueInformation
->Type
!= REG_SZ
)
3191 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3195 ValueName
.Length
= ValueName
.MaximumLength
= pValueInformation
->DataLength
;
3196 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3197 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3198 ValueName
.Length
-= sizeof(WCHAR
);
3199 if (RtlCompareUnicodeString(&ValueName
, &AcpiBiosIdentifier
, FALSE
) == 0)
3201 DPRINT("Found ACPI BIOS\n");
3207 ZwClose(hDeviceKey
);
3212 if (pDeviceInformation
)
3213 ExFreePool(pDeviceInformation
);
3214 if (pValueInformation
)
3215 ExFreePool(pValueInformation
);
3217 ZwClose(hDevicesKey
);
3219 ZwClose(hDeviceKey
);
3224 static NTSTATUS INIT_FUNCTION
3225 IopUpdateRootKey(VOID
)
3227 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum\\Root");
3228 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3229 UNICODE_STRING DeviceDescU
= RTL_CONSTANT_STRING(L
"DeviceDesc");
3230 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
3231 UNICODE_STRING HalAcpiDevice
= RTL_CONSTANT_STRING(L
"ACPI_HAL");
3232 UNICODE_STRING HalAcpiId
= RTL_CONSTANT_STRING(L
"0000");
3233 UNICODE_STRING HalAcpiDeviceDesc
= RTL_CONSTANT_STRING(L
"HAL ACPI");
3234 UNICODE_STRING HalAcpiHardwareID
= RTL_CONSTANT_STRING(L
"*PNP0C08\0");
3235 OBJECT_ATTRIBUTES ObjectAttributes
;
3236 HANDLE hRoot
, hHalAcpiDevice
, hHalAcpiId
;
3239 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
3240 Status
= ZwOpenKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
);
3241 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3243 /* We are probably in 1st stage */
3244 return STATUS_SUCCESS
;
3246 else if (!NT_SUCCESS(Status
))
3248 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3252 if (IopIsAcpiComputer())
3254 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiDevice
, OBJ_KERNEL_HANDLE
, hRoot
, NULL
);
3255 Status
= ZwCreateKey(&hHalAcpiDevice
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3257 if (!NT_SUCCESS(Status
))
3259 InitializeObjectAttributes(&ObjectAttributes
, &HalAcpiId
, OBJ_KERNEL_HANDLE
, hHalAcpiDevice
, NULL
);
3260 Status
= ZwCreateKey(&hHalAcpiId
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
3261 ZwClose(hHalAcpiDevice
);
3262 if (!NT_SUCCESS(Status
))
3264 Status
= ZwSetValueKey(hHalAcpiId
, &DeviceDescU
, 0, REG_SZ
, HalAcpiDeviceDesc
.Buffer
, HalAcpiDeviceDesc
.MaximumLength
);
3265 if (NT_SUCCESS(Status
))
3266 Status
= ZwSetValueKey(hHalAcpiId
, &HardwareIDU
, 0, REG_MULTI_SZ
, HalAcpiHardwareID
.Buffer
, HalAcpiHardwareID
.MaximumLength
);
3267 ZwClose(hHalAcpiId
);
3272 Status
= IopEnumerateDetectedDevices(
3284 static NTSTATUS INIT_FUNCTION
3286 PnpDriverInitializeEmpty(IN
struct _DRIVER_OBJECT
*DriverObject
, IN PUNICODE_STRING RegistryPath
)
3288 return STATUS_SUCCESS
;
3297 DPRINT("PnpInit()\n");
3299 KeInitializeSpinLock(&IopDeviceTreeLock
);
3301 /* Initialize the Bus Type GUID List */
3302 IopBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3303 RtlZeroMemory(IopBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
3304 ExInitializeFastMutex(&IopBusTypeGuidList
->Lock
);
3306 /* Initialize PnP-Event notification support */
3307 Status
= IopInitPlugPlayEvents();
3308 if (!NT_SUCCESS(Status
))
3310 CPRINT("IopInitPlugPlayEvents() failed\n");
3311 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3315 * Create root device node
3318 Status
= IopCreateDriver(NULL
, PnpDriverInitializeEmpty
, NULL
, &IopRootDriverObject
);
3319 if (!NT_SUCCESS(Status
))
3321 CPRINT("IoCreateDriverObject() failed\n");
3322 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3325 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
, FILE_DEVICE_CONTROLLER
,
3327 if (!NT_SUCCESS(Status
))
3329 CPRINT("IoCreateDevice() failed\n");
3330 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3333 Status
= IopCreateDeviceNode(NULL
, Pdo
, NULL
, &IopRootDeviceNode
);
3334 if (!NT_SUCCESS(Status
))
3336 CPRINT("Insufficient resources\n");
3337 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3340 if (!RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
3343 CPRINT("Failed to create the instance path!\n");
3344 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, STATUS_NO_MEMORY
, 0, 0, 0);
3347 /* Report the device to the user-mode pnp manager */
3348 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
3349 &IopRootDeviceNode
->InstancePath
);
3351 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
3352 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
3353 IopRootDeviceNode
->PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3354 IopRootDriverObject
->DriverExtension
->AddDevice(
3355 IopRootDriverObject
,
3356 IopRootDeviceNode
->PhysicalDeviceObject
);
3358 /* Move information about devices detected by Freeloader to SYSTEM\CurrentControlSet\Root\ */
3359 Status
= IopUpdateRootKey();
3360 if (!NT_SUCCESS(Status
))
3362 CPRINT("IopUpdateRootKey() failed\n");
3363 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
3367 RTL_GENERIC_COMPARE_RESULTS
3369 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3370 IN PVOID FirstStruct
,
3371 IN PVOID SecondStruct
)
3379 // The allocation function is called by the generic table package whenever
3380 // it needs to allocate memory for the table.
3385 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3395 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3404 PpInitializeDeviceReferenceTable(VOID
)
3406 /* Setup the guarded mutex and AVL table */
3407 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3408 RtlInitializeGenericTableAvl(
3409 &PpDeviceReferenceTable
,
3410 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3411 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3412 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3420 /* Initialize the resource when accessing device registry data */
3421 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3423 /* Setup the device reference AVL table */
3424 PpInitializeDeviceReferenceTable();
3432 /* Check the initialization phase */
3433 switch (ExpInitializationPhase
)
3438 return PiInitPhase0();
3444 //return PiInitPhase1();
3448 /* Don't know any other phase! Bugcheck! */
3449 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);