2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/iomgr/iorsrce.c
5 * PURPOSE: Hardware resource managment
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 * Alex Ionescu (alex@relsoft.net)
9 * Pierre Schweitzer (pierre.schweitzer@reactos.org)
12 /* INCLUDES *****************************************************************/
17 /* GLOBALS *******************************************************************/
19 static CONFIGURATION_INFORMATION
20 _SystemConfigurationInformation
= { 0, 0, 0, 0, 0, 0, 0, FALSE
, FALSE
, 0, 0 };
22 /* API Parameters to Pass in IopQueryBusDescription */
23 typedef struct IO_QUERY
{
24 PINTERFACE_TYPE BusType
;
26 PCONFIGURATION_TYPE ControllerType
;
27 PULONG ControllerNumber
;
28 PCONFIGURATION_TYPE PeripheralType
;
29 PULONG PeripheralNumber
;
30 PIO_QUERY_DEVICE_ROUTINE CalloutRoutine
;
32 } IO_QUERY
, *PIO_QUERY
;
34 PWSTR ArcTypes
[42] = {
37 L
"FloatingPointProcessor",
47 L
"MultifunctionAdapter",
55 L
"ParallelController",
57 L
"KeyboardController",
61 L
"FloppyDiskPeripheral",
67 L
"KeyboardPeripheral",
68 L
"TerminalPeripheral",
73 L
"DockingInformation",
74 L
"RealModeIrqRoutingTable",
75 L
"RealModePCIEnumeration",
79 /* PRIVATE FUNCTIONS **********************************************************/
82 * IopQueryDeviceDescription
85 * Reads and returns Hardware information from the appropriate hardware
86 * registry key. Helper sub of IopQueryBusDescription.
89 * Query - What the parent function wants.
90 * RootKey - Which key to look in
91 * RootKeyHandle - Handle to the key
93 * BusInformation - The Configuration Information Sent
100 IopQueryDeviceDescription(
102 UNICODE_STRING RootKey
,
103 HANDLE RootKeyHandle
,
105 PKEY_VALUE_FULL_INFORMATION
*BusInformation
)
107 NTSTATUS Status
= STATUS_SUCCESS
;
109 /* Controller Stuff */
110 UNICODE_STRING ControllerString
;
111 UNICODE_STRING ControllerRootRegName
= RootKey
;
112 UNICODE_STRING ControllerRegName
;
113 HANDLE ControllerKeyHandle
;
114 PKEY_FULL_INFORMATION ControllerFullInformation
= NULL
;
115 PKEY_VALUE_FULL_INFORMATION ControllerInformation
[3] = {NULL
, NULL
, NULL
};
116 ULONG ControllerNumber
;
117 ULONG ControllerLoop
;
118 ULONG MaximumControllerNumber
;
120 /* Peripheral Stuff */
121 UNICODE_STRING PeripheralString
;
122 HANDLE PeripheralKeyHandle
;
123 PKEY_FULL_INFORMATION PeripheralFullInformation
;
124 PKEY_VALUE_FULL_INFORMATION PeripheralInformation
[3] = {NULL
, NULL
, NULL
};
125 ULONG PeripheralNumber
;
126 ULONG PeripheralLoop
;
127 ULONG MaximumPeripheralNumber
;
129 /* Global Registry Stuff */
130 OBJECT_ATTRIBUTES ObjectAttributes
;
131 ULONG LenFullInformation
;
132 ULONG LenKeyFullInformation
;
133 UNICODE_STRING TempString
;
134 WCHAR TempBuffer
[14];
137 L
"Configuration Data",
138 L
"Component Information"
141 /* Temporary String */
142 TempString
.MaximumLength
= sizeof(TempBuffer
);
143 TempString
.Length
= 0;
144 TempString
.Buffer
= TempBuffer
;
146 /* Add Controller Name to String */
147 RtlAppendUnicodeToString(&ControllerRootRegName
, L
"\\");
148 RtlAppendUnicodeToString(&ControllerRootRegName
, ArcTypes
[*Query
->ControllerType
]);
150 /* Set the Controller Number if specified */
151 if (Query
->ControllerNumber
&& *(Query
->ControllerNumber
))
153 ControllerNumber
= *Query
->ControllerNumber
;
154 MaximumControllerNumber
= ControllerNumber
+ 1;
156 /* Find out how many Controller Numbers there are */
157 InitializeObjectAttributes(
159 &ControllerRootRegName
,
160 OBJ_CASE_INSENSITIVE
,
164 Status
= ZwOpenKey(&ControllerKeyHandle
, KEY_READ
, &ObjectAttributes
);
165 if (NT_SUCCESS(Status
))
167 /* How much buffer space */
168 ZwQueryKey(ControllerKeyHandle
, KeyFullInformation
, NULL
, 0, &LenFullInformation
);
171 ControllerFullInformation
= ExAllocatePoolWithTag(PagedPool
, LenFullInformation
, TAG_IO_RESOURCE
);
173 /* Get the Information */
174 Status
= ZwQueryKey(ControllerKeyHandle
, KeyFullInformation
, ControllerFullInformation
, LenFullInformation
, &LenFullInformation
);
175 ZwClose(ControllerKeyHandle
);
176 ControllerKeyHandle
= NULL
;
179 /* No controller was found, go back to function. */
180 if (!NT_SUCCESS(Status
))
182 if (ControllerFullInformation
!= NULL
)
183 ExFreePoolWithTag(ControllerFullInformation
, TAG_IO_RESOURCE
);
187 /* Find out Controller Numbers */
188 ControllerNumber
= 0;
189 MaximumControllerNumber
= ControllerFullInformation
->SubKeys
;
192 ExFreePoolWithTag(ControllerFullInformation
, TAG_IO_RESOURCE
);
193 ControllerFullInformation
= NULL
;
197 ControllerRegName
= ControllerRootRegName
;
199 /* Loop through controllers */
200 for (; ControllerNumber
< MaximumControllerNumber
; ControllerNumber
++)
203 ControllerRootRegName
= ControllerRegName
;
205 /* Controller Number to Registry String */
206 Status
= RtlIntegerToUnicodeString(ControllerNumber
, 10, &TempString
);
209 Status
|= RtlAppendUnicodeToString(&ControllerRootRegName
, L
"\\");
210 Status
|= RtlAppendUnicodeStringToString(&ControllerRootRegName
, &TempString
);
212 /* Something messed up */
213 if (!NT_SUCCESS(Status
)) break;
215 /* Open the Registry Key */
216 InitializeObjectAttributes(
218 &ControllerRootRegName
,
219 OBJ_CASE_INSENSITIVE
,
223 Status
= ZwOpenKey(&ControllerKeyHandle
, KEY_READ
, &ObjectAttributes
);
225 /* Read the Configuration Data... */
226 if (NT_SUCCESS(Status
))
228 for (ControllerLoop
= 0; ControllerLoop
< 3; ControllerLoop
++)
230 /* Identifier String First */
231 RtlInitUnicodeString(&ControllerString
, Strings
[ControllerLoop
]);
233 /* How much buffer space */
234 Status
= ZwQueryValueKey(ControllerKeyHandle
, &ControllerString
, KeyValueFullInformation
, NULL
, 0, &LenKeyFullInformation
);
236 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_TOO_SMALL
&& Status
!= STATUS_BUFFER_OVERFLOW
)
240 ControllerInformation
[ControllerLoop
] = ExAllocatePoolWithTag(PagedPool
, LenKeyFullInformation
, TAG_IO_RESOURCE
);
242 /* Get the Information */
243 Status
= ZwQueryValueKey(ControllerKeyHandle
, &ControllerString
, KeyValueFullInformation
, ControllerInformation
[ControllerLoop
], LenKeyFullInformation
, &LenKeyFullInformation
);
247 ZwClose(ControllerKeyHandle
);
248 ControllerKeyHandle
= NULL
;
251 /* Something messed up */
252 if (!NT_SUCCESS(Status
))
255 /* We now have Bus *AND* Controller Information.. is it enough? */
256 if (!Query
->PeripheralType
|| !(*Query
->PeripheralType
))
258 Status
= Query
->CalloutRoutine(
260 &ControllerRootRegName
,
264 *Query
->ControllerType
,
266 ControllerInformation
,
273 /* Not enough...caller also wants peripheral name */
274 Status
= RtlAppendUnicodeToString(&ControllerRootRegName
, L
"\\");
275 Status
|= RtlAppendUnicodeToString(&ControllerRootRegName
, ArcTypes
[*Query
->PeripheralType
]);
277 /* Something messed up */
278 if (!NT_SUCCESS(Status
)) goto EndLoop
;
280 /* Set the Peripheral Number if specified */
281 if (Query
->PeripheralNumber
&& *Query
->PeripheralNumber
)
283 PeripheralNumber
= *Query
->PeripheralNumber
;
284 MaximumPeripheralNumber
= PeripheralNumber
+ 1;
286 /* Find out how many Peripheral Numbers there are */
287 InitializeObjectAttributes(
289 &ControllerRootRegName
,
290 OBJ_CASE_INSENSITIVE
,
294 Status
= ZwOpenKey(&PeripheralKeyHandle
, KEY_READ
, &ObjectAttributes
);
296 if (NT_SUCCESS(Status
))
298 /* How much buffer space */
299 ZwQueryKey(PeripheralKeyHandle
, KeyFullInformation
, NULL
, 0, &LenFullInformation
);
302 PeripheralFullInformation
= ExAllocatePoolWithTag(PagedPool
, LenFullInformation
, TAG_IO_RESOURCE
);
304 /* Get the Information */
305 Status
= ZwQueryKey(PeripheralKeyHandle
, KeyFullInformation
, PeripheralFullInformation
, LenFullInformation
, &LenFullInformation
);
306 ZwClose(PeripheralKeyHandle
);
307 PeripheralKeyHandle
= NULL
;
310 /* No controller was found, go back to function but clean up first */
311 if (!NT_SUCCESS(Status
))
313 Status
= STATUS_SUCCESS
;
317 /* Find out Peripheral Number */
318 PeripheralNumber
= 0;
319 MaximumPeripheralNumber
= PeripheralFullInformation
->SubKeys
;
322 ExFreePoolWithTag(PeripheralFullInformation
, TAG_IO_RESOURCE
);
323 PeripheralFullInformation
= NULL
;
327 ControllerRegName
= ControllerRootRegName
;
329 /* Loop through Peripherals */
330 for (; PeripheralNumber
< MaximumPeripheralNumber
; PeripheralNumber
++)
333 ControllerRootRegName
= ControllerRegName
;
335 /* Peripheral Number to Registry String */
336 Status
= RtlIntegerToUnicodeString(PeripheralNumber
, 10, &TempString
);
339 Status
|= RtlAppendUnicodeToString(&ControllerRootRegName
, L
"\\");
340 Status
|= RtlAppendUnicodeStringToString(&ControllerRootRegName
, &TempString
);
342 /* Something messed up */
343 if (!NT_SUCCESS(Status
)) break;
345 /* Open the Registry Key */
346 InitializeObjectAttributes(
348 &ControllerRootRegName
,
349 OBJ_CASE_INSENSITIVE
,
353 Status
= ZwOpenKey(&PeripheralKeyHandle
, KEY_READ
, &ObjectAttributes
);
355 if (NT_SUCCESS(Status
))
357 for (PeripheralLoop
= 0; PeripheralLoop
< 3; PeripheralLoop
++)
359 /* Identifier String First */
360 RtlInitUnicodeString(&PeripheralString
, Strings
[PeripheralLoop
]);
362 /* How much buffer space */
363 Status
= ZwQueryValueKey(PeripheralKeyHandle
, &PeripheralString
, KeyValueFullInformation
, NULL
, 0, &LenKeyFullInformation
);
365 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_TOO_SMALL
&& Status
!= STATUS_BUFFER_OVERFLOW
)
367 PeripheralInformation
[PeripheralLoop
] = NULL
;
372 PeripheralInformation
[PeripheralLoop
] = ExAllocatePoolWithTag(PagedPool
, LenKeyFullInformation
, TAG_IO_RESOURCE
);
374 /* Get the Information */
375 Status
= ZwQueryValueKey(PeripheralKeyHandle
, &PeripheralString
, KeyValueFullInformation
, PeripheralInformation
[PeripheralLoop
], LenKeyFullInformation
, &LenKeyFullInformation
);
379 ZwClose(PeripheralKeyHandle
);
380 PeripheralKeyHandle
= NULL
;
382 /* We now have everything the caller could possibly want */
383 if (NT_SUCCESS(Status
))
385 Status
= Query
->CalloutRoutine(
387 &ControllerRootRegName
,
391 *Query
->ControllerType
,
393 ControllerInformation
,
394 *Query
->PeripheralType
,
396 PeripheralInformation
);
399 /* Free the allocated memory */
400 for (PeripheralLoop
= 0; PeripheralLoop
< 3; PeripheralLoop
++)
402 if (PeripheralInformation
[PeripheralLoop
])
404 ExFreePoolWithTag(PeripheralInformation
[PeripheralLoop
], TAG_IO_RESOURCE
);
405 PeripheralInformation
[PeripheralLoop
] = NULL
;
409 /* Something Messed up */
410 if (!NT_SUCCESS(Status
)) break;
415 /* Free the allocated memory */
416 for (ControllerLoop
= 0; ControllerLoop
< 3; ControllerLoop
++)
418 if (ControllerInformation
[ControllerLoop
])
420 ExFreePoolWithTag(ControllerInformation
[ControllerLoop
], TAG_IO_RESOURCE
);
421 ControllerInformation
[ControllerLoop
] = NULL
;
425 /* Something Messed up */
426 if (!NT_SUCCESS(Status
)) break;
433 * IopQueryBusDescription
436 * Reads and returns Hardware information from the appropriate hardware
437 * registry key. Helper sub of IoQueryDeviceDescription. Has two modes
438 * of operation, either looking for Root Bus Types or for sub-Bus
442 * Query - What the parent function wants.
443 * RootKey - Which key to look in
444 * RootKeyHandle - Handle to the key
446 * KeyIsRoot - Whether we are looking for Root Bus Types or
447 * information under them.
454 IopQueryBusDescription(
456 UNICODE_STRING RootKey
,
457 HANDLE RootKeyHandle
,
463 UNICODE_STRING SubRootRegName
;
464 UNICODE_STRING BusString
;
465 UNICODE_STRING SubBusString
;
466 ULONG LenBasicInformation
= 0;
467 ULONG LenFullInformation
;
468 ULONG LenKeyFullInformation
;
470 HANDLE SubRootKeyHandle
;
471 PKEY_FULL_INFORMATION FullInformation
;
472 PKEY_BASIC_INFORMATION BasicInformation
= NULL
;
473 OBJECT_ATTRIBUTES ObjectAttributes
;
474 PKEY_VALUE_FULL_INFORMATION BusInformation
[3] = {NULL
, NULL
, NULL
};
476 /* How much buffer space */
477 Status
= ZwQueryKey(RootKeyHandle
, KeyFullInformation
, NULL
, 0, &LenFullInformation
);
479 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_TOO_SMALL
&& Status
!= STATUS_BUFFER_OVERFLOW
)
483 FullInformation
= ExAllocatePoolWithTag(PagedPool
, LenFullInformation
, TAG_IO_RESOURCE
);
485 if (!FullInformation
)
486 return STATUS_NO_MEMORY
;
488 /* Get the Information */
489 Status
= ZwQueryKey(RootKeyHandle
, KeyFullInformation
, FullInformation
, LenFullInformation
, &LenFullInformation
);
491 /* Everything was fine */
492 if (NT_SUCCESS(Status
))
494 /* Buffer needed for all the keys under this one */
495 LenBasicInformation
= FullInformation
->MaxNameLen
+ sizeof(KEY_BASIC_INFORMATION
);
498 BasicInformation
= ExAllocatePoolWithTag(PagedPool
, LenBasicInformation
, TAG_IO_RESOURCE
);
501 /* Deallocate the old Buffer */
502 ExFreePoolWithTag(FullInformation
, TAG_IO_RESOURCE
);
504 /* Try to find a Bus */
505 for (BusLoop
= 0; NT_SUCCESS(Status
); BusLoop
++)
507 /* Bus parameter was passed and number was matched */
508 if ((Query
->BusNumber
) && (*(Query
->BusNumber
)) == *Bus
) break;
510 /* Enumerate the Key */
511 Status
= ZwEnumerateKey(
519 /* Everything enumerated */
520 if (!NT_SUCCESS(Status
)) break;
522 /* What Bus are we going to go down? (only check if this is a Root Key) */
525 if (wcsncmp(BasicInformation
->Name
, L
"MultifunctionAdapter", BasicInformation
->NameLength
/ 2) &&
526 wcsncmp(BasicInformation
->Name
, L
"EisaAdapter", BasicInformation
->NameLength
/ 2) &&
527 wcsncmp(BasicInformation
->Name
, L
"TcAdapter", BasicInformation
->NameLength
/ 2))
529 /* Nothing found, check next */
534 /* Enumerate the Bus. */
535 BusString
.Buffer
= BasicInformation
->Name
;
536 BusString
.Length
= (USHORT
)BasicInformation
->NameLength
;
537 BusString
.MaximumLength
= (USHORT
)BasicInformation
->NameLength
;
539 /* Open a handle to the Root Registry Key */
540 InitializeObjectAttributes(
543 OBJ_CASE_INSENSITIVE
,
547 Status
= ZwOpenKey(&SubRootKeyHandle
, KEY_READ
, &ObjectAttributes
);
549 /* Go on if we can't */
550 if (!NT_SUCCESS(Status
)) continue;
552 /* Key opened. Create the path */
553 SubRootRegName
= RootKey
;
554 RtlAppendUnicodeToString(&SubRootRegName
, L
"\\");
555 RtlAppendUnicodeStringToString(&SubRootRegName
, &BusString
);
559 /* Parsing a SubBus-key */
563 L
"Configuration Data",
564 L
"Component Information"};
566 for (SubBusLoop
= 0; SubBusLoop
< 3; SubBusLoop
++)
568 /* Identifier String First */
569 RtlInitUnicodeString(&SubBusString
, Strings
[SubBusLoop
]);
571 /* How much buffer space */
572 ZwQueryValueKey(SubRootKeyHandle
, &SubBusString
, KeyValueFullInformation
, NULL
, 0, &LenKeyFullInformation
);
575 BusInformation
[SubBusLoop
] = ExAllocatePoolWithTag(PagedPool
, LenKeyFullInformation
, TAG_IO_RESOURCE
);
577 /* Get the Information */
578 Status
= ZwQueryValueKey(SubRootKeyHandle
, &SubBusString
, KeyValueFullInformation
, BusInformation
[SubBusLoop
], LenKeyFullInformation
, &LenKeyFullInformation
);
581 if (NT_SUCCESS(Status
))
583 /* Do we have something */
584 if (BusInformation
[1] != NULL
&&
585 BusInformation
[1]->DataLength
!= 0 &&
586 /* Does it match what we want? */
587 (((PCM_FULL_RESOURCE_DESCRIPTOR
)((ULONG_PTR
)BusInformation
[1] + BusInformation
[1]->DataOffset
))->InterfaceType
== *(Query
->BusType
)))
592 /* Is it the bus we wanted */
593 if (Query
->BusNumber
== NULL
|| *(Query
->BusNumber
) == *Bus
)
595 /* If we don't want Controller Information, we're done... call the callback */
596 if (Query
->ControllerType
== NULL
)
598 Status
= Query
->CalloutRoutine(
611 /* We want Controller Info...get it */
612 Status
= IopQueryDeviceDescription(Query
, SubRootRegName
, RootKeyHandle
, *Bus
, (PKEY_VALUE_FULL_INFORMATION
*)BusInformation
);
618 /* Free the allocated memory */
619 for (SubBusLoop
= 0; SubBusLoop
< 3; SubBusLoop
++)
621 if (BusInformation
[SubBusLoop
])
623 ExFreePoolWithTag(BusInformation
[SubBusLoop
], TAG_IO_RESOURCE
);
624 BusInformation
[SubBusLoop
] = NULL
;
628 /* Exit the Loop if we found the bus */
629 if (Query
->BusNumber
!= NULL
&& *(Query
->BusNumber
) == *Bus
)
631 ZwClose(SubRootKeyHandle
);
632 SubRootKeyHandle
= NULL
;
637 /* Enumerate the buses below us recursively if we haven't found the bus yet */
638 Status
= IopQueryBusDescription(Query
, SubRootRegName
, SubRootKeyHandle
, Bus
, !KeyIsRoot
);
640 /* Everything enumerated */
641 if (Status
== STATUS_NO_MORE_ENTRIES
) Status
= STATUS_SUCCESS
;
643 ZwClose(SubRootKeyHandle
);
644 SubRootKeyHandle
= NULL
;
647 /* Free the last remaining Allocated Memory */
648 if (BasicInformation
)
649 ExFreePoolWithTag(BasicInformation
, TAG_IO_RESOURCE
);
656 IopFetchConfigurationInformation(OUT PWSTR
* SymbolicLinkList
,
658 IN ULONG ExpectedInterfaces
,
659 IN PULONG Interfaces
)
662 ULONG IntInterfaces
= 0;
663 PWSTR IntSymbolicLinkList
;
665 /* Get the associated enabled interfaces with the given GUID */
666 Status
= IoGetDeviceInterfaces(&Guid
, NULL
, 0, SymbolicLinkList
);
667 if (!NT_SUCCESS(Status
))
669 /* Zero output and leave */
670 if (SymbolicLinkList
!= 0)
672 *SymbolicLinkList
= 0;
675 return STATUS_UNSUCCESSFUL
;
678 IntSymbolicLinkList
= *SymbolicLinkList
;
680 /* Count the number of enabled interfaces by counting the number of symbolic links */
681 while (*IntSymbolicLinkList
!= UNICODE_NULL
)
684 IntSymbolicLinkList
+= wcslen(IntSymbolicLinkList
) + (sizeof(UNICODE_NULL
) / sizeof(WCHAR
));
687 /* Matching result will define the result */
688 Status
= (IntInterfaces
>= ExpectedInterfaces
) ? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
689 /* Finally, give back to the caller the number of found interfaces */
690 *Interfaces
= IntInterfaces
;
697 IopStoreSystemPartitionInformation(IN PUNICODE_STRING NtSystemPartitionDeviceName
,
698 IN PUNICODE_STRING OsLoaderPathName
)
701 UNICODE_STRING LinkTarget
, KeyName
;
702 OBJECT_ATTRIBUTES ObjectAttributes
;
703 HANDLE LinkHandle
, RegistryHandle
, KeyHandle
;
704 WCHAR LinkTargetBuffer
[256];
705 UNICODE_STRING CmRegistryMachineSystemName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM");
707 ASSERT(NtSystemPartitionDeviceName
->MaximumLength
>= NtSystemPartitionDeviceName
->Length
+ sizeof(WCHAR
));
708 ASSERT(NtSystemPartitionDeviceName
->Buffer
[NtSystemPartitionDeviceName
->Length
/ sizeof(WCHAR
)] == UNICODE_NULL
);
709 ASSERT(OsLoaderPathName
->MaximumLength
>= OsLoaderPathName
->Length
+ sizeof(WCHAR
));
710 ASSERT(OsLoaderPathName
->Buffer
[OsLoaderPathName
->Length
/ sizeof(WCHAR
)] == UNICODE_NULL
);
712 /* First define needed stuff to open NtSystemPartitionDeviceName symbolic link */
713 InitializeObjectAttributes(&ObjectAttributes
,
714 NtSystemPartitionDeviceName
,
715 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
719 /* Open NtSystemPartitionDeviceName symbolic link */
720 Status
= ZwOpenSymbolicLinkObject(&LinkHandle
,
723 if (!NT_SUCCESS(Status
))
725 DPRINT("Failed to open symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName
, Status
);
729 /* Prepare the string that will receive where symbolic link points to */
730 LinkTarget
.Length
= 0;
731 /* We will zero the end of the string after having received it */
732 LinkTarget
.MaximumLength
= sizeof(LinkTargetBuffer
) - sizeof(UNICODE_NULL
);
733 LinkTarget
.Buffer
= LinkTargetBuffer
;
736 Status
= ZwQuerySymbolicLinkObject(LinkHandle
,
740 /* We are done with symbolic link */
741 ObCloseHandle(LinkHandle
, KernelMode
);
743 if (!NT_SUCCESS(Status
))
745 DPRINT("Failed querying symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName
, Status
);
749 /* As promised, we zero the end */
750 LinkTarget
.Buffer
[LinkTarget
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
752 /* Open registry to save data (HKLM\SYSTEM) */
753 Status
= IopOpenRegistryKeyEx(&RegistryHandle
,
755 &CmRegistryMachineSystemName
,
757 if (!NT_SUCCESS(Status
))
759 DPRINT("Failed to open HKLM\\SYSTEM, Status=%lx\n", Status
);
763 /* Open or create the Setup subkey where we'll store in */
764 RtlInitUnicodeString(&KeyName
, L
"Setup");
766 Status
= IopCreateRegistryKeyEx(&KeyHandle
,
770 REG_OPTION_NON_VOLATILE
,
773 /* We're done with HKLM\SYSTEM */
774 ObCloseHandle(RegistryHandle
, KernelMode
);
776 if (!NT_SUCCESS(Status
))
778 DPRINT("Failed opening/creating Setup key, Status=%lx\n", Status
);
782 /* Prepare first data writing... */
783 RtlInitUnicodeString(&KeyName
, L
"SystemPartition");
785 /* Write SystemPartition value which is the target of the symbolic link */
786 Status
= ZwSetValueKey(KeyHandle
,
791 LinkTarget
.Length
+ sizeof(WCHAR
));
792 if (!NT_SUCCESS(Status
))
794 DPRINT("Failed writing SystemPartition value, Status=%lx\n", Status
);
797 /* Prepare for second data writing... */
798 RtlInitUnicodeString(&KeyName
, L
"OsLoaderPath");
800 /* Remove trailing slash if any (one slash only excepted) */
801 if (OsLoaderPathName
->Length
> sizeof(WCHAR
) &&
802 OsLoaderPathName
->Buffer
[(OsLoaderPathName
->Length
/ sizeof(WCHAR
)) - 1] == OBJ_NAME_PATH_SEPARATOR
)
804 OsLoaderPathName
->Length
-= sizeof(WCHAR
);
805 OsLoaderPathName
->Buffer
[OsLoaderPathName
->Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
808 /* Then, write down data */
809 Status
= ZwSetValueKey(KeyHandle
,
813 OsLoaderPathName
->Buffer
,
814 OsLoaderPathName
->Length
+ sizeof(UNICODE_NULL
));
815 if (!NT_SUCCESS(Status
))
817 DPRINT("Failed writing OsLoaderPath value, Status=%lx\n", Status
);
820 /* We're finally done! */
821 ObCloseHandle(KeyHandle
, KernelMode
);
824 /* PUBLIC FUNCTIONS ***********************************************************/
829 PCONFIGURATION_INFORMATION NTAPI
830 IoGetConfigurationInformation(VOID
)
832 return(&_SystemConfigurationInformation
);
839 IoReportResourceUsage(PUNICODE_STRING DriverClassName
,
840 PDRIVER_OBJECT DriverObject
,
841 PCM_RESOURCE_LIST DriverList
,
842 ULONG DriverListSize
,
843 PDEVICE_OBJECT DeviceObject
,
844 PCM_RESOURCE_LIST DeviceList
,
845 ULONG DeviceListSize
,
846 BOOLEAN OverrideConflict
,
847 PBOOLEAN ConflictDetected
)
849 * FUNCTION: Reports hardware resources in the
850 * \Registry\Machine\Hardware\ResourceMap tree, so that a subsequently
851 * loaded driver cannot attempt to use the same resources.
853 * DriverClassName - The class of driver under which the resource
854 * information should be stored.
855 * DriverObject - The driver object that was input to the
857 * DriverList - Resources that claimed for the driver rather than
859 * DriverListSize - Size in bytes of the DriverList.
860 * DeviceObject - The device object for which resources should be
862 * DeviceList - List of resources which should be claimed for the
864 * DeviceListSize - Size of the per-device resource list in bytes.
865 * OverrideConflict - True if the resources should be cliamed
866 * even if a conflict is found.
867 * ConflictDetected - Points to a variable that receives TRUE if
868 * a conflict is detected with another driver.
872 PCM_RESOURCE_LIST ResourceList
;
874 DPRINT1("IoReportResourceUsage is halfplemented!\n");
876 if (!DriverList
&& !DeviceList
)
877 return STATUS_INVALID_PARAMETER
;
880 ResourceList
= DeviceList
;
882 ResourceList
= DriverList
;
884 Status
= IopDetectResourceConflict(ResourceList
, FALSE
, NULL
);
885 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
887 *ConflictDetected
= TRUE
;
889 if (!OverrideConflict
)
891 DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
892 return STATUS_CONFLICTING_ADDRESSES
;
896 DPRINT1("Proceeding with conflicting resources\n");
899 else if (!NT_SUCCESS(Status
))
904 /* TODO: Claim resources in registry */
906 *ConflictDetected
= FALSE
;
908 return STATUS_SUCCESS
;
913 IopLegacyResourceAllocation(IN ARBITER_REQUEST_SOURCE AllocationType
,
914 IN PDRIVER_OBJECT DriverObject
,
915 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
916 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements
,
917 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
921 DPRINT1("IopLegacyResourceAllocation is halfplemented!\n");
923 Status
= IopFixupResourceListWithRequirements(ResourceRequirements
,
925 if (!NT_SUCCESS(Status
))
927 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
929 DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
935 /* TODO: Claim resources in registry */
936 return STATUS_SUCCESS
;
944 IoAssignResources(IN PUNICODE_STRING RegistryPath
,
945 IN PUNICODE_STRING DriverClassName
,
946 IN PDRIVER_OBJECT DriverObject
,
947 IN PDEVICE_OBJECT DeviceObject
,
948 IN PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources
,
949 IN OUT PCM_RESOURCE_LIST
* AllocatedResources
)
951 PDEVICE_NODE DeviceNode
;
953 /* Do we have a DO? */
956 /* Get its device node */
957 DeviceNode
= IopGetDeviceNode(DeviceObject
);
958 if ((DeviceNode
) && !(DeviceNode
->Flags
& DNF_LEGACY_RESOURCE_DEVICENODE
))
960 /* New drivers should not call this API */
961 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR
,
964 (ULONG_PTR
)DeviceObject
,
965 (ULONG_PTR
)DriverObject
);
969 /* Did the driver supply resources? */
970 if (RequestedResources
)
972 /* Make sure there's actually something useful in them */
973 if (!(RequestedResources
->AlternativeLists
) || !(RequestedResources
->List
[0].Count
))
975 /* Empty resources are no resources */
976 RequestedResources
= NULL
;
980 /* Initialize output if given */
981 if (AllocatedResources
) *AllocatedResources
= NULL
;
983 /* Call internal helper function */
984 return IopLegacyResourceAllocation(ArbiterRequestLegacyAssigned
,
993 * Reads and returns Hardware information from the appropriate hardware registry key.
996 * BusType - MCA, ISA, EISA...specifies the Bus Type
997 * BusNumber - Which bus of above should be queried
998 * ControllerType - Specifices the Controller Type
999 * ControllerNumber - Which of the controllers to query.
1000 * CalloutRoutine - Which function to call for each valid query.
1001 * Context - Value to pass to the callback.
1011 IoQueryDeviceDescription(PINTERFACE_TYPE BusType OPTIONAL
,
1012 PULONG BusNumber OPTIONAL
,
1013 PCONFIGURATION_TYPE ControllerType OPTIONAL
,
1014 PULONG ControllerNumber OPTIONAL
,
1015 PCONFIGURATION_TYPE PeripheralType OPTIONAL
,
1016 PULONG PeripheralNumber OPTIONAL
,
1017 PIO_QUERY_DEVICE_ROUTINE CalloutRoutine
,
1021 ULONG BusLoopNumber
= -1; /* Root Bus */
1022 OBJECT_ATTRIBUTES ObjectAttributes
;
1023 UNICODE_STRING RootRegKey
;
1024 HANDLE RootRegHandle
;
1027 /* Set up the String */
1028 RootRegKey
.Length
= 0;
1029 RootRegKey
.MaximumLength
= 2048;
1030 RootRegKey
.Buffer
= ExAllocatePoolWithTag(PagedPool
, RootRegKey
.MaximumLength
, TAG_IO_RESOURCE
);
1031 RtlAppendUnicodeToString(&RootRegKey
, L
"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
1033 /* Open a handle to the Root Registry Key */
1034 InitializeObjectAttributes(
1037 OBJ_CASE_INSENSITIVE
,
1041 Status
= ZwOpenKey(&RootRegHandle
, KEY_READ
, &ObjectAttributes
);
1043 if (NT_SUCCESS(Status
))
1045 /* Use a helper function to loop though this key and get the info */
1046 Query
.BusType
= BusType
;
1047 Query
.BusNumber
= BusNumber
;
1048 Query
.ControllerType
= ControllerType
;
1049 Query
.ControllerNumber
= ControllerNumber
;
1050 Query
.PeripheralType
= PeripheralType
;
1051 Query
.PeripheralNumber
= PeripheralNumber
;
1052 Query
.CalloutRoutine
= CalloutRoutine
;
1053 Query
.Context
= Context
;
1054 Status
= IopQueryBusDescription(&Query
, RootRegKey
, RootRegHandle
, &BusLoopNumber
, TRUE
);
1056 /* Close registry */
1057 ZwClose(RootRegHandle
);
1061 ExFreePoolWithTag(RootRegKey
.Buffer
, TAG_IO_RESOURCE
);
1070 IoReportHalResourceUsage(PUNICODE_STRING HalDescription
,
1071 PCM_RESOURCE_LIST RawList
,
1072 PCM_RESOURCE_LIST TranslatedList
,
1076 * Reports hardware resources of the HAL in the
1077 * \Registry\Machine\Hardware\ResourceMap tree.
1079 * HalDescription: Descriptive name of the HAL.
1080 * RawList: List of raw (bus specific) resources which should be
1081 * claimed for the HAL.
1082 * TranslatedList: List of translated (system wide) resources which
1083 * should be claimed for the HAL.
1084 * ListSize: Size in bytes of the raw and translated resource lists.
1085 * Both lists have the same size.
1090 OBJECT_ATTRIBUTES ObjectAttributes
;
1091 UNICODE_STRING Name
;
1094 HANDLE ResourcemapKey
;
1096 HANDLE DescriptionKey
;
1098 /* Open/Create 'RESOURCEMAP' key. */
1099 RtlInitUnicodeString(&Name
,
1100 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1101 InitializeObjectAttributes(&ObjectAttributes
,
1103 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1106 Status
= ZwCreateKey(&ResourcemapKey
,
1111 REG_OPTION_VOLATILE
,
1113 if (!NT_SUCCESS(Status
))
1116 /* Open/Create 'Hardware Abstraction Layer' key */
1117 RtlInitUnicodeString(&Name
,
1118 L
"Hardware Abstraction Layer");
1119 InitializeObjectAttributes(&ObjectAttributes
,
1121 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1124 Status
= ZwCreateKey(&HalKey
,
1129 REG_OPTION_VOLATILE
,
1131 ZwClose(ResourcemapKey
);
1132 if (!NT_SUCCESS(Status
))
1135 /* Create 'HalDescription' key */
1136 InitializeObjectAttributes(&ObjectAttributes
,
1138 OBJ_CASE_INSENSITIVE
,
1141 Status
= ZwCreateKey(&DescriptionKey
,
1146 REG_OPTION_VOLATILE
,
1149 if (!NT_SUCCESS(Status
))
1152 /* Add '.Raw' value. */
1153 RtlInitUnicodeString(&Name
,
1155 Status
= ZwSetValueKey(DescriptionKey
,
1161 if (!NT_SUCCESS(Status
))
1163 ZwClose(DescriptionKey
);
1167 /* Add '.Translated' value. */
1168 RtlInitUnicodeString(&Name
,
1170 Status
= ZwSetValueKey(DescriptionKey
,
1176 ZwClose(DescriptionKey
);