2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/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
);
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], KeyNameBuffer
[sizeof(L
"SystemPartition") / sizeof(WCHAR
)];
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 opening given symbolic link!\n");
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 given symbolic link!\n");
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 opening registry!\n");
763 /* We'll store in Setup subkey, and as we love fun, we use only one buffer for three writings... */
764 wcscpy(KeyNameBuffer
, L
"Setup");
765 KeyName
.Length
= sizeof(L
"Setup") - sizeof(UNICODE_NULL
);
766 KeyName
.MaximumLength
= sizeof(L
"Setup");
767 KeyName
.Buffer
= KeyNameBuffer
;
769 /* So, open or create the subkey */
770 Status
= IopCreateRegistryKeyEx(&KeyHandle
,
774 REG_OPTION_NON_VOLATILE
,
777 /* We're done with HKLM\SYSTEM */
778 ObCloseHandle(RegistryHandle
, KernelMode
);
780 if (!NT_SUCCESS(Status
))
782 DPRINT("Failed opening/creating Setup key!\n");
786 /* Prepare first data writing... */
787 wcscpy(KeyNameBuffer
, L
"SystemPartition");
788 KeyName
.Length
= sizeof(L
"SystemPartition") - sizeof(UNICODE_NULL
);
789 KeyName
.MaximumLength
= sizeof(L
"SystemPartition");
791 /* Write SystemPartition value which is the target of the symbolic link */
792 Status
= ZwSetValueKey(KeyHandle
,
797 LinkTarget
.Length
+ sizeof(WCHAR
));
798 if (!NT_SUCCESS(Status
))
800 DPRINT("Failed writing SystemPartition value!\n");
803 /* Prepare for second data writing... */
804 wcscpy(KeyName
.Buffer
, L
"OsLoaderPath");
805 KeyName
.Length
= sizeof(L
"OsLoaderPath") - sizeof(UNICODE_NULL
);
806 KeyName
.MaximumLength
= sizeof(L
"OsLoaderPath");
808 /* Remove trailing slash if any (one slash only excepted) */
809 if (OsLoaderPathName
->Length
> sizeof(WCHAR
) &&
810 OsLoaderPathName
->Buffer
[(OsLoaderPathName
->Length
/ sizeof(WCHAR
)) - 1] == OBJ_NAME_PATH_SEPARATOR
)
812 OsLoaderPathName
->Length
-= sizeof(WCHAR
);
813 OsLoaderPathName
->Buffer
[OsLoaderPathName
->Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
816 /* Then, write down data */
817 Status
= ZwSetValueKey(KeyHandle
,
821 OsLoaderPathName
->Buffer
,
822 OsLoaderPathName
->Length
+ sizeof(WCHAR
));
823 if (!NT_SUCCESS(Status
))
825 DPRINT("Failed writing OsLoaderPath value!\n");
828 /* We're finally done! */
829 ObCloseHandle(KeyHandle
, KernelMode
);
832 /* PUBLIC FUNCTIONS ***********************************************************/
837 PCONFIGURATION_INFORMATION NTAPI
838 IoGetConfigurationInformation(VOID
)
840 return(&_SystemConfigurationInformation
);
847 IoReportResourceUsage(PUNICODE_STRING DriverClassName
,
848 PDRIVER_OBJECT DriverObject
,
849 PCM_RESOURCE_LIST DriverList
,
850 ULONG DriverListSize
,
851 PDEVICE_OBJECT DeviceObject
,
852 PCM_RESOURCE_LIST DeviceList
,
853 ULONG DeviceListSize
,
854 BOOLEAN OverrideConflict
,
855 PBOOLEAN ConflictDetected
)
857 * FUNCTION: Reports hardware resources in the
858 * \Registry\Machine\Hardware\ResourceMap tree, so that a subsequently
859 * loaded driver cannot attempt to use the same resources.
861 * DriverClassName - The class of driver under which the resource
862 * information should be stored.
863 * DriverObject - The driver object that was input to the
865 * DriverList - Resources that claimed for the driver rather than
867 * DriverListSize - Size in bytes of the DriverList.
868 * DeviceObject - The device object for which resources should be
870 * DeviceList - List of resources which should be claimed for the
872 * DeviceListSize - Size of the per-device resource list in bytes.
873 * OverrideConflict - True if the resources should be cliamed
874 * even if a conflict is found.
875 * ConflictDetected - Points to a variable that receives TRUE if
876 * a conflict is detected with another driver.
880 PCM_RESOURCE_LIST ResourceList
;
882 DPRINT1("IoReportResourceUsage is halfplemented!\n");
884 if (!DriverList
&& !DeviceList
)
885 return STATUS_INVALID_PARAMETER
;
888 ResourceList
= DeviceList
;
890 ResourceList
= DriverList
;
892 Status
= IopDetectResourceConflict(ResourceList
, FALSE
, NULL
);
893 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
895 *ConflictDetected
= TRUE
;
897 if (!OverrideConflict
)
899 DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
900 return STATUS_CONFLICTING_ADDRESSES
;
904 DPRINT1("Proceeding with conflicting resources\n");
907 else if (!NT_SUCCESS(Status
))
912 /* TODO: Claim resources in registry */
914 *ConflictDetected
= FALSE
;
916 return STATUS_SUCCESS
;
923 IoAssignResources(PUNICODE_STRING RegistryPath
,
924 PUNICODE_STRING DriverClassName
,
925 PDRIVER_OBJECT DriverObject
,
926 PDEVICE_OBJECT DeviceObject
,
927 PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources
,
928 PCM_RESOURCE_LIST
* AllocatedResources
)
932 DPRINT1("IoAssignResources is halfplemented!\n");
934 *AllocatedResources
= NULL
;
935 Status
= IopFixupResourceListWithRequirements(RequestedResources
,
937 if (!NT_SUCCESS(Status
))
939 if (Status
== STATUS_CONFLICTING_ADDRESSES
)
940 DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
945 /* TODO: Claim resources in registry */
947 return STATUS_SUCCESS
;
952 * Reads and returns Hardware information from the appropriate hardware registry key.
955 * BusType - MCA, ISA, EISA...specifies the Bus Type
956 * BusNumber - Which bus of above should be queried
957 * ControllerType - Specifices the Controller Type
958 * ControllerNumber - Which of the controllers to query.
959 * CalloutRoutine - Which function to call for each valid query.
960 * Context - Value to pass to the callback.
970 IoQueryDeviceDescription(PINTERFACE_TYPE BusType OPTIONAL
,
971 PULONG BusNumber OPTIONAL
,
972 PCONFIGURATION_TYPE ControllerType OPTIONAL
,
973 PULONG ControllerNumber OPTIONAL
,
974 PCONFIGURATION_TYPE PeripheralType OPTIONAL
,
975 PULONG PeripheralNumber OPTIONAL
,
976 PIO_QUERY_DEVICE_ROUTINE CalloutRoutine
,
980 ULONG BusLoopNumber
= -1; /* Root Bus */
981 OBJECT_ATTRIBUTES ObjectAttributes
;
982 UNICODE_STRING RootRegKey
;
983 HANDLE RootRegHandle
;
986 /* Set up the String */
987 RootRegKey
.Length
= 0;
988 RootRegKey
.MaximumLength
= 2048;
989 RootRegKey
.Buffer
= ExAllocatePoolWithTag(PagedPool
, RootRegKey
.MaximumLength
, TAG_IO_RESOURCE
);
990 RtlAppendUnicodeToString(&RootRegKey
, L
"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
992 /* Open a handle to the Root Registry Key */
993 InitializeObjectAttributes(
996 OBJ_CASE_INSENSITIVE
,
1000 Status
= ZwOpenKey(&RootRegHandle
, KEY_READ
, &ObjectAttributes
);
1002 if (NT_SUCCESS(Status
))
1004 /* Use a helper function to loop though this key and get the info */
1005 Query
.BusType
= BusType
;
1006 Query
.BusNumber
= BusNumber
;
1007 Query
.ControllerType
= ControllerType
;
1008 Query
.ControllerNumber
= ControllerNumber
;
1009 Query
.PeripheralType
= PeripheralType
;
1010 Query
.PeripheralNumber
= PeripheralNumber
;
1011 Query
.CalloutRoutine
= CalloutRoutine
;
1012 Query
.Context
= Context
;
1013 Status
= IopQueryBusDescription(&Query
, RootRegKey
, RootRegHandle
, &BusLoopNumber
, TRUE
);
1015 /* Close registry */
1016 ZwClose(RootRegHandle
);
1020 ExFreePoolWithTag(RootRegKey
.Buffer
, TAG_IO_RESOURCE
);
1029 IoReportHalResourceUsage(PUNICODE_STRING HalDescription
,
1030 PCM_RESOURCE_LIST RawList
,
1031 PCM_RESOURCE_LIST TranslatedList
,
1035 * Reports hardware resources of the HAL in the
1036 * \Registry\Machine\Hardware\ResourceMap tree.
1038 * HalDescription: Descriptive name of the HAL.
1039 * RawList: List of raw (bus specific) resources which should be
1040 * claimed for the HAL.
1041 * TranslatedList: List of translated (system wide) resources which
1042 * should be claimed for the HAL.
1043 * ListSize: Size in bytes of the raw and translated resource lists.
1044 * Both lists have the same size.
1049 OBJECT_ATTRIBUTES ObjectAttributes
;
1050 UNICODE_STRING Name
;
1053 HANDLE ResourcemapKey
;
1055 HANDLE DescriptionKey
;
1057 /* Open/Create 'RESOURCEMAP' key. */
1058 RtlInitUnicodeString(&Name
,
1059 L
"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1060 InitializeObjectAttributes(&ObjectAttributes
,
1062 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1065 Status
= ZwCreateKey(&ResourcemapKey
,
1070 REG_OPTION_VOLATILE
,
1072 if (!NT_SUCCESS(Status
))
1075 /* Open/Create 'Hardware Abstraction Layer' key */
1076 RtlInitUnicodeString(&Name
,
1077 L
"Hardware Abstraction Layer");
1078 InitializeObjectAttributes(&ObjectAttributes
,
1080 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
1083 Status
= ZwCreateKey(&HalKey
,
1088 REG_OPTION_VOLATILE
,
1090 ZwClose(ResourcemapKey
);
1091 if (!NT_SUCCESS(Status
))
1094 /* Create 'HalDescription' key */
1095 InitializeObjectAttributes(&ObjectAttributes
,
1097 OBJ_CASE_INSENSITIVE
,
1100 Status
= ZwCreateKey(&DescriptionKey
,
1105 REG_OPTION_VOLATILE
,
1108 if (!NT_SUCCESS(Status
))
1111 /* Add '.Raw' value. */
1112 RtlInitUnicodeString(&Name
,
1114 Status
= ZwSetValueKey(DescriptionKey
,
1120 if (!NT_SUCCESS(Status
))
1122 ZwClose(DescriptionKey
);
1126 /* Add '.Translated' value. */
1127 RtlInitUnicodeString(&Name
,
1129 Status
= ZwSetValueKey(DescriptionKey
,
1135 ZwClose(DescriptionKey
);