2008-03-09 14:11:42 +00:00
|
|
|
/*
|
2023-05-27 20:48:50 +00:00
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
|
|
* PURPOSE: Hardware resource management
|
|
|
|
* COPYRIGHT: Copyright 1998 David Welch <welch@mcmail.com>
|
|
|
|
* Copyright 2001 Eric Kohl <eric.kohl@reactos.org>
|
|
|
|
* Copyright 2004-2013 Alex Ionescu <alex.ionescu@reactos.org>
|
|
|
|
* Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org>
|
|
|
|
* Copyright 2010 Pierre Schweitzer <pierre@reactos.org>
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
2023-05-28 20:44:08 +00:00
|
|
|
#define NDEBUG
|
2008-08-30 16:31:06 +00:00
|
|
|
#include <debug.h>
|
2002-09-07 15:13:13 +00:00
|
|
|
|
2023-05-28 20:44:08 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
#define IORSRCTRACE(...) DbgPrint(__VA_ARGS__)
|
|
|
|
#else
|
|
|
|
#if defined(_MSC_VER)
|
|
|
|
#define IORSRCTRACE __noop
|
|
|
|
#else
|
|
|
|
#define IORSRCTRACE(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0)
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
1998-10-05 04:01:30 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
2001-09-05 09:21:47 +00:00
|
|
|
static CONFIGURATION_INFORMATION
|
2008-12-03 17:28:59 +00:00
|
|
|
_SystemConfigurationInformation = { 0, 0, 0, 0, 0, 0, 0, FALSE, FALSE, 0, 0 };
|
1998-10-05 04:01:30 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* API parameters to pass to IopQueryBusDescription() */
|
|
|
|
typedef struct _IO_QUERY
|
|
|
|
{
|
|
|
|
PINTERFACE_TYPE BusType;
|
|
|
|
PULONG BusNumber;
|
|
|
|
PCONFIGURATION_TYPE ControllerType;
|
|
|
|
PULONG ControllerNumber;
|
|
|
|
PCONFIGURATION_TYPE PeripheralType;
|
|
|
|
PULONG PeripheralNumber;
|
|
|
|
PIO_QUERY_DEVICE_ROUTINE CalloutRoutine;
|
|
|
|
PVOID Context;
|
2004-05-30 18:30:03 +00:00
|
|
|
} IO_QUERY, *PIO_QUERY;
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Strings corresponding to CONFIGURATION_TYPE */
|
|
|
|
PCWSTR ArcTypes[MaximumType + 1] =
|
|
|
|
{
|
2004-05-30 18:30:03 +00:00
|
|
|
L"System",
|
|
|
|
L"CentralProcessor",
|
|
|
|
L"FloatingPointProcessor",
|
|
|
|
L"PrimaryICache",
|
|
|
|
L"PrimaryDCache",
|
|
|
|
L"SecondaryICache",
|
|
|
|
L"SecondaryDCache",
|
|
|
|
L"SecondaryCache",
|
|
|
|
L"EisaAdapter",
|
|
|
|
L"TcAdapter",
|
|
|
|
L"ScsiAdapter",
|
|
|
|
L"DtiAdapter",
|
|
|
|
L"MultifunctionAdapter",
|
|
|
|
L"DiskController",
|
|
|
|
L"TapeController",
|
|
|
|
L"CdRomController",
|
|
|
|
L"WormController",
|
|
|
|
L"SerialController",
|
|
|
|
L"NetworkController",
|
|
|
|
L"DisplayController",
|
|
|
|
L"ParallelController",
|
|
|
|
L"PointerController",
|
|
|
|
L"KeyboardController",
|
|
|
|
L"AudioController",
|
|
|
|
L"OtherController",
|
|
|
|
L"DiskPeripheral",
|
|
|
|
L"FloppyDiskPeripheral",
|
|
|
|
L"TapePeripheral",
|
|
|
|
L"ModemPeripheral",
|
|
|
|
L"MonitorPeripheral",
|
|
|
|
L"PrinterPeripheral",
|
|
|
|
L"PointerPeripheral",
|
|
|
|
L"KeyboardPeripheral",
|
|
|
|
L"TerminalPeripheral",
|
|
|
|
L"OtherPeripheral",
|
|
|
|
L"LinePeripheral",
|
|
|
|
L"NetworkPeripheral",
|
|
|
|
L"SystemMemory",
|
|
|
|
L"DockingInformation",
|
|
|
|
L"RealModeIrqRoutingTable",
|
|
|
|
L"RealModePCIEnumeration",
|
|
|
|
L"Undefined"
|
|
|
|
};
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Strings corresponding to IO_QUERY_DEVICE_DATA_FORMAT */
|
|
|
|
PCWSTR IoDeviceInfoNames[IoQueryDeviceMaxData] =
|
|
|
|
{
|
|
|
|
L"Identifier",
|
|
|
|
L"Configuration Data",
|
|
|
|
L"Component Information"
|
|
|
|
};
|
|
|
|
|
2004-05-30 18:30:03 +00:00
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/**
|
|
|
|
* @brief
|
|
|
|
* Reads and returns Hardware information from the appropriate hardware
|
|
|
|
* registry key. Helper stub of IopQueryBusDescription().
|
2004-05-30 18:30:03 +00:00
|
|
|
*
|
2023-05-27 20:48:50 +00:00
|
|
|
* @param[in] Query
|
|
|
|
* What the parent function wants.
|
2004-05-30 18:30:03 +00:00
|
|
|
*
|
2023-05-27 20:48:50 +00:00
|
|
|
* @param[in] RootKey
|
|
|
|
* Which key to look in.
|
2004-05-30 18:30:03 +00:00
|
|
|
*
|
2023-05-27 20:48:50 +00:00
|
|
|
* @param[in] RootKeyHandle
|
|
|
|
* Handle to the key.
|
|
|
|
*
|
|
|
|
* @param[in] Bus
|
|
|
|
* The bus number.
|
|
|
|
*
|
|
|
|
* @param[in] BusInformation
|
|
|
|
* The configuration information being sent.
|
|
|
|
*
|
|
|
|
* @return A status code.
|
|
|
|
**/
|
|
|
|
static NTSTATUS
|
2004-05-30 18:30:03 +00:00
|
|
|
IopQueryDeviceDescription(
|
2023-05-27 20:48:50 +00:00
|
|
|
_In_ PIO_QUERY Query,
|
|
|
|
_In_ UNICODE_STRING RootKey,
|
|
|
|
_In_ HANDLE RootKeyHandle,
|
|
|
|
_In_ ULONG Bus,
|
|
|
|
_In_ PKEY_VALUE_FULL_INFORMATION* BusInformation)
|
2004-05-30 18:30:03 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
/* Controller data */
|
|
|
|
UNICODE_STRING ControllerString;
|
|
|
|
UNICODE_STRING ControllerRootRegName = RootKey;
|
|
|
|
UNICODE_STRING ControllerRegName;
|
|
|
|
HANDLE ControllerKeyHandle;
|
|
|
|
PKEY_FULL_INFORMATION ControllerFullInformation = NULL;
|
|
|
|
PKEY_VALUE_FULL_INFORMATION ControllerInformation[IoQueryDeviceMaxData] =
|
|
|
|
{NULL, NULL, NULL};
|
|
|
|
ULONG ControllerNumber;
|
|
|
|
ULONG ControllerLoop;
|
|
|
|
ULONG MaximumControllerNumber;
|
|
|
|
|
|
|
|
/* Peripheral data */
|
|
|
|
UNICODE_STRING PeripheralString;
|
|
|
|
HANDLE PeripheralKeyHandle;
|
|
|
|
PKEY_FULL_INFORMATION PeripheralFullInformation;
|
|
|
|
PKEY_VALUE_FULL_INFORMATION PeripheralInformation[IoQueryDeviceMaxData] =
|
|
|
|
{NULL, NULL, NULL};
|
|
|
|
ULONG PeripheralNumber;
|
|
|
|
ULONG PeripheralLoop;
|
|
|
|
ULONG MaximumPeripheralNumber;
|
|
|
|
|
|
|
|
/* Global Registry data */
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
ULONG LenFullInformation;
|
|
|
|
ULONG LenKeyFullInformation;
|
|
|
|
UNICODE_STRING TempString;
|
|
|
|
WCHAR TempBuffer[14];
|
|
|
|
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE("\nIopQueryDeviceDescription(Query: 0x%p)\n"
|
|
|
|
" RootKey: '%wZ'\n"
|
|
|
|
" RootKeyHandle: 0x%p\n"
|
|
|
|
" Bus: %lu\n",
|
|
|
|
Query,
|
|
|
|
&RootKey, RootKeyHandle,
|
|
|
|
Bus);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Temporary string */
|
2023-05-27 20:55:40 +00:00
|
|
|
RtlInitEmptyUnicodeString(&TempString, TempBuffer, sizeof(TempBuffer));
|
2023-05-27 20:48:50 +00:00
|
|
|
|
|
|
|
/* Append controller name to string */
|
|
|
|
RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
|
|
|
|
RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->ControllerType]);
|
|
|
|
|
|
|
|
/* Set the controller number if specified */
|
2023-05-27 20:55:40 +00:00
|
|
|
if (Query->ControllerNumber)
|
2023-05-27 20:48:50 +00:00
|
|
|
{
|
2023-05-27 20:55:40 +00:00
|
|
|
ControllerNumber = *(Query->ControllerNumber);
|
2023-05-27 20:48:50 +00:00
|
|
|
MaximumControllerNumber = ControllerNumber + 1;
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" Getting controller #%lu\n", ControllerNumber);
|
2023-05-27 20:48:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" Enumerating controllers in '%wZ'...\n", &ControllerRootRegName);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Find out how many controllers there are */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&ControllerRootRegName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Retrieve the necessary buffer space */
|
|
|
|
ZwQueryKey(ControllerKeyHandle,
|
|
|
|
KeyFullInformation,
|
|
|
|
NULL, 0,
|
|
|
|
&LenFullInformation);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
/* Allocate it */
|
2023-05-27 20:48:50 +00:00
|
|
|
ControllerFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
|
2023-05-27 20:55:40 +00:00
|
|
|
if (!ControllerFullInformation)
|
|
|
|
{
|
|
|
|
ZwClose(ControllerKeyHandle);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
2023-05-27 20:48:50 +00:00
|
|
|
|
|
|
|
/* Get the information */
|
|
|
|
Status = ZwQueryKey(ControllerKeyHandle,
|
|
|
|
KeyFullInformation,
|
|
|
|
ControllerFullInformation,
|
|
|
|
LenFullInformation,
|
|
|
|
&LenFullInformation);
|
|
|
|
ZwClose(ControllerKeyHandle);
|
|
|
|
ControllerKeyHandle = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No controller was found, bail out */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2023-05-27 20:55:40 +00:00
|
|
|
if (ControllerFullInformation)
|
2023-05-27 20:48:50 +00:00
|
|
|
ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE);
|
|
|
|
return Status;
|
|
|
|
}
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Find out the controllers */
|
|
|
|
ControllerNumber = 0;
|
|
|
|
MaximumControllerNumber = ControllerFullInformation->SubKeys;
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Cleanup */
|
|
|
|
ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE);
|
|
|
|
ControllerFullInformation = NULL;
|
|
|
|
}
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Save string */
|
|
|
|
ControllerRegName = ControllerRootRegName;
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Loop through controllers */
|
|
|
|
for (; ControllerNumber < MaximumControllerNumber; ControllerNumber++)
|
|
|
|
{
|
|
|
|
/* Load string */
|
|
|
|
ControllerRootRegName = ControllerRegName;
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Convert controller number to registry string */
|
|
|
|
Status = RtlIntegerToUnicodeString(ControllerNumber, 10, &TempString);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Create string */
|
|
|
|
Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
|
|
|
|
Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Something messed up */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
break;
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" Retrieving controller '%wZ'\n", &ControllerRootRegName);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Open the registry key */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&ControllerRootRegName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Read the configuration data */
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
for (ControllerLoop = 0; ControllerLoop < RTL_NUMBER_OF(IoDeviceInfoNames); ControllerLoop++)
|
2004-05-30 18:30:03 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Identifier string first */
|
|
|
|
RtlInitUnicodeString(&ControllerString, IoDeviceInfoNames[ControllerLoop]);
|
|
|
|
|
|
|
|
/* Retrieve the necessary buffer space */
|
|
|
|
Status = ZwQueryValueKey(ControllerKeyHandle,
|
|
|
|
&ControllerString,
|
|
|
|
KeyValueFullInformation,
|
|
|
|
NULL, 0,
|
|
|
|
&LenKeyFullInformation);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status) &&
|
|
|
|
(Status != STATUS_BUFFER_TOO_SMALL) &&
|
|
|
|
(Status != STATUS_BUFFER_OVERFLOW))
|
|
|
|
{
|
2023-05-27 20:55:40 +00:00
|
|
|
ControllerInformation[ControllerLoop] = NULL;
|
2023-05-27 20:48:50 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
ControllerInformation[ControllerLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
|
2023-05-27 20:55:40 +00:00
|
|
|
if (!ControllerInformation[ControllerLoop])
|
|
|
|
{
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
break;
|
|
|
|
}
|
2023-05-27 20:48:50 +00:00
|
|
|
|
|
|
|
/* Get the information */
|
|
|
|
Status = ZwQueryValueKey(ControllerKeyHandle,
|
|
|
|
&ControllerString,
|
|
|
|
KeyValueFullInformation,
|
|
|
|
ControllerInformation[ControllerLoop],
|
|
|
|
LenKeyFullInformation,
|
|
|
|
&LenKeyFullInformation);
|
|
|
|
}
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Cleanup */
|
|
|
|
ZwClose(ControllerKeyHandle);
|
|
|
|
ControllerKeyHandle = NULL;
|
|
|
|
}
|
2004-06-20 04:50:02 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Something messed up */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
goto EndLoop;
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* We now have bus *AND* controller information, is it enough? */
|
|
|
|
if (!Query->PeripheralType || !(*Query->PeripheralType))
|
|
|
|
{
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" --> Bus #%lu Controller #%lu Callout: '%wZ'\n",
|
|
|
|
Bus, ControllerNumber, &ControllerRootRegName);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
Status = Query->CalloutRoutine(Query->Context,
|
|
|
|
&ControllerRootRegName,
|
|
|
|
*Query->BusType,
|
|
|
|
Bus,
|
|
|
|
BusInformation,
|
|
|
|
*Query->ControllerType,
|
|
|
|
ControllerNumber,
|
|
|
|
ControllerInformation,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
NULL);
|
|
|
|
goto EndLoop;
|
|
|
|
}
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Not enough: the caller also wants peripheral name */
|
|
|
|
Status = RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
|
|
|
|
Status |= RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->PeripheralType]);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Something messed up */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
goto EndLoop;
|
|
|
|
|
|
|
|
/* Set the peripheral number if specified */
|
2023-05-27 20:55:40 +00:00
|
|
|
if (Query->PeripheralNumber)
|
2023-05-27 20:48:50 +00:00
|
|
|
{
|
2023-05-27 20:55:40 +00:00
|
|
|
PeripheralNumber = *(Query->PeripheralNumber);
|
2023-05-27 20:48:50 +00:00
|
|
|
MaximumPeripheralNumber = PeripheralNumber + 1;
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" Getting peripheral #%lu\n", PeripheralNumber);
|
2023-05-27 20:48:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" Enumerating peripherals in '%wZ'...\n", &ControllerRootRegName);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Find out how many peripherals there are */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&ControllerRootRegName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Retrieve the necessary buffer space */
|
|
|
|
ZwQueryKey(PeripheralKeyHandle,
|
|
|
|
KeyFullInformation,
|
|
|
|
NULL, 0,
|
|
|
|
&LenFullInformation);
|
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
PeripheralFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
|
2023-05-27 20:55:40 +00:00
|
|
|
if (!PeripheralFullInformation)
|
|
|
|
{
|
|
|
|
ZwClose(PeripheralKeyHandle);
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
goto EndLoop;
|
|
|
|
}
|
2023-05-27 20:48:50 +00:00
|
|
|
|
|
|
|
/* Get the information */
|
|
|
|
Status = ZwQueryKey(PeripheralKeyHandle,
|
|
|
|
KeyFullInformation,
|
|
|
|
PeripheralFullInformation,
|
|
|
|
LenFullInformation,
|
|
|
|
&LenFullInformation);
|
|
|
|
ZwClose(PeripheralKeyHandle);
|
|
|
|
PeripheralKeyHandle = NULL;
|
2004-05-30 18:30:03 +00:00
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* No controller was found, cleanup and bail out */
|
|
|
|
if (!NT_SUCCESS(Status))
|
2004-05-30 18:30:03 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
goto EndLoop;
|
2004-05-30 18:30:03 +00:00
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Find out peripheral number */
|
|
|
|
PeripheralNumber = 0;
|
|
|
|
MaximumPeripheralNumber = PeripheralFullInformation->SubKeys;
|
|
|
|
|
|
|
|
/* Cleanup */
|
|
|
|
ExFreePoolWithTag(PeripheralFullInformation, TAG_IO_RESOURCE);
|
|
|
|
PeripheralFullInformation = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save name */
|
|
|
|
ControllerRegName = ControllerRootRegName;
|
|
|
|
|
|
|
|
/* Loop through peripherals */
|
|
|
|
for (; PeripheralNumber < MaximumPeripheralNumber; PeripheralNumber++)
|
|
|
|
{
|
|
|
|
/* Restore name */
|
|
|
|
ControllerRootRegName = ControllerRegName;
|
|
|
|
|
|
|
|
/* Convert peripheral number to registry string */
|
|
|
|
Status = RtlIntegerToUnicodeString(PeripheralNumber, 10, &TempString);
|
|
|
|
|
|
|
|
/* Create string */
|
|
|
|
Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
|
|
|
|
Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString);
|
|
|
|
|
|
|
|
/* Something messed up */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
break;
|
|
|
|
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" Retrieving peripheral '%wZ'\n", &ControllerRootRegName);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Open the registry key */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&ControllerRootRegName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
for (PeripheralLoop = 0; PeripheralLoop < RTL_NUMBER_OF(IoDeviceInfoNames); PeripheralLoop++)
|
|
|
|
{
|
|
|
|
/* Identifier string first */
|
|
|
|
RtlInitUnicodeString(&PeripheralString, IoDeviceInfoNames[PeripheralLoop]);
|
|
|
|
|
|
|
|
/* Retrieve the necessary buffer space */
|
|
|
|
Status = ZwQueryValueKey(PeripheralKeyHandle,
|
|
|
|
&PeripheralString,
|
|
|
|
KeyValueFullInformation,
|
|
|
|
NULL, 0,
|
|
|
|
&LenKeyFullInformation);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status) &&
|
|
|
|
(Status != STATUS_BUFFER_TOO_SMALL) &&
|
|
|
|
(Status != STATUS_BUFFER_OVERFLOW))
|
|
|
|
{
|
|
|
|
PeripheralInformation[PeripheralLoop] = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
PeripheralInformation[PeripheralLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
|
2023-05-27 20:55:40 +00:00
|
|
|
if (!PeripheralInformation[PeripheralLoop])
|
|
|
|
{
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
break;
|
|
|
|
}
|
2023-05-27 20:48:50 +00:00
|
|
|
|
|
|
|
/* Get the information */
|
|
|
|
Status = ZwQueryValueKey(PeripheralKeyHandle,
|
|
|
|
&PeripheralString,
|
|
|
|
KeyValueFullInformation,
|
|
|
|
PeripheralInformation[PeripheralLoop],
|
|
|
|
LenKeyFullInformation,
|
|
|
|
&LenKeyFullInformation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cleanup */
|
|
|
|
ZwClose(PeripheralKeyHandle);
|
|
|
|
PeripheralKeyHandle = NULL;
|
|
|
|
|
|
|
|
/* We now have everything the caller could possibly want */
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" --> Bus #%lu Controller #%lu Peripheral #%lu Callout: '%wZ'\n",
|
|
|
|
Bus, ControllerNumber, PeripheralNumber, &ControllerRootRegName);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
Status = Query->CalloutRoutine(Query->Context,
|
|
|
|
&ControllerRootRegName,
|
|
|
|
*Query->BusType,
|
|
|
|
Bus,
|
|
|
|
BusInformation,
|
|
|
|
*Query->ControllerType,
|
|
|
|
ControllerNumber,
|
|
|
|
ControllerInformation,
|
|
|
|
*Query->PeripheralType,
|
|
|
|
PeripheralNumber,
|
|
|
|
PeripheralInformation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the allocated memory */
|
|
|
|
for (PeripheralLoop = 0; PeripheralLoop < RTL_NUMBER_OF(IoDeviceInfoNames); PeripheralLoop++)
|
|
|
|
{
|
|
|
|
if (PeripheralInformation[PeripheralLoop])
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(PeripheralInformation[PeripheralLoop], TAG_IO_RESOURCE);
|
|
|
|
PeripheralInformation[PeripheralLoop] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Something messed up */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
EndLoop:
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Free the allocated memory */
|
|
|
|
for (ControllerLoop = 0; ControllerLoop < RTL_NUMBER_OF(IoDeviceInfoNames); ControllerLoop++)
|
|
|
|
{
|
|
|
|
if (ControllerInformation[ControllerLoop])
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(ControllerInformation[ControllerLoop], TAG_IO_RESOURCE);
|
|
|
|
ControllerInformation[ControllerLoop] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Something messed up */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
2004-05-30 18:30:03 +00:00
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/**
|
|
|
|
* @brief
|
|
|
|
* Reads and returns Hardware information from the appropriate hardware
|
|
|
|
* registry key. Helper stub of IoQueryDeviceDescription(). Has two modes
|
|
|
|
* of operation, either looking for root bus types or for sub-bus
|
|
|
|
* information.
|
2004-05-30 18:30:03 +00:00
|
|
|
*
|
2023-05-27 20:48:50 +00:00
|
|
|
* @param[in] Query
|
|
|
|
* What the parent function wants.
|
2004-05-30 18:30:03 +00:00
|
|
|
*
|
2023-05-27 20:48:50 +00:00
|
|
|
* @param[in] RootKey
|
|
|
|
* Which key to look in.
|
2004-05-30 18:30:03 +00:00
|
|
|
*
|
2023-05-27 20:48:50 +00:00
|
|
|
* @param[in] RootKeyHandle
|
|
|
|
* Handle to the key.
|
|
|
|
*
|
|
|
|
* @param[in,out] Bus
|
|
|
|
* Pointer to the current bus number.
|
|
|
|
*
|
|
|
|
* @param[in] KeyIsRoot
|
|
|
|
* Whether we are looking for root bus types or information under them.
|
|
|
|
*
|
|
|
|
* @return A status code.
|
|
|
|
**/
|
|
|
|
static NTSTATUS
|
2004-05-30 18:30:03 +00:00
|
|
|
IopQueryBusDescription(
|
2023-05-27 20:48:50 +00:00
|
|
|
_In_ PIO_QUERY Query,
|
|
|
|
_In_ UNICODE_STRING RootKey,
|
|
|
|
_In_ HANDLE RootKeyHandle,
|
|
|
|
_Inout_ PULONG Bus,
|
|
|
|
_In_ BOOLEAN KeyIsRoot)
|
2004-05-30 18:30:03 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG BusLoop;
|
|
|
|
UNICODE_STRING SubRootRegName;
|
|
|
|
UNICODE_STRING BusString;
|
|
|
|
UNICODE_STRING SubBusString;
|
|
|
|
ULONG LenBasicInformation = 0;
|
|
|
|
ULONG LenFullInformation;
|
|
|
|
ULONG LenKeyFullInformation;
|
|
|
|
ULONG LenKey;
|
|
|
|
HANDLE SubRootKeyHandle;
|
|
|
|
PKEY_FULL_INFORMATION FullInformation;
|
|
|
|
PKEY_BASIC_INFORMATION BasicInformation = NULL;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
PKEY_VALUE_FULL_INFORMATION BusInformation[IoQueryDeviceMaxData] =
|
|
|
|
{NULL, NULL, NULL};
|
|
|
|
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE("\nIopQueryBusDescription(Query: 0x%p)\n"
|
|
|
|
" RootKey: '%wZ'\n"
|
|
|
|
" RootKeyHandle: 0x%p\n"
|
|
|
|
" KeyIsRoot: %s\n"
|
|
|
|
" Bus: 0x%p (%lu)\n",
|
|
|
|
Query,
|
|
|
|
&RootKey, RootKeyHandle,
|
|
|
|
KeyIsRoot ? "TRUE" : "FALSE",
|
|
|
|
Bus, Bus ? *Bus : -1);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Retrieve the necessary buffer space */
|
|
|
|
Status = ZwQueryKey(RootKeyHandle,
|
|
|
|
KeyFullInformation,
|
|
|
|
NULL, 0,
|
|
|
|
&LenFullInformation);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status) &&
|
|
|
|
(Status != STATUS_BUFFER_TOO_SMALL) &&
|
|
|
|
(Status != STATUS_BUFFER_OVERFLOW))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
FullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
|
|
|
|
if (!FullInformation)
|
2023-05-27 20:55:40 +00:00
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
2023-05-27 20:48:50 +00:00
|
|
|
|
|
|
|
/* Get the information */
|
|
|
|
Status = ZwQueryKey(RootKeyHandle,
|
|
|
|
KeyFullInformation,
|
|
|
|
FullInformation,
|
|
|
|
LenFullInformation,
|
|
|
|
&LenFullInformation);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Buffer needed for all the keys under this one */
|
|
|
|
LenBasicInformation = FullInformation->MaxNameLen + sizeof(KEY_BASIC_INFORMATION);
|
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
BasicInformation = ExAllocatePoolWithTag(PagedPool, LenBasicInformation, TAG_IO_RESOURCE);
|
2023-05-27 20:55:40 +00:00
|
|
|
if (!BasicInformation)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(FullInformation, TAG_IO_RESOURCE);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
2023-05-27 20:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Deallocate the old buffer */
|
|
|
|
ExFreePoolWithTag(FullInformation, TAG_IO_RESOURCE);
|
|
|
|
|
|
|
|
/* Try to find a bus */
|
|
|
|
for (BusLoop = 0; NT_SUCCESS(Status); BusLoop++)
|
|
|
|
{
|
|
|
|
/* Bus parameter was passed and number was matched */
|
|
|
|
if (Query->BusNumber && (*(Query->BusNumber) == *Bus))
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Enumerate the Key */
|
|
|
|
Status = ZwEnumerateKey(RootKeyHandle,
|
|
|
|
BusLoop,
|
|
|
|
KeyBasicInformation,
|
|
|
|
BasicInformation,
|
|
|
|
LenBasicInformation,
|
|
|
|
&LenKey);
|
|
|
|
|
|
|
|
/* Stop if everything was enumerated */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
break;
|
|
|
|
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" Seen: '%.*ws'\n", BasicInformation->NameLength/sizeof(WCHAR), BasicInformation->Name);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* What bus are we going to go down? (only check if this is a root key) */
|
|
|
|
if (KeyIsRoot)
|
|
|
|
{
|
|
|
|
if (wcsncmp(BasicInformation->Name, L"MultifunctionAdapter", BasicInformation->NameLength / sizeof(WCHAR)) &&
|
|
|
|
wcsncmp(BasicInformation->Name, L"EisaAdapter", BasicInformation->NameLength / sizeof(WCHAR)) &&
|
|
|
|
wcsncmp(BasicInformation->Name, L"TcAdapter", BasicInformation->NameLength / sizeof(WCHAR)))
|
|
|
|
{
|
|
|
|
/* Nothing found, check next */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Enumerate the bus */
|
|
|
|
BusString.Buffer = BasicInformation->Name;
|
|
|
|
BusString.Length = (USHORT)BasicInformation->NameLength;
|
|
|
|
BusString.MaximumLength = (USHORT)BasicInformation->NameLength;
|
|
|
|
|
|
|
|
/* Open a handle to the root registry key */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&BusString,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
RootKeyHandle,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = ZwOpenKey(&SubRootKeyHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
|
|
|
|
/* Go on if we failed */
|
|
|
|
if (!NT_SUCCESS(Status))
|
2004-05-30 18:30:03 +00:00
|
|
|
continue;
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Key opened, create the path */
|
|
|
|
SubRootRegName = RootKey;
|
|
|
|
RtlAppendUnicodeToString(&SubRootRegName, L"\\");
|
|
|
|
RtlAppendUnicodeStringToString(&SubRootRegName, &BusString);
|
|
|
|
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" SubRootRegName: '%wZ'\n", &SubRootRegName);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
if (!KeyIsRoot)
|
|
|
|
{
|
|
|
|
/* Parsing a sub-bus key */
|
|
|
|
ULONG SubBusLoop;
|
|
|
|
for (SubBusLoop = 0; SubBusLoop < RTL_NUMBER_OF(IoDeviceInfoNames); SubBusLoop++)
|
2004-05-30 18:30:03 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Identifier string first */
|
|
|
|
RtlInitUnicodeString(&SubBusString, IoDeviceInfoNames[SubBusLoop]);
|
|
|
|
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" Getting bus value: '%wZ'\n", &SubBusString);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Retrieve the necessary buffer space */
|
|
|
|
ZwQueryValueKey(SubRootKeyHandle,
|
|
|
|
&SubBusString,
|
|
|
|
KeyValueFullInformation,
|
|
|
|
NULL, 0,
|
|
|
|
&LenKeyFullInformation);
|
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
BusInformation[SubBusLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
|
2023-05-27 20:55:40 +00:00
|
|
|
if (!BusInformation[SubBusLoop])
|
|
|
|
{
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
break;
|
|
|
|
}
|
2023-05-27 20:48:50 +00:00
|
|
|
|
|
|
|
/* Get the information */
|
|
|
|
Status = ZwQueryValueKey(SubRootKeyHandle,
|
|
|
|
&SubBusString,
|
|
|
|
KeyValueFullInformation,
|
|
|
|
BusInformation[SubBusLoop],
|
|
|
|
LenKeyFullInformation,
|
|
|
|
&LenKeyFullInformation);
|
2004-05-30 18:30:03 +00:00
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
2004-05-30 18:30:03 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
PKEY_VALUE_FULL_INFORMATION BusConfigData =
|
|
|
|
BusInformation[IoQueryDeviceConfigurationData];
|
|
|
|
|
|
|
|
/* Do we have something? */
|
|
|
|
if (BusConfigData != NULL &&
|
|
|
|
BusConfigData->DataLength != 0 &&
|
|
|
|
/* Does it match what we want? */
|
|
|
|
(((PCM_FULL_RESOURCE_DESCRIPTOR)((ULONG_PTR)BusConfigData +
|
|
|
|
BusConfigData->DataOffset))->InterfaceType == *(Query->BusType)))
|
|
|
|
{
|
|
|
|
/* Found a bus */
|
|
|
|
(*Bus)++;
|
|
|
|
|
|
|
|
/* Is it the bus we wanted? */
|
|
|
|
if (Query->BusNumber == NULL || *(Query->BusNumber) == *Bus)
|
|
|
|
{
|
|
|
|
if (Query->ControllerType == NULL)
|
|
|
|
{
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" --> Bus #%lu Callout: '%wZ'\n", *Bus, &SubRootRegName);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* We don't want controller information: call the callback */
|
|
|
|
Status = Query->CalloutRoutine(Query->Context,
|
|
|
|
&SubRootRegName,
|
|
|
|
*(Query->BusType),
|
|
|
|
*Bus,
|
|
|
|
BusInformation,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE(" --> Getting device on Bus #%lu : '%wZ'\n", *Bus, &SubRootRegName);
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* We want controller information: get it */
|
|
|
|
Status = IopQueryDeviceDescription(Query,
|
|
|
|
SubRootRegName,
|
|
|
|
RootKeyHandle,
|
|
|
|
*Bus,
|
|
|
|
(PKEY_VALUE_FULL_INFORMATION*)BusInformation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-05-30 18:30:03 +00:00
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Free the allocated memory */
|
|
|
|
for (SubBusLoop = 0; SubBusLoop < RTL_NUMBER_OF(IoDeviceInfoNames); SubBusLoop++)
|
|
|
|
{
|
|
|
|
if (BusInformation[SubBusLoop])
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(BusInformation[SubBusLoop], TAG_IO_RESOURCE);
|
|
|
|
BusInformation[SubBusLoop] = NULL;
|
|
|
|
}
|
|
|
|
}
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Exit the loop if we found the bus */
|
|
|
|
if (Query->BusNumber && (*(Query->BusNumber) == *Bus))
|
|
|
|
{
|
|
|
|
ZwClose(SubRootKeyHandle);
|
|
|
|
SubRootKeyHandle = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Enumerate the buses below us recursively if we haven't found the bus yet */
|
|
|
|
Status = IopQueryBusDescription(Query, SubRootRegName, SubRootKeyHandle, Bus, !KeyIsRoot);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Everything enumerated */
|
2023-05-27 20:55:40 +00:00
|
|
|
if (Status == STATUS_NO_MORE_ENTRIES)
|
|
|
|
Status = STATUS_SUCCESS;
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
ZwClose(SubRootKeyHandle);
|
|
|
|
SubRootKeyHandle = NULL;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Free the last remaining allocated memory */
|
|
|
|
if (BasicInformation)
|
|
|
|
ExFreePoolWithTag(BasicInformation, TAG_IO_RESOURCE);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
return Status;
|
2004-05-30 18:30:03 +00:00
|
|
|
}
|
|
|
|
|
[NTOSKRNL]
Implemented IopFetchConfigurationInformation(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopVerifyDiskSignature()
Removed IopApplyRosCdromArcHack(), IopGetDiskInformation(), IopAssignArcNamesToCdrom()
Finally, rewritten IopCreateArcNames()
To make it short, this is the rewrite of ARC names handling in the kernel.
This brings our kernel to a higher state of existence. Indeed, it's leaving NT4 design for a proper NT5.2 design, with less hacks, less ROS specific stuff and such.
This code handles the mount manager we don't have yet.
svn path=/trunk/; revision=49131
2010-10-12 20:29:50 +00:00
|
|
|
NTSTATUS
|
2023-05-27 20:48:50 +00:00
|
|
|
IopFetchConfigurationInformation(
|
|
|
|
_Out_ PWSTR* SymbolicLinkList,
|
|
|
|
_In_ GUID Guid,
|
|
|
|
_In_ ULONG ExpectedInterfaces,
|
|
|
|
_Out_ PULONG Interfaces)
|
[NTOSKRNL]
Implemented IopFetchConfigurationInformation(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopVerifyDiskSignature()
Removed IopApplyRosCdromArcHack(), IopGetDiskInformation(), IopAssignArcNamesToCdrom()
Finally, rewritten IopCreateArcNames()
To make it short, this is the rewrite of ARC names handling in the kernel.
This brings our kernel to a higher state of existence. Indeed, it's leaving NT4 design for a proper NT5.2 design, with less hacks, less ROS specific stuff and such.
This code handles the mount manager we don't have yet.
svn path=/trunk/; revision=49131
2010-10-12 20:29:50 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
2023-05-27 20:48:50 +00:00
|
|
|
ULONG interfaces = 0;
|
|
|
|
PWSTR symbolicLinkList;
|
[NTOSKRNL]
Implemented IopFetchConfigurationInformation(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopVerifyDiskSignature()
Removed IopApplyRosCdromArcHack(), IopGetDiskInformation(), IopAssignArcNamesToCdrom()
Finally, rewritten IopCreateArcNames()
To make it short, this is the rewrite of ARC names handling in the kernel.
This brings our kernel to a higher state of existence. Indeed, it's leaving NT4 design for a proper NT5.2 design, with less hacks, less ROS specific stuff and such.
This code handles the mount manager we don't have yet.
svn path=/trunk/; revision=49131
2010-10-12 20:29:50 +00:00
|
|
|
|
|
|
|
/* Get the associated enabled interfaces with the given GUID */
|
|
|
|
Status = IoGetDeviceInterfaces(&Guid, NULL, 0, SymbolicLinkList);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Zero output and leave */
|
2023-05-27 20:48:50 +00:00
|
|
|
if (SymbolicLinkList)
|
|
|
|
*SymbolicLinkList = NULL;
|
[NTOSKRNL]
Implemented IopFetchConfigurationInformation(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopVerifyDiskSignature()
Removed IopApplyRosCdromArcHack(), IopGetDiskInformation(), IopAssignArcNamesToCdrom()
Finally, rewritten IopCreateArcNames()
To make it short, this is the rewrite of ARC names handling in the kernel.
This brings our kernel to a higher state of existence. Indeed, it's leaving NT4 design for a proper NT5.2 design, with less hacks, less ROS specific stuff and such.
This code handles the mount manager we don't have yet.
svn path=/trunk/; revision=49131
2010-10-12 20:29:50 +00:00
|
|
|
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
symbolicLinkList = *SymbolicLinkList;
|
[NTOSKRNL]
Implemented IopFetchConfigurationInformation(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopVerifyDiskSignature()
Removed IopApplyRosCdromArcHack(), IopGetDiskInformation(), IopAssignArcNamesToCdrom()
Finally, rewritten IopCreateArcNames()
To make it short, this is the rewrite of ARC names handling in the kernel.
This brings our kernel to a higher state of existence. Indeed, it's leaving NT4 design for a proper NT5.2 design, with less hacks, less ROS specific stuff and such.
This code handles the mount manager we don't have yet.
svn path=/trunk/; revision=49131
2010-10-12 20:29:50 +00:00
|
|
|
|
|
|
|
/* Count the number of enabled interfaces by counting the number of symbolic links */
|
2023-05-27 20:48:50 +00:00
|
|
|
while (*symbolicLinkList != UNICODE_NULL)
|
[NTOSKRNL]
Implemented IopFetchConfigurationInformation(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopVerifyDiskSignature()
Removed IopApplyRosCdromArcHack(), IopGetDiskInformation(), IopAssignArcNamesToCdrom()
Finally, rewritten IopCreateArcNames()
To make it short, this is the rewrite of ARC names handling in the kernel.
This brings our kernel to a higher state of existence. Indeed, it's leaving NT4 design for a proper NT5.2 design, with less hacks, less ROS specific stuff and such.
This code handles the mount manager we don't have yet.
svn path=/trunk/; revision=49131
2010-10-12 20:29:50 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
interfaces++;
|
|
|
|
symbolicLinkList += (wcslen(symbolicLinkList) + 1);
|
[NTOSKRNL]
Implemented IopFetchConfigurationInformation(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopVerifyDiskSignature()
Removed IopApplyRosCdromArcHack(), IopGetDiskInformation(), IopAssignArcNamesToCdrom()
Finally, rewritten IopCreateArcNames()
To make it short, this is the rewrite of ARC names handling in the kernel.
This brings our kernel to a higher state of existence. Indeed, it's leaving NT4 design for a proper NT5.2 design, with less hacks, less ROS specific stuff and such.
This code handles the mount manager we don't have yet.
svn path=/trunk/; revision=49131
2010-10-12 20:29:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Matching result will define the result */
|
2023-05-27 20:48:50 +00:00
|
|
|
Status = (interfaces >= ExpectedInterfaces) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
[NTOSKRNL]
Implemented IopFetchConfigurationInformation(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopVerifyDiskSignature()
Removed IopApplyRosCdromArcHack(), IopGetDiskInformation(), IopAssignArcNamesToCdrom()
Finally, rewritten IopCreateArcNames()
To make it short, this is the rewrite of ARC names handling in the kernel.
This brings our kernel to a higher state of existence. Indeed, it's leaving NT4 design for a proper NT5.2 design, with less hacks, less ROS specific stuff and such.
This code handles the mount manager we don't have yet.
svn path=/trunk/; revision=49131
2010-10-12 20:29:50 +00:00
|
|
|
/* Finally, give back to the caller the number of found interfaces */
|
2023-05-27 20:48:50 +00:00
|
|
|
*Interfaces = interfaces;
|
[NTOSKRNL]
Implemented IopFetchConfigurationInformation(), IopCreateArcNamesCd(), IopCreateArcNamesDisk(), IopVerifyDiskSignature()
Removed IopApplyRosCdromArcHack(), IopGetDiskInformation(), IopAssignArcNamesToCdrom()
Finally, rewritten IopCreateArcNames()
To make it short, this is the rewrite of ARC names handling in the kernel.
This brings our kernel to a higher state of existence. Indeed, it's leaving NT4 design for a proper NT5.2 design, with less hacks, less ROS specific stuff and such.
This code handles the mount manager we don't have yet.
svn path=/trunk/; revision=49131
2010-10-12 20:29:50 +00:00
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2010-10-07 20:08:24 +00:00
|
|
|
VOID
|
2023-05-27 20:48:50 +00:00
|
|
|
IopStoreSystemPartitionInformation(
|
|
|
|
_In_ PUNICODE_STRING NtSystemPartitionDeviceName,
|
|
|
|
_In_ PUNICODE_STRING OsLoaderPathName)
|
2010-10-07 20:08:24 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
UNICODE_STRING LinkTarget, KeyName;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
HANDLE LinkHandle, RegistryHandle, KeyHandle;
|
[NTOSKRNL]
Coverity code defects fixes :
- Cache: CID 701441
- Config: CIDs 716570, 716669, 716760
- Dbgk: Kdbg: CIDs 716571, 515128/9, 500432
- Ex: CIDs 500156/7, 515122, 716200/67, 701301, 514669
- Fsrtl: Fstub: CIDs 701341/2, 701288, 716770, 701302, and CIDs 716576/7/8 + 514636 + 716805 thanks to Thomas Faber
- Io: CIDs 514576, 514643, 514672/3, 716203, 716269, 716581, 716591, 716713
- Ke: CIDs 515125, 716592
- Ps: CIDs 716603/4, 701422
- Ob: Po: CIDs 514671/680, 701419/420/421, 716763, 716601/2
All the details are given in the different bug reports.
CORE-6677 CORE-6679 CORE-6680 CORE-6683 CORE-6686 CORE-6692 CORE-6693 CORE-6694 CORE-6695 CORE-6696 #comment Committed in rev.57400 #resolve #close
svn path=/trunk/; revision=57400
2012-09-27 17:16:31 +00:00
|
|
|
WCHAR LinkTargetBuffer[256];
|
2010-10-07 20:08:24 +00:00
|
|
|
UNICODE_STRING CmRegistryMachineSystemName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM");
|
|
|
|
|
|
|
|
ASSERT(NtSystemPartitionDeviceName->MaximumLength >= NtSystemPartitionDeviceName->Length + sizeof(WCHAR));
|
|
|
|
ASSERT(NtSystemPartitionDeviceName->Buffer[NtSystemPartitionDeviceName->Length / sizeof(WCHAR)] == UNICODE_NULL);
|
|
|
|
ASSERT(OsLoaderPathName->MaximumLength >= OsLoaderPathName->Length + sizeof(WCHAR));
|
|
|
|
ASSERT(OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] == UNICODE_NULL);
|
|
|
|
|
|
|
|
/* First define needed stuff to open NtSystemPartitionDeviceName symbolic link */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
NtSystemPartitionDeviceName,
|
|
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Open NtSystemPartitionDeviceName symbolic link */
|
|
|
|
Status = ZwOpenSymbolicLinkObject(&LinkHandle,
|
|
|
|
SYMBOLIC_LINK_QUERY,
|
|
|
|
&ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2014-03-30 09:35:50 +00:00
|
|
|
DPRINT("Failed to open symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName, Status);
|
2010-10-07 20:08:24 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-27 20:55:40 +00:00
|
|
|
/* Prepare the string that will receive where symbolic link points to.
|
|
|
|
* We will zero the end of the string after having received it */
|
|
|
|
RtlInitEmptyUnicodeString(&LinkTarget, LinkTargetBuffer,
|
|
|
|
sizeof(LinkTargetBuffer) - sizeof(UNICODE_NULL));
|
2010-10-07 20:08:24 +00:00
|
|
|
|
|
|
|
/* Query target */
|
2023-05-27 20:48:50 +00:00
|
|
|
Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL);
|
2010-10-07 20:08:24 +00:00
|
|
|
|
|
|
|
/* We are done with symbolic link */
|
|
|
|
ObCloseHandle(LinkHandle, KernelMode);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2014-03-30 09:35:50 +00:00
|
|
|
DPRINT("Failed querying symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName, Status);
|
2010-10-07 20:08:24 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* As promised, we zero the end */
|
|
|
|
LinkTarget.Buffer[LinkTarget.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
|
|
|
|
/* Open registry to save data (HKLM\SYSTEM) */
|
|
|
|
Status = IopOpenRegistryKeyEx(&RegistryHandle,
|
|
|
|
NULL,
|
|
|
|
&CmRegistryMachineSystemName,
|
|
|
|
KEY_ALL_ACCESS);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2014-03-30 09:44:02 +00:00
|
|
|
DPRINT("Failed to open HKLM\\SYSTEM, Status=%lx\n", Status);
|
2010-10-07 20:08:24 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
[NTOSKRNL]
Coverity code defects fixes :
- Cache: CID 701441
- Config: CIDs 716570, 716669, 716760
- Dbgk: Kdbg: CIDs 716571, 515128/9, 500432
- Ex: CIDs 500156/7, 515122, 716200/67, 701301, 514669
- Fsrtl: Fstub: CIDs 701341/2, 701288, 716770, 701302, and CIDs 716576/7/8 + 514636 + 716805 thanks to Thomas Faber
- Io: CIDs 514576, 514643, 514672/3, 716203, 716269, 716581, 716591, 716713
- Ke: CIDs 515125, 716592
- Ps: CIDs 716603/4, 701422
- Ob: Po: CIDs 514671/680, 701419/420/421, 716763, 716601/2
All the details are given in the different bug reports.
CORE-6677 CORE-6679 CORE-6680 CORE-6683 CORE-6686 CORE-6692 CORE-6693 CORE-6694 CORE-6695 CORE-6696 #comment Committed in rev.57400 #resolve #close
svn path=/trunk/; revision=57400
2012-09-27 17:16:31 +00:00
|
|
|
/* Open or create the Setup subkey where we'll store in */
|
|
|
|
RtlInitUnicodeString(&KeyName, L"Setup");
|
2010-10-07 20:08:24 +00:00
|
|
|
|
|
|
|
Status = IopCreateRegistryKeyEx(&KeyHandle,
|
|
|
|
RegistryHandle,
|
|
|
|
&KeyName,
|
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
REG_OPTION_NON_VOLATILE,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* We're done with HKLM\SYSTEM */
|
|
|
|
ObCloseHandle(RegistryHandle, KernelMode);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2014-03-30 09:35:50 +00:00
|
|
|
DPRINT("Failed opening/creating Setup key, Status=%lx\n", Status);
|
2010-10-07 20:08:24 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Prepare first data writing */
|
[NTOSKRNL]
Coverity code defects fixes :
- Cache: CID 701441
- Config: CIDs 716570, 716669, 716760
- Dbgk: Kdbg: CIDs 716571, 515128/9, 500432
- Ex: CIDs 500156/7, 515122, 716200/67, 701301, 514669
- Fsrtl: Fstub: CIDs 701341/2, 701288, 716770, 701302, and CIDs 716576/7/8 + 514636 + 716805 thanks to Thomas Faber
- Io: CIDs 514576, 514643, 514672/3, 716203, 716269, 716581, 716591, 716713
- Ke: CIDs 515125, 716592
- Ps: CIDs 716603/4, 701422
- Ob: Po: CIDs 514671/680, 701419/420/421, 716763, 716601/2
All the details are given in the different bug reports.
CORE-6677 CORE-6679 CORE-6680 CORE-6683 CORE-6686 CORE-6692 CORE-6693 CORE-6694 CORE-6695 CORE-6696 #comment Committed in rev.57400 #resolve #close
svn path=/trunk/; revision=57400
2012-09-27 17:16:31 +00:00
|
|
|
RtlInitUnicodeString(&KeyName, L"SystemPartition");
|
2010-10-07 20:08:24 +00:00
|
|
|
|
|
|
|
/* Write SystemPartition value which is the target of the symbolic link */
|
|
|
|
Status = ZwSetValueKey(KeyHandle,
|
|
|
|
&KeyName,
|
|
|
|
0,
|
|
|
|
REG_SZ,
|
|
|
|
LinkTarget.Buffer,
|
|
|
|
LinkTarget.Length + sizeof(WCHAR));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2014-03-30 09:35:50 +00:00
|
|
|
DPRINT("Failed writing SystemPartition value, Status=%lx\n", Status);
|
2010-10-07 20:08:24 +00:00
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Prepare for second data writing */
|
[NTOSKRNL]
Coverity code defects fixes :
- Cache: CID 701441
- Config: CIDs 716570, 716669, 716760
- Dbgk: Kdbg: CIDs 716571, 515128/9, 500432
- Ex: CIDs 500156/7, 515122, 716200/67, 701301, 514669
- Fsrtl: Fstub: CIDs 701341/2, 701288, 716770, 701302, and CIDs 716576/7/8 + 514636 + 716805 thanks to Thomas Faber
- Io: CIDs 514576, 514643, 514672/3, 716203, 716269, 716581, 716591, 716713
- Ke: CIDs 515125, 716592
- Ps: CIDs 716603/4, 701422
- Ob: Po: CIDs 514671/680, 701419/420/421, 716763, 716601/2
All the details are given in the different bug reports.
CORE-6677 CORE-6679 CORE-6680 CORE-6683 CORE-6686 CORE-6692 CORE-6693 CORE-6694 CORE-6695 CORE-6696 #comment Committed in rev.57400 #resolve #close
svn path=/trunk/; revision=57400
2012-09-27 17:16:31 +00:00
|
|
|
RtlInitUnicodeString(&KeyName, L"OsLoaderPath");
|
2010-10-07 20:08:24 +00:00
|
|
|
|
|
|
|
/* Remove trailing slash if any (one slash only excepted) */
|
|
|
|
if (OsLoaderPathName->Length > sizeof(WCHAR) &&
|
|
|
|
OsLoaderPathName->Buffer[(OsLoaderPathName->Length / sizeof(WCHAR)) - 1] == OBJ_NAME_PATH_SEPARATOR)
|
|
|
|
{
|
|
|
|
OsLoaderPathName->Length -= sizeof(WCHAR);
|
|
|
|
OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Then, write down data */
|
|
|
|
Status = ZwSetValueKey(KeyHandle,
|
|
|
|
&KeyName,
|
|
|
|
0,
|
|
|
|
REG_SZ,
|
|
|
|
OsLoaderPathName->Buffer,
|
2014-03-30 09:35:50 +00:00
|
|
|
OsLoaderPathName->Length + sizeof(UNICODE_NULL));
|
2010-10-07 20:08:24 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2014-03-30 09:35:50 +00:00
|
|
|
DPRINT("Failed writing OsLoaderPath value, Status=%lx\n", Status);
|
2010-10-07 20:08:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* We're finally done! */
|
|
|
|
ObCloseHandle(KeyHandle, KernelMode);
|
|
|
|
}
|
|
|
|
|
2004-05-30 18:30:03 +00:00
|
|
|
/* PUBLIC FUNCTIONS ***********************************************************/
|
1998-08-25 04:27:26 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/**
|
|
|
|
* @brief
|
|
|
|
* Returns a pointer to the I/O manager's global configuration
|
|
|
|
* information structure.
|
|
|
|
*
|
|
|
|
* This structure contains the current values for how many physical storage
|
|
|
|
* media, SCSI HBA, serial, and parallel devices have device objects created
|
|
|
|
* to represent them by drivers as they are loaded.
|
|
|
|
**/
|
|
|
|
PCONFIGURATION_INFORMATION
|
|
|
|
NTAPI
|
2000-03-26 19:38:32 +00:00
|
|
|
IoGetConfigurationInformation(VOID)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
return &_SystemConfigurationInformation;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/**
|
2010-10-24 02:51:48 +00:00
|
|
|
* @halfplemented
|
2023-05-27 20:48:50 +00:00
|
|
|
*
|
|
|
|
* @brief
|
|
|
|
* Reports hardware resources in the \Registry\Machine\Hardware\ResourceMap
|
|
|
|
* tree, so that a subsequently loaded driver cannot attempt to use the
|
|
|
|
* same resources.
|
|
|
|
*
|
|
|
|
* @param[in] DriverClassName
|
|
|
|
* The driver class under which the resource information should be stored.
|
|
|
|
*
|
|
|
|
* @param[in] DriverObject
|
|
|
|
* The driver object that was provided to the DriverEntry routine.
|
|
|
|
*
|
|
|
|
* @param[in] DriverList
|
|
|
|
* Resources claimed for the all the driver's devices, rather than per-device.
|
|
|
|
*
|
|
|
|
* @param[in] DriverListSize
|
|
|
|
* Size in bytes of the DriverList.
|
|
|
|
*
|
|
|
|
* @param[in] DeviceObject
|
|
|
|
* The device object for which resources should be claimed.
|
|
|
|
*
|
|
|
|
* @param[in] DeviceList
|
|
|
|
* List of resources that should be claimed for the device.
|
|
|
|
*
|
|
|
|
* @param[in] DeviceListSize
|
|
|
|
* Size of the per-device resource list in bytes.
|
|
|
|
*
|
|
|
|
* @param[in] OverrideConflict
|
|
|
|
* TRUE if the resources should be claimed even if a conflict is found.
|
|
|
|
*
|
|
|
|
* @param[out] ConflictDetected
|
|
|
|
* Points to a variable that receives TRUE if a conflict is detected
|
|
|
|
* with another driver.
|
|
|
|
**/
|
|
|
|
NTSTATUS
|
|
|
|
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)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2010-10-24 02:51:48 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PCM_RESOURCE_LIST ResourceList;
|
2014-03-30 09:35:50 +00:00
|
|
|
|
2010-10-24 02:51:48 +00:00
|
|
|
DPRINT1("IoReportResourceUsage is halfplemented!\n");
|
2014-03-30 09:35:50 +00:00
|
|
|
|
2010-10-24 02:51:48 +00:00
|
|
|
if (!DriverList && !DeviceList)
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
2014-03-30 09:35:50 +00:00
|
|
|
|
2010-10-24 02:51:48 +00:00
|
|
|
if (DeviceList)
|
|
|
|
ResourceList = DeviceList;
|
|
|
|
else
|
|
|
|
ResourceList = DriverList;
|
2014-03-30 09:35:50 +00:00
|
|
|
|
2010-10-24 02:51:48 +00:00
|
|
|
Status = IopDetectResourceConflict(ResourceList, FALSE, NULL);
|
|
|
|
if (Status == STATUS_CONFLICTING_ADDRESSES)
|
|
|
|
{
|
|
|
|
*ConflictDetected = TRUE;
|
2014-03-30 09:35:50 +00:00
|
|
|
|
2010-10-24 02:51:48 +00:00
|
|
|
if (!OverrideConflict)
|
|
|
|
{
|
|
|
|
DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
|
|
|
|
return STATUS_CONFLICTING_ADDRESSES;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Proceeding with conflicting resources\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: Claim resources in registry */
|
2014-03-30 09:35:50 +00:00
|
|
|
|
2010-10-24 02:51:48 +00:00
|
|
|
*ConflictDetected = FALSE;
|
2014-03-30 09:35:50 +00:00
|
|
|
|
2010-10-24 02:51:48 +00:00
|
|
|
return STATUS_SUCCESS;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
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)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2010-10-24 02:51:48 +00:00
|
|
|
NTSTATUS Status;
|
2012-02-11 03:54:10 +00:00
|
|
|
|
2013-08-06 01:42:43 +00:00
|
|
|
DPRINT1("IopLegacyResourceAllocation is halfplemented!\n");
|
|
|
|
|
2021-10-30 09:10:08 +00:00
|
|
|
if (!ResourceRequirements)
|
|
|
|
{
|
|
|
|
/* We can get there by calling IoAssignResources() with RequestedResources = NULL.
|
|
|
|
* TODO: not sure what we should do, but we shouldn't crash.
|
2023-05-27 20:48:50 +00:00
|
|
|
*/
|
2021-10-30 09:10:08 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2013-08-06 01:42:43 +00:00
|
|
|
Status = IopFixupResourceListWithRequirements(ResourceRequirements,
|
2012-02-11 03:54:10 +00:00
|
|
|
AllocatedResources);
|
2010-10-24 02:51:48 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
if (Status == STATUS_CONFLICTING_ADDRESSES)
|
2013-08-06 01:42:43 +00:00
|
|
|
{
|
2010-10-24 02:51:48 +00:00
|
|
|
DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
|
2013-08-06 01:42:43 +00:00
|
|
|
}
|
|
|
|
|
2010-10-24 02:51:48 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2013-08-06 01:42:43 +00:00
|
|
|
|
2010-10-24 02:51:48 +00:00
|
|
|
/* TODO: Claim resources in registry */
|
|
|
|
return STATUS_SUCCESS;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2013-08-06 01:42:43 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2023-05-27 20:48:50 +00:00
|
|
|
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)
|
2013-08-06 01:42:43 +00:00
|
|
|
{
|
|
|
|
PDEVICE_NODE DeviceNode;
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
UNREFERENCED_PARAMETER(RegistryPath);
|
|
|
|
UNREFERENCED_PARAMETER(DriverClassName);
|
|
|
|
|
2013-08-06 01:42:43 +00:00
|
|
|
/* Do we have a DO? */
|
|
|
|
if (DeviceObject)
|
|
|
|
{
|
|
|
|
/* Get its device node */
|
|
|
|
DeviceNode = IopGetDeviceNode(DeviceObject);
|
2023-05-27 20:48:50 +00:00
|
|
|
if (DeviceNode && !(DeviceNode->Flags & DNF_LEGACY_RESOURCE_DEVICENODE))
|
2013-08-06 01:42:43 +00:00
|
|
|
{
|
|
|
|
/* New drivers should not call this API */
|
|
|
|
KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
|
2023-05-27 20:55:40 +00:00
|
|
|
0x2,
|
2013-08-06 01:42:43 +00:00
|
|
|
(ULONG_PTR)DeviceObject,
|
2023-05-27 20:55:40 +00:00
|
|
|
(ULONG_PTR)DriverObject,
|
|
|
|
0);
|
2013-08-06 01:42:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Did the driver supply resources? */
|
|
|
|
if (RequestedResources)
|
|
|
|
{
|
|
|
|
/* Make sure there's actually something useful in them */
|
|
|
|
if (!(RequestedResources->AlternativeLists) || !(RequestedResources->List[0].Count))
|
|
|
|
{
|
|
|
|
/* Empty resources are no resources */
|
|
|
|
RequestedResources = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize output if given */
|
2023-05-27 20:48:50 +00:00
|
|
|
if (AllocatedResources)
|
|
|
|
*AllocatedResources = NULL;
|
2013-08-06 01:42:43 +00:00
|
|
|
|
|
|
|
/* Call internal helper function */
|
|
|
|
return IopLegacyResourceAllocation(ArbiterRequestLegacyAssigned,
|
|
|
|
DriverObject,
|
|
|
|
DeviceObject,
|
|
|
|
RequestedResources,
|
|
|
|
AllocatedResources);
|
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/**
|
|
|
|
* @brief
|
|
|
|
* Reads and returns Hardware information from the appropriate
|
|
|
|
* hardware registry key.
|
2004-05-30 18:30:03 +00:00
|
|
|
*
|
2023-05-27 20:48:50 +00:00
|
|
|
* @param[in] BusType
|
|
|
|
* Specifies the bus type, for example: MCA, ISA, EISA, etc.
|
2004-05-30 18:30:03 +00:00
|
|
|
*
|
2023-05-27 20:48:50 +00:00
|
|
|
* @param[in] BusNumber
|
|
|
|
* The number of the specified bus type to query.
|
2004-05-30 18:30:03 +00:00
|
|
|
*
|
2023-05-27 20:48:50 +00:00
|
|
|
* @param[in] ControllerType
|
|
|
|
* Specifies the controller type
|
|
|
|
*
|
|
|
|
* @param[in] ControllerNumber
|
|
|
|
* The number of the specified controller type to query.
|
|
|
|
*
|
|
|
|
* @param[in] CalloutRoutine
|
|
|
|
* A user-provided callback function to call for each valid query.
|
|
|
|
*
|
|
|
|
* @param[in] Context
|
|
|
|
* A callback-specific context value.
|
|
|
|
*
|
|
|
|
* @return A status code.
|
|
|
|
**/
|
|
|
|
NTSTATUS
|
|
|
|
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)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG BusLoopNumber = -1; /* Root Bus */
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING RootRegKey;
|
|
|
|
HANDLE RootRegHandle;
|
|
|
|
IO_QUERY Query;
|
|
|
|
|
2023-05-28 20:44:08 +00:00
|
|
|
IORSRCTRACE("\nIoQueryDeviceDescription()\n"
|
|
|
|
" BusType: 0x%p (%lu)\n"
|
|
|
|
" BusNumber: 0x%p (%lu)\n"
|
|
|
|
" ControllerType: 0x%p (%lu)\n"
|
|
|
|
" ControllerNumber: 0x%p (%lu)\n"
|
|
|
|
" PeripheralType: 0x%p (%lu)\n"
|
|
|
|
" PeripheralNumber: 0x%p (%lu)\n"
|
|
|
|
" CalloutRoutine: 0x%p\n"
|
|
|
|
" Context: 0x%p\n"
|
|
|
|
"--> Query: 0x%p\n",
|
|
|
|
BusType, BusType ? *BusType : -1,
|
|
|
|
BusNumber, BusNumber ? *BusNumber : -1,
|
|
|
|
ControllerType, ControllerType ? *ControllerType : -1,
|
|
|
|
ControllerNumber, ControllerNumber ? *ControllerNumber : -1,
|
|
|
|
PeripheralType, PeripheralType ? *PeripheralType : -1,
|
|
|
|
PeripheralNumber, PeripheralNumber ? *PeripheralNumber : -1,
|
|
|
|
CalloutRoutine, Context,
|
|
|
|
&Query);
|
|
|
|
|
2023-05-27 20:55:40 +00:00
|
|
|
if (!BusType)
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Set up the string */
|
|
|
|
RootRegKey.Length = 0;
|
|
|
|
RootRegKey.MaximumLength = 2048;
|
|
|
|
RootRegKey.Buffer = ExAllocatePoolWithTag(PagedPool, RootRegKey.MaximumLength, TAG_IO_RESOURCE);
|
2023-05-27 20:55:40 +00:00
|
|
|
if (!RootRegKey.Buffer)
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
RtlAppendUnicodeToString(&RootRegKey, L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
|
|
|
|
|
|
|
|
/* Open a handle to the Root Registry Key */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&RootRegKey,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = ZwOpenKey(&RootRegHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Use a helper function to loop though this key and get the information */
|
|
|
|
Query.BusType = BusType;
|
|
|
|
Query.BusNumber = BusNumber;
|
|
|
|
Query.ControllerType = ControllerType;
|
|
|
|
Query.ControllerNumber = ControllerNumber;
|
|
|
|
Query.PeripheralType = PeripheralType;
|
|
|
|
Query.PeripheralNumber = PeripheralNumber;
|
|
|
|
Query.CalloutRoutine = CalloutRoutine;
|
|
|
|
Query.Context = Context;
|
|
|
|
Status = IopQueryBusDescription(&Query,
|
|
|
|
RootRegKey,
|
|
|
|
RootRegHandle,
|
|
|
|
&BusLoopNumber,
|
|
|
|
TRUE);
|
|
|
|
|
|
|
|
/* Close registry key */
|
|
|
|
ZwClose(RootRegHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cleanup */
|
|
|
|
ExFreePoolWithTag(RootRegKey.Buffer, TAG_IO_RESOURCE);
|
|
|
|
|
|
|
|
return Status;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
2000-03-26 19:38:32 +00:00
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/**
|
|
|
|
* @brief
|
|
|
|
* Reports hardware resources of the HAL in the
|
|
|
|
* \Registry\Machine\Hardware\ResourceMap tree.
|
|
|
|
*
|
|
|
|
* @param[in] HalName
|
|
|
|
* Descriptive name of the HAL.
|
|
|
|
*
|
|
|
|
* @param[in] RawResourceList
|
|
|
|
* List of raw (bus specific) resources which should be claimed
|
|
|
|
* for the HAL.
|
|
|
|
*
|
|
|
|
* @param[in] TranslatedResourceList
|
|
|
|
* List of translated (system wide) resources which should be claimed
|
|
|
|
* for the HAL.
|
|
|
|
*
|
|
|
|
* @param[in] ResourceListSize
|
|
|
|
* Size in bytes of the raw and translated resource lists.
|
|
|
|
* Both lists have the same size.
|
|
|
|
*
|
|
|
|
* @return A status code.
|
|
|
|
**/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IoReportHalResourceUsage(
|
|
|
|
_In_ PUNICODE_STRING HalName,
|
|
|
|
_In_ PCM_RESOURCE_LIST RawResourceList,
|
|
|
|
_In_ PCM_RESOURCE_LIST TranslatedResourceList,
|
|
|
|
_In_ ULONG ResourceListSize)
|
2000-04-05 15:52:45 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING Name;
|
|
|
|
ULONG Disposition;
|
|
|
|
HANDLE ResourceMapKey;
|
|
|
|
HANDLE HalKey;
|
|
|
|
HANDLE DescriptionKey;
|
|
|
|
|
|
|
|
/* Open/Create 'RESOURCEMAP' key */
|
|
|
|
RtlInitUnicodeString(&Name, L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&Name,
|
|
|
|
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
|
|
|
|
0,
|
|
|
|
NULL);
|
|
|
|
Status = ZwCreateKey(&ResourceMapKey,
|
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
&ObjectAttributes,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
REG_OPTION_VOLATILE,
|
|
|
|
&Disposition);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
|
|
|
|
|
|
|
/* Open/Create 'Hardware Abstraction Layer' key */
|
|
|
|
RtlInitUnicodeString(&Name, L"Hardware Abstraction Layer");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&Name,
|
|
|
|
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
|
|
|
|
ResourceMapKey,
|
|
|
|
NULL);
|
|
|
|
Status = ZwCreateKey(&HalKey,
|
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
&ObjectAttributes,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
REG_OPTION_VOLATILE,
|
|
|
|
&Disposition);
|
|
|
|
ZwClose(ResourceMapKey);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
|
|
|
|
|
|
|
/* Create 'HalName' key */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
HalName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
HalKey,
|
|
|
|
NULL);
|
|
|
|
Status = ZwCreateKey(&DescriptionKey,
|
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
&ObjectAttributes,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
REG_OPTION_VOLATILE,
|
|
|
|
&Disposition);
|
|
|
|
ZwClose(HalKey);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return Status;
|
|
|
|
|
|
|
|
/* Add '.Raw' value */
|
|
|
|
RtlInitUnicodeString(&Name, L".Raw");
|
|
|
|
Status = ZwSetValueKey(DescriptionKey,
|
|
|
|
&Name,
|
|
|
|
0,
|
|
|
|
REG_RESOURCE_LIST,
|
|
|
|
RawResourceList,
|
|
|
|
ResourceListSize);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-09-05 09:21:47 +00:00
|
|
|
{
|
2023-05-27 20:48:50 +00:00
|
|
|
ZwClose(DescriptionKey);
|
|
|
|
return Status;
|
2001-09-05 09:21:47 +00:00
|
|
|
}
|
|
|
|
|
2023-05-27 20:48:50 +00:00
|
|
|
/* Add '.Translated' value */
|
|
|
|
RtlInitUnicodeString(&Name, L".Translated");
|
|
|
|
Status = ZwSetValueKey(DescriptionKey,
|
|
|
|
&Name,
|
|
|
|
0,
|
|
|
|
REG_RESOURCE_LIST,
|
|
|
|
TranslatedResourceList,
|
|
|
|
ResourceListSize);
|
|
|
|
ZwClose(DescriptionKey);
|
|
|
|
|
|
|
|
return Status;
|
2000-04-05 15:52:45 +00:00
|
|
|
}
|
|
|
|
|
2000-03-26 19:38:32 +00:00
|
|
|
/* EOF */
|