2008-03-09 14:11:42 +00:00
|
|
|
/*
|
2005-01-26 13:58:37 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
1998-08-25 04:27:26 +00:00
|
|
|
* PROJECT: ReactOS kernel
|
2015-10-04 11:54:25 +00:00
|
|
|
* FILE: ntoskrnl/io/iomgr/iorsrce.c
|
1998-08-25 04:27:26 +00:00
|
|
|
* PURPOSE: Hardware resource managment
|
2005-05-09 01:38:29 +00:00
|
|
|
*
|
2005-01-26 13:58:37 +00:00
|
|
|
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
2004-05-30 18:30:03 +00:00
|
|
|
* Alex Ionescu (alex@relsoft.net)
|
2010-10-07 20:08:24 +00:00
|
|
|
* Pierre Schweitzer (pierre.schweitzer@reactos.org)
|
1998-08-25 04:27:26 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
2008-08-30 16:31:06 +00:00
|
|
|
#include <debug.h>
|
2002-09-07 15:13:13 +00:00
|
|
|
|
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
|
|
|
|
2004-05-30 18:30:03 +00:00
|
|
|
/* API Parameters to Pass in 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;
|
|
|
|
} IO_QUERY, *PIO_QUERY;
|
|
|
|
|
|
|
|
PWSTR ArcTypes[42] = {
|
|
|
|
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"
|
|
|
|
};
|
|
|
|
|
|
|
|
/* PRIVATE FUNCTIONS **********************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IopQueryDeviceDescription
|
|
|
|
*
|
|
|
|
* FUNCTION:
|
|
|
|
* Reads and returns Hardware information from the appropriate hardware
|
2005-05-09 01:38:29 +00:00
|
|
|
* registry key. Helper sub of IopQueryBusDescription.
|
2004-05-30 18:30:03 +00:00
|
|
|
*
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Query - What the parent function wants.
|
|
|
|
* RootKey - Which key to look in
|
|
|
|
* RootKeyHandle - Handle to the key
|
|
|
|
* Bus - Bus Number.
|
|
|
|
* BusInformation - The Configuration Information Sent
|
|
|
|
*
|
|
|
|
* RETURNS:
|
|
|
|
* Status
|
|
|
|
*/
|
|
|
|
|
2008-11-29 20:47:48 +00:00
|
|
|
NTSTATUS NTAPI
|
2004-05-30 18:30:03 +00:00
|
|
|
IopQueryDeviceDescription(
|
|
|
|
PIO_QUERY Query,
|
|
|
|
UNICODE_STRING RootKey,
|
|
|
|
HANDLE RootKeyHandle,
|
|
|
|
ULONG Bus,
|
2005-05-09 01:38:29 +00:00
|
|
|
PKEY_VALUE_FULL_INFORMATION *BusInformation)
|
2004-05-30 18:30:03 +00:00
|
|
|
{
|
2004-07-03 17:40:27 +00:00
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
/* Controller Stuff */
|
|
|
|
UNICODE_STRING ControllerString;
|
|
|
|
UNICODE_STRING ControllerRootRegName = RootKey;
|
|
|
|
UNICODE_STRING ControllerRegName;
|
|
|
|
HANDLE ControllerKeyHandle;
|
2004-06-20 04:50:02 +00:00
|
|
|
PKEY_FULL_INFORMATION ControllerFullInformation = NULL;
|
2004-05-30 18:30:03 +00:00
|
|
|
PKEY_VALUE_FULL_INFORMATION ControllerInformation[3] = {NULL, NULL, NULL};
|
|
|
|
ULONG ControllerNumber;
|
|
|
|
ULONG ControllerLoop;
|
|
|
|
ULONG MaximumControllerNumber;
|
|
|
|
|
|
|
|
/* Peripheral Stuff */
|
|
|
|
UNICODE_STRING PeripheralString;
|
|
|
|
HANDLE PeripheralKeyHandle;
|
|
|
|
PKEY_FULL_INFORMATION PeripheralFullInformation;
|
|
|
|
PKEY_VALUE_FULL_INFORMATION PeripheralInformation[3] = {NULL, NULL, NULL};
|
|
|
|
ULONG PeripheralNumber;
|
|
|
|
ULONG PeripheralLoop;
|
|
|
|
ULONG MaximumPeripheralNumber;
|
|
|
|
|
|
|
|
/* Global Registry Stuff */
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
ULONG LenFullInformation;
|
|
|
|
ULONG LenKeyFullInformation;
|
|
|
|
UNICODE_STRING TempString;
|
|
|
|
WCHAR TempBuffer[14];
|
|
|
|
PWSTR Strings[3] = {
|
|
|
|
L"Identifier",
|
|
|
|
L"Configuration Data",
|
|
|
|
L"Component Information"
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Temporary String */
|
|
|
|
TempString.MaximumLength = sizeof(TempBuffer);
|
|
|
|
TempString.Length = 0;
|
|
|
|
TempString.Buffer = TempBuffer;
|
|
|
|
|
|
|
|
/* Add Controller Name to String */
|
|
|
|
RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
|
|
|
|
RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->ControllerType]);
|
|
|
|
|
|
|
|
/* Set the Controller Number if specified */
|
|
|
|
if (Query->ControllerNumber && *(Query->ControllerNumber))
|
|
|
|
{
|
|
|
|
ControllerNumber = *Query->ControllerNumber;
|
|
|
|
MaximumControllerNumber = ControllerNumber + 1;
|
|
|
|
} else {
|
|
|
|
/* Find out how many Controller Numbers there are */
|
|
|
|
InitializeObjectAttributes(
|
|
|
|
&ObjectAttributes,
|
|
|
|
&ControllerRootRegName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* How much buffer space */
|
|
|
|
ZwQueryKey(ControllerKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation);
|
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
ControllerFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
|
|
|
|
|
|
|
|
/* Get the Information */
|
|
|
|
Status = ZwQueryKey(ControllerKeyHandle, KeyFullInformation, ControllerFullInformation, LenFullInformation, &LenFullInformation);
|
|
|
|
ZwClose(ControllerKeyHandle);
|
|
|
|
ControllerKeyHandle = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No controller was found, go back to function. */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
if (ControllerFullInformation != NULL)
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE);
|
2004-05-30 18:30:03 +00:00
|
|
|
return Status;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-05-30 18:30:03 +00:00
|
|
|
/* Find out Controller Numbers */
|
|
|
|
ControllerNumber = 0;
|
|
|
|
MaximumControllerNumber = ControllerFullInformation->SubKeys;
|
|
|
|
|
|
|
|
/* Free Memory */
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE);
|
2004-05-30 18:30:03 +00:00
|
|
|
ControllerFullInformation = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save String */
|
|
|
|
ControllerRegName = ControllerRootRegName;
|
|
|
|
|
|
|
|
/* Loop through controllers */
|
|
|
|
for (; ControllerNumber < MaximumControllerNumber; ControllerNumber++)
|
|
|
|
{
|
|
|
|
/* Load String */
|
|
|
|
ControllerRootRegName = ControllerRegName;
|
|
|
|
|
|
|
|
/* Controller Number to Registry String */
|
|
|
|
Status = RtlIntegerToUnicodeString(ControllerNumber, 10, &TempString);
|
|
|
|
|
|
|
|
/* Create String */
|
|
|
|
Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
|
|
|
|
Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-05-30 18:30:03 +00:00
|
|
|
/* Something messed up */
|
|
|
|
if (!NT_SUCCESS(Status)) break;
|
|
|
|
|
|
|
|
/* Open the Registry Key */
|
|
|
|
InitializeObjectAttributes(
|
|
|
|
&ObjectAttributes,
|
|
|
|
&ControllerRootRegName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
|
|
|
|
/* Read the Configuration Data... */
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
for (ControllerLoop = 0; ControllerLoop < 3; ControllerLoop++)
|
|
|
|
{
|
|
|
|
/* Identifier String First */
|
|
|
|
RtlInitUnicodeString(&ControllerString, Strings[ControllerLoop]);
|
|
|
|
|
|
|
|
/* How much buffer space */
|
2004-06-20 04:50:02 +00:00
|
|
|
Status = ZwQueryValueKey(ControllerKeyHandle, &ControllerString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation);
|
|
|
|
|
2014-03-30 09:35:50 +00:00
|
|
|
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW)
|
|
|
|
continue;
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
ControllerInformation[ControllerLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
|
|
|
|
|
|
|
|
/* Get the Information */
|
|
|
|
Status = ZwQueryValueKey(ControllerKeyHandle, &ControllerString, KeyValueFullInformation, ControllerInformation[ControllerLoop], LenKeyFullInformation, &LenKeyFullInformation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clean Up */
|
|
|
|
ZwClose(ControllerKeyHandle);
|
|
|
|
ControllerKeyHandle = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Something messed up */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
goto EndLoop;
|
|
|
|
|
|
|
|
/* We now have Bus *AND* Controller Information.. is it enough? */
|
2005-05-10 09:38:20 +00:00
|
|
|
if (!Query->PeripheralType || !(*Query->PeripheralType))
|
2004-05-30 18:30:03 +00:00
|
|
|
{
|
|
|
|
Status = Query->CalloutRoutine(
|
|
|
|
Query->Context,
|
|
|
|
&ControllerRootRegName,
|
|
|
|
*Query->BusType,
|
|
|
|
Bus,
|
|
|
|
BusInformation,
|
|
|
|
*Query->ControllerType,
|
|
|
|
ControllerNumber,
|
|
|
|
ControllerInformation,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
NULL);
|
|
|
|
goto EndLoop;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not enough...caller also wants peripheral name */
|
|
|
|
Status = RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
|
|
|
|
Status |= RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->PeripheralType]);
|
|
|
|
|
|
|
|
/* Something messed up */
|
2005-05-09 01:38:29 +00:00
|
|
|
if (!NT_SUCCESS(Status)) goto EndLoop;
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
/* Set the Peripheral Number if specified */
|
|
|
|
if (Query->PeripheralNumber && *Query->PeripheralNumber)
|
|
|
|
{
|
|
|
|
PeripheralNumber = *Query->PeripheralNumber;
|
|
|
|
MaximumPeripheralNumber = PeripheralNumber + 1;
|
|
|
|
} else {
|
|
|
|
/* Find out how many Peripheral Numbers there are */
|
|
|
|
InitializeObjectAttributes(
|
|
|
|
&ObjectAttributes,
|
|
|
|
&ControllerRootRegName,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* How much buffer space */
|
|
|
|
ZwQueryKey(PeripheralKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation);
|
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
PeripheralFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
|
|
|
|
|
|
|
|
/* Get the Information */
|
|
|
|
Status = ZwQueryKey(PeripheralKeyHandle, KeyFullInformation, PeripheralFullInformation, LenFullInformation, &LenFullInformation);
|
|
|
|
ZwClose(PeripheralKeyHandle);
|
|
|
|
PeripheralKeyHandle = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No controller was found, go back to function but clean up first */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
goto EndLoop;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find out Peripheral Number */
|
|
|
|
PeripheralNumber = 0;
|
|
|
|
MaximumPeripheralNumber = PeripheralFullInformation->SubKeys;
|
|
|
|
|
|
|
|
/* Free Memory */
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(PeripheralFullInformation, TAG_IO_RESOURCE);
|
2004-05-30 18:30:03 +00:00
|
|
|
PeripheralFullInformation = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save Name */
|
|
|
|
ControllerRegName = ControllerRootRegName;
|
|
|
|
|
|
|
|
/* Loop through Peripherals */
|
|
|
|
for (; PeripheralNumber < MaximumPeripheralNumber; PeripheralNumber++)
|
|
|
|
{
|
|
|
|
/* Restore Name */
|
|
|
|
ControllerRootRegName = ControllerRegName;
|
|
|
|
|
|
|
|
/* Peripheral Number to Registry String */
|
|
|
|
Status = RtlIntegerToUnicodeString(PeripheralNumber, 10, &TempString);
|
|
|
|
|
|
|
|
/* Create String */
|
|
|
|
Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\");
|
2014-03-30 09:35:50 +00:00
|
|
|
Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString);
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-05-30 18:30:03 +00:00
|
|
|
/* Something messed up */
|
|
|
|
if (!NT_SUCCESS(Status)) break;
|
|
|
|
|
|
|
|
/* 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 < 3; PeripheralLoop++)
|
|
|
|
{
|
|
|
|
/* Identifier String First */
|
|
|
|
RtlInitUnicodeString(&PeripheralString, Strings[PeripheralLoop]);
|
|
|
|
|
|
|
|
/* How much buffer space */
|
2004-06-20 04:50:02 +00:00
|
|
|
Status = ZwQueryValueKey(PeripheralKeyHandle, &PeripheralString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation);
|
|
|
|
|
2014-03-30 09:35:50 +00:00
|
|
|
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW)
|
|
|
|
{
|
|
|
|
PeripheralInformation[PeripheralLoop] = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
PeripheralInformation[PeripheralLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
|
|
|
|
|
|
|
|
/* Get the Information */
|
|
|
|
Status = ZwQueryValueKey(PeripheralKeyHandle, &PeripheralString, KeyValueFullInformation, PeripheralInformation[PeripheralLoop], LenKeyFullInformation, &LenKeyFullInformation);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clean Up */
|
|
|
|
ZwClose(PeripheralKeyHandle);
|
|
|
|
PeripheralKeyHandle = NULL;
|
|
|
|
|
|
|
|
/* We now have everything the caller could possibly want */
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
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 < 3; PeripheralLoop++)
|
|
|
|
{
|
|
|
|
if (PeripheralInformation[PeripheralLoop])
|
|
|
|
{
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(PeripheralInformation[PeripheralLoop], TAG_IO_RESOURCE);
|
2004-05-30 18:30:03 +00:00
|
|
|
PeripheralInformation[PeripheralLoop] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Something Messed up */
|
|
|
|
if (!NT_SUCCESS(Status)) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EndLoop:
|
|
|
|
/* Free the allocated memory */
|
|
|
|
for (ControllerLoop = 0; ControllerLoop < 3; ControllerLoop++)
|
|
|
|
{
|
|
|
|
if (ControllerInformation[ControllerLoop])
|
|
|
|
{
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(ControllerInformation[ControllerLoop], TAG_IO_RESOURCE);
|
2004-05-30 18:30:03 +00:00
|
|
|
ControllerInformation[ControllerLoop] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Something Messed up */
|
|
|
|
if (!NT_SUCCESS(Status)) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* IopQueryBusDescription
|
|
|
|
*
|
|
|
|
* FUNCTION:
|
|
|
|
* Reads and returns Hardware information from the appropriate hardware
|
|
|
|
* registry key. Helper sub of IoQueryDeviceDescription. Has two modes
|
|
|
|
* of operation, either looking for Root Bus Types or for sub-Bus
|
|
|
|
* information.
|
|
|
|
*
|
|
|
|
* ARGUMENTS:
|
|
|
|
* Query - What the parent function wants.
|
|
|
|
* RootKey - Which key to look in
|
|
|
|
* RootKeyHandle - Handle to the key
|
|
|
|
* Bus - Bus Number.
|
|
|
|
* KeyIsRoot - Whether we are looking for Root Bus Types or
|
|
|
|
* information under them.
|
|
|
|
*
|
|
|
|
* RETURNS:
|
|
|
|
* Status
|
|
|
|
*/
|
|
|
|
|
2008-11-29 20:47:48 +00:00
|
|
|
NTSTATUS NTAPI
|
2004-05-30 18:30:03 +00:00
|
|
|
IopQueryBusDescription(
|
|
|
|
PIO_QUERY Query,
|
|
|
|
UNICODE_STRING RootKey,
|
|
|
|
HANDLE RootKeyHandle,
|
|
|
|
PULONG Bus,
|
2005-05-09 01:38:29 +00:00
|
|
|
BOOLEAN KeyIsRoot)
|
2004-05-30 18:30:03 +00:00
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG BusLoop;
|
|
|
|
UNICODE_STRING SubRootRegName;
|
|
|
|
UNICODE_STRING BusString;
|
|
|
|
UNICODE_STRING SubBusString;
|
2004-07-03 17:40:27 +00:00
|
|
|
ULONG LenBasicInformation = 0;
|
2004-05-30 18:30:03 +00:00
|
|
|
ULONG LenFullInformation;
|
|
|
|
ULONG LenKeyFullInformation;
|
|
|
|
ULONG LenKey;
|
|
|
|
HANDLE SubRootKeyHandle;
|
|
|
|
PKEY_FULL_INFORMATION FullInformation;
|
2004-07-03 17:40:27 +00:00
|
|
|
PKEY_BASIC_INFORMATION BasicInformation = NULL;
|
2004-05-30 18:30:03 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
PKEY_VALUE_FULL_INFORMATION BusInformation[3] = {NULL, NULL, NULL};
|
|
|
|
|
|
|
|
/* How much buffer space */
|
|
|
|
Status = ZwQueryKey(RootKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation);
|
|
|
|
|
2004-06-20 04:50:02 +00:00
|
|
|
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW)
|
2004-05-30 18:30:03 +00:00
|
|
|
return Status;
|
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
FullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE);
|
|
|
|
|
2014-03-30 09:35:50 +00:00
|
|
|
if (!FullInformation)
|
2004-06-20 04:50:02 +00:00
|
|
|
return STATUS_NO_MEMORY;
|
|
|
|
|
2004-05-30 18:30:03 +00:00
|
|
|
/* Get the Information */
|
|
|
|
Status = ZwQueryKey(RootKeyHandle, KeyFullInformation, FullInformation, LenFullInformation, &LenFullInformation);
|
|
|
|
|
|
|
|
/* Everything was fine */
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Deallocate the old Buffer */
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(FullInformation, TAG_IO_RESOURCE);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
/* Everything enumerated */
|
|
|
|
if (!NT_SUCCESS(Status)) break;
|
|
|
|
|
|
|
|
/* 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 / 2) &&
|
|
|
|
wcsncmp(BasicInformation->Name, L"EisaAdapter", BasicInformation->NameLength / 2) &&
|
|
|
|
wcsncmp(BasicInformation->Name, L"TcAdapter", BasicInformation->NameLength / 2))
|
|
|
|
{
|
|
|
|
/* Nothing found, check next */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Enumerate the Bus. */
|
|
|
|
BusString.Buffer = BasicInformation->Name;
|
2007-08-04 08:49:47 +00:00
|
|
|
BusString.Length = (USHORT)BasicInformation->NameLength;
|
|
|
|
BusString.MaximumLength = (USHORT)BasicInformation->NameLength;
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
/* 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 can't */
|
|
|
|
if (!NT_SUCCESS(Status)) continue;
|
|
|
|
|
|
|
|
/* Key opened. Create the path */
|
|
|
|
SubRootRegName = RootKey;
|
|
|
|
RtlAppendUnicodeToString(&SubRootRegName, L"\\");
|
|
|
|
RtlAppendUnicodeStringToString(&SubRootRegName, &BusString);
|
|
|
|
|
|
|
|
if (!KeyIsRoot)
|
|
|
|
{
|
|
|
|
/* Parsing a SubBus-key */
|
|
|
|
int SubBusLoop;
|
|
|
|
PWSTR Strings[3] = {
|
|
|
|
L"Identifier",
|
|
|
|
L"Configuration Data",
|
|
|
|
L"Component Information"};
|
|
|
|
|
|
|
|
for (SubBusLoop = 0; SubBusLoop < 3; SubBusLoop++)
|
|
|
|
{
|
|
|
|
/* Identifier String First */
|
|
|
|
RtlInitUnicodeString(&SubBusString, Strings[SubBusLoop]);
|
|
|
|
|
|
|
|
/* How much buffer space */
|
|
|
|
ZwQueryValueKey(SubRootKeyHandle, &SubBusString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation);
|
|
|
|
|
|
|
|
/* Allocate it */
|
|
|
|
BusInformation[SubBusLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE);
|
|
|
|
|
|
|
|
/* Get the Information */
|
|
|
|
Status = ZwQueryValueKey(SubRootKeyHandle, &SubBusString, KeyValueFullInformation, BusInformation[SubBusLoop], LenKeyFullInformation, &LenKeyFullInformation);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Do we have something */
|
|
|
|
if (BusInformation[1] != NULL &&
|
|
|
|
BusInformation[1]->DataLength != 0 &&
|
|
|
|
/* Does it match what we want? */
|
|
|
|
(((PCM_FULL_RESOURCE_DESCRIPTOR)((ULONG_PTR)BusInformation[1] + BusInformation[1]->DataOffset))->InterfaceType == *(Query->BusType)))
|
|
|
|
{
|
|
|
|
/* Found a bus */
|
|
|
|
(*Bus)++;
|
|
|
|
|
|
|
|
/* Is it the bus we wanted */
|
|
|
|
if (Query->BusNumber == NULL || *(Query->BusNumber) == *Bus)
|
|
|
|
{
|
|
|
|
/* If we don't want Controller Information, we're done... call the callback */
|
|
|
|
if (Query->ControllerType == NULL)
|
|
|
|
{
|
|
|
|
Status = Query->CalloutRoutine(
|
|
|
|
Query->Context,
|
|
|
|
&SubRootRegName,
|
|
|
|
*(Query->BusType),
|
|
|
|
*Bus,
|
|
|
|
BusInformation,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
NULL);
|
|
|
|
} else {
|
|
|
|
/* We want Controller Info...get it */
|
|
|
|
Status = IopQueryDeviceDescription(Query, SubRootRegName, RootKeyHandle, *Bus, (PKEY_VALUE_FULL_INFORMATION*)BusInformation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the allocated memory */
|
|
|
|
for (SubBusLoop = 0; SubBusLoop < 3; SubBusLoop++)
|
|
|
|
{
|
|
|
|
if (BusInformation[SubBusLoop])
|
|
|
|
{
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(BusInformation[SubBusLoop], TAG_IO_RESOURCE);
|
2004-05-30 18:30:03 +00:00
|
|
|
BusInformation[SubBusLoop] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Exit the Loop if we found the bus */
|
|
|
|
if (Query->BusNumber != NULL && *(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);
|
|
|
|
|
|
|
|
/* Everything enumerated */
|
|
|
|
if (Status == STATUS_NO_MORE_ENTRIES) Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
ZwClose(SubRootKeyHandle);
|
|
|
|
SubRootKeyHandle = NULL;
|
|
|
|
}
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-05-30 18:30:03 +00:00
|
|
|
/* Free the last remaining Allocated Memory */
|
|
|
|
if (BasicInformation)
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(BasicInformation, TAG_IO_RESOURCE);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
[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
|
|
|
|
NTAPI
|
|
|
|
IopFetchConfigurationInformation(OUT PWSTR * SymbolicLinkList,
|
|
|
|
IN GUID Guid,
|
|
|
|
IN ULONG ExpectedInterfaces,
|
|
|
|
IN PULONG Interfaces)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG IntInterfaces = 0;
|
|
|
|
PWSTR IntSymbolicLinkList;
|
|
|
|
|
|
|
|
/* Get the associated enabled interfaces with the given GUID */
|
|
|
|
Status = IoGetDeviceInterfaces(&Guid, NULL, 0, SymbolicLinkList);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Zero output and leave */
|
|
|
|
if (SymbolicLinkList != 0)
|
|
|
|
{
|
|
|
|
*SymbolicLinkList = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
|
|
|
|
IntSymbolicLinkList = *SymbolicLinkList;
|
|
|
|
|
|
|
|
/* Count the number of enabled interfaces by counting the number of symbolic links */
|
|
|
|
while (*IntSymbolicLinkList != UNICODE_NULL)
|
|
|
|
{
|
|
|
|
IntInterfaces++;
|
|
|
|
IntSymbolicLinkList += wcslen(IntSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Matching result will define the result */
|
|
|
|
Status = (IntInterfaces >= ExpectedInterfaces) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
|
|
|
/* Finally, give back to the caller the number of found interfaces */
|
|
|
|
*Interfaces = IntInterfaces;
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2010-10-07 20:08:24 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
IopStoreSystemPartitionInformation(IN PUNICODE_STRING NtSystemPartitionDeviceName,
|
|
|
|
IN PUNICODE_STRING OsLoaderPathName)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Prepare the string that will receive where symbolic link points to */
|
|
|
|
LinkTarget.Length = 0;
|
|
|
|
/* We will zero the end of the string after having received it */
|
|
|
|
LinkTarget.MaximumLength = sizeof(LinkTargetBuffer) - sizeof(UNICODE_NULL);
|
|
|
|
LinkTarget.Buffer = LinkTargetBuffer;
|
|
|
|
|
|
|
|
/* Query target */
|
|
|
|
Status = ZwQuerySymbolicLinkObject(LinkHandle,
|
|
|
|
&LinkTarget,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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
|
|
|
}
|
|
|
|
|
[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
|
|
|
/* Prepare for second data writing... */
|
|
|
|
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
|
|
|
|
2003-07-10 15:47:00 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-29 20:47:48 +00:00
|
|
|
PCONFIGURATION_INFORMATION NTAPI
|
2000-03-26 19:38:32 +00:00
|
|
|
IoGetConfigurationInformation(VOID)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2005-06-18 18:32:29 +00:00
|
|
|
return(&_SystemConfigurationInformation);
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 15:47:00 +00:00
|
|
|
/*
|
2010-10-24 02:51:48 +00:00
|
|
|
* @halfplemented
|
2003-07-10 15:47:00 +00:00
|
|
|
*/
|
2008-11-29 20:47:48 +00:00
|
|
|
NTSTATUS NTAPI
|
2000-03-26 19:38:32 +00:00
|
|
|
IoReportResourceUsage(PUNICODE_STRING DriverClassName,
|
2001-04-04 22:21:32 +00:00
|
|
|
PDRIVER_OBJECT DriverObject,
|
|
|
|
PCM_RESOURCE_LIST DriverList,
|
|
|
|
ULONG DriverListSize,
|
|
|
|
PDEVICE_OBJECT DeviceObject,
|
|
|
|
PCM_RESOURCE_LIST DeviceList,
|
|
|
|
ULONG DeviceListSize,
|
|
|
|
BOOLEAN OverrideConflict,
|
|
|
|
PBOOLEAN ConflictDetected)
|
|
|
|
/*
|
2005-05-09 01:38:29 +00:00
|
|
|
* FUNCTION: Reports hardware resources in the
|
2001-04-04 22:21:32 +00:00
|
|
|
* \Registry\Machine\Hardware\ResourceMap tree, so that a subsequently
|
|
|
|
* loaded driver cannot attempt to use the same resources.
|
|
|
|
* ARGUMENTS:
|
|
|
|
* DriverClassName - The class of driver under which the resource
|
|
|
|
* information should be stored.
|
2005-05-09 01:38:29 +00:00
|
|
|
* DriverObject - The driver object that was input to the
|
2001-04-04 22:21:32 +00:00
|
|
|
* DriverEntry.
|
|
|
|
* DriverList - Resources that claimed for the driver rather than
|
|
|
|
* per-device.
|
|
|
|
* DriverListSize - Size in bytes of the DriverList.
|
|
|
|
* DeviceObject - The device object for which resources should be
|
|
|
|
* claimed.
|
|
|
|
* DeviceList - List of resources which should be claimed for the
|
|
|
|
* device.
|
|
|
|
* DeviceListSize - Size of the per-device resource list in bytes.
|
|
|
|
* OverrideConflict - True if the resources should be cliamed
|
|
|
|
* even if a conflict is found.
|
|
|
|
* ConflictDetected - Points to a variable that receives TRUE if
|
|
|
|
* a conflict is detected with another driver.
|
|
|
|
*/
|
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
|
|
|
}
|
|
|
|
|
2013-08-06 01:42:43 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
IopLegacyResourceAllocation(IN ARBITER_REQUEST_SOURCE AllocationType,
|
|
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
|
|
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
|
|
|
IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements,
|
|
|
|
IN OUT 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.
|
|
|
|
* */
|
|
|
|
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
|
|
|
|
IoAssignResources(IN PUNICODE_STRING RegistryPath,
|
|
|
|
IN PUNICODE_STRING DriverClassName,
|
|
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources,
|
|
|
|
IN OUT PCM_RESOURCE_LIST* AllocatedResources)
|
|
|
|
{
|
|
|
|
PDEVICE_NODE DeviceNode;
|
|
|
|
|
|
|
|
/* Do we have a DO? */
|
|
|
|
if (DeviceObject)
|
|
|
|
{
|
|
|
|
/* Get its device node */
|
|
|
|
DeviceNode = IopGetDeviceNode(DeviceObject);
|
|
|
|
if ((DeviceNode) && !(DeviceNode->Flags & DNF_LEGACY_RESOURCE_DEVICENODE))
|
|
|
|
{
|
|
|
|
/* New drivers should not call this API */
|
|
|
|
KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
(ULONG_PTR)DeviceObject,
|
|
|
|
(ULONG_PTR)DriverObject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
if (AllocatedResources) *AllocatedResources = NULL;
|
|
|
|
|
|
|
|
/* Call internal helper function */
|
|
|
|
return IopLegacyResourceAllocation(ArbiterRequestLegacyAssigned,
|
|
|
|
DriverObject,
|
|
|
|
DeviceObject,
|
|
|
|
RequestedResources,
|
|
|
|
AllocatedResources);
|
|
|
|
}
|
|
|
|
|
2003-07-10 15:47:00 +00:00
|
|
|
/*
|
2004-05-30 18:30:03 +00:00
|
|
|
* FUNCTION:
|
|
|
|
* Reads and returns Hardware information from the appropriate hardware registry key.
|
|
|
|
*
|
|
|
|
* ARGUMENTS:
|
|
|
|
* BusType - MCA, ISA, EISA...specifies the Bus Type
|
|
|
|
* BusNumber - Which bus of above should be queried
|
|
|
|
* ControllerType - Specifices the Controller Type
|
|
|
|
* ControllerNumber - Which of the controllers to query.
|
|
|
|
* CalloutRoutine - Which function to call for each valid query.
|
|
|
|
* Context - Value to pass to the callback.
|
|
|
|
*
|
|
|
|
* RETURNS:
|
|
|
|
* Status
|
|
|
|
*
|
|
|
|
* STATUS:
|
|
|
|
* @implemented
|
2003-07-10 15:47:00 +00:00
|
|
|
*/
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
NTSTATUS NTAPI
|
2005-05-10 09:38:20 +00:00
|
|
|
IoQueryDeviceDescription(PINTERFACE_TYPE BusType OPTIONAL,
|
|
|
|
PULONG BusNumber OPTIONAL,
|
|
|
|
PCONFIGURATION_TYPE ControllerType OPTIONAL,
|
|
|
|
PULONG ControllerNumber OPTIONAL,
|
|
|
|
PCONFIGURATION_TYPE PeripheralType OPTIONAL,
|
|
|
|
PULONG PeripheralNumber OPTIONAL,
|
2001-04-04 22:21:32 +00:00
|
|
|
PIO_QUERY_DEVICE_ROUTINE CalloutRoutine,
|
|
|
|
PVOID Context)
|
1998-08-25 04:27:26 +00:00
|
|
|
{
|
2004-05-30 18:30:03 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG BusLoopNumber = -1; /* Root Bus */
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING RootRegKey;
|
|
|
|
HANDLE RootRegHandle;
|
|
|
|
IO_QUERY Query;
|
2001-09-27 02:14:35 +00:00
|
|
|
|
2004-05-30 18:30:03 +00:00
|
|
|
/* Set up the String */
|
|
|
|
RootRegKey.Length = 0;
|
|
|
|
RootRegKey.MaximumLength = 2048;
|
|
|
|
RootRegKey.Buffer = ExAllocatePoolWithTag(PagedPool, RootRegKey.MaximumLength, TAG_IO_RESOURCE);
|
2010-12-21 22:24:50 +00:00
|
|
|
RtlAppendUnicodeToString(&RootRegKey, L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2004-05-30 18:30:03 +00:00
|
|
|
/* 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 info */
|
|
|
|
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 */
|
|
|
|
ZwClose(RootRegHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free Memory */
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(RootRegKey.Buffer, TAG_IO_RESOURCE);
|
2004-05-30 18:30:03 +00:00
|
|
|
|
|
|
|
return Status;
|
1998-08-25 04:27:26 +00:00
|
|
|
}
|
2000-03-26 19:38:32 +00:00
|
|
|
|
2003-07-10 15:47:00 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2008-11-29 20:47:48 +00:00
|
|
|
NTSTATUS NTAPI
|
2001-09-05 09:21:47 +00:00
|
|
|
IoReportHalResourceUsage(PUNICODE_STRING HalDescription,
|
|
|
|
PCM_RESOURCE_LIST RawList,
|
|
|
|
PCM_RESOURCE_LIST TranslatedList,
|
|
|
|
ULONG ListSize)
|
|
|
|
/*
|
|
|
|
* FUNCTION:
|
|
|
|
* Reports hardware resources of the HAL in the
|
|
|
|
* \Registry\Machine\Hardware\ResourceMap tree.
|
|
|
|
* ARGUMENTS:
|
|
|
|
* HalDescription: Descriptive name of the HAL.
|
|
|
|
* RawList: List of raw (bus specific) resources which should be
|
|
|
|
* claimed for the HAL.
|
|
|
|
* TranslatedList: List of translated (system wide) resources which
|
|
|
|
* should be claimed for the HAL.
|
|
|
|
* ListSize: Size in bytes of the raw and translated resource lists.
|
|
|
|
* Both lists have the same size.
|
|
|
|
* RETURNS:
|
|
|
|
* Status.
|
|
|
|
*/
|
2000-04-05 15:52:45 +00:00
|
|
|
{
|
2001-09-05 09:21:47 +00:00
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
UNICODE_STRING Name;
|
|
|
|
ULONG Disposition;
|
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE ResourcemapKey;
|
|
|
|
HANDLE HalKey;
|
|
|
|
HANDLE DescriptionKey;
|
|
|
|
|
|
|
|
/* Open/Create 'RESOURCEMAP' key. */
|
2005-06-25 14:04:56 +00:00
|
|
|
RtlInitUnicodeString(&Name,
|
2001-09-05 09:21:47 +00:00
|
|
|
L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&Name,
|
|
|
|
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
|
|
|
|
0,
|
|
|
|
NULL);
|
2005-02-07 10:33:44 +00:00
|
|
|
Status = ZwCreateKey(&ResourcemapKey,
|
2001-09-05 09:21:47 +00:00
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
&ObjectAttributes,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
REG_OPTION_VOLATILE,
|
|
|
|
&Disposition);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return(Status);
|
|
|
|
|
|
|
|
/* Open/Create 'Hardware Abstraction Layer' key */
|
2005-06-25 14:04:56 +00:00
|
|
|
RtlInitUnicodeString(&Name,
|
2001-09-05 09:21:47 +00:00
|
|
|
L"Hardware Abstraction Layer");
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&Name,
|
|
|
|
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
|
|
|
|
ResourcemapKey,
|
|
|
|
NULL);
|
2005-02-07 10:33:44 +00:00
|
|
|
Status = ZwCreateKey(&HalKey,
|
2001-09-05 09:21:47 +00:00
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
&ObjectAttributes,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
REG_OPTION_VOLATILE,
|
|
|
|
&Disposition);
|
2005-02-07 10:33:44 +00:00
|
|
|
ZwClose(ResourcemapKey);
|
2001-09-05 09:21:47 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return(Status);
|
|
|
|
|
|
|
|
/* Create 'HalDescription' key */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
HalDescription,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
HalKey,
|
|
|
|
NULL);
|
2005-02-07 10:33:44 +00:00
|
|
|
Status = ZwCreateKey(&DescriptionKey,
|
2001-09-05 09:21:47 +00:00
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
&ObjectAttributes,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
REG_OPTION_VOLATILE,
|
|
|
|
&Disposition);
|
2005-02-07 10:33:44 +00:00
|
|
|
ZwClose(HalKey);
|
2001-09-05 09:21:47 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return(Status);
|
|
|
|
|
|
|
|
/* Add '.Raw' value. */
|
2005-06-25 14:04:56 +00:00
|
|
|
RtlInitUnicodeString(&Name,
|
2001-09-05 09:21:47 +00:00
|
|
|
L".Raw");
|
2005-02-07 10:33:44 +00:00
|
|
|
Status = ZwSetValueKey(DescriptionKey,
|
2001-09-05 09:21:47 +00:00
|
|
|
&Name,
|
|
|
|
0,
|
|
|
|
REG_RESOURCE_LIST,
|
|
|
|
RawList,
|
|
|
|
ListSize);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2005-02-07 10:33:44 +00:00
|
|
|
ZwClose(DescriptionKey);
|
2001-09-05 09:21:47 +00:00
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add '.Translated' value. */
|
2005-06-25 14:04:56 +00:00
|
|
|
RtlInitUnicodeString(&Name,
|
2001-09-05 09:21:47 +00:00
|
|
|
L".Translated");
|
2005-02-07 10:33:44 +00:00
|
|
|
Status = ZwSetValueKey(DescriptionKey,
|
2001-09-05 09:21:47 +00:00
|
|
|
&Name,
|
|
|
|
0,
|
|
|
|
REG_RESOURCE_LIST,
|
|
|
|
TranslatedList,
|
|
|
|
ListSize);
|
2005-02-07 10:33:44 +00:00
|
|
|
ZwClose(DescriptionKey);
|
2001-09-05 09:21:47 +00:00
|
|
|
|
|
|
|
return(Status);
|
2000-04-05 15:52:45 +00:00
|
|
|
}
|
|
|
|
|
2000-03-26 19:38:32 +00:00
|
|
|
/* EOF */
|