2 * PROJECT: ReactOS Kernel
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnpmgr.c
5 * PURPOSE: Initializes the PnP manager
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Copyright 2007 Hervé Poussineau (hpoussin@reactos.org)
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 ERESOURCE PpRegistryDeviceResource
;
19 KGUARDED_MUTEX PpDeviceReferenceTableLock
;
20 RTL_AVL_TABLE PpDeviceReferenceTable
;
22 extern ULONG ExpInitializationPhase
;
24 /* DATA **********************************************************************/
26 PDRIVER_OBJECT IopRootDriverObject
;
27 PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList
= NULL
;
29 /* FUNCTIONS *****************************************************************/
32 IopFixupDeviceId(PWCHAR String
)
34 SIZE_T Length
= wcslen(String
), i
;
36 for (i
= 0; i
< Length
; i
++)
38 if (String
[i
] == L
'\\')
45 IopInstallCriticalDevice(PDEVICE_NODE DeviceNode
)
48 HANDLE CriticalDeviceKey
, InstanceKey
;
49 OBJECT_ATTRIBUTES ObjectAttributes
;
50 UNICODE_STRING CriticalDeviceKeyU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\CriticalDeviceDatabase");
51 UNICODE_STRING CompatibleIdU
= RTL_CONSTANT_STRING(L
"CompatibleIDs");
52 UNICODE_STRING HardwareIdU
= RTL_CONSTANT_STRING(L
"HardwareID");
53 UNICODE_STRING ServiceU
= RTL_CONSTANT_STRING(L
"Service");
54 UNICODE_STRING ClassGuidU
= RTL_CONSTANT_STRING(L
"ClassGUID");
55 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
56 ULONG HidLength
= 0, CidLength
= 0, BufferLength
;
57 PWCHAR IdBuffer
, OriginalIdBuffer
;
59 /* Open the device instance key */
60 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, REG_OPTION_NON_VOLATILE
, &InstanceKey
);
61 if (Status
!= STATUS_SUCCESS
)
64 Status
= ZwQueryValueKey(InstanceKey
,
66 KeyValuePartialInformation
,
70 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
76 Status
= ZwQueryValueKey(InstanceKey
,
78 KeyValuePartialInformation
,
82 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
87 BufferLength
= HidLength
+ CidLength
;
88 BufferLength
-= (((CidLength
!= 0) ? 2 : 1) * FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
));
90 /* Allocate a buffer to hold data from both */
91 OriginalIdBuffer
= IdBuffer
= ExAllocatePool(PagedPool
, BufferLength
);
98 /* Compute the buffer size */
99 if (HidLength
> CidLength
)
100 BufferLength
= HidLength
;
102 BufferLength
= CidLength
;
104 PartialInfo
= ExAllocatePool(PagedPool
, BufferLength
);
107 ZwClose(InstanceKey
);
108 ExFreePool(OriginalIdBuffer
);
112 Status
= ZwQueryValueKey(InstanceKey
,
114 KeyValuePartialInformation
,
118 if (Status
!= STATUS_SUCCESS
)
120 ExFreePool(PartialInfo
);
121 ExFreePool(OriginalIdBuffer
);
122 ZwClose(InstanceKey
);
126 /* Copy in HID info first (without 2nd terminating NULL if CID is present) */
127 HidLength
= PartialInfo
->DataLength
- ((CidLength
!= 0) ? sizeof(WCHAR
) : 0);
128 RtlCopyMemory(IdBuffer
, PartialInfo
->Data
, HidLength
);
132 Status
= ZwQueryValueKey(InstanceKey
,
134 KeyValuePartialInformation
,
138 if (Status
!= STATUS_SUCCESS
)
140 ExFreePool(PartialInfo
);
141 ExFreePool(OriginalIdBuffer
);
142 ZwClose(InstanceKey
);
147 CidLength
= PartialInfo
->DataLength
;
148 RtlCopyMemory(((PUCHAR
)IdBuffer
) + HidLength
, PartialInfo
->Data
, CidLength
);
151 /* Free our temp buffer */
152 ExFreePool(PartialInfo
);
154 InitializeObjectAttributes(&ObjectAttributes
,
156 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
159 Status
= ZwOpenKey(&CriticalDeviceKey
,
160 KEY_ENUMERATE_SUB_KEYS
,
162 if (!NT_SUCCESS(Status
))
164 /* The critical device database doesn't exist because
165 * we're probably in 1st stage setup, but it's ok */
166 ExFreePool(OriginalIdBuffer
);
167 ZwClose(InstanceKey
);
173 USHORT StringLength
= (USHORT
)wcslen(IdBuffer
) + 1, Index
;
175 IopFixupDeviceId(IdBuffer
);
177 /* Look through all subkeys for a match */
178 for (Index
= 0; TRUE
; Index
++)
181 PKEY_BASIC_INFORMATION BasicInfo
;
183 Status
= ZwEnumerateKey(CriticalDeviceKey
,
189 if (Status
== STATUS_NO_MORE_ENTRIES
)
191 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
193 UNICODE_STRING ChildIdNameU
, RegKeyNameU
;
195 BasicInfo
= ExAllocatePool(PagedPool
, NeededLength
);
199 ExFreePool(OriginalIdBuffer
);
200 ZwClose(CriticalDeviceKey
);
201 ZwClose(InstanceKey
);
205 Status
= ZwEnumerateKey(CriticalDeviceKey
,
211 if (Status
!= STATUS_SUCCESS
)
213 /* This shouldn't happen */
214 ExFreePool(BasicInfo
);
218 ChildIdNameU
.Buffer
= IdBuffer
;
219 ChildIdNameU
.MaximumLength
= ChildIdNameU
.Length
= (StringLength
- 1) * sizeof(WCHAR
);
220 RegKeyNameU
.Buffer
= BasicInfo
->Name
;
221 RegKeyNameU
.MaximumLength
= RegKeyNameU
.Length
= (USHORT
)BasicInfo
->NameLength
;
223 if (RtlEqualUnicodeString(&ChildIdNameU
, &RegKeyNameU
, TRUE
))
225 HANDLE ChildKeyHandle
;
227 InitializeObjectAttributes(&ObjectAttributes
,
229 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
233 Status
= ZwOpenKey(&ChildKeyHandle
,
236 if (Status
!= STATUS_SUCCESS
)
238 ExFreePool(BasicInfo
);
242 /* Check if there's already a driver installed */
243 Status
= ZwQueryValueKey(InstanceKey
,
245 KeyValuePartialInformation
,
249 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
251 ExFreePool(BasicInfo
);
255 Status
= ZwQueryValueKey(ChildKeyHandle
,
257 KeyValuePartialInformation
,
261 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
263 ExFreePool(BasicInfo
);
267 PartialInfo
= ExAllocatePool(PagedPool
, NeededLength
);
270 ExFreePool(OriginalIdBuffer
);
271 ExFreePool(BasicInfo
);
272 ZwClose(InstanceKey
);
273 ZwClose(ChildKeyHandle
);
274 ZwClose(CriticalDeviceKey
);
278 /* Read ClassGUID entry in the CDDB */
279 Status
= ZwQueryValueKey(ChildKeyHandle
,
281 KeyValuePartialInformation
,
285 if (Status
!= STATUS_SUCCESS
)
287 ExFreePool(BasicInfo
);
291 /* Write it to the ENUM key */
292 Status
= ZwSetValueKey(InstanceKey
,
297 PartialInfo
->DataLength
);
298 if (Status
!= STATUS_SUCCESS
)
300 ExFreePool(BasicInfo
);
301 ExFreePool(PartialInfo
);
302 ZwClose(ChildKeyHandle
);
306 Status
= ZwQueryValueKey(ChildKeyHandle
,
308 KeyValuePartialInformation
,
312 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
314 ExFreePool(PartialInfo
);
315 PartialInfo
= ExAllocatePool(PagedPool
, NeededLength
);
318 ExFreePool(OriginalIdBuffer
);
319 ExFreePool(BasicInfo
);
320 ZwClose(InstanceKey
);
321 ZwClose(ChildKeyHandle
);
322 ZwClose(CriticalDeviceKey
);
326 /* Read the service entry from the CDDB */
327 Status
= ZwQueryValueKey(ChildKeyHandle
,
329 KeyValuePartialInformation
,
333 if (Status
!= STATUS_SUCCESS
)
335 ExFreePool(BasicInfo
);
336 ExFreePool(PartialInfo
);
337 ZwClose(ChildKeyHandle
);
341 /* Write it to the ENUM key */
342 Status
= ZwSetValueKey(InstanceKey
,
347 PartialInfo
->DataLength
);
348 if (Status
!= STATUS_SUCCESS
)
350 ExFreePool(BasicInfo
);
351 ExFreePool(PartialInfo
);
352 ZwClose(ChildKeyHandle
);
356 DPRINT("Installed service '%S' for critical device '%wZ'\n", PartialInfo
->Data
, &ChildIdNameU
);
360 DPRINT1("Installed NULL service for critical device '%wZ'\n", &ChildIdNameU
);
363 ExFreePool(OriginalIdBuffer
);
364 ExFreePool(PartialInfo
);
365 ExFreePool(BasicInfo
);
366 ZwClose(InstanceKey
);
367 ZwClose(ChildKeyHandle
);
368 ZwClose(CriticalDeviceKey
);
374 ExFreePool(BasicInfo
);
378 /* Umm, not sure what happened here */
383 /* Advance to the next ID */
384 IdBuffer
+= StringLength
;
387 ExFreePool(OriginalIdBuffer
);
388 ZwClose(InstanceKey
);
389 ZwClose(CriticalDeviceKey
);
393 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
397 if (PopSystemPowerDeviceNode
)
399 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
400 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
401 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
403 return STATUS_SUCCESS
;
406 return STATUS_UNSUCCESSFUL
;
411 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
413 USHORT i
= 0, FoundIndex
= 0xFFFF;
417 /* Acquire the lock */
418 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
420 /* Loop all entries */
421 while (i
< PnpBusTypeGuidList
->GuidCount
)
423 /* Try to find a match */
424 if (RtlCompareMemory(BusTypeGuid
,
425 &PnpBusTypeGuidList
->Guids
[i
],
426 sizeof(GUID
)) == sizeof(GUID
))
435 /* Check if we have to grow the list */
436 if (PnpBusTypeGuidList
->GuidCount
)
438 /* Calculate the new size */
439 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
440 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
442 /* Allocate the new copy */
443 NewList
= ExAllocatePool(PagedPool
, NewSize
);
448 ExFreePool(PnpBusTypeGuidList
);
452 /* Now copy them, decrease the size too */
453 NewSize
-= sizeof(GUID
);
454 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
456 /* Free the old list */
457 ExFreePool(PnpBusTypeGuidList
);
459 /* Use the new buffer */
460 PnpBusTypeGuidList
= NewList
;
463 /* Copy the new GUID */
464 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
468 /* The new entry is the index */
469 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
470 PnpBusTypeGuidList
->GuidCount
++;
473 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
479 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
480 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
481 IN UCHAR MinorFunction
,
482 IN PIO_STACK_LOCATION Stack OPTIONAL
)
484 IO_STACK_LOCATION IoStackLocation
;
486 /* Fill out the stack information */
487 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
488 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
489 IoStackLocation
.MinorFunction
= MinorFunction
;
493 RtlCopyMemory(&IoStackLocation
.Parameters
,
495 sizeof(Stack
->Parameters
));
498 /* Do the PnP call */
499 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
501 (PVOID
)&IoStatusBlock
->Information
);
502 return IoStatusBlock
->Status
;
506 * IopCreateDeviceKeyPath
508 * Creates a registry key
512 * Name of the key to be created.
514 * Handle to the newly created key
517 * This method can create nested trees, so parent of RegistryPath can
518 * be not existant, and will be created if needed.
522 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
523 IN ULONG CreateOptions
,
526 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
527 HANDLE hParent
= NULL
, hKey
;
528 OBJECT_ATTRIBUTES ObjectAttributes
;
529 UNICODE_STRING KeyName
;
530 PCWSTR Current
, Last
;
537 /* Open root key for device instances */
538 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
539 if (!NT_SUCCESS(Status
))
541 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
545 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
546 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
548 /* Go up to the end of the string */
549 while (Current
<= Last
)
551 if (Current
!= Last
&& *Current
!= L
'\\')
553 /* Not the end of the string and not a separator */
558 /* Prepare relative key name */
559 Length
= (USHORT
)((ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
);
560 KeyName
.MaximumLength
= KeyName
.Length
= Length
;
561 DPRINT("Create '%wZ'\n", &KeyName
);
564 InitializeObjectAttributes(&ObjectAttributes
,
566 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
569 Status
= ZwCreateKey(&hKey
,
570 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
577 /* Close parent key handle, we don't need it anymore */
581 /* Key opening/creating failed? */
582 if (!NT_SUCCESS(Status
))
584 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
588 /* Check if it is the end of the string */
591 /* Yes, return success */
593 return STATUS_SUCCESS
;
596 /* Start with this new parent key */
599 KeyName
.Buffer
= (PWSTR
)Current
;
602 return STATUS_UNSUCCESSFUL
;
606 IopSetDeviceInstanceData(HANDLE InstanceKey
,
607 PDEVICE_NODE DeviceNode
)
609 OBJECT_ATTRIBUTES ObjectAttributes
;
610 UNICODE_STRING KeyName
;
611 HANDLE LogConfKey
, ControlKey
, DeviceParamsKey
;
616 DPRINT("IopSetDeviceInstanceData() called\n");
618 /* Create the 'LogConf' key */
619 RtlInitUnicodeString(&KeyName
, L
"LogConf");
620 InitializeObjectAttributes(&ObjectAttributes
,
622 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
625 Status
= ZwCreateKey(&LogConfKey
,
630 // FIXME? In r53694 it was silently turned from non-volatile into this,
631 // without any extra warning. Is this still needed??
634 if (NT_SUCCESS(Status
))
636 /* Set 'BootConfig' value */
637 if (DeviceNode
->BootResources
!= NULL
)
639 ResCount
= DeviceNode
->BootResources
->Count
;
642 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
643 Status
= ZwSetValueKey(LogConfKey
,
647 DeviceNode
->BootResources
,
648 PnpDetermineResourceListSize(DeviceNode
->BootResources
));
652 /* Set 'BasicConfigVector' value */
653 if (DeviceNode
->ResourceRequirements
!= NULL
&&
654 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
656 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
657 Status
= ZwSetValueKey(LogConfKey
,
660 REG_RESOURCE_REQUIREMENTS_LIST
,
661 DeviceNode
->ResourceRequirements
,
662 DeviceNode
->ResourceRequirements
->ListSize
);
668 /* Set the 'ConfigFlags' value */
669 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
670 Status
= ZwQueryValueKey(InstanceKey
,
672 KeyValueBasicInformation
,
676 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
678 /* Write the default value */
679 ULONG DefaultConfigFlags
= 0;
680 Status
= ZwSetValueKey(InstanceKey
,
685 sizeof(DefaultConfigFlags
));
688 /* Create the 'Control' key */
689 RtlInitUnicodeString(&KeyName
, L
"Control");
690 InitializeObjectAttributes(&ObjectAttributes
,
692 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
695 Status
= ZwCreateKey(&ControlKey
,
702 if (NT_SUCCESS(Status
))
705 /* Create the 'Device Parameters' key and set the 'FirmwareIdentified' value for all ACPI-enumerated devices */
706 if (_wcsnicmp(DeviceNode
->InstancePath
.Buffer
, L
"ACPI\\", 5) == 0)
708 RtlInitUnicodeString(&KeyName
, L
"Device Parameters");
709 InitializeObjectAttributes(&ObjectAttributes
,
711 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
714 Status
= ZwCreateKey(&DeviceParamsKey
,
719 REG_OPTION_NON_VOLATILE
,
721 if (NT_SUCCESS(Status
))
723 ULONG FirmwareIdentified
= 1;
724 RtlInitUnicodeString(&KeyName
, L
"FirmwareIdentified");
725 Status
= ZwSetValueKey(DeviceParamsKey
,
730 sizeof(FirmwareIdentified
));
732 ZwClose(DeviceParamsKey
);
736 DPRINT("IopSetDeviceInstanceData() done\n");
742 * IopGetParentIdPrefix
744 * Retrieve (or create) a string which identifies a device.
748 * Pointer to device node.
750 * Pointer to the string where is returned the parent node identifier
753 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
754 * valid and its Buffer field is NULL-terminated. The caller needs to
755 * to free the string with RtlFreeUnicodeString when it is no longer
760 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
761 PUNICODE_STRING ParentIdPrefix
)
763 const UNICODE_STRING EnumKeyPath
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
764 ULONG KeyNameBufferLength
;
765 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
766 UNICODE_STRING KeyName
= {0, 0, NULL
};
767 UNICODE_STRING KeyValue
;
768 UNICODE_STRING ValueName
;
773 /* HACK: As long as some devices have a NULL device
774 * instance path, the following test is required :(
776 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
778 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
779 &DeviceNode
->InstancePath
);
780 return STATUS_UNSUCCESSFUL
;
783 /* 1. Try to retrieve ParentIdPrefix from registry */
784 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
) + sizeof(L
"12345678&12345678");
785 ParentIdPrefixInformation
= ExAllocatePoolWithTag(PagedPool
,
786 KeyNameBufferLength
+ sizeof(UNICODE_NULL
),
788 if (!ParentIdPrefixInformation
)
790 return STATUS_INSUFFICIENT_RESOURCES
;
794 KeyName
.MaximumLength
= EnumKeyPath
.Length
+
795 DeviceNode
->Parent
->InstancePath
.Length
+
796 sizeof(UNICODE_NULL
);
797 KeyName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
798 KeyName
.MaximumLength
,
802 Status
= STATUS_INSUFFICIENT_RESOURCES
;
806 RtlCopyUnicodeString(&KeyName
, &EnumKeyPath
);
807 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
809 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
810 if (!NT_SUCCESS(Status
))
814 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
815 Status
= ZwQueryValueKey(hKey
,
817 KeyValuePartialInformation
,
818 ParentIdPrefixInformation
,
820 &KeyNameBufferLength
);
821 if (NT_SUCCESS(Status
))
823 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
825 Status
= STATUS_UNSUCCESSFUL
;
829 KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
830 KeyValue
.Length
= KeyValue
.MaximumLength
- sizeof(UNICODE_NULL
);
831 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
832 ASSERT(KeyValue
.Buffer
[KeyValue
.Length
/ sizeof(WCHAR
)] == UNICODE_NULL
);
836 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
838 /* FIXME how do we get here and why is ParentIdPrefixInformation valid? */
839 KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
840 KeyValue
.Length
= KeyValue
.MaximumLength
- sizeof(UNICODE_NULL
);
841 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
842 ASSERT(KeyValue
.Buffer
[KeyValue
.Length
/ sizeof(WCHAR
)] == UNICODE_NULL
);
846 /* 2. Create the ParentIdPrefix value */
847 crc32
= RtlComputeCrc32(0,
848 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
849 DeviceNode
->Parent
->InstancePath
.Length
);
851 RtlStringCbPrintfW((PWSTR
)ParentIdPrefixInformation
,
854 DeviceNode
->Parent
->Level
,
856 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
);
858 /* 3. Try to write the ParentIdPrefix to registry */
859 Status
= ZwSetValueKey(hKey
,
864 ((ULONG
)wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
867 if (NT_SUCCESS(Status
))
869 /* Duplicate the string to return it */
870 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
874 ExFreePoolWithTag(ParentIdPrefixInformation
, TAG_IO
);
875 RtlFreeUnicodeString(&KeyName
);
886 IopEnumerateDetectedDevices(
888 IN PUNICODE_STRING RelativePath OPTIONAL
,
890 IN BOOLEAN EnumerateSubKeys
,
891 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
892 IN ULONG ParentBootResourcesLength
)
894 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
895 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
896 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
897 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
898 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
899 OBJECT_ATTRIBUTES ObjectAttributes
;
900 HANDLE hDevicesKey
= NULL
;
901 HANDLE hDeviceKey
= NULL
;
902 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
903 UNICODE_STRING Level2NameU
;
905 ULONG IndexDevice
= 0;
907 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
908 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
909 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
910 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
911 UNICODE_STRING DeviceName
, ValueName
;
913 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
914 ULONG BootResourcesLength
;
917 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
918 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
919 static ULONG DeviceIndexSerial
= 0;
920 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
921 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
922 static ULONG DeviceIndexKeyboard
= 0;
923 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
924 /* FIXME: IopEnumerateDetectedDevices() should be rewritten.
925 * The PnP identifiers can either be hardcoded or parsed from a LegacyXlate
926 * sections of driver INF files.
928 #if defined(SARCH_PC98)
929 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*nEC1F00\0");
931 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
933 static ULONG DeviceIndexMouse
= 0;
934 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
935 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
936 static ULONG DeviceIndexParallel
= 0;
937 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
938 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
939 static ULONG DeviceIndexFloppy
= 0;
940 UNICODE_STRING HardwareIdKey
;
941 PUNICODE_STRING pHardwareId
;
942 ULONG DeviceIndex
= 0;
943 PUCHAR CmResourceList
;
948 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
949 if (!NT_SUCCESS(Status
))
951 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
956 hDevicesKey
= hBaseKey
;
958 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
959 if (!pDeviceInformation
)
961 DPRINT("ExAllocatePool() failed\n");
962 Status
= STATUS_NO_MEMORY
;
966 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
967 if (!pValueInformation
)
969 DPRINT("ExAllocatePool() failed\n");
970 Status
= STATUS_NO_MEMORY
;
976 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
977 if (Status
== STATUS_NO_MORE_ENTRIES
)
979 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
981 ExFreePool(pDeviceInformation
);
982 DeviceInfoLength
= RequiredSize
;
983 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
984 if (!pDeviceInformation
)
986 DPRINT("ExAllocatePool() failed\n");
987 Status
= STATUS_NO_MEMORY
;
990 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
992 if (!NT_SUCCESS(Status
))
994 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
999 /* Open device key */
1000 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
1001 DeviceName
.Buffer
= pDeviceInformation
->Name
;
1003 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
1004 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
1005 if (!NT_SUCCESS(Status
))
1007 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
1011 /* Read boot resources, and add then to parent ones */
1012 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
1013 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1015 ExFreePool(pValueInformation
);
1016 ValueInfoLength
= RequiredSize
;
1017 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
1018 if (!pValueInformation
)
1020 DPRINT("ExAllocatePool() failed\n");
1021 ZwDeleteKey(hLevel2Key
);
1022 Status
= STATUS_NO_MEMORY
;
1025 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
1027 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1029 BootResources
= ParentBootResources
;
1030 BootResourcesLength
= ParentBootResourcesLength
;
1032 else if (!NT_SUCCESS(Status
))
1034 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
1037 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
1039 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
1044 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
1046 /* Concatenate current resources and parent ones */
1047 if (ParentBootResourcesLength
== 0)
1048 BootResourcesLength
= pValueInformation
->DataLength
;
1050 BootResourcesLength
= ParentBootResourcesLength
1051 + pValueInformation
->DataLength
1053 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
1056 DPRINT("ExAllocatePool() failed\n");
1059 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
1061 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
1063 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
1065 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
1067 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
1068 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
1069 ParentBootResourcesLength
- Header
);
1070 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
1074 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
1076 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
1077 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
1078 ParentBootResourcesLength
- Header
);
1080 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
1081 pValueInformation
->Data
+ Header
,
1082 pValueInformation
->DataLength
- Header
);
1083 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
1087 if (EnumerateSubKeys
)
1092 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
1093 if (Status
== STATUS_NO_MORE_ENTRIES
)
1095 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1097 ExFreePool(pDeviceInformation
);
1098 DeviceInfoLength
= RequiredSize
;
1099 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
1100 if (!pDeviceInformation
)
1102 DPRINT("ExAllocatePool() failed\n");
1103 Status
= STATUS_NO_MEMORY
;
1106 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
1108 if (!NT_SUCCESS(Status
))
1110 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
1114 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
1115 DeviceName
.Buffer
= pDeviceInformation
->Name
;
1117 Status
= IopEnumerateDetectedDevices(
1123 BootResourcesLength
);
1124 if (!NT_SUCCESS(Status
))
1129 /* Read identifier */
1130 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
1131 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
1133 ExFreePool(pValueInformation
);
1134 ValueInfoLength
= RequiredSize
;
1135 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
1136 if (!pValueInformation
)
1138 DPRINT("ExAllocatePool() failed\n");
1139 Status
= STATUS_NO_MEMORY
;
1142 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
1144 if (!NT_SUCCESS(Status
))
1146 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1148 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
1151 ValueName
.Length
= ValueName
.MaximumLength
= 0;
1153 else if (pValueInformation
->Type
!= REG_SZ
)
1155 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
1160 /* Assign hardware id to this device */
1161 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
1162 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
1163 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
1164 ValueName
.Length
-= sizeof(WCHAR
);
1167 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
1169 pHardwareId
= &HardwareIdSerial
;
1170 DeviceIndex
= DeviceIndexSerial
++;
1172 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
1174 pHardwareId
= &HardwareIdKeyboard
;
1175 DeviceIndex
= DeviceIndexKeyboard
++;
1177 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
1179 pHardwareId
= &HardwareIdMouse
;
1180 DeviceIndex
= DeviceIndexMouse
++;
1182 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
1184 pHardwareId
= &HardwareIdParallel
;
1185 DeviceIndex
= DeviceIndexParallel
++;
1187 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
1189 pHardwareId
= &HardwareIdFloppy
;
1190 DeviceIndex
= DeviceIndexFloppy
++;
1194 /* Unknown key path */
1195 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
1199 /* Prepare hardware id key (hardware id value without final \0) */
1200 HardwareIdKey
= *pHardwareId
;
1201 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
1203 /* Add the detected device to Root key */
1204 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
1205 Status
= ZwCreateKey(
1211 REG_OPTION_NON_VOLATILE
,
1213 if (!NT_SUCCESS(Status
))
1215 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
1218 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
1219 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
1220 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
1221 Status
= ZwCreateKey(
1223 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
1227 REG_OPTION_NON_VOLATILE
,
1229 ZwClose(hLevel1Key
);
1230 if (!NT_SUCCESS(Status
))
1232 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
1235 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
1236 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
1237 if (!NT_SUCCESS(Status
))
1239 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
1240 ZwDeleteKey(hLevel2Key
);
1243 /* Create 'LogConf' subkey */
1244 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
1245 Status
= ZwCreateKey(
1251 REG_OPTION_VOLATILE
,
1253 if (!NT_SUCCESS(Status
))
1255 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
1256 ZwDeleteKey(hLevel2Key
);
1259 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
1261 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
1262 if (!CmResourceList
)
1265 ZwDeleteKey(hLevel2Key
);
1269 /* Add the list count (1st member of CM_RESOURCE_LIST) */
1271 RtlCopyMemory(CmResourceList
,
1275 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
1276 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
1278 BootResourcesLength
);
1280 /* Save boot resources to 'LogConf\BootConfig' */
1281 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
1282 if (!NT_SUCCESS(Status
))
1284 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
1286 ZwDeleteKey(hLevel2Key
);
1293 if (BootResources
&& BootResources
!= ParentBootResources
)
1295 ExFreePool(BootResources
);
1296 BootResources
= NULL
;
1300 ZwClose(hLevel2Key
);
1305 ZwClose(hDeviceKey
);
1310 Status
= STATUS_SUCCESS
;
1313 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
1314 ZwClose(hDevicesKey
);
1316 ZwClose(hDeviceKey
);
1317 if (pDeviceInformation
)
1318 ExFreePool(pDeviceInformation
);
1319 if (pValueInformation
)
1320 ExFreePool(pValueInformation
);
1327 IopIsFirmwareMapperDisabled(VOID
)
1329 UNICODE_STRING KeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CURRENTCONTROLSET\\Control\\Pnp");
1330 UNICODE_STRING KeyNameU
= RTL_CONSTANT_STRING(L
"DisableFirmwareMapper");
1331 OBJECT_ATTRIBUTES ObjectAttributes
;
1333 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
;
1334 ULONG DesiredLength
, Length
;
1338 InitializeObjectAttributes(&ObjectAttributes
, &KeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1339 Status
= ZwOpenKey(&hPnpKey
, KEY_QUERY_VALUE
, &ObjectAttributes
);
1340 if (NT_SUCCESS(Status
))
1342 Status
= ZwQueryValueKey(hPnpKey
,
1344 KeyValuePartialInformation
,
1348 if ((Status
== STATUS_BUFFER_TOO_SMALL
) ||
1349 (Status
== STATUS_BUFFER_OVERFLOW
))
1351 Length
= DesiredLength
;
1352 KeyInformation
= ExAllocatePool(PagedPool
, Length
);
1355 Status
= ZwQueryValueKey(hPnpKey
,
1357 KeyValuePartialInformation
,
1361 if (NT_SUCCESS(Status
) && KeyInformation
->DataLength
== sizeof(ULONG
))
1363 KeyValue
= (ULONG
)(*KeyInformation
->Data
);
1367 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed\n", &KeyPathU
, &KeyNameU
);
1370 ExFreePool(KeyInformation
);
1374 DPRINT1("Failed to allocate memory for registry query\n");
1379 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed with status 0x%08lx\n", &KeyPathU
, &KeyNameU
, Status
);
1386 DPRINT1("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyPathU
, Status
);
1389 DPRINT("Firmware mapper is %s\n", KeyValue
!= 0 ? "disabled" : "enabled");
1391 return (KeyValue
!= 0) ? TRUE
: FALSE
;
1397 IopUpdateRootKey(VOID
)
1399 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
1400 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
1401 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
1402 OBJECT_ATTRIBUTES ObjectAttributes
;
1403 HANDLE hEnum
, hRoot
;
1406 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1407 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
1408 if (!NT_SUCCESS(Status
))
1410 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
1414 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
1415 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
1417 if (!NT_SUCCESS(Status
))
1419 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
1423 if (!IopIsFirmwareMapperDisabled())
1425 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
1426 if (!NT_SUCCESS(Status
))
1428 /* Nothing to do, don't return with an error status */
1429 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
1431 return STATUS_SUCCESS
;
1433 Status
= IopEnumerateDetectedDevices(
1444 /* Enumeration is disabled */
1445 Status
= STATUS_SUCCESS
;
1455 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
1457 PUNICODE_STRING Name
,
1458 ACCESS_MASK DesiredAccess
)
1460 OBJECT_ATTRIBUTES ObjectAttributes
;
1467 InitializeObjectAttributes(&ObjectAttributes
,
1469 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1473 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
1480 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
1481 IN HANDLE RootHandle OPTIONAL
,
1482 IN PUNICODE_STRING KeyName
,
1483 IN ACCESS_MASK DesiredAccess
,
1484 IN ULONG CreateOptions
,
1485 OUT PULONG Disposition OPTIONAL
)
1487 OBJECT_ATTRIBUTES ObjectAttributes
;
1488 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0;
1490 HANDLE HandleArray
[2];
1491 BOOLEAN Recursing
= TRUE
;
1493 UNICODE_STRING KeyString
;
1494 NTSTATUS Status
= STATUS_SUCCESS
;
1497 /* P1 is start, pp is end */
1498 p1
= KeyName
->Buffer
;
1499 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
1501 /* Create the target key */
1502 InitializeObjectAttributes(&ObjectAttributes
,
1504 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1507 Status
= ZwCreateKey(&HandleArray
[i
],
1515 /* Now we check if this failed */
1516 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
1518 /* Target key failed, so we'll need to create its parent. Setup array */
1519 HandleArray
[0] = NULL
;
1520 HandleArray
[1] = RootHandle
;
1522 /* Keep recursing for each missing parent */
1525 /* And if we're deep enough, close the last handle */
1526 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
1528 /* We're setup to ping-pong between the two handle array entries */
1529 RootHandleIndex
= i
;
1532 /* Clear the one we're attempting to open now */
1533 HandleArray
[i
] = NULL
;
1535 /* Process the parent key name */
1536 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
1537 Length
= (USHORT
)(p
- p1
) * sizeof(WCHAR
);
1539 /* Is there a parent name? */
1542 /* Build the unicode string for it */
1543 KeyString
.Buffer
= p1
;
1544 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
1546 /* Now try opening the parent */
1547 InitializeObjectAttributes(&ObjectAttributes
,
1549 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1550 HandleArray
[RootHandleIndex
],
1552 Status
= ZwCreateKey(&HandleArray
[i
],
1559 if (NT_SUCCESS(Status
))
1561 /* It worked, we have one more handle */
1566 /* Parent key creation failed, abandon loop */
1573 /* We don't have a parent name, probably corrupted key name */
1574 Status
= STATUS_INVALID_PARAMETER
;
1579 /* Now see if there's more parents to create */
1581 if ((p
== pp
) || (p1
== pp
))
1583 /* We're done, hopefully successfully, so stop */
1588 /* Outer loop check for handle nesting that requires closing the top handle */
1589 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
1592 /* Check if we broke out of the loop due to success */
1593 if (NT_SUCCESS(Status
))
1595 /* Return the target handle (we closed all the parent ones) and disposition */
1596 *Handle
= HandleArray
[i
];
1597 if (Disposition
) *Disposition
= KeyDisposition
;
1600 /* Return the success state */
1606 IopGetRegistryValue(IN HANDLE Handle
,
1608 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
1610 UNICODE_STRING ValueString
;
1612 PKEY_VALUE_FULL_INFORMATION FullInformation
;
1616 RtlInitUnicodeString(&ValueString
, ValueName
);
1618 Status
= ZwQueryValueKey(Handle
,
1620 KeyValueFullInformation
,
1624 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
1625 (Status
!= STATUS_BUFFER_TOO_SMALL
))
1630 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
1631 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
1633 Status
= ZwQueryValueKey(Handle
,
1635 KeyValueFullInformation
,
1639 if (!NT_SUCCESS(Status
))
1641 ExFreePool(FullInformation
);
1645 *Information
= FullInformation
;
1646 return STATUS_SUCCESS
;
1649 RTL_GENERIC_COMPARE_RESULTS
1651 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
1652 IN PVOID FirstStruct
,
1653 IN PVOID SecondStruct
)
1661 // The allocation function is called by the generic table package whenever
1662 // it needs to allocate memory for the table.
1667 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
1677 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
1686 PpInitializeDeviceReferenceTable(VOID
)
1688 /* Setup the guarded mutex and AVL table */
1689 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
1690 RtlInitializeGenericTableAvl(
1691 &PpDeviceReferenceTable
,
1692 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
1693 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
1694 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
1702 /* Initialize the resource when accessing device registry data */
1703 ExInitializeResourceLite(&PpRegistryDeviceResource
);
1705 /* Setup the device reference AVL table */
1706 PpInitializeDeviceReferenceTable();
1714 /* Check the initialization phase */
1715 switch (ExpInitializationPhase
)
1720 return PiInitPhase0();
1726 //return PiInitPhase1();
1730 /* Don't know any other phase! Bugcheck! */
1731 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
1736 /* PUBLIC FUNCTIONS **********************************************************/
1740 PnpBusTypeGuidGet(IN USHORT Index
,
1741 IN LPGUID BusTypeGuid
)
1743 NTSTATUS Status
= STATUS_SUCCESS
;
1745 /* Acquire the lock */
1746 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
1749 if (Index
< PnpBusTypeGuidList
->GuidCount
)
1752 RtlCopyMemory(BusTypeGuid
, &PnpBusTypeGuidList
->Guids
[Index
], sizeof(GUID
));
1757 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1760 /* Release lock and return status */
1761 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
1767 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject
,
1768 IN PHANDLE DeviceInstanceHandle
,
1769 IN ACCESS_MASK DesiredAccess
)
1773 PDEVICE_NODE DeviceNode
;
1774 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
1777 /* Open the enum key */
1778 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
1782 if (!NT_SUCCESS(Status
)) return Status
;
1784 /* Make sure we have an instance path */
1785 DeviceNode
= IopGetDeviceNode(DeviceObject
);
1786 if ((DeviceNode
) && (DeviceNode
->InstancePath
.Length
))
1788 /* Get the instance key */
1789 Status
= IopOpenRegistryKeyEx(DeviceInstanceHandle
,
1791 &DeviceNode
->InstancePath
,
1797 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1800 /* Close the handle and return status */
1807 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList
)
1809 ULONG FinalSize
, PartialSize
, EntrySize
, i
, j
;
1810 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
1811 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
1813 /* If we don't have one, that's easy */
1814 if (!ResourceList
) return 0;
1816 /* Start with the minimum size possible */
1817 FinalSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
1819 /* Loop each full descriptor */
1820 FullDescriptor
= ResourceList
->List
;
1821 for (i
= 0; i
< ResourceList
->Count
; i
++)
1823 /* Start with the minimum size possible */
1824 PartialSize
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
) +
1825 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
);
1827 /* Loop each partial descriptor */
1828 PartialDescriptor
= FullDescriptor
->PartialResourceList
.PartialDescriptors
;
1829 for (j
= 0; j
< FullDescriptor
->PartialResourceList
.Count
; j
++)
1831 /* Start with the minimum size possible */
1832 EntrySize
= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
1834 /* Check if there is extra data */
1835 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
1838 EntrySize
+= PartialDescriptor
->u
.DeviceSpecificData
.DataSize
;
1841 /* The size of partial descriptors is bigger */
1842 PartialSize
+= EntrySize
;
1844 /* Go to the next partial descriptor */
1845 PartialDescriptor
= (PVOID
)((ULONG_PTR
)PartialDescriptor
+ EntrySize
);
1848 /* The size of full descriptors is bigger */
1849 FinalSize
+= PartialSize
;
1851 /* Go to the next full descriptor */
1852 FullDescriptor
= (PVOID
)((ULONG_PTR
)FullDescriptor
+ PartialSize
);
1855 /* Return the final size */
1861 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject
,
1866 IN PULONG BufferLength
)
1869 HANDLE KeyHandle
, SubHandle
;
1870 UNICODE_STRING KeyString
;
1871 PKEY_VALUE_FULL_INFORMATION KeyValueInfo
= NULL
;
1875 /* Find the instance key */
1876 Status
= PnpDeviceObjectToDeviceInstance(DeviceObject
, &KeyHandle
, KEY_READ
);
1877 if (NT_SUCCESS(Status
))
1879 /* Check for name given by caller */
1883 RtlInitUnicodeString(&KeyString
, KeyName
);
1884 Status
= IopOpenRegistryKeyEx(&SubHandle
,
1888 if (NT_SUCCESS(Status
))
1890 /* And use this handle instead */
1892 KeyHandle
= SubHandle
;
1896 /* Check if sub-key handle succeeded (or no-op if no key name given) */
1897 if (NT_SUCCESS(Status
))
1899 /* Now get the size of the property */
1900 Status
= IopGetRegistryValue(KeyHandle
,
1909 /* Fail if any of the registry operations failed */
1910 if (!NT_SUCCESS(Status
)) return Status
;
1912 /* Check how much data we have to copy */
1913 Length
= KeyValueInfo
->DataLength
;
1914 if (*BufferLength
>= Length
)
1916 /* Check for a match in the value type */
1917 if (KeyValueInfo
->Type
== ValueType
)
1920 RtlCopyMemory(Buffer
,
1921 (PVOID
)((ULONG_PTR
)KeyValueInfo
+
1922 KeyValueInfo
->DataOffset
),
1927 /* Invalid registry property type, fail */
1928 Status
= STATUS_INVALID_PARAMETER_2
;
1933 /* Buffer is too small to hold data */
1934 Status
= STATUS_BUFFER_TOO_SMALL
;
1937 /* Return the required buffer length, free the buffer, and return status */
1938 *BufferLength
= Length
;
1939 ExFreePool(KeyValueInfo
);
1943 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
1944 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
1945 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED_DBGBREAK(); break;}
1952 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
1953 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
1954 IN ULONG BufferLength
,
1955 OUT PVOID PropertyBuffer
,
1956 OUT PULONG ResultLength
)
1958 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
1959 DEVICE_CAPABILITIES DeviceCaps
;
1960 ULONG ReturnLength
= 0, Length
= 0, ValueType
;
1961 PWCHAR ValueName
= NULL
, EnumeratorNameEnd
, DeviceInstanceName
;
1963 NTSTATUS Status
= STATUS_BUFFER_TOO_SMALL
;
1965 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
1966 BOOLEAN NullTerminate
= FALSE
;
1967 DEVICE_REMOVAL_POLICY Policy
;
1969 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
1971 /* Assume failure */
1974 /* Only PDOs can call this */
1975 if (!DeviceNode
) return STATUS_INVALID_DEVICE_REQUEST
;
1977 /* Handle all properties */
1978 switch (DeviceProperty
)
1980 case DevicePropertyBusTypeGuid
:
1982 /* Get the GUID from the internal cache */
1983 Status
= PnpBusTypeGuidGet(DeviceNode
->ChildBusTypeIndex
, &BusTypeGuid
);
1984 if (!NT_SUCCESS(Status
)) return Status
;
1986 /* This is the format of the returned data */
1987 PIP_RETURN_DATA(sizeof(GUID
), &BusTypeGuid
);
1989 case DevicePropertyLegacyBusType
:
1991 /* Validate correct interface type */
1992 if (DeviceNode
->ChildInterfaceType
== InterfaceTypeUndefined
)
1993 return STATUS_OBJECT_NAME_NOT_FOUND
;
1995 /* This is the format of the returned data */
1996 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE
), &DeviceNode
->ChildInterfaceType
);
1998 case DevicePropertyBusNumber
:
2000 /* Validate correct bus number */
2001 if ((DeviceNode
->ChildBusNumber
& 0x80000000) == 0x80000000)
2002 return STATUS_OBJECT_NAME_NOT_FOUND
;
2004 /* This is the format of the returned data */
2005 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceNode
->ChildBusNumber
);
2007 case DevicePropertyEnumeratorName
:
2009 /* Get the instance path */
2010 DeviceInstanceName
= DeviceNode
->InstancePath
.Buffer
;
2013 ASSERT((BufferLength
& 1) == 0);
2014 ASSERT(DeviceInstanceName
!= NULL
);
2016 /* Get the name from the path */
2017 EnumeratorNameEnd
= wcschr(DeviceInstanceName
, OBJ_NAME_PATH_SEPARATOR
);
2018 ASSERT(EnumeratorNameEnd
);
2020 /* This string needs to be NULL-terminated */
2021 NullTerminate
= TRUE
;
2023 /* This is the format of the returned data */
2024 PIP_RETURN_DATA((ULONG
)(EnumeratorNameEnd
- DeviceInstanceName
) * sizeof(WCHAR
),
2025 DeviceInstanceName
);
2027 case DevicePropertyAddress
:
2029 /* Query the device caps */
2030 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
2031 if (!NT_SUCCESS(Status
) || (DeviceCaps
.Address
== MAXULONG
))
2032 return STATUS_OBJECT_NAME_NOT_FOUND
;
2034 /* This is the format of the returned data */
2035 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceCaps
.Address
);
2037 case DevicePropertyBootConfigurationTranslated
:
2039 /* Validate we have resources */
2040 if (!DeviceNode
->BootResources
)
2041 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
2043 /* No resources will still fake success, but with 0 bytes */
2045 return STATUS_SUCCESS
;
2048 /* This is the format of the returned data */
2049 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode
->BootResources
), // FIXFIX: Should use BootResourcesTranslated
2050 DeviceNode
->BootResources
); // FIXFIX: Should use BootResourcesTranslated
2052 case DevicePropertyPhysicalDeviceObjectName
:
2054 /* Sanity check for Unicode-sized string */
2055 ASSERT((BufferLength
& 1) == 0);
2057 /* Allocate name buffer */
2058 Length
= BufferLength
+ sizeof(OBJECT_NAME_INFORMATION
);
2059 ObjectNameInfo
= ExAllocatePool(PagedPool
, Length
);
2060 if (!ObjectNameInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
2062 /* Query the PDO name */
2063 Status
= ObQueryNameString(DeviceObject
,
2067 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
2069 /* It's up to the caller to try again */
2070 Status
= STATUS_BUFFER_TOO_SMALL
;
2073 /* This string needs to be NULL-terminated */
2074 NullTerminate
= TRUE
;
2076 /* Return if successful */
2077 if (NT_SUCCESS(Status
)) PIP_RETURN_DATA(ObjectNameInfo
->Name
.Length
,
2078 ObjectNameInfo
->Name
.Buffer
);
2080 /* Let the caller know how big the name is */
2081 *ResultLength
-= sizeof(OBJECT_NAME_INFORMATION
);
2084 case DevicePropertyRemovalPolicy
:
2086 Policy
= DeviceNode
->RemovalPolicy
;
2087 PIP_RETURN_DATA(sizeof(Policy
), &Policy
);
2089 /* Handle the registry-based properties */
2090 case DevicePropertyUINumber
:
2091 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER
, REG_DWORD
);
2092 case DevicePropertyLocationInformation
:
2093 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION
, REG_SZ
);
2094 case DevicePropertyDeviceDescription
:
2095 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC
, REG_SZ
);
2096 case DevicePropertyHardwareID
:
2097 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID
, REG_MULTI_SZ
);
2098 case DevicePropertyCompatibleIDs
:
2099 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS
, REG_MULTI_SZ
);
2100 case DevicePropertyBootConfiguration
:
2101 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG
, REG_RESOURCE_LIST
);
2102 case DevicePropertyClassName
:
2103 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS
, REG_SZ
);
2104 case DevicePropertyClassGuid
:
2105 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID
, REG_SZ
);
2106 case DevicePropertyDriverKeyName
:
2107 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER
, REG_SZ
);
2108 case DevicePropertyManufacturer
:
2109 PIP_REGISTRY_DATA(REGSTR_VAL_MFG
, REG_SZ
);
2110 case DevicePropertyFriendlyName
:
2111 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME
, REG_SZ
);
2112 case DevicePropertyContainerID
:
2113 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
2114 PIP_UNIMPLEMENTED();
2116 case DevicePropertyInstallState
:
2117 PIP_REGISTRY_DATA(REGSTR_VAL_CONFIGFLAGS
, REG_DWORD
);
2119 case DevicePropertyResourceRequirements
:
2120 PIP_UNIMPLEMENTED();
2121 case DevicePropertyAllocatedResources
:
2122 PIP_UNIMPLEMENTED();
2124 return STATUS_INVALID_PARAMETER_2
;
2127 /* Having a registry value name implies registry data */
2130 /* We know up-front how much data to expect */
2131 *ResultLength
= BufferLength
;
2133 /* Go get the data, use the LogConf subkey if necessary */
2134 Status
= PiGetDeviceRegistryProperty(DeviceObject
,
2138 DevicePropertyBootConfiguration
) ?
2143 else if (NT_SUCCESS(Status
))
2145 /* We know up-front how much data to expect, check the caller's buffer */
2146 *ResultLength
= ReturnLength
+ (NullTerminate
? sizeof(UNICODE_NULL
) : 0);
2147 if (*ResultLength
<= BufferLength
)
2149 /* Buffer is all good, copy the data */
2150 RtlCopyMemory(PropertyBuffer
, Data
, ReturnLength
);
2152 /* Check if we need to NULL-terminate the string */
2155 /* Terminate the string */
2156 ((PWCHAR
)PropertyBuffer
)[ReturnLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
2159 /* This is the success path */
2160 Status
= STATUS_SUCCESS
;
2165 Status
= STATUS_BUFFER_TOO_SMALL
;
2169 /* Free any allocation we may have made, and return the status code */
2170 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
2175 * @name IoOpenDeviceRegistryKey
2177 * Open a registry key unique for a specified driver or device instance.
2179 * @param DeviceObject Device to get the registry key for.
2180 * @param DevInstKeyType Type of the key to return.
2181 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
2182 * @param DevInstRegKey Handle to the opened registry key on
2183 * successful return.
2191 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
2192 IN ULONG DevInstKeyType
,
2193 IN ACCESS_MASK DesiredAccess
,
2194 OUT PHANDLE DevInstRegKey
)
2196 static WCHAR RootKeyName
[] =
2197 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
2198 static WCHAR ProfileKeyName
[] =
2199 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
2200 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
2201 static WCHAR EnumKeyName
[] = L
"Enum\\";
2202 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
2203 ULONG KeyNameLength
;
2204 PWSTR KeyNameBuffer
;
2205 UNICODE_STRING KeyName
;
2206 ULONG DriverKeyLength
;
2207 OBJECT_ATTRIBUTES ObjectAttributes
;
2208 PDEVICE_NODE DeviceNode
= NULL
;
2211 DPRINT("IoOpenDeviceRegistryKey() called\n");
2213 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
2215 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting...\n");
2216 return STATUS_INVALID_PARAMETER
;
2219 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
2220 return STATUS_INVALID_DEVICE_REQUEST
;
2221 DeviceNode
= IopGetDeviceNode(DeviceObject
);
2224 * Calculate the length of the base key name. This is the full
2225 * name for driver key or the name excluding "Device Parameters"
2226 * subkey for device key.
2229 KeyNameLength
= sizeof(RootKeyName
);
2230 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
2231 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
2232 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
2234 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
2235 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
2236 0, NULL
, &DriverKeyLength
);
2237 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
2239 KeyNameLength
+= DriverKeyLength
;
2243 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
2244 DeviceNode
->InstancePath
.Length
;
2248 * Now allocate the buffer for the key name...
2251 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
2252 if (KeyNameBuffer
== NULL
)
2253 return STATUS_INSUFFICIENT_RESOURCES
;
2256 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
2257 KeyName
.Buffer
= KeyNameBuffer
;
2260 * ...and build the key name.
2263 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
2264 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
2266 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
2267 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
2269 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
2271 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
2272 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
2273 DriverKeyLength
, KeyNameBuffer
+
2274 (KeyName
.Length
/ sizeof(WCHAR
)),
2276 if (!NT_SUCCESS(Status
))
2278 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
2279 ExFreePool(KeyNameBuffer
);
2282 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
2286 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
2287 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
2288 if (DeviceNode
->InstancePath
.Length
== 0)
2290 ExFreePool(KeyNameBuffer
);
2296 * Open the base key.
2298 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
2299 if (!NT_SUCCESS(Status
))
2301 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
2302 ExFreePool(KeyNameBuffer
);
2305 ExFreePool(KeyNameBuffer
);
2308 * For driver key we're done now.
2311 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
2315 * Let's go further. For device key we must open "Device Parameters"
2316 * subkey and create it if it doesn't exist yet.
2319 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
2320 InitializeObjectAttributes(&ObjectAttributes
,
2322 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
2325 Status
= ZwCreateKey(DevInstRegKey
,
2330 REG_OPTION_NON_VOLATILE
,
2332 ZwClose(ObjectAttributes
.RootDirectory
);
2342 IoInvalidateDeviceRelations(
2343 IN PDEVICE_OBJECT DeviceObject
,
2344 IN DEVICE_RELATION_TYPE Type
)
2346 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
2348 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR
, 0x2, (ULONG_PTR
)DeviceObject
, 0, 0);
2354 /* Enumerate the device */
2355 PiQueueDeviceAction(DeviceObject
, PiActionEnumDeviceTree
, NULL
, NULL
);
2358 /* Everything else is not implemented */
2368 IoSynchronousInvalidateDeviceRelations(
2369 IN PDEVICE_OBJECT DeviceObject
,
2370 IN DEVICE_RELATION_TYPE Type
)
2374 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
2376 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR
, 0x2, (ULONG_PTR
)DeviceObject
, 0, 0);
2382 /* Enumerate the device */
2383 return PiPerformSyncDeviceAction(DeviceObject
, PiActionEnumDeviceTree
);
2384 case PowerRelations
:
2385 /* Not handled yet */
2386 return STATUS_NOT_IMPLEMENTED
;
2387 case TargetDeviceRelation
:
2389 return STATUS_SUCCESS
;
2391 /* Ejection relations are not supported */
2392 return STATUS_NOT_SUPPORTED
;
2401 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
2403 IN PHYSICAL_ADDRESS BusAddress
,
2404 IN OUT PULONG AddressSpace
,
2405 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
2407 /* FIXME: Notify the resource arbiter */
2409 return HalTranslateBusAddress(InterfaceType
,
2418 IoInvalidateDeviceState(
2419 IN PDEVICE_OBJECT DeviceObject
)
2421 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
2423 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR
, 0x2, (ULONG_PTR
)DeviceObject
, 0, 0);
2426 PiQueueDeviceAction(DeviceObject
, PiActionQueryState
, NULL
, NULL
);