xref: /reactos/ntoskrnl/io/iomgr/iorsrce.c (revision 84b4a80b)
1c2c66affSColin Finck /*
22674e26cSHermès Bélusca-Maïto  * PROJECT:     ReactOS Kernel
32674e26cSHermès Bélusca-Maïto  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
42674e26cSHermès Bélusca-Maïto  * PURPOSE:     Hardware resource management
52674e26cSHermès Bélusca-Maïto  * COPYRIGHT:   Copyright 1998 David Welch <welch@mcmail.com>
62674e26cSHermès Bélusca-Maïto  *              Copyright 2001 Eric Kohl <eric.kohl@reactos.org>
72674e26cSHermès Bélusca-Maïto  *              Copyright 2004-2013 Alex Ionescu <alex.ionescu@reactos.org>
82674e26cSHermès Bélusca-Maïto  *              Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
92674e26cSHermès Bélusca-Maïto  *              Copyright 2010 Pierre Schweitzer <pierre@reactos.org>
10c2c66affSColin Finck  */
11c2c66affSColin Finck 
12c2c66affSColin Finck /* INCLUDES *****************************************************************/
13c2c66affSColin Finck 
14c2c66affSColin Finck #include <ntoskrnl.h>
150b695a6fSHermès Bélusca-Maïto #define NDEBUG
16c2c66affSColin Finck #include <debug.h>
17c2c66affSColin Finck 
180b695a6fSHermès Bélusca-Maïto #ifndef NDEBUG
190b695a6fSHermès Bélusca-Maïto     #define IORSRCTRACE(...)    DbgPrint(__VA_ARGS__)
200b695a6fSHermès Bélusca-Maïto #else
210b695a6fSHermès Bélusca-Maïto     #if defined(_MSC_VER)
220b695a6fSHermès Bélusca-Maïto     #define IORSRCTRACE     __noop
230b695a6fSHermès Bélusca-Maïto     #else
240b695a6fSHermès Bélusca-Maïto     #define IORSRCTRACE(...)    do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
250b695a6fSHermès Bélusca-Maïto     #endif
260b695a6fSHermès Bélusca-Maïto #endif
270b695a6fSHermès Bélusca-Maïto 
28c2c66affSColin Finck /* GLOBALS *******************************************************************/
29c2c66affSColin Finck 
30c2c66affSColin Finck static CONFIGURATION_INFORMATION
31c2c66affSColin Finck _SystemConfigurationInformation = { 0, 0, 0, 0, 0, 0, 0, FALSE, FALSE, 0, 0 };
32c2c66affSColin Finck 
332674e26cSHermès Bélusca-Maïto /* API parameters to pass to IopQueryBusDescription() */
342674e26cSHermès Bélusca-Maïto typedef struct _IO_QUERY
352674e26cSHermès Bélusca-Maïto {
36c2c66affSColin Finck     PINTERFACE_TYPE BusType;
37c2c66affSColin Finck     PULONG BusNumber;
38c2c66affSColin Finck     PCONFIGURATION_TYPE ControllerType;
39c2c66affSColin Finck     PULONG ControllerNumber;
40c2c66affSColin Finck     PCONFIGURATION_TYPE PeripheralType;
41c2c66affSColin Finck     PULONG PeripheralNumber;
42c2c66affSColin Finck     PIO_QUERY_DEVICE_ROUTINE CalloutRoutine;
43c2c66affSColin Finck     PVOID Context;
44c2c66affSColin Finck } IO_QUERY, *PIO_QUERY;
45c2c66affSColin Finck 
462674e26cSHermès Bélusca-Maïto /* Strings corresponding to CONFIGURATION_TYPE */
472674e26cSHermès Bélusca-Maïto PCWSTR ArcTypes[MaximumType + 1] =
482674e26cSHermès Bélusca-Maïto {
49c2c66affSColin Finck     L"System",
50c2c66affSColin Finck     L"CentralProcessor",
51c2c66affSColin Finck     L"FloatingPointProcessor",
52c2c66affSColin Finck     L"PrimaryICache",
53c2c66affSColin Finck     L"PrimaryDCache",
54c2c66affSColin Finck     L"SecondaryICache",
55c2c66affSColin Finck     L"SecondaryDCache",
56c2c66affSColin Finck     L"SecondaryCache",
57c2c66affSColin Finck     L"EisaAdapter",
58c2c66affSColin Finck     L"TcAdapter",
59c2c66affSColin Finck     L"ScsiAdapter",
60c2c66affSColin Finck     L"DtiAdapter",
61c2c66affSColin Finck     L"MultifunctionAdapter",
62c2c66affSColin Finck     L"DiskController",
63c2c66affSColin Finck     L"TapeController",
64c2c66affSColin Finck     L"CdRomController",
65c2c66affSColin Finck     L"WormController",
66c2c66affSColin Finck     L"SerialController",
67c2c66affSColin Finck     L"NetworkController",
68c2c66affSColin Finck     L"DisplayController",
69c2c66affSColin Finck     L"ParallelController",
70c2c66affSColin Finck     L"PointerController",
71c2c66affSColin Finck     L"KeyboardController",
72c2c66affSColin Finck     L"AudioController",
73c2c66affSColin Finck     L"OtherController",
74c2c66affSColin Finck     L"DiskPeripheral",
75c2c66affSColin Finck     L"FloppyDiskPeripheral",
76c2c66affSColin Finck     L"TapePeripheral",
77c2c66affSColin Finck     L"ModemPeripheral",
78c2c66affSColin Finck     L"MonitorPeripheral",
79c2c66affSColin Finck     L"PrinterPeripheral",
80c2c66affSColin Finck     L"PointerPeripheral",
81c2c66affSColin Finck     L"KeyboardPeripheral",
82c2c66affSColin Finck     L"TerminalPeripheral",
83c2c66affSColin Finck     L"OtherPeripheral",
84c2c66affSColin Finck     L"LinePeripheral",
85c2c66affSColin Finck     L"NetworkPeripheral",
86c2c66affSColin Finck     L"SystemMemory",
87c2c66affSColin Finck     L"DockingInformation",
88c2c66affSColin Finck     L"RealModeIrqRoutingTable",
89c2c66affSColin Finck     L"RealModePCIEnumeration",
90c2c66affSColin Finck     L"Undefined"
91c2c66affSColin Finck };
92c2c66affSColin Finck 
932674e26cSHermès Bélusca-Maïto /* Strings corresponding to IO_QUERY_DEVICE_DATA_FORMAT */
942674e26cSHermès Bélusca-Maïto PCWSTR IoDeviceInfoNames[IoQueryDeviceMaxData] =
95c2c66affSColin Finck {
96c2c66affSColin Finck     L"Identifier",
97c2c66affSColin Finck     L"Configuration Data",
98c2c66affSColin Finck     L"Component Information"
99c2c66affSColin Finck };
100c2c66affSColin Finck 
1012674e26cSHermès Bélusca-Maïto /* PRIVATE FUNCTIONS **********************************************************/
1022674e26cSHermès Bélusca-Maïto 
1032674e26cSHermès Bélusca-Maïto /**
1042674e26cSHermès Bélusca-Maïto  * @brief
1052674e26cSHermès Bélusca-Maïto  * Reads and returns Hardware information from the appropriate hardware
1062674e26cSHermès Bélusca-Maïto  * registry key. Helper stub of IopQueryBusDescription().
1072674e26cSHermès Bélusca-Maïto  *
1082674e26cSHermès Bélusca-Maïto  * @param[in]   Query
1092674e26cSHermès Bélusca-Maïto  * What the parent function wants.
1102674e26cSHermès Bélusca-Maïto  *
1112674e26cSHermès Bélusca-Maïto  * @param[in]   RootKey
1122674e26cSHermès Bélusca-Maïto  * Which key to look in.
1132674e26cSHermès Bélusca-Maïto  *
1142674e26cSHermès Bélusca-Maïto  * @param[in]   RootKeyHandle
1152674e26cSHermès Bélusca-Maïto  * Handle to the key.
1162674e26cSHermès Bélusca-Maïto  *
1172674e26cSHermès Bélusca-Maïto  * @param[in]   Bus
1182674e26cSHermès Bélusca-Maïto  * The bus number.
1192674e26cSHermès Bélusca-Maïto  *
1202674e26cSHermès Bélusca-Maïto  * @param[in]   BusInformation
1212674e26cSHermès Bélusca-Maïto  * The configuration information being sent.
1222674e26cSHermès Bélusca-Maïto  *
1232674e26cSHermès Bélusca-Maïto  * @return  A status code.
1242674e26cSHermès Bélusca-Maïto  **/
1252674e26cSHermès Bélusca-Maïto static NTSTATUS
IopQueryDeviceDescription(_In_ PIO_QUERY Query,_In_ UNICODE_STRING RootKey,_In_ HANDLE RootKeyHandle,_In_ ULONG Bus,_In_ PKEY_VALUE_FULL_INFORMATION * BusInformation)1262674e26cSHermès Bélusca-Maïto IopQueryDeviceDescription(
1272674e26cSHermès Bélusca-Maïto     _In_ PIO_QUERY Query,
1282674e26cSHermès Bélusca-Maïto     _In_ UNICODE_STRING RootKey,
1292674e26cSHermès Bélusca-Maïto     _In_ HANDLE RootKeyHandle,
1302674e26cSHermès Bélusca-Maïto     _In_ ULONG Bus,
1312674e26cSHermès Bélusca-Maïto     _In_ PKEY_VALUE_FULL_INFORMATION* BusInformation)
1322674e26cSHermès Bélusca-Maïto {
1332674e26cSHermès Bélusca-Maïto     NTSTATUS Status = STATUS_SUCCESS;
1342674e26cSHermès Bélusca-Maïto 
1352674e26cSHermès Bélusca-Maïto     /* Controller data */
1362674e26cSHermès Bélusca-Maïto     UNICODE_STRING ControllerString;
1372674e26cSHermès Bélusca-Maïto     UNICODE_STRING ControllerRootRegName = RootKey;
1382674e26cSHermès Bélusca-Maïto     UNICODE_STRING ControllerRegName;
1392674e26cSHermès Bélusca-Maïto     HANDLE ControllerKeyHandle;
1402674e26cSHermès Bélusca-Maïto     PKEY_FULL_INFORMATION ControllerFullInformation = NULL;
1412674e26cSHermès Bélusca-Maïto     PKEY_VALUE_FULL_INFORMATION ControllerInformation[IoQueryDeviceMaxData] =
1422674e26cSHermès Bélusca-Maïto         {NULL, NULL, NULL};
1432674e26cSHermès Bélusca-Maïto     ULONG ControllerNumber;
1442674e26cSHermès Bélusca-Maïto     ULONG ControllerLoop;
1452674e26cSHermès Bélusca-Maïto     ULONG MaximumControllerNumber;
1462674e26cSHermès Bélusca-Maïto 
1472674e26cSHermès Bélusca-Maïto     /* Peripheral data */
1482674e26cSHermès Bélusca-Maïto     UNICODE_STRING PeripheralString;
1492674e26cSHermès Bélusca-Maïto     HANDLE PeripheralKeyHandle;
1502674e26cSHermès Bélusca-Maïto     PKEY_FULL_INFORMATION PeripheralFullInformation;
1512674e26cSHermès Bélusca-Maïto     PKEY_VALUE_FULL_INFORMATION PeripheralInformation[IoQueryDeviceMaxData] =
1522674e26cSHermès Bélusca-Maïto         {NULL, NULL, NULL};
1532674e26cSHermès Bélusca-Maïto     ULONG PeripheralNumber;
1542674e26cSHermès Bélusca-Maïto     ULONG PeripheralLoop;
1552674e26cSHermès Bélusca-Maïto     ULONG MaximumPeripheralNumber;
1562674e26cSHermès Bélusca-Maïto 
1572674e26cSHermès Bélusca-Maïto     /* Global Registry data */
1582674e26cSHermès Bélusca-Maïto     OBJECT_ATTRIBUTES ObjectAttributes;
1592674e26cSHermès Bélusca-Maïto     ULONG LenFullInformation;
1602674e26cSHermès Bélusca-Maïto     ULONG LenKeyFullInformation;
1612674e26cSHermès Bélusca-Maïto     UNICODE_STRING TempString;
1622674e26cSHermès Bélusca-Maïto     WCHAR TempBuffer[14];
1632674e26cSHermès Bélusca-Maïto 
1640b695a6fSHermès Bélusca-Maïto     IORSRCTRACE("\nIopQueryDeviceDescription(Query: 0x%p)\n"
1650b695a6fSHermès Bélusca-Maïto                 "    RootKey: '%wZ'\n"
1660b695a6fSHermès Bélusca-Maïto                 "    RootKeyHandle: 0x%p\n"
1670b695a6fSHermès Bélusca-Maïto                 "    Bus: %lu\n",
1680b695a6fSHermès Bélusca-Maïto                 Query,
1690b695a6fSHermès Bélusca-Maïto                 &RootKey, RootKeyHandle,
1700b695a6fSHermès Bélusca-Maïto                 Bus);
1710b695a6fSHermès Bélusca-Maïto 
1722674e26cSHermès Bélusca-Maïto     /* Temporary string */
173*84b4a80bSHermès Bélusca-Maïto     RtlInitEmptyUnicodeString(&TempString, TempBuffer, sizeof(TempBuffer));
174c2c66affSColin Finck 
1752674e26cSHermès Bélusca-Maïto     /* Append controller name to string */
176c2c66affSColin Finck     RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
177c2c66affSColin Finck     RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->ControllerType]);
178c2c66affSColin Finck 
1792674e26cSHermès Bélusca-Maïto     /* Set the controller number if specified */
180*84b4a80bSHermès Bélusca-Maïto     if (Query->ControllerNumber)
181c2c66affSColin Finck     {
182*84b4a80bSHermès Bélusca-Maïto         ControllerNumber = *(Query->ControllerNumber);
183c2c66affSColin Finck         MaximumControllerNumber = ControllerNumber + 1;
1840b695a6fSHermès Bélusca-Maïto         IORSRCTRACE("    Getting controller #%lu\n", ControllerNumber);
1852674e26cSHermès Bélusca-Maïto     }
1862674e26cSHermès Bélusca-Maïto     else
1872674e26cSHermès Bélusca-Maïto     {
1880b695a6fSHermès Bélusca-Maïto         IORSRCTRACE("    Enumerating controllers in '%wZ'...\n", &ControllerRootRegName);
1890b695a6fSHermès Bélusca-Maïto 
1902674e26cSHermès Bélusca-Maïto         /* Find out how many controllers there are */
1912674e26cSHermès Bélusca-Maïto         InitializeObjectAttributes(&ObjectAttributes,
192c2c66affSColin Finck                                    &ControllerRootRegName,
193c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
194c2c66affSColin Finck                                    NULL,
195c2c66affSColin Finck                                    NULL);
196c2c66affSColin Finck 
197c2c66affSColin Finck         Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes);
1982674e26cSHermès Bélusca-Maïto 
199c2c66affSColin Finck         if (NT_SUCCESS(Status))
200c2c66affSColin Finck         {
2012674e26cSHermès Bélusca-Maïto             /* Retrieve the necessary buffer space */
2022674e26cSHermès Bélusca-Maïto             ZwQueryKey(ControllerKeyHandle,
2032674e26cSHermès Bélusca-Maïto                        KeyFullInformation,
2042674e26cSHermès Bélusca-Maïto                        NULL, 0,
2052674e26cSHermès Bélusca-Maïto                        &LenFullInformation);
206c2c66affSColin Finck 
207c2c66affSColin Finck             /* Allocate it */
208c2c66affSColin Finck             ControllerFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
209*84b4a80bSHermès Bélusca-Maïto             if (!ControllerFullInformation)
210*84b4a80bSHermès Bélusca-Maïto             {
211*84b4a80bSHermès Bélusca-Maïto                 ZwClose(ControllerKeyHandle);
212*84b4a80bSHermès Bélusca-Maïto                 return STATUS_INSUFFICIENT_RESOURCES;
213*84b4a80bSHermès Bélusca-Maïto             }
214c2c66affSColin Finck 
2152674e26cSHermès Bélusca-Maïto             /* Get the information */
2162674e26cSHermès Bélusca-Maïto             Status = ZwQueryKey(ControllerKeyHandle,
2172674e26cSHermès Bélusca-Maïto                                 KeyFullInformation,
2182674e26cSHermès Bélusca-Maïto                                 ControllerFullInformation,
2192674e26cSHermès Bélusca-Maïto                                 LenFullInformation,
2202674e26cSHermès Bélusca-Maïto                                 &LenFullInformation);
221c2c66affSColin Finck             ZwClose(ControllerKeyHandle);
222c2c66affSColin Finck             ControllerKeyHandle = NULL;
223c2c66affSColin Finck         }
224c2c66affSColin Finck 
2252674e26cSHermès Bélusca-Maïto         /* No controller was found, bail out */
226c2c66affSColin Finck         if (!NT_SUCCESS(Status))
227c2c66affSColin Finck         {
228*84b4a80bSHermès Bélusca-Maïto             if (ControllerFullInformation)
229c2c66affSColin Finck                 ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE);
230c2c66affSColin Finck             return Status;
231c2c66affSColin Finck         }
232c2c66affSColin Finck 
2332674e26cSHermès Bélusca-Maïto         /* Find out the controllers */
234c2c66affSColin Finck         ControllerNumber = 0;
235c2c66affSColin Finck         MaximumControllerNumber = ControllerFullInformation->SubKeys;
236c2c66affSColin Finck 
2372674e26cSHermès Bélusca-Maïto         /* Cleanup */
238c2c66affSColin Finck         ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE);
239c2c66affSColin Finck         ControllerFullInformation = NULL;
240c2c66affSColin Finck     }
241c2c66affSColin Finck 
2422674e26cSHermès Bélusca-Maïto     /* Save string */
243c2c66affSColin Finck     ControllerRegName = ControllerRootRegName;
244c2c66affSColin Finck 
245c2c66affSColin Finck     /* Loop through controllers */
246c2c66affSColin Finck     for (; ControllerNumber < MaximumControllerNumber; ControllerNumber++)
247c2c66affSColin Finck     {
2482674e26cSHermès Bélusca-Maïto         /* Load string */
249c2c66affSColin Finck         ControllerRootRegName = ControllerRegName;
250c2c66affSColin Finck 
2512674e26cSHermès Bélusca-Maïto         /* Convert controller number to registry string */
252c2c66affSColin Finck         Status = RtlIntegerToUnicodeString(ControllerNumber, 10, &TempString);
253c2c66affSColin Finck 
2542674e26cSHermès Bélusca-Maïto         /* Create string */
255c2c66affSColin Finck         Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
256c2c66affSColin Finck         Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString);
257c2c66affSColin Finck 
258c2c66affSColin Finck         /* Something messed up */
2592674e26cSHermès Bélusca-Maïto         if (!NT_SUCCESS(Status))
2602674e26cSHermès Bélusca-Maïto             break;
261c2c66affSColin Finck 
2620b695a6fSHermès Bélusca-Maïto         IORSRCTRACE("    Retrieving controller '%wZ'\n", &ControllerRootRegName);
2630b695a6fSHermès Bélusca-Maïto 
2642674e26cSHermès Bélusca-Maïto         /* Open the registry key */
2652674e26cSHermès Bélusca-Maïto         InitializeObjectAttributes(&ObjectAttributes,
266c2c66affSColin Finck                                    &ControllerRootRegName,
267c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
268c2c66affSColin Finck                                    NULL,
269c2c66affSColin Finck                                    NULL);
270c2c66affSColin Finck 
271c2c66affSColin Finck         Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes);
272c2c66affSColin Finck 
2732674e26cSHermès Bélusca-Maïto         /* Read the configuration data */
274c2c66affSColin Finck         if (NT_SUCCESS(Status))
275c2c66affSColin Finck         {
2762674e26cSHermès Bélusca-Maïto             for (ControllerLoop = 0; ControllerLoop < RTL_NUMBER_OF(IoDeviceInfoNames); ControllerLoop++)
277c2c66affSColin Finck             {
2782674e26cSHermès Bélusca-Maïto                 /* Identifier string first */
2792674e26cSHermès Bélusca-Maïto                 RtlInitUnicodeString(&ControllerString, IoDeviceInfoNames[ControllerLoop]);
280c2c66affSColin Finck 
2812674e26cSHermès Bélusca-Maïto                 /* Retrieve the necessary buffer space */
2822674e26cSHermès Bélusca-Maïto                 Status = ZwQueryValueKey(ControllerKeyHandle,
2832674e26cSHermès Bélusca-Maïto                                          &ControllerString,
2842674e26cSHermès Bélusca-Maïto                                          KeyValueFullInformation,
2852674e26cSHermès Bélusca-Maïto                                          NULL, 0,
2862674e26cSHermès Bélusca-Maïto                                          &LenKeyFullInformation);
287c2c66affSColin Finck 
2882674e26cSHermès Bélusca-Maïto                 if (!NT_SUCCESS(Status) &&
2892674e26cSHermès Bélusca-Maïto                     (Status != STATUS_BUFFER_TOO_SMALL) &&
2902674e26cSHermès Bélusca-Maïto                     (Status != STATUS_BUFFER_OVERFLOW))
2912674e26cSHermès Bélusca-Maïto                 {
292*84b4a80bSHermès Bélusca-Maïto                     ControllerInformation[ControllerLoop] = NULL;
293c2c66affSColin Finck                     continue;
2942674e26cSHermès Bélusca-Maïto                 }
295c2c66affSColin Finck 
296c2c66affSColin Finck                 /* Allocate it */
297c2c66affSColin Finck                 ControllerInformation[ControllerLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
298*84b4a80bSHermès Bélusca-Maïto                 if (!ControllerInformation[ControllerLoop])
299*84b4a80bSHermès Bélusca-Maïto                 {
300*84b4a80bSHermès Bélusca-Maïto                     Status = STATUS_INSUFFICIENT_RESOURCES;
301*84b4a80bSHermès Bélusca-Maïto                     break;
302*84b4a80bSHermès Bélusca-Maïto                 }
303c2c66affSColin Finck 
3042674e26cSHermès Bélusca-Maïto                 /* Get the information */
3052674e26cSHermès Bélusca-Maïto                 Status = ZwQueryValueKey(ControllerKeyHandle,
3062674e26cSHermès Bélusca-Maïto                                          &ControllerString,
3072674e26cSHermès Bélusca-Maïto                                          KeyValueFullInformation,
3082674e26cSHermès Bélusca-Maïto                                          ControllerInformation[ControllerLoop],
3092674e26cSHermès Bélusca-Maïto                                          LenKeyFullInformation,
3102674e26cSHermès Bélusca-Maïto                                          &LenKeyFullInformation);
311c2c66affSColin Finck             }
312c2c66affSColin Finck 
3132674e26cSHermès Bélusca-Maïto             /* Cleanup */
314c2c66affSColin Finck             ZwClose(ControllerKeyHandle);
315c2c66affSColin Finck             ControllerKeyHandle = NULL;
316c2c66affSColin Finck         }
317c2c66affSColin Finck 
318c2c66affSColin Finck         /* Something messed up */
319c2c66affSColin Finck         if (!NT_SUCCESS(Status))
320c2c66affSColin Finck             goto EndLoop;
321c2c66affSColin Finck 
3222674e26cSHermès Bélusca-Maïto         /* We now have bus *AND* controller information, is it enough? */
323c2c66affSColin Finck         if (!Query->PeripheralType || !(*Query->PeripheralType))
324c2c66affSColin Finck         {
3250b695a6fSHermès Bélusca-Maïto             IORSRCTRACE("    --> Bus #%lu Controller #%lu Callout: '%wZ'\n",
3260b695a6fSHermès Bélusca-Maïto                         Bus, ControllerNumber, &ControllerRootRegName);
3270b695a6fSHermès Bélusca-Maïto 
3282674e26cSHermès Bélusca-Maïto             Status = Query->CalloutRoutine(Query->Context,
329c2c66affSColin Finck                                            &ControllerRootRegName,
330c2c66affSColin Finck                                            *Query->BusType,
331c2c66affSColin Finck                                            Bus,
332c2c66affSColin Finck                                            BusInformation,
333c2c66affSColin Finck                                            *Query->ControllerType,
334c2c66affSColin Finck                                            ControllerNumber,
335c2c66affSColin Finck                                            ControllerInformation,
336c2c66affSColin Finck                                            0,
337c2c66affSColin Finck                                            0,
338c2c66affSColin Finck                                            NULL);
339c2c66affSColin Finck             goto EndLoop;
340c2c66affSColin Finck         }
341c2c66affSColin Finck 
3422674e26cSHermès Bélusca-Maïto         /* Not enough: the caller also wants peripheral name */
343c2c66affSColin Finck         Status = RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
344c2c66affSColin Finck         Status |= RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->PeripheralType]);
345c2c66affSColin Finck 
346c2c66affSColin Finck         /* Something messed up */
3472674e26cSHermès Bélusca-Maïto         if (!NT_SUCCESS(Status))
3482674e26cSHermès Bélusca-Maïto             goto EndLoop;
349c2c66affSColin Finck 
3502674e26cSHermès Bélusca-Maïto         /* Set the peripheral number if specified */
351*84b4a80bSHermès Bélusca-Maïto         if (Query->PeripheralNumber)
352c2c66affSColin Finck         {
353*84b4a80bSHermès Bélusca-Maïto             PeripheralNumber = *(Query->PeripheralNumber);
354c2c66affSColin Finck             MaximumPeripheralNumber = PeripheralNumber + 1;
3550b695a6fSHermès Bélusca-Maïto             IORSRCTRACE("    Getting peripheral #%lu\n", PeripheralNumber);
3562674e26cSHermès Bélusca-Maïto         }
3572674e26cSHermès Bélusca-Maïto         else
3582674e26cSHermès Bélusca-Maïto         {
3590b695a6fSHermès Bélusca-Maïto             IORSRCTRACE("    Enumerating peripherals in '%wZ'...\n", &ControllerRootRegName);
3600b695a6fSHermès Bélusca-Maïto 
3612674e26cSHermès Bélusca-Maïto             /* Find out how many peripherals there are */
3622674e26cSHermès Bélusca-Maïto             InitializeObjectAttributes(&ObjectAttributes,
363c2c66affSColin Finck                                        &ControllerRootRegName,
364c2c66affSColin Finck                                        OBJ_CASE_INSENSITIVE,
365c2c66affSColin Finck                                        NULL,
366c2c66affSColin Finck                                        NULL);
367c2c66affSColin Finck 
368c2c66affSColin Finck             Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes);
369c2c66affSColin Finck 
370c2c66affSColin Finck             if (NT_SUCCESS(Status))
371c2c66affSColin Finck             {
3722674e26cSHermès Bélusca-Maïto                 /* Retrieve the necessary buffer space */
3732674e26cSHermès Bélusca-Maïto                 ZwQueryKey(PeripheralKeyHandle,
3742674e26cSHermès Bélusca-Maïto                            KeyFullInformation,
3752674e26cSHermès Bélusca-Maïto                            NULL, 0,
3762674e26cSHermès Bélusca-Maïto                            &LenFullInformation);
377c2c66affSColin Finck 
378c2c66affSColin Finck                 /* Allocate it */
379c2c66affSColin Finck                 PeripheralFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
380*84b4a80bSHermès Bélusca-Maïto                 if (!PeripheralFullInformation)
381*84b4a80bSHermès Bélusca-Maïto                 {
382*84b4a80bSHermès Bélusca-Maïto                     ZwClose(PeripheralKeyHandle);
383*84b4a80bSHermès Bélusca-Maïto                     Status = STATUS_INSUFFICIENT_RESOURCES;
384*84b4a80bSHermès Bélusca-Maïto                     goto EndLoop;
385*84b4a80bSHermès Bélusca-Maïto                 }
386c2c66affSColin Finck 
3872674e26cSHermès Bélusca-Maïto                 /* Get the information */
3882674e26cSHermès Bélusca-Maïto                 Status = ZwQueryKey(PeripheralKeyHandle,
3892674e26cSHermès Bélusca-Maïto                                     KeyFullInformation,
3902674e26cSHermès Bélusca-Maïto                                     PeripheralFullInformation,
3912674e26cSHermès Bélusca-Maïto                                     LenFullInformation,
3922674e26cSHermès Bélusca-Maïto                                     &LenFullInformation);
393c2c66affSColin Finck                 ZwClose(PeripheralKeyHandle);
394c2c66affSColin Finck                 PeripheralKeyHandle = NULL;
395c2c66affSColin Finck             }
396c2c66affSColin Finck 
3972674e26cSHermès Bélusca-Maïto             /* No controller was found, cleanup and bail out */
398c2c66affSColin Finck             if (!NT_SUCCESS(Status))
399c2c66affSColin Finck             {
400c2c66affSColin Finck                 Status = STATUS_SUCCESS;
401c2c66affSColin Finck                 goto EndLoop;
402c2c66affSColin Finck             }
403c2c66affSColin Finck 
4042674e26cSHermès Bélusca-Maïto             /* Find out peripheral number */
405c2c66affSColin Finck             PeripheralNumber = 0;
406c2c66affSColin Finck             MaximumPeripheralNumber = PeripheralFullInformation->SubKeys;
407c2c66affSColin Finck 
4082674e26cSHermès Bélusca-Maïto             /* Cleanup */
409c2c66affSColin Finck             ExFreePoolWithTag(PeripheralFullInformation, TAG_IO_RESOURCE);
410c2c66affSColin Finck             PeripheralFullInformation = NULL;
411c2c66affSColin Finck         }
412c2c66affSColin Finck 
4132674e26cSHermès Bélusca-Maïto         /* Save name */
414c2c66affSColin Finck         ControllerRegName = ControllerRootRegName;
415c2c66affSColin Finck 
4162674e26cSHermès Bélusca-Maïto         /* Loop through peripherals */
417c2c66affSColin Finck         for (; PeripheralNumber < MaximumPeripheralNumber; PeripheralNumber++)
418c2c66affSColin Finck         {
4192674e26cSHermès Bélusca-Maïto             /* Restore name */
420c2c66affSColin Finck             ControllerRootRegName = ControllerRegName;
421c2c66affSColin Finck 
4222674e26cSHermès Bélusca-Maïto             /* Convert peripheral number to registry string */
423c2c66affSColin Finck             Status = RtlIntegerToUnicodeString(PeripheralNumber, 10, &TempString);
424c2c66affSColin Finck 
4252674e26cSHermès Bélusca-Maïto             /* Create string */
426c2c66affSColin Finck             Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
427c2c66affSColin Finck             Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString);
428c2c66affSColin Finck 
429c2c66affSColin Finck             /* Something messed up */
4302674e26cSHermès Bélusca-Maïto             if (!NT_SUCCESS(Status))
4312674e26cSHermès Bélusca-Maïto                 break;
432c2c66affSColin Finck 
4330b695a6fSHermès Bélusca-Maïto             IORSRCTRACE("    Retrieving peripheral '%wZ'\n", &ControllerRootRegName);
4340b695a6fSHermès Bélusca-Maïto 
4352674e26cSHermès Bélusca-Maïto             /* Open the registry key */
4362674e26cSHermès Bélusca-Maïto             InitializeObjectAttributes(&ObjectAttributes,
437c2c66affSColin Finck                                        &ControllerRootRegName,
438c2c66affSColin Finck                                        OBJ_CASE_INSENSITIVE,
439c2c66affSColin Finck                                        NULL,
440c2c66affSColin Finck                                        NULL);
441c2c66affSColin Finck 
442c2c66affSColin Finck             Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes);
443c2c66affSColin Finck 
444c2c66affSColin Finck             if (NT_SUCCESS(Status))
445c2c66affSColin Finck             {
4462674e26cSHermès Bélusca-Maïto                 for (PeripheralLoop = 0; PeripheralLoop < RTL_NUMBER_OF(IoDeviceInfoNames); PeripheralLoop++)
447c2c66affSColin Finck                 {
4482674e26cSHermès Bélusca-Maïto                     /* Identifier string first */
4492674e26cSHermès Bélusca-Maïto                     RtlInitUnicodeString(&PeripheralString, IoDeviceInfoNames[PeripheralLoop]);
450c2c66affSColin Finck 
4512674e26cSHermès Bélusca-Maïto                     /* Retrieve the necessary buffer space */
4522674e26cSHermès Bélusca-Maïto                     Status = ZwQueryValueKey(PeripheralKeyHandle,
4532674e26cSHermès Bélusca-Maïto                                              &PeripheralString,
4542674e26cSHermès Bélusca-Maïto                                              KeyValueFullInformation,
4552674e26cSHermès Bélusca-Maïto                                              NULL, 0,
4562674e26cSHermès Bélusca-Maïto                                              &LenKeyFullInformation);
457c2c66affSColin Finck 
4582674e26cSHermès Bélusca-Maïto                     if (!NT_SUCCESS(Status) &&
4592674e26cSHermès Bélusca-Maïto                         (Status != STATUS_BUFFER_TOO_SMALL) &&
4602674e26cSHermès Bélusca-Maïto                         (Status != STATUS_BUFFER_OVERFLOW))
461c2c66affSColin Finck                     {
462c2c66affSColin Finck                         PeripheralInformation[PeripheralLoop] = NULL;
463c2c66affSColin Finck                         continue;
464c2c66affSColin Finck                     }
465c2c66affSColin Finck 
466c2c66affSColin Finck                     /* Allocate it */
467c2c66affSColin Finck                     PeripheralInformation[PeripheralLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
468*84b4a80bSHermès Bélusca-Maïto                     if (!PeripheralInformation[PeripheralLoop])
469*84b4a80bSHermès Bélusca-Maïto                     {
470*84b4a80bSHermès Bélusca-Maïto                         Status = STATUS_INSUFFICIENT_RESOURCES;
471*84b4a80bSHermès Bélusca-Maïto                         break;
472*84b4a80bSHermès Bélusca-Maïto                     }
473c2c66affSColin Finck 
4742674e26cSHermès Bélusca-Maïto                     /* Get the information */
4752674e26cSHermès Bélusca-Maïto                     Status = ZwQueryValueKey(PeripheralKeyHandle,
4762674e26cSHermès Bélusca-Maïto                                              &PeripheralString,
4772674e26cSHermès Bélusca-Maïto                                              KeyValueFullInformation,
4782674e26cSHermès Bélusca-Maïto                                              PeripheralInformation[PeripheralLoop],
4792674e26cSHermès Bélusca-Maïto                                              LenKeyFullInformation,
4802674e26cSHermès Bélusca-Maïto                                              &LenKeyFullInformation);
481c2c66affSColin Finck                 }
482c2c66affSColin Finck 
4832674e26cSHermès Bélusca-Maïto                 /* Cleanup */
484c2c66affSColin Finck                 ZwClose(PeripheralKeyHandle);
485c2c66affSColin Finck                 PeripheralKeyHandle = NULL;
486c2c66affSColin Finck 
487c2c66affSColin Finck                 /* We now have everything the caller could possibly want */
488c2c66affSColin Finck                 if (NT_SUCCESS(Status))
489c2c66affSColin Finck                 {
4900b695a6fSHermès Bélusca-Maïto                     IORSRCTRACE("    --> Bus #%lu Controller #%lu Peripheral #%lu Callout: '%wZ'\n",
4910b695a6fSHermès Bélusca-Maïto                                 Bus, ControllerNumber, PeripheralNumber, &ControllerRootRegName);
4920b695a6fSHermès Bélusca-Maïto 
4932674e26cSHermès Bélusca-Maïto                     Status = Query->CalloutRoutine(Query->Context,
494c2c66affSColin Finck                                                    &ControllerRootRegName,
495c2c66affSColin Finck                                                    *Query->BusType,
496c2c66affSColin Finck                                                    Bus,
497c2c66affSColin Finck                                                    BusInformation,
498c2c66affSColin Finck                                                    *Query->ControllerType,
499c2c66affSColin Finck                                                    ControllerNumber,
500c2c66affSColin Finck                                                    ControllerInformation,
501c2c66affSColin Finck                                                    *Query->PeripheralType,
502c2c66affSColin Finck                                                    PeripheralNumber,
503c2c66affSColin Finck                                                    PeripheralInformation);
504c2c66affSColin Finck                 }
505c2c66affSColin Finck 
506c2c66affSColin Finck                 /* Free the allocated memory */
5072674e26cSHermès Bélusca-Maïto                 for (PeripheralLoop = 0; PeripheralLoop < RTL_NUMBER_OF(IoDeviceInfoNames); PeripheralLoop++)
508c2c66affSColin Finck                 {
509c2c66affSColin Finck                     if (PeripheralInformation[PeripheralLoop])
510c2c66affSColin Finck                     {
511c2c66affSColin Finck                         ExFreePoolWithTag(PeripheralInformation[PeripheralLoop], TAG_IO_RESOURCE);
512c2c66affSColin Finck                         PeripheralInformation[PeripheralLoop] = NULL;
513c2c66affSColin Finck                     }
514c2c66affSColin Finck                 }
515c2c66affSColin Finck 
5162674e26cSHermès Bélusca-Maïto                 /* Something messed up */
5172674e26cSHermès Bélusca-Maïto                 if (!NT_SUCCESS(Status))
5182674e26cSHermès Bélusca-Maïto                     break;
519c2c66affSColin Finck             }
520c2c66affSColin Finck         }
521c2c66affSColin Finck 
522c2c66affSColin Finck EndLoop:
523c2c66affSColin Finck         /* Free the allocated memory */
5242674e26cSHermès Bélusca-Maïto         for (ControllerLoop = 0; ControllerLoop < RTL_NUMBER_OF(IoDeviceInfoNames); ControllerLoop++)
525c2c66affSColin Finck         {
526c2c66affSColin Finck             if (ControllerInformation[ControllerLoop])
527c2c66affSColin Finck             {
528c2c66affSColin Finck                 ExFreePoolWithTag(ControllerInformation[ControllerLoop], TAG_IO_RESOURCE);
529c2c66affSColin Finck                 ControllerInformation[ControllerLoop] = NULL;
530c2c66affSColin Finck             }
531c2c66affSColin Finck         }
532c2c66affSColin Finck 
5332674e26cSHermès Bélusca-Maïto         /* Something messed up */
5342674e26cSHermès Bélusca-Maïto         if (!NT_SUCCESS(Status))
5352674e26cSHermès Bélusca-Maïto             break;
536c2c66affSColin Finck     }
537c2c66affSColin Finck 
538c2c66affSColin Finck     return Status;
539c2c66affSColin Finck }
540c2c66affSColin Finck 
5412674e26cSHermès Bélusca-Maïto /**
5422674e26cSHermès Bélusca-Maïto  * @brief
543c2c66affSColin Finck  * Reads and returns Hardware information from the appropriate hardware
5442674e26cSHermès Bélusca-Maïto  * registry key. Helper stub of IoQueryDeviceDescription(). Has two modes
5452674e26cSHermès Bélusca-Maïto  * of operation, either looking for root bus types or for sub-bus
546c2c66affSColin Finck  * information.
547c2c66affSColin Finck  *
5482674e26cSHermès Bélusca-Maïto  * @param[in]   Query
5492674e26cSHermès Bélusca-Maïto  * What the parent function wants.
550c2c66affSColin Finck  *
5512674e26cSHermès Bélusca-Maïto  * @param[in]   RootKey
5522674e26cSHermès Bélusca-Maïto  * Which key to look in.
5532674e26cSHermès Bélusca-Maïto  *
5542674e26cSHermès Bélusca-Maïto  * @param[in]   RootKeyHandle
5552674e26cSHermès Bélusca-Maïto  * Handle to the key.
5562674e26cSHermès Bélusca-Maïto  *
5572674e26cSHermès Bélusca-Maïto  * @param[in,out]   Bus
5582674e26cSHermès Bélusca-Maïto  * Pointer to the current bus number.
5592674e26cSHermès Bélusca-Maïto  *
5602674e26cSHermès Bélusca-Maïto  * @param[in]   KeyIsRoot
5612674e26cSHermès Bélusca-Maïto  * Whether we are looking for root bus types or information under them.
5622674e26cSHermès Bélusca-Maïto  *
5632674e26cSHermès Bélusca-Maïto  * @return  A status code.
5642674e26cSHermès Bélusca-Maïto  **/
5652674e26cSHermès Bélusca-Maïto static NTSTATUS
IopQueryBusDescription(_In_ PIO_QUERY Query,_In_ UNICODE_STRING RootKey,_In_ HANDLE RootKeyHandle,_Inout_ PULONG Bus,_In_ BOOLEAN KeyIsRoot)566c2c66affSColin Finck IopQueryBusDescription(
5672674e26cSHermès Bélusca-Maïto     _In_ PIO_QUERY Query,
5682674e26cSHermès Bélusca-Maïto     _In_ UNICODE_STRING RootKey,
5692674e26cSHermès Bélusca-Maïto     _In_ HANDLE RootKeyHandle,
5702674e26cSHermès Bélusca-Maïto     _Inout_ PULONG Bus,
5712674e26cSHermès Bélusca-Maïto     _In_ BOOLEAN KeyIsRoot)
572c2c66affSColin Finck {
573c2c66affSColin Finck     NTSTATUS Status;
574c2c66affSColin Finck     ULONG BusLoop;
575c2c66affSColin Finck     UNICODE_STRING SubRootRegName;
576c2c66affSColin Finck     UNICODE_STRING BusString;
577c2c66affSColin Finck     UNICODE_STRING SubBusString;
578c2c66affSColin Finck     ULONG LenBasicInformation = 0;
579c2c66affSColin Finck     ULONG LenFullInformation;
580c2c66affSColin Finck     ULONG LenKeyFullInformation;
581c2c66affSColin Finck     ULONG LenKey;
582c2c66affSColin Finck     HANDLE SubRootKeyHandle;
583c2c66affSColin Finck     PKEY_FULL_INFORMATION FullInformation;
584c2c66affSColin Finck     PKEY_BASIC_INFORMATION BasicInformation = NULL;
585c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
5862674e26cSHermès Bélusca-Maïto     PKEY_VALUE_FULL_INFORMATION BusInformation[IoQueryDeviceMaxData] =
5872674e26cSHermès Bélusca-Maïto         {NULL, NULL, NULL};
588c2c66affSColin Finck 
5890b695a6fSHermès Bélusca-Maïto     IORSRCTRACE("\nIopQueryBusDescription(Query: 0x%p)\n"
5900b695a6fSHermès Bélusca-Maïto                 "    RootKey: '%wZ'\n"
5910b695a6fSHermès Bélusca-Maïto                 "    RootKeyHandle: 0x%p\n"
5920b695a6fSHermès Bélusca-Maïto                 "    KeyIsRoot: %s\n"
5930b695a6fSHermès Bélusca-Maïto                 "    Bus: 0x%p (%lu)\n",
5940b695a6fSHermès Bélusca-Maïto                 Query,
5950b695a6fSHermès Bélusca-Maïto                 &RootKey, RootKeyHandle,
5960b695a6fSHermès Bélusca-Maïto                 KeyIsRoot ? "TRUE" : "FALSE",
5970b695a6fSHermès Bélusca-Maïto                 Bus, Bus ? *Bus : -1);
5980b695a6fSHermès Bélusca-Maïto 
5992674e26cSHermès Bélusca-Maïto     /* Retrieve the necessary buffer space */
6002674e26cSHermès Bélusca-Maïto     Status = ZwQueryKey(RootKeyHandle,
6012674e26cSHermès Bélusca-Maïto                         KeyFullInformation,
6022674e26cSHermès Bélusca-Maïto                         NULL, 0,
6032674e26cSHermès Bélusca-Maïto                         &LenFullInformation);
604c2c66affSColin Finck 
6052674e26cSHermès Bélusca-Maïto     if (!NT_SUCCESS(Status) &&
6062674e26cSHermès Bélusca-Maïto         (Status != STATUS_BUFFER_TOO_SMALL) &&
6072674e26cSHermès Bélusca-Maïto         (Status != STATUS_BUFFER_OVERFLOW))
6082674e26cSHermès Bélusca-Maïto     {
609c2c66affSColin Finck         return Status;
6102674e26cSHermès Bélusca-Maïto     }
611c2c66affSColin Finck 
612c2c66affSColin Finck     /* Allocate it */
613c2c66affSColin Finck     FullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
614c2c66affSColin Finck     if (!FullInformation)
615*84b4a80bSHermès Bélusca-Maïto         return STATUS_INSUFFICIENT_RESOURCES;
616c2c66affSColin Finck 
6172674e26cSHermès Bélusca-Maïto     /* Get the information */
6182674e26cSHermès Bélusca-Maïto     Status = ZwQueryKey(RootKeyHandle,
6192674e26cSHermès Bélusca-Maïto                         KeyFullInformation,
6202674e26cSHermès Bélusca-Maïto                         FullInformation,
6212674e26cSHermès Bélusca-Maïto                         LenFullInformation,
6222674e26cSHermès Bélusca-Maïto                         &LenFullInformation);
623c2c66affSColin Finck     if (NT_SUCCESS(Status))
624c2c66affSColin Finck     {
625c2c66affSColin Finck         /* Buffer needed for all the keys under this one */
626c2c66affSColin Finck         LenBasicInformation = FullInformation->MaxNameLen + sizeof(KEY_BASIC_INFORMATION);
627c2c66affSColin Finck 
628c2c66affSColin Finck         /* Allocate it */
629c2c66affSColin Finck         BasicInformation = ExAllocatePoolWithTag(PagedPool, LenBasicInformation, TAG_IO_RESOURCE);
630*84b4a80bSHermès Bélusca-Maïto         if (!BasicInformation)
631*84b4a80bSHermès Bélusca-Maïto         {
632*84b4a80bSHermès Bélusca-Maïto             ExFreePoolWithTag(FullInformation, TAG_IO_RESOURCE);
633*84b4a80bSHermès Bélusca-Maïto             return STATUS_INSUFFICIENT_RESOURCES;
634*84b4a80bSHermès Bélusca-Maïto         }
635c2c66affSColin Finck     }
636c2c66affSColin Finck 
6372674e26cSHermès Bélusca-Maïto     /* Deallocate the old buffer */
638c2c66affSColin Finck     ExFreePoolWithTag(FullInformation, TAG_IO_RESOURCE);
639c2c66affSColin Finck 
6402674e26cSHermès Bélusca-Maïto     /* Try to find a bus */
641c2c66affSColin Finck     for (BusLoop = 0; NT_SUCCESS(Status); BusLoop++)
642c2c66affSColin Finck     {
643c2c66affSColin Finck         /* Bus parameter was passed and number was matched */
6442674e26cSHermès Bélusca-Maïto         if (Query->BusNumber && (*(Query->BusNumber) == *Bus))
6452674e26cSHermès Bélusca-Maïto             break;
646c2c66affSColin Finck 
647c2c66affSColin Finck         /* Enumerate the Key */
6482674e26cSHermès Bélusca-Maïto         Status = ZwEnumerateKey(RootKeyHandle,
649c2c66affSColin Finck                                 BusLoop,
650c2c66affSColin Finck                                 KeyBasicInformation,
651c2c66affSColin Finck                                 BasicInformation,
652c2c66affSColin Finck                                 LenBasicInformation,
653c2c66affSColin Finck                                 &LenKey);
654c2c66affSColin Finck 
6552674e26cSHermès Bélusca-Maïto         /* Stop if everything was enumerated */
6562674e26cSHermès Bélusca-Maïto         if (!NT_SUCCESS(Status))
6572674e26cSHermès Bélusca-Maïto             break;
658c2c66affSColin Finck 
6590b695a6fSHermès Bélusca-Maïto         IORSRCTRACE("    Seen: '%.*ws'\n", BasicInformation->NameLength/sizeof(WCHAR), BasicInformation->Name);
6600b695a6fSHermès Bélusca-Maïto 
6612674e26cSHermès Bélusca-Maïto         /* What bus are we going to go down? (only check if this is a root key) */
662c2c66affSColin Finck         if (KeyIsRoot)
663c2c66affSColin Finck         {
6642674e26cSHermès Bélusca-Maïto             if (wcsncmp(BasicInformation->Name, L"MultifunctionAdapter", BasicInformation->NameLength / sizeof(WCHAR)) &&
6652674e26cSHermès Bélusca-Maïto                 wcsncmp(BasicInformation->Name, L"EisaAdapter", BasicInformation->NameLength / sizeof(WCHAR)) &&
6662674e26cSHermès Bélusca-Maïto                 wcsncmp(BasicInformation->Name, L"TcAdapter", BasicInformation->NameLength / sizeof(WCHAR)))
667c2c66affSColin Finck             {
668c2c66affSColin Finck                 /* Nothing found, check next */
669c2c66affSColin Finck                 continue;
670c2c66affSColin Finck             }
671c2c66affSColin Finck         }
672c2c66affSColin Finck 
6732674e26cSHermès Bélusca-Maïto         /* Enumerate the bus */
674c2c66affSColin Finck         BusString.Buffer = BasicInformation->Name;
675c2c66affSColin Finck         BusString.Length = (USHORT)BasicInformation->NameLength;
676c2c66affSColin Finck         BusString.MaximumLength = (USHORT)BasicInformation->NameLength;
677c2c66affSColin Finck 
6782674e26cSHermès Bélusca-Maïto         /* Open a handle to the root registry key */
6792674e26cSHermès Bélusca-Maïto         InitializeObjectAttributes(&ObjectAttributes,
680c2c66affSColin Finck                                    &BusString,
681c2c66affSColin Finck                                    OBJ_CASE_INSENSITIVE,
682c2c66affSColin Finck                                    RootKeyHandle,
683c2c66affSColin Finck                                    NULL);
684c2c66affSColin Finck 
685c2c66affSColin Finck         Status = ZwOpenKey(&SubRootKeyHandle, KEY_READ, &ObjectAttributes);
686c2c66affSColin Finck 
6872674e26cSHermès Bélusca-Maïto         /* Go on if we failed */
6882674e26cSHermès Bélusca-Maïto         if (!NT_SUCCESS(Status))
6892674e26cSHermès Bélusca-Maïto             continue;
690c2c66affSColin Finck 
6912674e26cSHermès Bélusca-Maïto         /* Key opened, create the path */
692c2c66affSColin Finck         SubRootRegName = RootKey;
693c2c66affSColin Finck         RtlAppendUnicodeToString(&SubRootRegName, L"\\");
694c2c66affSColin Finck         RtlAppendUnicodeStringToString(&SubRootRegName, &BusString);
695c2c66affSColin Finck 
6960b695a6fSHermès Bélusca-Maïto         IORSRCTRACE("    SubRootRegName: '%wZ'\n", &SubRootRegName);
6970b695a6fSHermès Bélusca-Maïto 
698c2c66affSColin Finck         if (!KeyIsRoot)
699c2c66affSColin Finck         {
7002674e26cSHermès Bélusca-Maïto             /* Parsing a sub-bus key */
7012674e26cSHermès Bélusca-Maïto             ULONG SubBusLoop;
7022674e26cSHermès Bélusca-Maïto             for (SubBusLoop = 0; SubBusLoop < RTL_NUMBER_OF(IoDeviceInfoNames); SubBusLoop++)
703c2c66affSColin Finck             {
7042674e26cSHermès Bélusca-Maïto                 /* Identifier string first */
7052674e26cSHermès Bélusca-Maïto                 RtlInitUnicodeString(&SubBusString, IoDeviceInfoNames[SubBusLoop]);
706c2c66affSColin Finck 
7070b695a6fSHermès Bélusca-Maïto                 IORSRCTRACE("    Getting bus value: '%wZ'\n", &SubBusString);
7080b695a6fSHermès Bélusca-Maïto 
7092674e26cSHermès Bélusca-Maïto                 /* Retrieve the necessary buffer space */
7102674e26cSHermès Bélusca-Maïto                 ZwQueryValueKey(SubRootKeyHandle,
7112674e26cSHermès Bélusca-Maïto                                 &SubBusString,
7122674e26cSHermès Bélusca-Maïto                                 KeyValueFullInformation,
7132674e26cSHermès Bélusca-Maïto                                 NULL, 0,
7142674e26cSHermès Bélusca-Maïto                                 &LenKeyFullInformation);
715c2c66affSColin Finck 
716c2c66affSColin Finck                 /* Allocate it */
717c2c66affSColin Finck                 BusInformation[SubBusLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
718*84b4a80bSHermès Bélusca-Maïto                 if (!BusInformation[SubBusLoop])
719*84b4a80bSHermès Bélusca-Maïto                 {
720*84b4a80bSHermès Bélusca-Maïto                     Status = STATUS_INSUFFICIENT_RESOURCES;
721*84b4a80bSHermès Bélusca-Maïto                     break;
722*84b4a80bSHermès Bélusca-Maïto                 }
723c2c66affSColin Finck 
7242674e26cSHermès Bélusca-Maïto                 /* Get the information */
7252674e26cSHermès Bélusca-Maïto                 Status = ZwQueryValueKey(SubRootKeyHandle,
7262674e26cSHermès Bélusca-Maïto                                          &SubBusString,
7272674e26cSHermès Bélusca-Maïto                                          KeyValueFullInformation,
7282674e26cSHermès Bélusca-Maïto                                          BusInformation[SubBusLoop],
7292674e26cSHermès Bélusca-Maïto                                          LenKeyFullInformation,
7302674e26cSHermès Bélusca-Maïto                                          &LenKeyFullInformation);
731c2c66affSColin Finck             }
732c2c66affSColin Finck 
733c2c66affSColin Finck             if (NT_SUCCESS(Status))
734c2c66affSColin Finck             {
7352674e26cSHermès Bélusca-Maïto                 PKEY_VALUE_FULL_INFORMATION BusConfigData =
7362674e26cSHermès Bélusca-Maïto                     BusInformation[IoQueryDeviceConfigurationData];
7372674e26cSHermès Bélusca-Maïto 
7382674e26cSHermès Bélusca-Maïto                 /* Do we have something? */
7392674e26cSHermès Bélusca-Maïto                 if (BusConfigData != NULL &&
7402674e26cSHermès Bélusca-Maïto                     BusConfigData->DataLength != 0 &&
741c2c66affSColin Finck                     /* Does it match what we want? */
7422674e26cSHermès Bélusca-Maïto                     (((PCM_FULL_RESOURCE_DESCRIPTOR)((ULONG_PTR)BusConfigData +
7432674e26cSHermès Bélusca-Maïto                         BusConfigData->DataOffset))->InterfaceType == *(Query->BusType)))
744c2c66affSColin Finck                 {
745c2c66affSColin Finck                     /* Found a bus */
746c2c66affSColin Finck                     (*Bus)++;
747c2c66affSColin Finck 
7482674e26cSHermès Bélusca-Maïto                     /* Is it the bus we wanted? */
749c2c66affSColin Finck                     if (Query->BusNumber == NULL || *(Query->BusNumber) == *Bus)
750c2c66affSColin Finck                     {
751c2c66affSColin Finck                         if (Query->ControllerType == NULL)
752c2c66affSColin Finck                         {
7530b695a6fSHermès Bélusca-Maïto                             IORSRCTRACE("    --> Bus #%lu Callout: '%wZ'\n", *Bus, &SubRootRegName);
7540b695a6fSHermès Bélusca-Maïto 
7552674e26cSHermès Bélusca-Maïto                             /* We don't want controller information: call the callback */
7562674e26cSHermès Bélusca-Maïto                             Status = Query->CalloutRoutine(Query->Context,
757c2c66affSColin Finck                                                            &SubRootRegName,
758c2c66affSColin Finck                                                            *(Query->BusType),
759c2c66affSColin Finck                                                            *Bus,
760c2c66affSColin Finck                                                            BusInformation,
761c2c66affSColin Finck                                                            0,
762c2c66affSColin Finck                                                            0,
763c2c66affSColin Finck                                                            NULL,
764c2c66affSColin Finck                                                            0,
765c2c66affSColin Finck                                                            0,
766c2c66affSColin Finck                                                            NULL);
7672674e26cSHermès Bélusca-Maïto                         }
7682674e26cSHermès Bélusca-Maïto                         else
7692674e26cSHermès Bélusca-Maïto                         {
7700b695a6fSHermès Bélusca-Maïto                             IORSRCTRACE("    --> Getting device on Bus #%lu : '%wZ'\n", *Bus, &SubRootRegName);
7710b695a6fSHermès Bélusca-Maïto 
7722674e26cSHermès Bélusca-Maïto                             /* We want controller information: get it */
7732674e26cSHermès Bélusca-Maïto                             Status = IopQueryDeviceDescription(Query,
7742674e26cSHermès Bélusca-Maïto                                                                SubRootRegName,
7752674e26cSHermès Bélusca-Maïto                                                                RootKeyHandle,
7762674e26cSHermès Bélusca-Maïto                                                                *Bus,
7772674e26cSHermès Bélusca-Maïto                                                                (PKEY_VALUE_FULL_INFORMATION*)BusInformation);
778c2c66affSColin Finck                         }
779c2c66affSColin Finck                     }
780c2c66affSColin Finck                 }
781c2c66affSColin Finck             }
782c2c66affSColin Finck 
783c2c66affSColin Finck             /* Free the allocated memory */
7842674e26cSHermès Bélusca-Maïto             for (SubBusLoop = 0; SubBusLoop < RTL_NUMBER_OF(IoDeviceInfoNames); SubBusLoop++)
785c2c66affSColin Finck             {
786c2c66affSColin Finck                 if (BusInformation[SubBusLoop])
787c2c66affSColin Finck                 {
788c2c66affSColin Finck                     ExFreePoolWithTag(BusInformation[SubBusLoop], TAG_IO_RESOURCE);
789c2c66affSColin Finck                     BusInformation[SubBusLoop] = NULL;
790c2c66affSColin Finck                 }
791c2c66affSColin Finck             }
792c2c66affSColin Finck 
7932674e26cSHermès Bélusca-Maïto             /* Exit the loop if we found the bus */
7942674e26cSHermès Bélusca-Maïto             if (Query->BusNumber && (*(Query->BusNumber) == *Bus))
795c2c66affSColin Finck             {
796c2c66affSColin Finck                 ZwClose(SubRootKeyHandle);
797c2c66affSColin Finck                 SubRootKeyHandle = NULL;
798c2c66affSColin Finck                 continue;
799c2c66affSColin Finck             }
800c2c66affSColin Finck         }
801c2c66affSColin Finck 
802c2c66affSColin Finck         /* Enumerate the buses below us recursively if we haven't found the bus yet */
803c2c66affSColin Finck         Status = IopQueryBusDescription(Query, SubRootRegName, SubRootKeyHandle, Bus, !KeyIsRoot);
804c2c66affSColin Finck 
805c2c66affSColin Finck         /* Everything enumerated */
806*84b4a80bSHermès Bélusca-Maïto         if (Status == STATUS_NO_MORE_ENTRIES)
807*84b4a80bSHermès Bélusca-Maïto             Status = STATUS_SUCCESS;
808c2c66affSColin Finck 
809c2c66affSColin Finck         ZwClose(SubRootKeyHandle);
810c2c66affSColin Finck         SubRootKeyHandle = NULL;
811c2c66affSColin Finck     }
812c2c66affSColin Finck 
8132674e26cSHermès Bélusca-Maïto     /* Free the last remaining allocated memory */
814c2c66affSColin Finck     if (BasicInformation)
815c2c66affSColin Finck         ExFreePoolWithTag(BasicInformation, TAG_IO_RESOURCE);
816c2c66affSColin Finck 
817c2c66affSColin Finck     return Status;
818c2c66affSColin Finck }
819c2c66affSColin Finck 
820c2c66affSColin Finck NTSTATUS
IopFetchConfigurationInformation(_Out_ PWSTR * SymbolicLinkList,_In_ GUID Guid,_In_ ULONG ExpectedInterfaces,_Out_ PULONG Interfaces)8212674e26cSHermès Bélusca-Maïto IopFetchConfigurationInformation(
8222674e26cSHermès Bélusca-Maïto     _Out_ PWSTR* SymbolicLinkList,
8232674e26cSHermès Bélusca-Maïto     _In_ GUID Guid,
8242674e26cSHermès Bélusca-Maïto     _In_ ULONG ExpectedInterfaces,
8252674e26cSHermès Bélusca-Maïto     _Out_ PULONG Interfaces)
826c2c66affSColin Finck {
827c2c66affSColin Finck     NTSTATUS Status;
8282674e26cSHermès Bélusca-Maïto     ULONG interfaces = 0;
8292674e26cSHermès Bélusca-Maïto     PWSTR symbolicLinkList;
830c2c66affSColin Finck 
831c2c66affSColin Finck     /* Get the associated enabled interfaces with the given GUID */
832c2c66affSColin Finck     Status = IoGetDeviceInterfaces(&Guid, NULL, 0, SymbolicLinkList);
833c2c66affSColin Finck     if (!NT_SUCCESS(Status))
834c2c66affSColin Finck     {
835c2c66affSColin Finck         /* Zero output and leave */
8362674e26cSHermès Bélusca-Maïto         if (SymbolicLinkList)
8372674e26cSHermès Bélusca-Maïto             *SymbolicLinkList = NULL;
838c2c66affSColin Finck 
839c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
840c2c66affSColin Finck     }
841c2c66affSColin Finck 
8422674e26cSHermès Bélusca-Maïto     symbolicLinkList = *SymbolicLinkList;
843c2c66affSColin Finck 
844c2c66affSColin Finck     /* Count the number of enabled interfaces by counting the number of symbolic links */
8452674e26cSHermès Bélusca-Maïto     while (*symbolicLinkList != UNICODE_NULL)
846c2c66affSColin Finck     {
8472674e26cSHermès Bélusca-Maïto         interfaces++;
8482674e26cSHermès Bélusca-Maïto         symbolicLinkList += (wcslen(symbolicLinkList) + 1);
849c2c66affSColin Finck     }
850c2c66affSColin Finck 
851c2c66affSColin Finck     /* Matching result will define the result */
8522674e26cSHermès Bélusca-Maïto     Status = (interfaces >= ExpectedInterfaces) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
853c2c66affSColin Finck     /* Finally, give back to the caller the number of found interfaces */
8542674e26cSHermès Bélusca-Maïto     *Interfaces = interfaces;
855c2c66affSColin Finck 
856c2c66affSColin Finck     return Status;
857c2c66affSColin Finck }
858c2c66affSColin Finck 
859c2c66affSColin Finck VOID
IopStoreSystemPartitionInformation(_In_ PUNICODE_STRING NtSystemPartitionDeviceName,_In_ PUNICODE_STRING OsLoaderPathName)8602674e26cSHermès Bélusca-Maïto IopStoreSystemPartitionInformation(
8612674e26cSHermès Bélusca-Maïto     _In_ PUNICODE_STRING NtSystemPartitionDeviceName,
8622674e26cSHermès Bélusca-Maïto     _In_ PUNICODE_STRING OsLoaderPathName)
863c2c66affSColin Finck {
864c2c66affSColin Finck     NTSTATUS Status;
865c2c66affSColin Finck     UNICODE_STRING LinkTarget, KeyName;
866c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
867c2c66affSColin Finck     HANDLE LinkHandle, RegistryHandle, KeyHandle;
868c2c66affSColin Finck     WCHAR LinkTargetBuffer[256];
869c2c66affSColin Finck     UNICODE_STRING CmRegistryMachineSystemName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM");
870c2c66affSColin Finck 
871c2c66affSColin Finck     ASSERT(NtSystemPartitionDeviceName->MaximumLength >= NtSystemPartitionDeviceName->Length + sizeof(WCHAR));
872c2c66affSColin Finck     ASSERT(NtSystemPartitionDeviceName->Buffer[NtSystemPartitionDeviceName->Length / sizeof(WCHAR)] == UNICODE_NULL);
873c2c66affSColin Finck     ASSERT(OsLoaderPathName->MaximumLength >= OsLoaderPathName->Length + sizeof(WCHAR));
874c2c66affSColin Finck     ASSERT(OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] == UNICODE_NULL);
875c2c66affSColin Finck 
876c2c66affSColin Finck     /* First define needed stuff to open NtSystemPartitionDeviceName symbolic link */
877c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
878c2c66affSColin Finck                                NtSystemPartitionDeviceName,
879c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
880c2c66affSColin Finck                                NULL,
881c2c66affSColin Finck                                NULL);
882c2c66affSColin Finck 
883c2c66affSColin Finck     /* Open NtSystemPartitionDeviceName symbolic link */
884c2c66affSColin Finck     Status = ZwOpenSymbolicLinkObject(&LinkHandle,
885c2c66affSColin Finck                                       SYMBOLIC_LINK_QUERY,
886c2c66affSColin Finck                                       &ObjectAttributes);
887c2c66affSColin Finck     if (!NT_SUCCESS(Status))
888c2c66affSColin Finck     {
889c2c66affSColin Finck         DPRINT("Failed to open symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName, Status);
890c2c66affSColin Finck         return;
891c2c66affSColin Finck     }
892c2c66affSColin Finck 
893*84b4a80bSHermès Bélusca-Maïto     /* Prepare the string that will receive where symbolic link points to.
894*84b4a80bSHermès Bélusca-Maïto      * We will zero the end of the string after having received it */
895*84b4a80bSHermès Bélusca-Maïto     RtlInitEmptyUnicodeString(&LinkTarget, LinkTargetBuffer,
896*84b4a80bSHermès Bélusca-Maïto                               sizeof(LinkTargetBuffer) - sizeof(UNICODE_NULL));
897c2c66affSColin Finck 
898c2c66affSColin Finck     /* Query target */
8992674e26cSHermès Bélusca-Maïto     Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL);
900c2c66affSColin Finck 
901c2c66affSColin Finck     /* We are done with symbolic link */
902c2c66affSColin Finck     ObCloseHandle(LinkHandle, KernelMode);
903c2c66affSColin Finck 
904c2c66affSColin Finck     if (!NT_SUCCESS(Status))
905c2c66affSColin Finck     {
906c2c66affSColin Finck         DPRINT("Failed querying symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName, Status);
907c2c66affSColin Finck         return;
908c2c66affSColin Finck     }
909c2c66affSColin Finck 
910c2c66affSColin Finck     /* As promised, we zero the end */
911c2c66affSColin Finck     LinkTarget.Buffer[LinkTarget.Length / sizeof(WCHAR)] = UNICODE_NULL;
912c2c66affSColin Finck 
913c2c66affSColin Finck     /* Open registry to save data (HKLM\SYSTEM) */
914c2c66affSColin Finck     Status = IopOpenRegistryKeyEx(&RegistryHandle,
915c2c66affSColin Finck                                   NULL,
916c2c66affSColin Finck                                   &CmRegistryMachineSystemName,
917c2c66affSColin Finck                                   KEY_ALL_ACCESS);
918c2c66affSColin Finck     if (!NT_SUCCESS(Status))
919c2c66affSColin Finck     {
920c2c66affSColin Finck         DPRINT("Failed to open HKLM\\SYSTEM, Status=%lx\n", Status);
921c2c66affSColin Finck         return;
922c2c66affSColin Finck     }
923c2c66affSColin Finck 
924c2c66affSColin Finck     /* Open or create the Setup subkey where we'll store in */
925c2c66affSColin Finck     RtlInitUnicodeString(&KeyName, L"Setup");
926c2c66affSColin Finck 
927c2c66affSColin Finck     Status = IopCreateRegistryKeyEx(&KeyHandle,
928c2c66affSColin Finck                                     RegistryHandle,
929c2c66affSColin Finck                                     &KeyName,
930c2c66affSColin Finck                                     KEY_ALL_ACCESS,
931c2c66affSColin Finck                                     REG_OPTION_NON_VOLATILE,
932c2c66affSColin Finck                                     NULL);
933c2c66affSColin Finck 
934c2c66affSColin Finck     /* We're done with HKLM\SYSTEM */
935c2c66affSColin Finck     ObCloseHandle(RegistryHandle, KernelMode);
936c2c66affSColin Finck 
937c2c66affSColin Finck     if (!NT_SUCCESS(Status))
938c2c66affSColin Finck     {
939c2c66affSColin Finck         DPRINT("Failed opening/creating Setup key, Status=%lx\n", Status);
940c2c66affSColin Finck         return;
941c2c66affSColin Finck     }
942c2c66affSColin Finck 
9432674e26cSHermès Bélusca-Maïto     /* Prepare first data writing */
944c2c66affSColin Finck     RtlInitUnicodeString(&KeyName, L"SystemPartition");
945c2c66affSColin Finck 
946c2c66affSColin Finck     /* Write SystemPartition value which is the target of the symbolic link */
947c2c66affSColin Finck     Status = ZwSetValueKey(KeyHandle,
948c2c66affSColin Finck                            &KeyName,
949c2c66affSColin Finck                            0,
950c2c66affSColin Finck                            REG_SZ,
951c2c66affSColin Finck                            LinkTarget.Buffer,
952c2c66affSColin Finck                            LinkTarget.Length + sizeof(WCHAR));
953c2c66affSColin Finck     if (!NT_SUCCESS(Status))
954c2c66affSColin Finck     {
955c2c66affSColin Finck         DPRINT("Failed writing SystemPartition value, Status=%lx\n", Status);
956c2c66affSColin Finck     }
957c2c66affSColin Finck 
9582674e26cSHermès Bélusca-Maïto     /* Prepare for second data writing */
959c2c66affSColin Finck     RtlInitUnicodeString(&KeyName, L"OsLoaderPath");
960c2c66affSColin Finck 
961c2c66affSColin Finck     /* Remove trailing slash if any (one slash only excepted) */
962c2c66affSColin Finck     if (OsLoaderPathName->Length > sizeof(WCHAR) &&
963c2c66affSColin Finck         OsLoaderPathName->Buffer[(OsLoaderPathName->Length / sizeof(WCHAR)) - 1] == OBJ_NAME_PATH_SEPARATOR)
964c2c66affSColin Finck     {
965c2c66affSColin Finck         OsLoaderPathName->Length -= sizeof(WCHAR);
966c2c66affSColin Finck         OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] = UNICODE_NULL;
967c2c66affSColin Finck     }
968c2c66affSColin Finck 
969c2c66affSColin Finck     /* Then, write down data */
970c2c66affSColin Finck     Status = ZwSetValueKey(KeyHandle,
971c2c66affSColin Finck                            &KeyName,
972c2c66affSColin Finck                            0,
973c2c66affSColin Finck                            REG_SZ,
974c2c66affSColin Finck                            OsLoaderPathName->Buffer,
975c2c66affSColin Finck                            OsLoaderPathName->Length + sizeof(UNICODE_NULL));
976c2c66affSColin Finck     if (!NT_SUCCESS(Status))
977c2c66affSColin Finck     {
978c2c66affSColin Finck         DPRINT("Failed writing OsLoaderPath value, Status=%lx\n", Status);
979c2c66affSColin Finck     }
980c2c66affSColin Finck 
981c2c66affSColin Finck     /* We're finally done! */
982c2c66affSColin Finck     ObCloseHandle(KeyHandle, KernelMode);
983c2c66affSColin Finck }
984c2c66affSColin Finck 
985c2c66affSColin Finck /* PUBLIC FUNCTIONS ***********************************************************/
986c2c66affSColin Finck 
9872674e26cSHermès Bélusca-Maïto /**
9882674e26cSHermès Bélusca-Maïto  * @brief
9892674e26cSHermès Bélusca-Maïto  * Returns a pointer to the I/O manager's global configuration
9902674e26cSHermès Bélusca-Maïto  * information structure.
9912674e26cSHermès Bélusca-Maïto  *
9922674e26cSHermès Bélusca-Maïto  * This structure contains the current values for how many physical storage
9932674e26cSHermès Bélusca-Maïto  * media, SCSI HBA, serial, and parallel devices have device objects created
9942674e26cSHermès Bélusca-Maïto  * to represent them by drivers as they are loaded.
9952674e26cSHermès Bélusca-Maïto  **/
9962674e26cSHermès Bélusca-Maïto PCONFIGURATION_INFORMATION
9972674e26cSHermès Bélusca-Maïto NTAPI
IoGetConfigurationInformation(VOID)998c2c66affSColin Finck IoGetConfigurationInformation(VOID)
999c2c66affSColin Finck {
10002674e26cSHermès Bélusca-Maïto     return &_SystemConfigurationInformation;
1001c2c66affSColin Finck }
1002c2c66affSColin Finck 
10032674e26cSHermès Bélusca-Maïto /**
1004c2c66affSColin Finck  * @halfplemented
10052674e26cSHermès Bélusca-Maïto  *
10062674e26cSHermès Bélusca-Maïto  * @brief
10072674e26cSHermès Bélusca-Maïto  * Reports hardware resources in the \Registry\Machine\Hardware\ResourceMap
10082674e26cSHermès Bélusca-Maïto  * tree, so that a subsequently loaded driver cannot attempt to use the
10092674e26cSHermès Bélusca-Maïto  * same resources.
10102674e26cSHermès Bélusca-Maïto  *
10112674e26cSHermès Bélusca-Maïto  * @param[in]   DriverClassName
10122674e26cSHermès Bélusca-Maïto  * The driver class under which the resource information should be stored.
10132674e26cSHermès Bélusca-Maïto  *
10142674e26cSHermès Bélusca-Maïto  * @param[in]   DriverObject
10152674e26cSHermès Bélusca-Maïto  * The driver object that was provided to the DriverEntry routine.
10162674e26cSHermès Bélusca-Maïto  *
10172674e26cSHermès Bélusca-Maïto  * @param[in]   DriverList
10182674e26cSHermès Bélusca-Maïto  * Resources claimed for the all the driver's devices, rather than per-device.
10192674e26cSHermès Bélusca-Maïto  *
10202674e26cSHermès Bélusca-Maïto  * @param[in]   DriverListSize
10212674e26cSHermès Bélusca-Maïto  * Size in bytes of the DriverList.
10222674e26cSHermès Bélusca-Maïto  *
10232674e26cSHermès Bélusca-Maïto  * @param[in]   DeviceObject
10242674e26cSHermès Bélusca-Maïto  * The device object for which resources should be claimed.
10252674e26cSHermès Bélusca-Maïto  *
10262674e26cSHermès Bélusca-Maïto  * @param[in]   DeviceList
10272674e26cSHermès Bélusca-Maïto  * List of resources that should be claimed for the device.
10282674e26cSHermès Bélusca-Maïto  *
10292674e26cSHermès Bélusca-Maïto  * @param[in]   DeviceListSize
10302674e26cSHermès Bélusca-Maïto  * Size of the per-device resource list in bytes.
10312674e26cSHermès Bélusca-Maïto  *
10322674e26cSHermès Bélusca-Maïto  * @param[in]   OverrideConflict
10332674e26cSHermès Bélusca-Maïto  * TRUE if the resources should be claimed even if a conflict is found.
10342674e26cSHermès Bélusca-Maïto  *
10352674e26cSHermès Bélusca-Maïto  * @param[out]  ConflictDetected
10362674e26cSHermès Bélusca-Maïto  * Points to a variable that receives TRUE if a conflict is detected
10372674e26cSHermès Bélusca-Maïto  * with another driver.
10382674e26cSHermès Bélusca-Maïto  **/
10392674e26cSHermès Bélusca-Maïto NTSTATUS
10402674e26cSHermès Bélusca-Maïto NTAPI
IoReportResourceUsage(_In_opt_ PUNICODE_STRING DriverClassName,_In_ PDRIVER_OBJECT DriverObject,_In_reads_bytes_opt_ (DriverListSize)PCM_RESOURCE_LIST DriverList,_In_opt_ ULONG DriverListSize,_In_opt_ PDEVICE_OBJECT DeviceObject,_In_reads_bytes_opt_ (DeviceListSize)PCM_RESOURCE_LIST DeviceList,_In_opt_ ULONG DeviceListSize,_In_ BOOLEAN OverrideConflict,_Out_ PBOOLEAN ConflictDetected)10412674e26cSHermès Bélusca-Maïto IoReportResourceUsage(
10422674e26cSHermès Bélusca-Maïto     _In_opt_ PUNICODE_STRING DriverClassName,
10432674e26cSHermès Bélusca-Maïto     _In_ PDRIVER_OBJECT DriverObject,
10442674e26cSHermès Bélusca-Maïto     _In_reads_bytes_opt_(DriverListSize) PCM_RESOURCE_LIST DriverList,
10452674e26cSHermès Bélusca-Maïto     _In_opt_ ULONG DriverListSize,
10462674e26cSHermès Bélusca-Maïto     _In_opt_ PDEVICE_OBJECT DeviceObject,
10472674e26cSHermès Bélusca-Maïto     _In_reads_bytes_opt_(DeviceListSize) PCM_RESOURCE_LIST DeviceList,
10482674e26cSHermès Bélusca-Maïto     _In_opt_ ULONG DeviceListSize,
10492674e26cSHermès Bélusca-Maïto     _In_ BOOLEAN OverrideConflict,
10502674e26cSHermès Bélusca-Maïto     _Out_ PBOOLEAN ConflictDetected)
1051c2c66affSColin Finck {
1052c2c66affSColin Finck     NTSTATUS Status;
1053c2c66affSColin Finck     PCM_RESOURCE_LIST ResourceList;
1054c2c66affSColin Finck 
1055c2c66affSColin Finck     DPRINT1("IoReportResourceUsage is halfplemented!\n");
1056c2c66affSColin Finck 
1057c2c66affSColin Finck     if (!DriverList && !DeviceList)
1058c2c66affSColin Finck         return STATUS_INVALID_PARAMETER;
1059c2c66affSColin Finck 
1060c2c66affSColin Finck     if (DeviceList)
1061c2c66affSColin Finck         ResourceList = DeviceList;
1062c2c66affSColin Finck     else
1063c2c66affSColin Finck         ResourceList = DriverList;
1064c2c66affSColin Finck 
1065c2c66affSColin Finck     Status = IopDetectResourceConflict(ResourceList, FALSE, NULL);
1066c2c66affSColin Finck     if (Status == STATUS_CONFLICTING_ADDRESSES)
1067c2c66affSColin Finck     {
1068c2c66affSColin Finck         *ConflictDetected = TRUE;
1069c2c66affSColin Finck 
1070c2c66affSColin Finck         if (!OverrideConflict)
1071c2c66affSColin Finck         {
1072c2c66affSColin Finck             DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
1073c2c66affSColin Finck             return STATUS_CONFLICTING_ADDRESSES;
1074c2c66affSColin Finck         }
1075c2c66affSColin Finck         else
1076c2c66affSColin Finck         {
1077c2c66affSColin Finck             DPRINT1("Proceeding with conflicting resources\n");
1078c2c66affSColin Finck         }
1079c2c66affSColin Finck     }
1080c2c66affSColin Finck     else if (!NT_SUCCESS(Status))
1081c2c66affSColin Finck     {
1082c2c66affSColin Finck         return Status;
1083c2c66affSColin Finck     }
1084c2c66affSColin Finck 
1085c2c66affSColin Finck     /* TODO: Claim resources in registry */
1086c2c66affSColin Finck 
1087c2c66affSColin Finck     *ConflictDetected = FALSE;
1088c2c66affSColin Finck 
1089c2c66affSColin Finck     return STATUS_SUCCESS;
1090c2c66affSColin Finck }
1091c2c66affSColin Finck 
10922674e26cSHermès Bélusca-Maïto static NTSTATUS
IopLegacyResourceAllocation(_In_ ARBITER_REQUEST_SOURCE AllocationType,_In_ PDRIVER_OBJECT DriverObject,_In_opt_ PDEVICE_OBJECT DeviceObject,_In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements,_Inout_ PCM_RESOURCE_LIST * AllocatedResources)10932674e26cSHermès Bélusca-Maïto IopLegacyResourceAllocation(
10942674e26cSHermès Bélusca-Maïto     _In_ ARBITER_REQUEST_SOURCE AllocationType,
10952674e26cSHermès Bélusca-Maïto     _In_ PDRIVER_OBJECT DriverObject,
10962674e26cSHermès Bélusca-Maïto     _In_opt_ PDEVICE_OBJECT DeviceObject,
10972674e26cSHermès Bélusca-Maïto     _In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements,
10982674e26cSHermès Bélusca-Maïto     _Inout_ PCM_RESOURCE_LIST* AllocatedResources)
1099c2c66affSColin Finck {
1100c2c66affSColin Finck     NTSTATUS Status;
1101c2c66affSColin Finck 
1102c2c66affSColin Finck     DPRINT1("IopLegacyResourceAllocation is halfplemented!\n");
1103c2c66affSColin Finck 
11049967d9aaSHervé Poussineau     if (!ResourceRequirements)
11059967d9aaSHervé Poussineau     {
11069967d9aaSHervé Poussineau         /* We can get there by calling IoAssignResources() with RequestedResources = NULL.
11079967d9aaSHervé Poussineau          * TODO: not sure what we should do, but we shouldn't crash.
11082674e26cSHermès Bélusca-Maïto          */
11099967d9aaSHervé Poussineau         UNIMPLEMENTED;
11109967d9aaSHervé Poussineau         return STATUS_NOT_IMPLEMENTED;
11119967d9aaSHervé Poussineau     }
11129967d9aaSHervé Poussineau 
1113c2c66affSColin Finck     Status = IopFixupResourceListWithRequirements(ResourceRequirements,
1114c2c66affSColin Finck                                                   AllocatedResources);
1115c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1116c2c66affSColin Finck     {
1117c2c66affSColin Finck         if (Status == STATUS_CONFLICTING_ADDRESSES)
1118c2c66affSColin Finck         {
1119c2c66affSColin Finck             DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
1120c2c66affSColin Finck         }
1121c2c66affSColin Finck 
1122c2c66affSColin Finck         return Status;
1123c2c66affSColin Finck     }
1124c2c66affSColin Finck 
1125c2c66affSColin Finck     /* TODO: Claim resources in registry */
1126c2c66affSColin Finck     return STATUS_SUCCESS;
1127c2c66affSColin Finck }
1128c2c66affSColin Finck 
1129c2c66affSColin Finck /*
1130c2c66affSColin Finck  * @implemented
1131c2c66affSColin Finck  */
1132c2c66affSColin Finck NTSTATUS
1133c2c66affSColin Finck NTAPI
IoAssignResources(_In_ PUNICODE_STRING RegistryPath,_In_opt_ PUNICODE_STRING DriverClassName,_In_ PDRIVER_OBJECT DriverObject,_In_opt_ PDEVICE_OBJECT DeviceObject,_In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources,_Inout_ PCM_RESOURCE_LIST * AllocatedResources)11342674e26cSHermès Bélusca-Maïto IoAssignResources(
11352674e26cSHermès Bélusca-Maïto     _In_ PUNICODE_STRING RegistryPath,
11362674e26cSHermès Bélusca-Maïto     _In_opt_ PUNICODE_STRING DriverClassName,
11372674e26cSHermès Bélusca-Maïto     _In_ PDRIVER_OBJECT DriverObject,
11382674e26cSHermès Bélusca-Maïto     _In_opt_ PDEVICE_OBJECT DeviceObject,
11392674e26cSHermès Bélusca-Maïto     _In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources,
11402674e26cSHermès Bélusca-Maïto     _Inout_ PCM_RESOURCE_LIST* AllocatedResources)
1141c2c66affSColin Finck {
1142c2c66affSColin Finck     PDEVICE_NODE DeviceNode;
1143c2c66affSColin Finck 
11442674e26cSHermès Bélusca-Maïto     UNREFERENCED_PARAMETER(RegistryPath);
11452674e26cSHermès Bélusca-Maïto     UNREFERENCED_PARAMETER(DriverClassName);
11462674e26cSHermès Bélusca-Maïto 
1147c2c66affSColin Finck     /* Do we have a DO? */
1148c2c66affSColin Finck     if (DeviceObject)
1149c2c66affSColin Finck     {
1150c2c66affSColin Finck         /* Get its device node */
1151c2c66affSColin Finck         DeviceNode = IopGetDeviceNode(DeviceObject);
11522674e26cSHermès Bélusca-Maïto         if (DeviceNode && !(DeviceNode->Flags & DNF_LEGACY_RESOURCE_DEVICENODE))
1153c2c66affSColin Finck         {
1154c2c66affSColin Finck             /* New drivers should not call this API */
1155c2c66affSColin Finck             KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
1156*84b4a80bSHermès Bélusca-Maïto                          0x2,
1157c2c66affSColin Finck                          (ULONG_PTR)DeviceObject,
1158*84b4a80bSHermès Bélusca-Maïto                          (ULONG_PTR)DriverObject,
1159*84b4a80bSHermès Bélusca-Maïto                          0);
1160c2c66affSColin Finck         }
1161c2c66affSColin Finck     }
1162c2c66affSColin Finck 
1163c2c66affSColin Finck     /* Did the driver supply resources? */
1164c2c66affSColin Finck     if (RequestedResources)
1165c2c66affSColin Finck     {
1166c2c66affSColin Finck         /* Make sure there's actually something useful in them */
1167c2c66affSColin Finck         if (!(RequestedResources->AlternativeLists) || !(RequestedResources->List[0].Count))
1168c2c66affSColin Finck         {
1169c2c66affSColin Finck             /* Empty resources are no resources */
1170c2c66affSColin Finck             RequestedResources = NULL;
1171c2c66affSColin Finck         }
1172c2c66affSColin Finck     }
1173c2c66affSColin Finck 
1174c2c66affSColin Finck     /* Initialize output if given */
11752674e26cSHermès Bélusca-Maïto     if (AllocatedResources)
11762674e26cSHermès Bélusca-Maïto         *AllocatedResources = NULL;
1177c2c66affSColin Finck 
1178c2c66affSColin Finck     /* Call internal helper function */
1179c2c66affSColin Finck     return IopLegacyResourceAllocation(ArbiterRequestLegacyAssigned,
1180c2c66affSColin Finck                                        DriverObject,
1181c2c66affSColin Finck                                        DeviceObject,
1182c2c66affSColin Finck                                        RequestedResources,
1183c2c66affSColin Finck                                        AllocatedResources);
1184c2c66affSColin Finck }
1185c2c66affSColin Finck 
11862674e26cSHermès Bélusca-Maïto /**
11872674e26cSHermès Bélusca-Maïto  * @brief
11882674e26cSHermès Bélusca-Maïto  * Reads and returns Hardware information from the appropriate
11892674e26cSHermès Bélusca-Maïto  * hardware registry key.
1190c2c66affSColin Finck  *
11912674e26cSHermès Bélusca-Maïto  * @param[in]   BusType
11922674e26cSHermès Bélusca-Maïto  * Specifies the bus type, for example: MCA, ISA, EISA, etc.
1193c2c66affSColin Finck  *
11942674e26cSHermès Bélusca-Maïto  * @param[in]   BusNumber
11952674e26cSHermès Bélusca-Maïto  * The number of the specified bus type to query.
1196c2c66affSColin Finck  *
11972674e26cSHermès Bélusca-Maïto  * @param[in]   ControllerType
11982674e26cSHermès Bélusca-Maïto  * Specifies the controller type
11992674e26cSHermès Bélusca-Maïto  *
12002674e26cSHermès Bélusca-Maïto  * @param[in]   ControllerNumber
12012674e26cSHermès Bélusca-Maïto  * The number of the specified controller type to query.
12022674e26cSHermès Bélusca-Maïto  *
12032674e26cSHermès Bélusca-Maïto  * @param[in]   CalloutRoutine
12042674e26cSHermès Bélusca-Maïto  * A user-provided callback function to call for each valid query.
12052674e26cSHermès Bélusca-Maïto  *
12062674e26cSHermès Bélusca-Maïto  * @param[in]   Context
12072674e26cSHermès Bélusca-Maïto  * A callback-specific context value.
12082674e26cSHermès Bélusca-Maïto  *
12092674e26cSHermès Bélusca-Maïto  * @return  A status code.
12102674e26cSHermès Bélusca-Maïto  **/
12112674e26cSHermès Bélusca-Maïto NTSTATUS
12122674e26cSHermès Bélusca-Maïto NTAPI
IoQueryDeviceDescription(_In_opt_ PINTERFACE_TYPE BusType,_In_opt_ PULONG BusNumber,_In_opt_ PCONFIGURATION_TYPE ControllerType,_In_opt_ PULONG ControllerNumber,_In_opt_ PCONFIGURATION_TYPE PeripheralType,_In_opt_ PULONG PeripheralNumber,_In_ PIO_QUERY_DEVICE_ROUTINE CalloutRoutine,_In_opt_ PVOID Context)12132674e26cSHermès Bélusca-Maïto IoQueryDeviceDescription(
12142674e26cSHermès Bélusca-Maïto     _In_opt_ PINTERFACE_TYPE BusType,
12152674e26cSHermès Bélusca-Maïto     _In_opt_ PULONG BusNumber,
12162674e26cSHermès Bélusca-Maïto     _In_opt_ PCONFIGURATION_TYPE ControllerType,
12172674e26cSHermès Bélusca-Maïto     _In_opt_ PULONG ControllerNumber,
12182674e26cSHermès Bélusca-Maïto     _In_opt_ PCONFIGURATION_TYPE PeripheralType,
12192674e26cSHermès Bélusca-Maïto     _In_opt_ PULONG PeripheralNumber,
12202674e26cSHermès Bélusca-Maïto     _In_ PIO_QUERY_DEVICE_ROUTINE CalloutRoutine,
12212674e26cSHermès Bélusca-Maïto     _In_opt_ PVOID Context)
1222c2c66affSColin Finck {
1223c2c66affSColin Finck     NTSTATUS Status;
1224c2c66affSColin Finck     ULONG BusLoopNumber = -1; /* Root Bus */
1225c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
1226c2c66affSColin Finck     UNICODE_STRING RootRegKey;
1227c2c66affSColin Finck     HANDLE RootRegHandle;
1228c2c66affSColin Finck     IO_QUERY Query;
1229c2c66affSColin Finck 
12300b695a6fSHermès Bélusca-Maïto     IORSRCTRACE("\nIoQueryDeviceDescription()\n"
12310b695a6fSHermès Bélusca-Maïto                 "    BusType:          0x%p (%lu)\n"
12320b695a6fSHermès Bélusca-Maïto                 "    BusNumber:        0x%p (%lu)\n"
12330b695a6fSHermès Bélusca-Maïto                 "    ControllerType:   0x%p (%lu)\n"
12340b695a6fSHermès Bélusca-Maïto                 "    ControllerNumber: 0x%p (%lu)\n"
12350b695a6fSHermès Bélusca-Maïto                 "    PeripheralType:   0x%p (%lu)\n"
12360b695a6fSHermès Bélusca-Maïto                 "    PeripheralNumber: 0x%p (%lu)\n"
12370b695a6fSHermès Bélusca-Maïto                 "    CalloutRoutine:   0x%p\n"
12380b695a6fSHermès Bélusca-Maïto                 "    Context:          0x%p\n"
12390b695a6fSHermès Bélusca-Maïto                 "--> Query: 0x%p\n",
12400b695a6fSHermès Bélusca-Maïto                 BusType, BusType ? *BusType : -1,
12410b695a6fSHermès Bélusca-Maïto                 BusNumber, BusNumber ? *BusNumber : -1,
12420b695a6fSHermès Bélusca-Maïto                 ControllerType, ControllerType ? *ControllerType : -1,
12430b695a6fSHermès Bélusca-Maïto                 ControllerNumber, ControllerNumber ? *ControllerNumber : -1,
12440b695a6fSHermès Bélusca-Maïto                 PeripheralType, PeripheralType ? *PeripheralType : -1,
12450b695a6fSHermès Bélusca-Maïto                 PeripheralNumber, PeripheralNumber ? *PeripheralNumber : -1,
12460b695a6fSHermès Bélusca-Maïto                 CalloutRoutine, Context,
12470b695a6fSHermès Bélusca-Maïto                 &Query);
12480b695a6fSHermès Bélusca-Maïto 
1249*84b4a80bSHermès Bélusca-Maïto     if (!BusType)
1250*84b4a80bSHermès Bélusca-Maïto         return STATUS_NOT_IMPLEMENTED;
1251*84b4a80bSHermès Bélusca-Maïto 
12522674e26cSHermès Bélusca-Maïto     /* Set up the string */
1253c2c66affSColin Finck     RootRegKey.Length = 0;
1254c2c66affSColin Finck     RootRegKey.MaximumLength = 2048;
1255c2c66affSColin Finck     RootRegKey.Buffer = ExAllocatePoolWithTag(PagedPool, RootRegKey.MaximumLength, TAG_IO_RESOURCE);
1256*84b4a80bSHermès Bélusca-Maïto     if (!RootRegKey.Buffer)
1257*84b4a80bSHermès Bélusca-Maïto         return STATUS_INSUFFICIENT_RESOURCES;
1258*84b4a80bSHermès Bélusca-Maïto 
1259c2c66affSColin Finck     RtlAppendUnicodeToString(&RootRegKey, L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
1260c2c66affSColin Finck 
1261c2c66affSColin Finck     /* Open a handle to the Root Registry Key */
12622674e26cSHermès Bélusca-Maïto     InitializeObjectAttributes(&ObjectAttributes,
1263c2c66affSColin Finck                                &RootRegKey,
1264c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
1265c2c66affSColin Finck                                NULL,
1266c2c66affSColin Finck                                NULL);
1267c2c66affSColin Finck 
1268c2c66affSColin Finck     Status = ZwOpenKey(&RootRegHandle, KEY_READ, &ObjectAttributes);
1269c2c66affSColin Finck 
1270c2c66affSColin Finck     if (NT_SUCCESS(Status))
1271c2c66affSColin Finck     {
12722674e26cSHermès Bélusca-Maïto         /* Use a helper function to loop though this key and get the information */
1273c2c66affSColin Finck         Query.BusType = BusType;
1274c2c66affSColin Finck         Query.BusNumber = BusNumber;
1275c2c66affSColin Finck         Query.ControllerType = ControllerType;
1276c2c66affSColin Finck         Query.ControllerNumber = ControllerNumber;
1277c2c66affSColin Finck         Query.PeripheralType = PeripheralType;
1278c2c66affSColin Finck         Query.PeripheralNumber = PeripheralNumber;
1279c2c66affSColin Finck         Query.CalloutRoutine = CalloutRoutine;
1280c2c66affSColin Finck         Query.Context = Context;
12812674e26cSHermès Bélusca-Maïto         Status = IopQueryBusDescription(&Query,
12822674e26cSHermès Bélusca-Maïto                                         RootRegKey,
12832674e26cSHermès Bélusca-Maïto                                         RootRegHandle,
12842674e26cSHermès Bélusca-Maïto                                         &BusLoopNumber,
12852674e26cSHermès Bélusca-Maïto                                         TRUE);
1286c2c66affSColin Finck 
12872674e26cSHermès Bélusca-Maïto         /* Close registry key */
1288c2c66affSColin Finck         ZwClose(RootRegHandle);
1289c2c66affSColin Finck     }
1290c2c66affSColin Finck 
12912674e26cSHermès Bélusca-Maïto     /* Cleanup */
1292c2c66affSColin Finck     ExFreePoolWithTag(RootRegKey.Buffer, TAG_IO_RESOURCE);
1293c2c66affSColin Finck 
1294c2c66affSColin Finck     return Status;
1295c2c66affSColin Finck }
1296c2c66affSColin Finck 
12972674e26cSHermès Bélusca-Maïto /**
12982674e26cSHermès Bélusca-Maïto  * @brief
1299c2c66affSColin Finck  * Reports hardware resources of the HAL in the
1300c2c66affSColin Finck  * \Registry\Machine\Hardware\ResourceMap tree.
13012674e26cSHermès Bélusca-Maïto  *
13022674e26cSHermès Bélusca-Maïto  * @param[in]   HalName
13032674e26cSHermès Bélusca-Maïto  * Descriptive name of the HAL.
13042674e26cSHermès Bélusca-Maïto  *
13052674e26cSHermès Bélusca-Maïto  * @param[in]   RawResourceList
13062674e26cSHermès Bélusca-Maïto  * List of raw (bus specific) resources which should be claimed
13072674e26cSHermès Bélusca-Maïto  * for the HAL.
13082674e26cSHermès Bélusca-Maïto  *
13092674e26cSHermès Bélusca-Maïto  * @param[in]   TranslatedResourceList
13102674e26cSHermès Bélusca-Maïto  * List of translated (system wide) resources which should be claimed
13112674e26cSHermès Bélusca-Maïto  * for the HAL.
13122674e26cSHermès Bélusca-Maïto  *
13132674e26cSHermès Bélusca-Maïto  * @param[in]   ResourceListSize
13142674e26cSHermès Bélusca-Maïto  * Size in bytes of the raw and translated resource lists.
1315c2c66affSColin Finck  * Both lists have the same size.
13162674e26cSHermès Bélusca-Maïto  *
13172674e26cSHermès Bélusca-Maïto  * @return  A status code.
13182674e26cSHermès Bélusca-Maïto  **/
13192674e26cSHermès Bélusca-Maïto NTSTATUS
13202674e26cSHermès Bélusca-Maïto NTAPI
IoReportHalResourceUsage(_In_ PUNICODE_STRING HalName,_In_ PCM_RESOURCE_LIST RawResourceList,_In_ PCM_RESOURCE_LIST TranslatedResourceList,_In_ ULONG ResourceListSize)13212674e26cSHermès Bélusca-Maïto IoReportHalResourceUsage(
13222674e26cSHermès Bélusca-Maïto     _In_ PUNICODE_STRING HalName,
13232674e26cSHermès Bélusca-Maïto     _In_ PCM_RESOURCE_LIST RawResourceList,
13242674e26cSHermès Bélusca-Maïto     _In_ PCM_RESOURCE_LIST TranslatedResourceList,
13252674e26cSHermès Bélusca-Maïto     _In_ ULONG ResourceListSize)
1326c2c66affSColin Finck {
13272674e26cSHermès Bélusca-Maïto     NTSTATUS Status;
1328c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
1329c2c66affSColin Finck     UNICODE_STRING Name;
1330c2c66affSColin Finck     ULONG Disposition;
13312674e26cSHermès Bélusca-Maïto     HANDLE ResourceMapKey;
1332c2c66affSColin Finck     HANDLE HalKey;
1333c2c66affSColin Finck     HANDLE DescriptionKey;
1334c2c66affSColin Finck 
13352674e26cSHermès Bélusca-Maïto     /* Open/Create 'RESOURCEMAP' key */
13362674e26cSHermès Bélusca-Maïto     RtlInitUnicodeString(&Name, L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
1337c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
1338c2c66affSColin Finck                                &Name,
1339c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
1340c2c66affSColin Finck                                0,
1341c2c66affSColin Finck                                NULL);
13422674e26cSHermès Bélusca-Maïto     Status = ZwCreateKey(&ResourceMapKey,
1343c2c66affSColin Finck                          KEY_ALL_ACCESS,
1344c2c66affSColin Finck                          &ObjectAttributes,
1345c2c66affSColin Finck                          0,
1346c2c66affSColin Finck                          NULL,
1347c2c66affSColin Finck                          REG_OPTION_VOLATILE,
1348c2c66affSColin Finck                          &Disposition);
1349c2c66affSColin Finck     if (!NT_SUCCESS(Status))
13502674e26cSHermès Bélusca-Maïto         return Status;
1351c2c66affSColin Finck 
1352c2c66affSColin Finck     /* Open/Create 'Hardware Abstraction Layer' key */
13532674e26cSHermès Bélusca-Maïto     RtlInitUnicodeString(&Name, L"Hardware Abstraction Layer");
1354c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
1355c2c66affSColin Finck                                &Name,
1356c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
13572674e26cSHermès Bélusca-Maïto                                ResourceMapKey,
1358c2c66affSColin Finck                                NULL);
1359c2c66affSColin Finck     Status = ZwCreateKey(&HalKey,
1360c2c66affSColin Finck                          KEY_ALL_ACCESS,
1361c2c66affSColin Finck                          &ObjectAttributes,
1362c2c66affSColin Finck                          0,
1363c2c66affSColin Finck                          NULL,
1364c2c66affSColin Finck                          REG_OPTION_VOLATILE,
1365c2c66affSColin Finck                          &Disposition);
13662674e26cSHermès Bélusca-Maïto     ZwClose(ResourceMapKey);
1367c2c66affSColin Finck     if (!NT_SUCCESS(Status))
13682674e26cSHermès Bélusca-Maïto         return Status;
1369c2c66affSColin Finck 
13702674e26cSHermès Bélusca-Maïto     /* Create 'HalName' key */
1371c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
13722674e26cSHermès Bélusca-Maïto                                HalName,
1373c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE,
1374c2c66affSColin Finck                                HalKey,
1375c2c66affSColin Finck                                NULL);
1376c2c66affSColin Finck     Status = ZwCreateKey(&DescriptionKey,
1377c2c66affSColin Finck                          KEY_ALL_ACCESS,
1378c2c66affSColin Finck                          &ObjectAttributes,
1379c2c66affSColin Finck                          0,
1380c2c66affSColin Finck                          NULL,
1381c2c66affSColin Finck                          REG_OPTION_VOLATILE,
1382c2c66affSColin Finck                          &Disposition);
1383c2c66affSColin Finck     ZwClose(HalKey);
1384c2c66affSColin Finck     if (!NT_SUCCESS(Status))
13852674e26cSHermès Bélusca-Maïto         return Status;
1386c2c66affSColin Finck 
13872674e26cSHermès Bélusca-Maïto     /* Add '.Raw' value */
13882674e26cSHermès Bélusca-Maïto     RtlInitUnicodeString(&Name, L".Raw");
1389c2c66affSColin Finck     Status = ZwSetValueKey(DescriptionKey,
1390c2c66affSColin Finck                            &Name,
1391c2c66affSColin Finck                            0,
1392c2c66affSColin Finck                            REG_RESOURCE_LIST,
13932674e26cSHermès Bélusca-Maïto                            RawResourceList,
13942674e26cSHermès Bélusca-Maïto                            ResourceListSize);
1395c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1396c2c66affSColin Finck     {
1397c2c66affSColin Finck         ZwClose(DescriptionKey);
13982674e26cSHermès Bélusca-Maïto         return Status;
1399c2c66affSColin Finck     }
1400c2c66affSColin Finck 
14012674e26cSHermès Bélusca-Maïto     /* Add '.Translated' value */
14022674e26cSHermès Bélusca-Maïto     RtlInitUnicodeString(&Name, L".Translated");
1403c2c66affSColin Finck     Status = ZwSetValueKey(DescriptionKey,
1404c2c66affSColin Finck                            &Name,
1405c2c66affSColin Finck                            0,
1406c2c66affSColin Finck                            REG_RESOURCE_LIST,
14072674e26cSHermès Bélusca-Maïto                            TranslatedResourceList,
14082674e26cSHermès Bélusca-Maïto                            ResourceListSize);
1409c2c66affSColin Finck     ZwClose(DescriptionKey);
1410c2c66affSColin Finck 
14112674e26cSHermès Bélusca-Maïto     return Status;
1412c2c66affSColin Finck }
1413c2c66affSColin Finck 
1414c2c66affSColin Finck /* EOF */
1415