2007-12-15 18:14:41 +00:00
|
|
|
/*
|
|
|
|
* 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 *****************************************************************/
|
|
|
|
|
|
|
|
LANGID
|
|
|
|
NTAPI
|
2010-11-02 16:29:06 +00:00
|
|
|
INIT_FUNCTION
|
2007-12-15 18:14:41 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
HCELL_INDEX
|
|
|
|
NTAPI
|
2010-11-02 16:29:06 +00:00
|
|
|
INIT_FUNCTION
|
2007-12-15 18:14:41 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
2010-11-02 16:29:06 +00:00
|
|
|
INIT_FUNCTION
|
2007-12-15 18:14:41 +00:00
|
|
|
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 */
|
2011-09-01 15:30:19 +00:00
|
|
|
RtlZeroMemory(SystemHive, sizeof(*SystemHive));
|
2007-12-15 18:14:41 +00:00
|
|
|
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;
|
|
|
|
}
|