reactos/ntoskrnl/config/cmcontrl.c
Timo Kreuzer 71fefa32db
[NDK][NTOS] Add global definition of INIT_FUNCTION/INIT_SECTION (#779)
* Add an NDK header to define INIT_FUNCTION/INIT_SECTION globally
* Use _declspec(allocate(x)) and _declspec(code_seg(x)) on MSVC versions that support it
* Use INIT_FUNCTION on functions only and INIT_SECTION on data only (required by MSVC)
* Place INIT_FUNCTION before the return type (required by MSVC)
* Make sure declarations and implementations share the same modifiers (required by MSVC)
* Add a global linker option to suppress warnings about defined but unused INIT section
* Merge INIT section into .text in freeldr
2018-12-30 12:19:11 +01:00

273 lines
8.3 KiB
C

/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmcontrl.c
* PURPOSE: Configuration Manager - Control Set Management
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
INIT_FUNCTION
LANGID
NTAPI
CmpConvertLangId(IN LPWSTR Name,
IN ULONG NameLength)
{
ULONG i;
WCHAR p;
LANGID LangId = 0;
ULONG IdCode;
/* Convert the length in chars and loop */
NameLength = NameLength / sizeof(WCHAR);
for (i = 0; i < NameLength; i++)
{
/* Get the character */
p = Name[i];
/* Handle each case */
if ((p >= L'0') && (p <= L'9'))
{
/* Handle digits*/
IdCode = p - L'0';
}
else if ((p >= L'A') && (p <= L'F'))
{
/* Handle upper-case letters */
IdCode = p - L'A' + 10;
}
else if ((p >= L'a') && (p <= L'f'))
{
/* Handle lower-case letters */
IdCode = p - L'a' + 10;
}
else
{
/* Unhandled case, return what we have till now */
break;
}
/* If the ID Code is >= 16, then we're done */
if (IdCode >= 16) break;
/* Build the Language ID */
LangId = (LangId << 4) | (LANGID)IdCode;
}
/* Return the Language ID */
return LangId;
}
INIT_FUNCTION
HCELL_INDEX
NTAPI
CmpWalkPath(IN PHHIVE SystemHive,
IN HCELL_INDEX ParentCell,
IN LPWSTR Path)
{
UNICODE_STRING UnicodePath, NextName;
BOOLEAN LastName;
HCELL_INDEX CurrentCell = ParentCell;
PCM_KEY_NODE Node;
/* We shouldn't have a release routine at this point */
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
/* Initialize the Unicode path and start looping */
RtlInitUnicodeString(&UnicodePath, Path);
while (TRUE)
{
/* Get the next name */
CmpGetNextName(&UnicodePath, &NextName, &LastName);
if (!NextName.Length) return CurrentCell;
/* Get the subkey */
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, CurrentCell);
if (!Node) return HCELL_NIL;
CurrentCell = CmpFindSubKeyByName(SystemHive, Node, &NextName);
if (CurrentCell == HCELL_NIL) return CurrentCell;
}
}
INIT_FUNCTION
VOID
NTAPI
CmGetSystemControlValues(IN PVOID SystemHiveData,
IN PCM_SYSTEM_CONTROL_VECTOR ControlVector)
{
PHHIVE SystemHive = (PHHIVE)&CmControlHive;
NTSTATUS Status;
HCELL_INDEX RootCell, BaseCell, KeyCell, ValueCell;
ULONG Length, DataSize;
PCM_KEY_NODE Node;
PCM_KEY_VALUE ValueData;
UNICODE_STRING KeyName;
BOOLEAN Auto, IsSmallKey;
PVOID Buffer;
/* LUDDDIIIICRROOOUUSSSS KI^H^H HACKKKK */
if (!SystemHiveData) return;
/* Initialize the Hive View List and the security cache */
RtlZeroMemory(SystemHive, sizeof(*SystemHive));
CmpInitHiveViewList((PCMHIVE)SystemHive);
CmpInitSecurityCache((PCMHIVE)SystemHive);
/* Initialize the Hive */
Status = HvInitialize(SystemHive,
HINIT_FLAT,
HIVE_VOLATILE,
HFILE_TYPE_PRIMARY,
SystemHiveData,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
1,
NULL);
if (!NT_SUCCESS(Status)) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 1, 0, 0);
/* Sanity check, flat hives don't have release routines */
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
/* Set the Root Cell */
RootCell = ((PHBASE_BLOCK)SystemHiveData)->RootCell;
/* Find the current control set */
RtlInitUnicodeString(&KeyName, L"current");
BaseCell = CmpFindControlSet(SystemHive, RootCell, &KeyName, &Auto);
if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 2, 0, 0);
/* Find the control subkey */
RtlInitUnicodeString(&KeyName, L"control");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, BaseCell);
BaseCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO,1 , 3, 0, 0);
/* Loop each key */
while (ControlVector->KeyPath)
{
/* Assume failure */
Length = -1;
/* Get the cell for this key */
KeyCell = CmpWalkPath(SystemHive, BaseCell, ControlVector->KeyPath);
if (KeyCell != HCELL_NIL)
{
/* Now get the cell for the value */
RtlInitUnicodeString(&KeyName, ControlVector->ValueName);
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, KeyCell);
ValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
if (ValueCell != HCELL_NIL)
{
/* Check if there's any data */
if (!ControlVector->BufferLength)
{
/* No, the buffer will only be large enough for a ULONG */
DataSize = sizeof(ULONG);
}
else
{
/* Yes, save the data size */
DataSize = *ControlVector->BufferLength;
}
/* Get the actual data */
ValueData = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
/* Check if this is a small key */
IsSmallKey = CmpIsKeyValueSmall(&Length, ValueData->DataLength);
/* If the length is bigger then our buffer, normalize it */
if (DataSize < Length) Length = DataSize;
/* Make sure we have some data */
if (Length > 0)
{
/* Check if this was a small key */
if (IsSmallKey)
{
/* The buffer is directly safe to read */
Buffer = (PVOID)(&(ValueData->Data));
}
else
{
/* Use the longer path */
Buffer = (PVOID)HvGetCell(SystemHive, ValueData->Data);
}
/* Sanity check if this is a small key */
ASSERT((IsSmallKey ?
(Length <= CM_KEY_VALUE_SMALL) : TRUE));
/* Copy the data in the buffer */
RtlCopyMemory(ControlVector->Buffer, Buffer, Length);
}
/* Check if we should return the data type */
if (ControlVector->Type)
{
/* Return the type that we read */
*ControlVector->Type = ValueData->Type;
}
}
}
/* Return the size that we read */
if (ControlVector->BufferLength) *ControlVector->BufferLength = Length;
/* Go to the next entry */
ControlVector++;
}
/* Check if the ID is in the registry */
if (CmDefaultLanguageIdType == REG_SZ)
{
/* Read it */
PsDefaultSystemLocaleId =
(LCID)CmpConvertLangId(CmDefaultLanguageId,
CmDefaultLanguageIdLength);
}
else
{
/* Use EN_US by default */
PsDefaultSystemLocaleId = 0x409;
}
/* Check if the ID Is in the registry */
if (CmInstallUILanguageIdType == REG_SZ)
{
/* Read it */
PsInstallUILanguageId = CmpConvertLangId(CmInstallUILanguageId,
CmInstallUILanguageIdLength);
}
else
{
/* Otherwise, use the default */
PsInstallUILanguageId = LANGIDFROMLCID(PsDefaultSystemLocaleId);
}
/* Set the defaults for the Thread UI */
PsDefaultThreadLocaleId = PsDefaultSystemLocaleId;
PsDefaultUILanguageId = PsInstallUILanguageId;
}
NTSTATUS
NTAPI
CmpSaveBootControlSet(IN USHORT ControlSet)
{
DPRINT1("CmpSaveBootControlSet(%lu)\n", ControlSet);
return STATUS_SUCCESS;
}