- Implement NtCreateKey using the new parse routine.

- NtOpenKey should only return the key handle if the operation was successful.
- Point to new parse routine, and rename it to CmParseKey instead of CmParseKey2 which was used during the test phase.
- Delete all of the "cm" directory, this code is now fully gone; the new Configuration Manager is in place.
- Move cm.h and cm_x.h to include/internal where they belong to and fix all their includers.

svn path=/trunk/; revision=31252
This commit is contained in:
Aleksey Bragin 2007-12-15 18:14:41 +00:00
parent ffa5f05eca
commit 0b6a2fda00
34 changed files with 11540 additions and 12666 deletions

View file

@ -1,18 +0,0 @@
#ifndef __INCLUDE_CM_H
#define __INCLUDE_CM_H
#include "ntoskrnl/config/cm.h"
extern POBJECT_TYPE CmpKeyObjectType;
extern ERESOURCE CmpRegistryLock;
extern EX_PUSH_LOCK CmpHiveListHeadLock;
#define VERIFY_BIN_HEADER(x) ASSERT(x->HeaderId == REG_BIN_ID)
#define VERIFY_KEY_CELL(x) ASSERT(x->Signature == CM_KEY_NODE_SIGNATURE)
#define VERIFY_ROOT_KEY_CELL(x) ASSERT(x->Signature == CM_KEY_NODE_SIGNATURE)
#define VERIFY_VALUE_CELL(x) ASSERT(x->Signature == CM_KEY_VALUE_SIGNATURE)
#define VERIFY_VALUE_LIST_CELL(x)
#define VERIFY_KEY_OBJECT(x)
#define VERIFY_REGISTRY_HIVE(x)
#endif /*__INCLUDE_CM_H*/

File diff suppressed because it is too large Load diff

View file

@ -11,7 +11,6 @@
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#include "cm.h"
/* GLOBALS *******************************************************************/

View file

@ -9,7 +9,6 @@
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"

View file

@ -1,127 +1,126 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmboot.c
* PURPOSE: Configuration Manager - Boot Initialization
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
HCELL_INDEX
NTAPI
CmpFindControlSet(IN PHHIVE SystemHive,
IN HCELL_INDEX RootCell,
IN PUNICODE_STRING SelectKeyName,
OUT PBOOLEAN AutoSelect)
{
UNICODE_STRING KeyName;
PCM_KEY_NODE Node;
HCELL_INDEX SelectCell, AutoSelectCell, SelectValueCell, ControlSetCell;
HCELL_INDEX CurrentValueCell;
PCM_KEY_VALUE KeyValue;
ULONG Length;
PULONG ControlSetId;
ANSI_STRING ControlSetAnsiName;
CHAR Buffer[128];
WCHAR WideBuffer[128];
NTSTATUS Status;
PULONG CurrentData;
/* Sanity check */
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
/* Get the Select subkey */
RtlInitUnicodeString(&KeyName, L"select");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
if (!Node) return HCELL_NIL;
SelectCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
if (SelectCell == HCELL_NIL) return SelectCell;
/* Get AutoSelect value */
RtlInitUnicodeString(&KeyName, L"AutoSelect");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
if (!Node) return HCELL_NIL;
AutoSelectCell = CmpFindValueByName(SystemHive, Node, &KeyName);
if (AutoSelectCell == HCELL_NIL)
{
/* Assume TRUE if the value is missing. */
*AutoSelect = TRUE;
}
else
{
/* Read the value */
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
if (KeyValue == NULL) return HCELL_NIL;
/* Convert it to a boolean */
*AutoSelect = *(PBOOLEAN)CmpValueToData(SystemHive, KeyValue, &Length);
}
/* Now find the control set being looked up */
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
if (!Node) return HCELL_NIL;
SelectValueCell = CmpFindValueByName(SystemHive, Node, SelectKeyName);
if (SelectValueCell == HCELL_NIL) return SelectValueCell;
/* Read the value (corresponding to the CCS ID) */
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, SelectValueCell);
if (!KeyValue) return HCELL_NIL;
if (KeyValue->Type != REG_DWORD) return HCELL_NIL;
ControlSetId = (PULONG)CmpValueToData(SystemHive, KeyValue, &Length);
/* Now build an Ansi String for the CCS's Name */
sprintf(Buffer, "ControlSet%03lu", *ControlSetId);
ControlSetAnsiName.Length = (USHORT)strlen(Buffer);
ControlSetAnsiName.MaximumLength = (USHORT)strlen(Buffer);
ControlSetAnsiName.Buffer = Buffer;
/* And convert it to Unicode... */
KeyName.MaximumLength = 256;
KeyName.Buffer = WideBuffer;
Status = RtlAnsiStringToUnicodeString(&KeyName,
&ControlSetAnsiName,
FALSE);
if (!NT_SUCCESS(Status)) return HCELL_NIL;
/* Now open it */
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
if (!Node) return HCELL_NIL;
ControlSetCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
if (ControlSetCell == HCELL_NIL) return ControlSetCell;
/* Get the value of the "Current" CCS */
RtlInitUnicodeString(&KeyName, L"Current");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
if (!Node) return HCELL_NIL;
CurrentValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
/* Make sure it exists */
if (CurrentValueCell != HCELL_NIL)
{
/* Get the current value and make sure its a ULONG */
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, CurrentValueCell);
if (!KeyValue) return HCELL_NIL;
if (KeyValue->Type == REG_DWORD)
{
/* Get the data and update it */
CurrentData = (PULONG)CmpValueToData(SystemHive,
KeyValue,
&Length);
if (!CurrentData) return HCELL_NIL;
*CurrentData = *ControlSetId;
}
}
/* Return the CCS Cell */
return ControlSetCell;
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmboot.c
* PURPOSE: Configuration Manager - Boot Initialization
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
HCELL_INDEX
NTAPI
CmpFindControlSet(IN PHHIVE SystemHive,
IN HCELL_INDEX RootCell,
IN PUNICODE_STRING SelectKeyName,
OUT PBOOLEAN AutoSelect)
{
UNICODE_STRING KeyName;
PCM_KEY_NODE Node;
HCELL_INDEX SelectCell, AutoSelectCell, SelectValueCell, ControlSetCell;
HCELL_INDEX CurrentValueCell;
PCM_KEY_VALUE KeyValue;
ULONG Length;
PULONG ControlSetId;
ANSI_STRING ControlSetAnsiName;
CHAR Buffer[128];
WCHAR WideBuffer[128];
NTSTATUS Status;
PULONG CurrentData;
/* Sanity check */
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
/* Get the Select subkey */
RtlInitUnicodeString(&KeyName, L"select");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
if (!Node) return HCELL_NIL;
SelectCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
if (SelectCell == HCELL_NIL) return SelectCell;
/* Get AutoSelect value */
RtlInitUnicodeString(&KeyName, L"AutoSelect");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
if (!Node) return HCELL_NIL;
AutoSelectCell = CmpFindValueByName(SystemHive, Node, &KeyName);
if (AutoSelectCell == HCELL_NIL)
{
/* Assume TRUE if the value is missing. */
*AutoSelect = TRUE;
}
else
{
/* Read the value */
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
if (KeyValue == NULL) return HCELL_NIL;
/* Convert it to a boolean */
*AutoSelect = *(PBOOLEAN)CmpValueToData(SystemHive, KeyValue, &Length);
}
/* Now find the control set being looked up */
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
if (!Node) return HCELL_NIL;
SelectValueCell = CmpFindValueByName(SystemHive, Node, SelectKeyName);
if (SelectValueCell == HCELL_NIL) return SelectValueCell;
/* Read the value (corresponding to the CCS ID) */
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, SelectValueCell);
if (!KeyValue) return HCELL_NIL;
if (KeyValue->Type != REG_DWORD) return HCELL_NIL;
ControlSetId = (PULONG)CmpValueToData(SystemHive, KeyValue, &Length);
/* Now build an Ansi String for the CCS's Name */
sprintf(Buffer, "ControlSet%03lu", *ControlSetId);
ControlSetAnsiName.Length = (USHORT)strlen(Buffer);
ControlSetAnsiName.MaximumLength = (USHORT)strlen(Buffer);
ControlSetAnsiName.Buffer = Buffer;
/* And convert it to Unicode... */
KeyName.MaximumLength = 256;
KeyName.Buffer = WideBuffer;
Status = RtlAnsiStringToUnicodeString(&KeyName,
&ControlSetAnsiName,
FALSE);
if (!NT_SUCCESS(Status)) return HCELL_NIL;
/* Now open it */
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
if (!Node) return HCELL_NIL;
ControlSetCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
if (ControlSetCell == HCELL_NIL) return ControlSetCell;
/* Get the value of the "Current" CCS */
RtlInitUnicodeString(&KeyName, L"Current");
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
if (!Node) return HCELL_NIL;
CurrentValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
/* Make sure it exists */
if (CurrentValueCell != HCELL_NIL)
{
/* Get the current value and make sure its a ULONG */
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, CurrentValueCell);
if (!KeyValue) return HCELL_NIL;
if (KeyValue->Type == REG_DWORD)
{
/* Get the data and update it */
CurrentData = (PULONG)CmpValueToData(SystemHive,
KeyValue,
&Length);
if (!CurrentData) return HCELL_NIL;
*CurrentData = *ControlSetId;
}
}
/* Return the CCS Cell */
return ControlSetCell;
}

View file

@ -1,27 +1,26 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmcheck.c
* PURPOSE: Configuration Manager - Hive and Key Validation
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
ULONG
NTAPI
CmCheckRegistry(IN PCMHIVE RegistryHive,
IN ULONG Flags)
{
/* FIXME: HACK! */
return 0;
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmcheck.c
* PURPOSE: Configuration Manager - Hive and Key Validation
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
ULONG
NTAPI
CmCheckRegistry(IN PCMHIVE RegistryHive,
IN ULONG Flags)
{
/* FIXME: HACK! */
return 0;
}

View file

@ -1,399 +1,398 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmconfig.c
* PURPOSE: Configuration Manager - System Configuration Routines
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
IN HANDLE NodeHandle,
OUT PHANDLE NewHandle,
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN PUSHORT DeviceIndexTable)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName, ValueName, ValueData;
HANDLE KeyHandle, ParentHandle;
ANSI_STRING TempString;
CHAR TempBuffer[12];
WCHAR Buffer[12];
PCONFIGURATION_COMPONENT Component;
ULONG Disposition, Length = 0;
/* Get the component */
Component = &CurrentEntry->ComponentEntry;
/* Set system class components to ARC system type */
if (Component->Class == SystemClass) Component->Type = ArcSystem;
/* Create a key for the component */
InitializeObjectAttributes(&ObjectAttributes,
&CmTypeName[Component->Type],
OBJ_CASE_INSENSITIVE,
NodeHandle,
NULL);
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
&Disposition);
if (!NT_SUCCESS(Status)) return Status;
/* Check if this is anything but a system class component */
if (Component->Class != SystemClass)
{
/* Build the sub-component string */
RtlIntegerToChar(DeviceIndexTable[Component->Type]++,
10,
12,
TempBuffer);
RtlInitAnsiString(&TempString, TempBuffer);
/* Convert it to Unicode */
RtlInitEmptyUnicodeString(&KeyName, Buffer, sizeof(Buffer));
RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE);
/* Create the key */
ParentHandle = KeyHandle;
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ParentHandle,
NULL);
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
&Disposition);
NtClose(ParentHandle);
/* Fail if the key couldn't be created, and make sure it's a new key */
if (!NT_SUCCESS(Status)) return Status;
ASSERT(Disposition == REG_CREATED_NEW_KEY);
}
/* Setup the component information key */
RtlInitUnicodeString(&ValueName, L"Component Information");
Status = NtSetValueKey(KeyHandle,
&ValueName,
0,
REG_BINARY,
&Component->Flags,
FIELD_OFFSET(CONFIGURATION_COMPONENT,
ConfigurationDataLength) -
FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags));
if (!NT_SUCCESS(Status))
{
/* Fail */
NtClose(KeyHandle);
return Status;
}
/* Check if we have an identifier */
if (Component->IdentifierLength)
{
/* Build the string and convert it to Unicode */
RtlInitUnicodeString(&ValueName, L"Identifier");
RtlInitAnsiString(&TempString, Component->Identifier);
Status = RtlAnsiStringToUnicodeString(&ValueData,
&TempString,
TRUE);
RtlCreateUnicodeString(&ValueData, (PWCHAR)Component->Identifier);
if (NT_SUCCESS(Status))
{
/* Save the identifier in the registry */
Status = NtSetValueKey(KeyHandle,
&ValueName,
0,
REG_SZ,
ValueData.Buffer,
ValueData.Length + sizeof(UNICODE_NULL));
RtlFreeUnicodeString(&ValueData);
}
/* Check for failure during conversion or registry write */
if (!NT_SUCCESS(Status))
{
/* Fail */
NtClose(KeyHandle);
return Status;
}
}
/* Setup the configuration data string */
RtlInitUnicodeString(&ValueName, L"Configuration Data");
/* Check if we got configuration data */
if (CurrentEntry->ConfigurationData)
{
/* Calculate the total length and check if it fits into our buffer */
Length = Component->ConfigurationDataLength +
FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList);
if (Length > CmpConfigurationAreaSize)
{
ASSERTMSG("Component too large -- need reallocation!", FALSE);
}
else
{
/* Copy the data */
RtlCopyMemory(&CmpConfigurationData->PartialResourceList.Version,
CurrentEntry->ConfigurationData,
Component->ConfigurationDataLength);
}
}
else
{
/* No configuration data, setup defaults */
CmpConfigurationData->PartialResourceList.Version = 0;
CmpConfigurationData->PartialResourceList.Revision = 0;
CmpConfigurationData->PartialResourceList.Count = 0;
Length = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList);
}
/* Set the interface type and bus number */
CmpConfigurationData->InterfaceType = InterfaceType;
CmpConfigurationData->BusNumber = BusNumber;
/* Save the actual data */
Status = NtSetValueKey(KeyHandle,
&ValueName,
0,
REG_FULL_RESOURCE_DESCRIPTOR,
CmpConfigurationData,
Length);
if (!NT_SUCCESS(Status))
{
/* Fail */
NtClose(KeyHandle);
}
else
{
/* Return the new handle */
*NewHandle = KeyHandle;
}
/* Return status */
return Status;
}
NTSTATUS
NTAPI
CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
IN HANDLE ParentHandle,
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber)
{
PCONFIGURATION_COMPONENT Component;
USHORT DeviceIndexTable[MaximumType + 1] = {0};
ULONG Interface = InterfaceType, Bus = BusNumber, i;
NTSTATUS Status;
HANDLE NewHandle;
/* Loop each entry */
while (CurrentEntry)
{
/* Check if this is an adapter */
Component = &CurrentEntry->ComponentEntry;
if ((Component->Class == AdapterClass) &&
(CurrentEntry->Parent->ComponentEntry.Class == SystemClass))
{
/* Check what kind of adapter it is */
switch (Component->Type)
{
/* EISA */
case EisaAdapter:
/* Fixup information */
Interface = Eisa;
Bus = CmpTypeCount[EisaAdapter]++;
break;
/* Turbo-channel */
case TcAdapter:
/* Fixup information */
Interface = TurboChannel;
Bus = CmpTypeCount[TurboChannel]++;
break;
/* ISA, PCI, etc busses */
case MultiFunctionAdapter:
/* Check if we have an identifier */
if (Component->Identifier)
{
/* Loop each multi-function adapter type */
for (i = 0; CmpMultifunctionTypes[i].Identifier; i++)
{
/* Check for a name match */
if (!_wcsicmp(CmpMultifunctionTypes[i].Identifier,
(PWCHAR)Component->Identifier))
{
/* Match found */
break;
}
}
/* Fix up information */
Interface = CmpMultifunctionTypes[i].InterfaceType;
Bus = CmpMultifunctionTypes[i].Count++;
}
break;
/* SCSI Bus */
case ScsiAdapter:
/* Fix up */
Interface = Internal;
Bus = CmpTypeCount[ScsiAdapter]++;
break;
/* Unknown */
default:
Interface = -1;
Bus = CmpUnknownBusCount++;
break;
}
}
/* Dump information on the component */
/* Setup the hardware node */
Status = CmpInitializeRegistryNode(CurrentEntry,
ParentHandle,
&NewHandle,
Interface,
Bus,
DeviceIndexTable);
if (!NT_SUCCESS(Status)) return Status;
/* Check for children */
if (CurrentEntry->Child)
{
/* Recurse child */
Status = CmpSetupConfigurationTree(CurrentEntry->Child,
NewHandle,
Interface,
Bus);
if (!NT_SUCCESS(Status))
{
/* Fail */
NtClose(NewHandle);
return Status;
}
}
/* Get to the next entry */
NtClose(NewHandle);
CurrentEntry = CurrentEntry->Sibling;
}
/* We're done */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE KeyHandle;
ULONG Disposition;
UNICODE_STRING KeyName;
/* Setup the key name */
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\Hardware\\DeviceMap");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
/* Create the device map key */
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
&Disposition);
if (!NT_SUCCESS(Status)) return Status;
NtClose(KeyHandle);
/* Nobody should've created this key yet! */
ASSERT(Disposition == REG_CREATED_NEW_KEY);
/* Setup the key name */
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\Hardware\\Description");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
/* Create the description key */
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
&Disposition);
if (!NT_SUCCESS(Status)) return Status;
/* Nobody should've created this key yet! */
ASSERT(Disposition == REG_CREATED_NEW_KEY);
/* Allocate the configuration data buffer */
CmpConfigurationData = ExAllocatePoolWithTag(PagedPool,
CmpConfigurationAreaSize,
TAG_CM);
if (!CmpConfigurationData) return STATUS_INSUFFICIENT_RESOURCES;
/* Check if we got anything from NTLDR */
if (LoaderBlock->ConfigurationRoot)
{
/* Setup the configuration tree */
Status = CmpSetupConfigurationTree(LoaderBlock->ConfigurationRoot,
KeyHandle,
-1,
-1);
}
else
{
/* Nothing else to do */
Status = STATUS_SUCCESS;
}
/* Close our handle, free the buffer and return status */
ExFreePool(CmpConfigurationData);
NtClose(KeyHandle);
return Status;
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmconfig.c
* PURPOSE: Configuration Manager - System Configuration Routines
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
IN HANDLE NodeHandle,
OUT PHANDLE NewHandle,
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber,
IN PUSHORT DeviceIndexTable)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName, ValueName, ValueData;
HANDLE KeyHandle, ParentHandle;
ANSI_STRING TempString;
CHAR TempBuffer[12];
WCHAR Buffer[12];
PCONFIGURATION_COMPONENT Component;
ULONG Disposition, Length = 0;
/* Get the component */
Component = &CurrentEntry->ComponentEntry;
/* Set system class components to ARC system type */
if (Component->Class == SystemClass) Component->Type = ArcSystem;
/* Create a key for the component */
InitializeObjectAttributes(&ObjectAttributes,
&CmTypeName[Component->Type],
OBJ_CASE_INSENSITIVE,
NodeHandle,
NULL);
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
&Disposition);
if (!NT_SUCCESS(Status)) return Status;
/* Check if this is anything but a system class component */
if (Component->Class != SystemClass)
{
/* Build the sub-component string */
RtlIntegerToChar(DeviceIndexTable[Component->Type]++,
10,
12,
TempBuffer);
RtlInitAnsiString(&TempString, TempBuffer);
/* Convert it to Unicode */
RtlInitEmptyUnicodeString(&KeyName, Buffer, sizeof(Buffer));
RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE);
/* Create the key */
ParentHandle = KeyHandle;
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ParentHandle,
NULL);
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
&Disposition);
NtClose(ParentHandle);
/* Fail if the key couldn't be created, and make sure it's a new key */
if (!NT_SUCCESS(Status)) return Status;
ASSERT(Disposition == REG_CREATED_NEW_KEY);
}
/* Setup the component information key */
RtlInitUnicodeString(&ValueName, L"Component Information");
Status = NtSetValueKey(KeyHandle,
&ValueName,
0,
REG_BINARY,
&Component->Flags,
FIELD_OFFSET(CONFIGURATION_COMPONENT,
ConfigurationDataLength) -
FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags));
if (!NT_SUCCESS(Status))
{
/* Fail */
NtClose(KeyHandle);
return Status;
}
/* Check if we have an identifier */
if (Component->IdentifierLength)
{
/* Build the string and convert it to Unicode */
RtlInitUnicodeString(&ValueName, L"Identifier");
RtlInitAnsiString(&TempString, Component->Identifier);
Status = RtlAnsiStringToUnicodeString(&ValueData,
&TempString,
TRUE);
RtlCreateUnicodeString(&ValueData, (PWCHAR)Component->Identifier);
if (NT_SUCCESS(Status))
{
/* Save the identifier in the registry */
Status = NtSetValueKey(KeyHandle,
&ValueName,
0,
REG_SZ,
ValueData.Buffer,
ValueData.Length + sizeof(UNICODE_NULL));
RtlFreeUnicodeString(&ValueData);
}
/* Check for failure during conversion or registry write */
if (!NT_SUCCESS(Status))
{
/* Fail */
NtClose(KeyHandle);
return Status;
}
}
/* Setup the configuration data string */
RtlInitUnicodeString(&ValueName, L"Configuration Data");
/* Check if we got configuration data */
if (CurrentEntry->ConfigurationData)
{
/* Calculate the total length and check if it fits into our buffer */
Length = Component->ConfigurationDataLength +
FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList);
if (Length > CmpConfigurationAreaSize)
{
ASSERTMSG("Component too large -- need reallocation!", FALSE);
}
else
{
/* Copy the data */
RtlCopyMemory(&CmpConfigurationData->PartialResourceList.Version,
CurrentEntry->ConfigurationData,
Component->ConfigurationDataLength);
}
}
else
{
/* No configuration data, setup defaults */
CmpConfigurationData->PartialResourceList.Version = 0;
CmpConfigurationData->PartialResourceList.Revision = 0;
CmpConfigurationData->PartialResourceList.Count = 0;
Length = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList);
}
/* Set the interface type and bus number */
CmpConfigurationData->InterfaceType = InterfaceType;
CmpConfigurationData->BusNumber = BusNumber;
/* Save the actual data */
Status = NtSetValueKey(KeyHandle,
&ValueName,
0,
REG_FULL_RESOURCE_DESCRIPTOR,
CmpConfigurationData,
Length);
if (!NT_SUCCESS(Status))
{
/* Fail */
NtClose(KeyHandle);
}
else
{
/* Return the new handle */
*NewHandle = KeyHandle;
}
/* Return status */
return Status;
}
NTSTATUS
NTAPI
CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
IN HANDLE ParentHandle,
IN INTERFACE_TYPE InterfaceType,
IN ULONG BusNumber)
{
PCONFIGURATION_COMPONENT Component;
USHORT DeviceIndexTable[MaximumType + 1] = {0};
ULONG Interface = InterfaceType, Bus = BusNumber, i;
NTSTATUS Status;
HANDLE NewHandle;
/* Loop each entry */
while (CurrentEntry)
{
/* Check if this is an adapter */
Component = &CurrentEntry->ComponentEntry;
if ((Component->Class == AdapterClass) &&
(CurrentEntry->Parent->ComponentEntry.Class == SystemClass))
{
/* Check what kind of adapter it is */
switch (Component->Type)
{
/* EISA */
case EisaAdapter:
/* Fixup information */
Interface = Eisa;
Bus = CmpTypeCount[EisaAdapter]++;
break;
/* Turbo-channel */
case TcAdapter:
/* Fixup information */
Interface = TurboChannel;
Bus = CmpTypeCount[TurboChannel]++;
break;
/* ISA, PCI, etc busses */
case MultiFunctionAdapter:
/* Check if we have an identifier */
if (Component->Identifier)
{
/* Loop each multi-function adapter type */
for (i = 0; CmpMultifunctionTypes[i].Identifier; i++)
{
/* Check for a name match */
if (!_wcsicmp(CmpMultifunctionTypes[i].Identifier,
(PWCHAR)Component->Identifier))
{
/* Match found */
break;
}
}
/* Fix up information */
Interface = CmpMultifunctionTypes[i].InterfaceType;
Bus = CmpMultifunctionTypes[i].Count++;
}
break;
/* SCSI Bus */
case ScsiAdapter:
/* Fix up */
Interface = Internal;
Bus = CmpTypeCount[ScsiAdapter]++;
break;
/* Unknown */
default:
Interface = -1;
Bus = CmpUnknownBusCount++;
break;
}
}
/* Dump information on the component */
/* Setup the hardware node */
Status = CmpInitializeRegistryNode(CurrentEntry,
ParentHandle,
&NewHandle,
Interface,
Bus,
DeviceIndexTable);
if (!NT_SUCCESS(Status)) return Status;
/* Check for children */
if (CurrentEntry->Child)
{
/* Recurse child */
Status = CmpSetupConfigurationTree(CurrentEntry->Child,
NewHandle,
Interface,
Bus);
if (!NT_SUCCESS(Status))
{
/* Fail */
NtClose(NewHandle);
return Status;
}
}
/* Get to the next entry */
NtClose(NewHandle);
CurrentEntry = CurrentEntry->Sibling;
}
/* We're done */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE KeyHandle;
ULONG Disposition;
UNICODE_STRING KeyName;
/* Setup the key name */
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\Hardware\\DeviceMap");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
/* Create the device map key */
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
&Disposition);
if (!NT_SUCCESS(Status)) return Status;
NtClose(KeyHandle);
/* Nobody should've created this key yet! */
ASSERT(Disposition == REG_CREATED_NEW_KEY);
/* Setup the key name */
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\Hardware\\Description");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
/* Create the description key */
Status = NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
0,
NULL,
0,
&Disposition);
if (!NT_SUCCESS(Status)) return Status;
/* Nobody should've created this key yet! */
ASSERT(Disposition == REG_CREATED_NEW_KEY);
/* Allocate the configuration data buffer */
CmpConfigurationData = ExAllocatePoolWithTag(PagedPool,
CmpConfigurationAreaSize,
TAG_CM);
if (!CmpConfigurationData) return STATUS_INSUFFICIENT_RESOURCES;
/* Check if we got anything from NTLDR */
if (LoaderBlock->ConfigurationRoot)
{
/* Setup the configuration tree */
Status = CmpSetupConfigurationTree(LoaderBlock->ConfigurationRoot,
KeyHandle,
-1,
-1);
}
else
{
/* Nothing else to do */
Status = STATUS_SUCCESS;
}
/* Close our handle, free the buffer and return status */
ExFreePool(CmpConfigurationData);
NtClose(KeyHandle);
return Status;
}

View file

@ -1,265 +1,264 @@
/*
* 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"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
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;
}
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;
}
}
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);
/* FIXME: Prepare it */
CmPrepareHive(SystemHive);
/* 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;
}
/*
* 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
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
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
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);
/* FIXME: Prepare it */
CmPrepareHive(SystemHive);
/* 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;
}

File diff suppressed because it is too large Load diff

View file

@ -11,7 +11,6 @@
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#include "cm.h"
/* GLOBALS *******************************************************************/

View file

@ -1,198 +1,197 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmhook.c
* PURPOSE: Configuration Manager - Registry Notifications/Callbacks
* PROGRAMMERS: Thomas Weidenmueller (w3seek@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
ULONG CmpCallBackCount = 0;
EX_CALLBACK CmpCallBackVector[100];
LIST_ENTRY CmiCallbackHead;
FAST_MUTEX CmiCallbackLock;
typedef struct _REGISTRY_CALLBACK
{
LIST_ENTRY ListEntry;
EX_RUNDOWN_REF RundownRef;
PEX_CALLBACK_FUNCTION Function;
PVOID Context;
LARGE_INTEGER Cookie;
BOOLEAN PendingDelete;
} REGISTRY_CALLBACK, *PREGISTRY_CALLBACK;
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
CmpInitCallback(VOID)
{
ULONG i;
PAGED_CODE();
/* Reset counter */
CmpCallBackCount = 0;
/* Loop all the callbacks */
for (i = 0; i < CMP_MAX_CALLBACKS; i++)
{
/* Initialize this one */
ExInitializeCallBack(&CmpCallBackVector[i]);
}
/* ROS: Initialize old-style callbacks for now */
InitializeListHead(&CmiCallbackHead);
ExInitializeFastMutex(&CmiCallbackLock);
}
NTSTATUS
CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
IN PVOID Argument2)
{
PLIST_ENTRY CurrentEntry;
NTSTATUS Status = STATUS_SUCCESS;
PREGISTRY_CALLBACK CurrentCallback;
PAGED_CODE();
ExAcquireFastMutex(&CmiCallbackLock);
for (CurrentEntry = CmiCallbackHead.Flink;
CurrentEntry != &CmiCallbackHead;
CurrentEntry = CurrentEntry->Flink)
{
CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
if (!CurrentCallback->PendingDelete &&
ExAcquireRundownProtection(&CurrentCallback->RundownRef))
{
/* don't hold locks during the callbacks! */
ExReleaseFastMutex(&CmiCallbackLock);
Status = CurrentCallback->Function(CurrentCallback->Context,
(PVOID)Argument1,
Argument2);
ExAcquireFastMutex(&CmiCallbackLock);
/* don't release the rundown protection before holding the callback lock
so the pointer to the next callback isn't cleared in case this callback
get's deleted */
ExReleaseRundownProtection(&CurrentCallback->RundownRef);
if(!NT_SUCCESS(Status))
{
/* one callback returned failure, don't call any more callbacks */
break;
}
}
}
ExReleaseFastMutex(&CmiCallbackLock);
return Status;
}
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
*/
NTSTATUS
NTAPI
CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
IN PVOID Context,
IN OUT PLARGE_INTEGER Cookie)
{
PREGISTRY_CALLBACK Callback;
PAGED_CODE();
ASSERT(Function && Cookie);
Callback = ExAllocatePoolWithTag(PagedPool,
sizeof(REGISTRY_CALLBACK),
TAG('C', 'M', 'c', 'b'));
if (Callback != NULL)
{
/* initialize the callback */
ExInitializeRundownProtection(&Callback->RundownRef);
Callback->Function = Function;
Callback->Context = Context;
Callback->PendingDelete = FALSE;
/* add it to the callback list and receive a cookie for the callback */
ExAcquireFastMutex(&CmiCallbackLock);
/* FIXME - to receive a unique cookie we'll just return the pointer to the
callback object */
Callback->Cookie.QuadPart = (ULONG_PTR)Callback;
InsertTailList(&CmiCallbackHead, &Callback->ListEntry);
ExReleaseFastMutex(&CmiCallbackLock);
*Cookie = Callback->Cookie;
return STATUS_SUCCESS;
}
return STATUS_INSUFFICIENT_RESOURCES;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
{
PLIST_ENTRY CurrentEntry;
PREGISTRY_CALLBACK CurrentCallback;
PAGED_CODE();
ExAcquireFastMutex(&CmiCallbackLock);
for (CurrentEntry = CmiCallbackHead.Flink;
CurrentEntry != &CmiCallbackHead;
CurrentEntry = CurrentEntry->Flink)
{
CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
if (CurrentCallback->Cookie.QuadPart == Cookie.QuadPart)
{
if (!CurrentCallback->PendingDelete)
{
/* found the callback, don't unlink it from the list yet so we don't screw
the calling loop */
CurrentCallback->PendingDelete = TRUE;
ExReleaseFastMutex(&CmiCallbackLock);
/* if the callback is currently executing, wait until it finished */
ExWaitForRundownProtectionRelease(&CurrentCallback->RundownRef);
/* time to unlink it. It's now safe because every attempt to acquire a
runtime protection on this callback will fail */
ExAcquireFastMutex(&CmiCallbackLock);
RemoveEntryList(&CurrentCallback->ListEntry);
ExReleaseFastMutex(&CmiCallbackLock);
/* free the callback */
ExFreePool(CurrentCallback);
return STATUS_SUCCESS;
}
else
{
/* pending delete, pretend like it already is deleted */
ExReleaseFastMutex(&CmiCallbackLock);
return STATUS_UNSUCCESSFUL;
}
}
}
ExReleaseFastMutex(&CmiCallbackLock);
return STATUS_UNSUCCESSFUL;
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmhook.c
* PURPOSE: Configuration Manager - Registry Notifications/Callbacks
* PROGRAMMERS: Thomas Weidenmueller (w3seek@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
ULONG CmpCallBackCount = 0;
EX_CALLBACK CmpCallBackVector[100];
LIST_ENTRY CmiCallbackHead;
FAST_MUTEX CmiCallbackLock;
typedef struct _REGISTRY_CALLBACK
{
LIST_ENTRY ListEntry;
EX_RUNDOWN_REF RundownRef;
PEX_CALLBACK_FUNCTION Function;
PVOID Context;
LARGE_INTEGER Cookie;
BOOLEAN PendingDelete;
} REGISTRY_CALLBACK, *PREGISTRY_CALLBACK;
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
CmpInitCallback(VOID)
{
ULONG i;
PAGED_CODE();
/* Reset counter */
CmpCallBackCount = 0;
/* Loop all the callbacks */
for (i = 0; i < CMP_MAX_CALLBACKS; i++)
{
/* Initialize this one */
ExInitializeCallBack(&CmpCallBackVector[i]);
}
/* ROS: Initialize old-style callbacks for now */
InitializeListHead(&CmiCallbackHead);
ExInitializeFastMutex(&CmiCallbackLock);
}
NTSTATUS
CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
IN PVOID Argument2)
{
PLIST_ENTRY CurrentEntry;
NTSTATUS Status = STATUS_SUCCESS;
PREGISTRY_CALLBACK CurrentCallback;
PAGED_CODE();
ExAcquireFastMutex(&CmiCallbackLock);
for (CurrentEntry = CmiCallbackHead.Flink;
CurrentEntry != &CmiCallbackHead;
CurrentEntry = CurrentEntry->Flink)
{
CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
if (!CurrentCallback->PendingDelete &&
ExAcquireRundownProtection(&CurrentCallback->RundownRef))
{
/* don't hold locks during the callbacks! */
ExReleaseFastMutex(&CmiCallbackLock);
Status = CurrentCallback->Function(CurrentCallback->Context,
(PVOID)Argument1,
Argument2);
ExAcquireFastMutex(&CmiCallbackLock);
/* don't release the rundown protection before holding the callback lock
so the pointer to the next callback isn't cleared in case this callback
get's deleted */
ExReleaseRundownProtection(&CurrentCallback->RundownRef);
if(!NT_SUCCESS(Status))
{
/* one callback returned failure, don't call any more callbacks */
break;
}
}
}
ExReleaseFastMutex(&CmiCallbackLock);
return Status;
}
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
*/
NTSTATUS
NTAPI
CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
IN PVOID Context,
IN OUT PLARGE_INTEGER Cookie)
{
PREGISTRY_CALLBACK Callback;
PAGED_CODE();
ASSERT(Function && Cookie);
Callback = ExAllocatePoolWithTag(PagedPool,
sizeof(REGISTRY_CALLBACK),
TAG('C', 'M', 'c', 'b'));
if (Callback != NULL)
{
/* initialize the callback */
ExInitializeRundownProtection(&Callback->RundownRef);
Callback->Function = Function;
Callback->Context = Context;
Callback->PendingDelete = FALSE;
/* add it to the callback list and receive a cookie for the callback */
ExAcquireFastMutex(&CmiCallbackLock);
/* FIXME - to receive a unique cookie we'll just return the pointer to the
callback object */
Callback->Cookie.QuadPart = (ULONG_PTR)Callback;
InsertTailList(&CmiCallbackHead, &Callback->ListEntry);
ExReleaseFastMutex(&CmiCallbackLock);
*Cookie = Callback->Cookie;
return STATUS_SUCCESS;
}
return STATUS_INSUFFICIENT_RESOURCES;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
{
PLIST_ENTRY CurrentEntry;
PREGISTRY_CALLBACK CurrentCallback;
PAGED_CODE();
ExAcquireFastMutex(&CmiCallbackLock);
for (CurrentEntry = CmiCallbackHead.Flink;
CurrentEntry != &CmiCallbackHead;
CurrentEntry = CurrentEntry->Flink)
{
CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
if (CurrentCallback->Cookie.QuadPart == Cookie.QuadPart)
{
if (!CurrentCallback->PendingDelete)
{
/* found the callback, don't unlink it from the list yet so we don't screw
the calling loop */
CurrentCallback->PendingDelete = TRUE;
ExReleaseFastMutex(&CmiCallbackLock);
/* if the callback is currently executing, wait until it finished */
ExWaitForRundownProtectionRelease(&CurrentCallback->RundownRef);
/* time to unlink it. It's now safe because every attempt to acquire a
runtime protection on this callback will fail */
ExAcquireFastMutex(&CmiCallbackLock);
RemoveEntryList(&CurrentCallback->ListEntry);
ExReleaseFastMutex(&CmiCallbackLock);
/* free the callback */
ExFreePool(CurrentCallback);
return STATUS_SUCCESS;
}
else
{
/* pending delete, pretend like it already is deleted */
ExReleaseFastMutex(&CmiCallbackLock);
return STATUS_UNSUCCESSFUL;
}
}
}
ExReleaseFastMutex(&CmiCallbackLock);
return STATUS_UNSUCCESSFUL;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,221 +1,220 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmkeydel.c
* PURPOSE: Configuration Manager - Key Body Deletion
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
CmpMarkKeyDirty(IN PHHIVE Hive,
IN HCELL_INDEX Cell,
IN BOOLEAN CheckNoSubkeys)
{
PCELL_DATA CellData, ListData, SecurityData, ValueData;
ULONG i;
/* Get the cell data for our target */
CellData = HvGetCell(Hive, Cell);
if (!CellData) return FALSE;
/* Check if sanity checks requested */
if (CheckNoSubkeys)
{
/* Do them */
ASSERT(CellData->u.KeyNode.SubKeyCounts[Stable] == 0);
ASSERT(CellData->u.KeyNode.SubKeyCounts[Volatile] == 0);
}
/* If this is an exit hive, there's nothing to do */
if (CellData->u.KeyNode.Flags & KEY_HIVE_EXIT)
{
/* Release the cell and get out */
HvReleaseCell(Hive, Cell);
return TRUE;
}
/* Otherwise, mark it dirty and release it */
HvMarkCellDirty(Hive, Cell, FALSE);
HvReleaseCell(Hive, Cell);
/* Check if we have a class */
if (CellData->u.KeyNode.Class != HCELL_NIL)
{
/* Mark it dirty */
HvMarkCellDirty(Hive, CellData->u.KeyNode.Class, FALSE);
}
/* Check if we have security */
if (CellData->u.KeyNode.Security != HCELL_NIL)
{
/* Mark it dirty */
HvMarkCellDirty(Hive, CellData->u.KeyNode.Security, FALSE);
/* Get the security data and release it */
SecurityData = HvGetCell(Hive, CellData->u.KeyNode.Security);
if (!SecurityData) ASSERT(FALSE);
HvReleaseCell(Hive, CellData->u.KeyNode.Security);
/* Mark the security links dirty too */
HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Flink, FALSE);
HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Blink, FALSE);
}
/* Check if we have any values */
if (CellData->u.KeyNode.ValueList.Count > 0)
{
/* Dirty the value list */
HvMarkCellDirty(Hive, CellData->u.KeyNode.ValueList.List, FALSE);
/* Get the list data itself, and release it */
ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
if (!ListData) ASSERT(FALSE);
HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
/* Loop all values */
for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
{
/* Dirty each value */
HvMarkCellDirty(Hive, ListData->u.KeyList[i], FALSE);
/* Get the value data and release it */
ValueData = HvGetCell(Hive, ListData->u.KeyList[i]);
ASSERT(ValueData);
HvReleaseCell(Hive,ListData->u.KeyList[i]);
/* Mark the value data dirty too */
if (!CmpMarkValueDataDirty(Hive, &ValueData->u.KeyValue))
{
/* Failure */
return FALSE;
}
}
}
/* If this is an entry hive, we're done */
if (CellData->u.KeyNode.Flags & KEY_HIVE_ENTRY) return TRUE;
/* Otherwise mark the index dirty too */
if (!CmpMarkIndexDirty(Hive, CellData->u.KeyNode.Parent, Cell))
{
/* Failure */
return FALSE;
}
/* Finally, mark the parent dirty */
HvMarkCellDirty(Hive, CellData->u.KeyNode.Parent, FALSE);
return TRUE;
}
BOOLEAN
NTAPI
CmpFreeKeyBody(IN PHHIVE Hive,
IN HCELL_INDEX Cell)
{
PCELL_DATA CellData;
/* Get the key node */
CellData = HvGetCell(Hive, Cell);
if (!CellData) ASSERT(FALSE);
/* Check if we can delete the child cells */
if (!(CellData->u.KeyNode.Flags & KEY_HIVE_EXIT))
{
/* Check if we have a security cell */
if (CellData->u.KeyNode.Security != HCELL_NIL)
{
/* Free the security cell */
HvFreeCell(Hive, CellData->u.KeyNode.Security);
}
/* Check if we have a class */
if (CellData->u.KeyNode.ClassLength > 0)
{
/* Free it */
HvFreeCell(Hive, CellData->u.KeyNode.Class);
}
}
/* Release and free the cell */
HvReleaseCell(Hive, Cell);
HvFreeCell(Hive, Cell);
return TRUE;
}
NTSTATUS
NTAPI
CmpFreeKeyByCell(IN PHHIVE Hive,
IN HCELL_INDEX Cell,
IN BOOLEAN Unlink)
{
PCELL_DATA CellData, ParentData, ListData;
ULONG i;
BOOLEAN Result;
/* Mark the entire key dirty */
CmpMarkKeyDirty(Hive, Cell ,TRUE);
/* Get the target node and release it */
CellData = HvGetCell(Hive, Cell);
if (!CellData) ASSERT(FALSE);
HvReleaseCell(Hive, Cell);
/* Make sure we don't have subkeys */
ASSERT((CellData->u.KeyNode.SubKeyCounts[Stable] +
CellData->u.KeyNode.SubKeyCounts[Volatile]) == 0);
/* Check if we have to unlink */
if (Unlink)
{
/* Remove the subkey */
Result = CmpRemoveSubKey(Hive, CellData->u.KeyNode.Parent, Cell);
if (!Result) return STATUS_INSUFFICIENT_RESOURCES;
/* Get the parent node and release it */
ParentData = HvGetCell(Hive, CellData->u.KeyNode.Parent);
if (!ParentData) ASSERT(FALSE);
HvReleaseCell(Hive, CellData->u.KeyNode.Parent);
/* Check if the parent node has no more subkeys */
if (!(ParentData->u.KeyNode.SubKeyCounts[Stable] +
ParentData->u.KeyNode.SubKeyCounts[Volatile]))
{
/* Then free the cached name/class lengths */
ParentData->u.KeyNode.MaxNameLen = 0;
ParentData->u.KeyNode.MaxClassLen = 0;
}
}
/* Check if we have any values */
if (CellData->u.KeyNode.ValueList.Count > 0)
{
/* Get the value list and release it */
ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
if (!ListData) ASSERT(FALSE);
HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
/* Loop every value */
for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
{
/* Free it */
if (!CmpFreeValue(Hive, ListData->u.KeyList[i])) ASSERT(FALSE);
}
/* Free the value list */
HvFreeCell(Hive, CellData->u.KeyNode.ValueList.List);
}
/* Free the key body itself, and then return our status */
if (!CmpFreeKeyBody(Hive, Cell)) return STATUS_INSUFFICIENT_RESOURCES;
return STATUS_SUCCESS;
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmkeydel.c
* PURPOSE: Configuration Manager - Key Body Deletion
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
CmpMarkKeyDirty(IN PHHIVE Hive,
IN HCELL_INDEX Cell,
IN BOOLEAN CheckNoSubkeys)
{
PCELL_DATA CellData, ListData, SecurityData, ValueData;
ULONG i;
/* Get the cell data for our target */
CellData = HvGetCell(Hive, Cell);
if (!CellData) return FALSE;
/* Check if sanity checks requested */
if (CheckNoSubkeys)
{
/* Do them */
ASSERT(CellData->u.KeyNode.SubKeyCounts[Stable] == 0);
ASSERT(CellData->u.KeyNode.SubKeyCounts[Volatile] == 0);
}
/* If this is an exit hive, there's nothing to do */
if (CellData->u.KeyNode.Flags & KEY_HIVE_EXIT)
{
/* Release the cell and get out */
HvReleaseCell(Hive, Cell);
return TRUE;
}
/* Otherwise, mark it dirty and release it */
HvMarkCellDirty(Hive, Cell, FALSE);
HvReleaseCell(Hive, Cell);
/* Check if we have a class */
if (CellData->u.KeyNode.Class != HCELL_NIL)
{
/* Mark it dirty */
HvMarkCellDirty(Hive, CellData->u.KeyNode.Class, FALSE);
}
/* Check if we have security */
if (CellData->u.KeyNode.Security != HCELL_NIL)
{
/* Mark it dirty */
HvMarkCellDirty(Hive, CellData->u.KeyNode.Security, FALSE);
/* Get the security data and release it */
SecurityData = HvGetCell(Hive, CellData->u.KeyNode.Security);
if (!SecurityData) ASSERT(FALSE);
HvReleaseCell(Hive, CellData->u.KeyNode.Security);
/* Mark the security links dirty too */
HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Flink, FALSE);
HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Blink, FALSE);
}
/* Check if we have any values */
if (CellData->u.KeyNode.ValueList.Count > 0)
{
/* Dirty the value list */
HvMarkCellDirty(Hive, CellData->u.KeyNode.ValueList.List, FALSE);
/* Get the list data itself, and release it */
ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
if (!ListData) ASSERT(FALSE);
HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
/* Loop all values */
for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
{
/* Dirty each value */
HvMarkCellDirty(Hive, ListData->u.KeyList[i], FALSE);
/* Get the value data and release it */
ValueData = HvGetCell(Hive, ListData->u.KeyList[i]);
ASSERT(ValueData);
HvReleaseCell(Hive,ListData->u.KeyList[i]);
/* Mark the value data dirty too */
if (!CmpMarkValueDataDirty(Hive, &ValueData->u.KeyValue))
{
/* Failure */
return FALSE;
}
}
}
/* If this is an entry hive, we're done */
if (CellData->u.KeyNode.Flags & KEY_HIVE_ENTRY) return TRUE;
/* Otherwise mark the index dirty too */
if (!CmpMarkIndexDirty(Hive, CellData->u.KeyNode.Parent, Cell))
{
/* Failure */
return FALSE;
}
/* Finally, mark the parent dirty */
HvMarkCellDirty(Hive, CellData->u.KeyNode.Parent, FALSE);
return TRUE;
}
BOOLEAN
NTAPI
CmpFreeKeyBody(IN PHHIVE Hive,
IN HCELL_INDEX Cell)
{
PCELL_DATA CellData;
/* Get the key node */
CellData = HvGetCell(Hive, Cell);
if (!CellData) ASSERT(FALSE);
/* Check if we can delete the child cells */
if (!(CellData->u.KeyNode.Flags & KEY_HIVE_EXIT))
{
/* Check if we have a security cell */
if (CellData->u.KeyNode.Security != HCELL_NIL)
{
/* Free the security cell */
HvFreeCell(Hive, CellData->u.KeyNode.Security);
}
/* Check if we have a class */
if (CellData->u.KeyNode.ClassLength > 0)
{
/* Free it */
HvFreeCell(Hive, CellData->u.KeyNode.Class);
}
}
/* Release and free the cell */
HvReleaseCell(Hive, Cell);
HvFreeCell(Hive, Cell);
return TRUE;
}
NTSTATUS
NTAPI
CmpFreeKeyByCell(IN PHHIVE Hive,
IN HCELL_INDEX Cell,
IN BOOLEAN Unlink)
{
PCELL_DATA CellData, ParentData, ListData;
ULONG i;
BOOLEAN Result;
/* Mark the entire key dirty */
CmpMarkKeyDirty(Hive, Cell ,TRUE);
/* Get the target node and release it */
CellData = HvGetCell(Hive, Cell);
if (!CellData) ASSERT(FALSE);
HvReleaseCell(Hive, Cell);
/* Make sure we don't have subkeys */
ASSERT((CellData->u.KeyNode.SubKeyCounts[Stable] +
CellData->u.KeyNode.SubKeyCounts[Volatile]) == 0);
/* Check if we have to unlink */
if (Unlink)
{
/* Remove the subkey */
Result = CmpRemoveSubKey(Hive, CellData->u.KeyNode.Parent, Cell);
if (!Result) return STATUS_INSUFFICIENT_RESOURCES;
/* Get the parent node and release it */
ParentData = HvGetCell(Hive, CellData->u.KeyNode.Parent);
if (!ParentData) ASSERT(FALSE);
HvReleaseCell(Hive, CellData->u.KeyNode.Parent);
/* Check if the parent node has no more subkeys */
if (!(ParentData->u.KeyNode.SubKeyCounts[Stable] +
ParentData->u.KeyNode.SubKeyCounts[Volatile]))
{
/* Then free the cached name/class lengths */
ParentData->u.KeyNode.MaxNameLen = 0;
ParentData->u.KeyNode.MaxClassLen = 0;
}
}
/* Check if we have any values */
if (CellData->u.KeyNode.ValueList.Count > 0)
{
/* Get the value list and release it */
ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
if (!ListData) ASSERT(FALSE);
HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
/* Loop every value */
for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
{
/* Free it */
if (!CmpFreeValue(Hive, ListData->u.KeyList[i])) ASSERT(FALSE);
}
/* Free the value list */
HvFreeCell(Hive, CellData->u.KeyNode.ValueList.List);
}
/* Free the key body itself, and then return our status */
if (!CmpFreeKeyBody(Hive, Cell)) return STATUS_INSUFFICIENT_RESOURCES;
return STATUS_SUCCESS;
}

View file

@ -9,7 +9,6 @@
/* INCLUDES *******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"

View file

@ -1,33 +1,32 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmmapvw.c
* PURPOSE: Configuration Manager - Map-Viewed Hive Support
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
CmpInitHiveViewList(IN PCMHIVE Hive)
{
/* Initialize the list heads */
InitializeListHead(&Hive->LRUViewListHead);
InitializeListHead(&Hive->PinViewListHead);
/* Reset data */
Hive->MappedViews = 0;
Hive->PinnedViews = 0;
Hive->UseCount = 0;
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmmapvw.c
* PURPOSE: Configuration Manager - Map-Viewed Hive Support
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
CmpInitHiveViewList(IN PCMHIVE Hive)
{
/* Initialize the list heads */
InitializeListHead(&Hive->LRUViewListHead);
InitializeListHead(&Hive->PinViewListHead);
/* Reset data */
Hive->MappedViews = 0;
Hive->PinnedViews = 0;
Hive->UseCount = 0;
}

View file

@ -1,254 +1,253 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmname.c
* PURPOSE: Configuration Manager - Name Management
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
USHORT
NTAPI
CmpCopyName(IN PHHIVE Hive,
IN PWCHAR Destination,
IN PUNICODE_STRING Source)
{
ULONG i;
/* Check for old hives */
if (Hive->Version == 1)
{
/* Just copy the source directly */
RtlCopyMemory(Destination, Source->Buffer, Source->Length);
return Source->Length;
}
/* For new versions, check for compressed name */
for (i = 0; i < (Source->Length / sizeof(WCHAR)); i++)
{
/* Check if the name is non compressed */
if (Source->Buffer[i] > (UCHAR)-1)
{
/* Do the copy */
RtlCopyMemory(Destination, Source->Buffer, Source->Length);
return Source->Length;
}
/* Copy this character */
((PCHAR)Destination)[i] = (CHAR)(Source->Buffer[i]);
}
/* Compressed name, return length */
return Source->Length / sizeof(WCHAR);
}
VOID
NTAPI
CmpCopyCompressedName(IN PWCHAR Destination,
IN ULONG DestinationLength,
IN PWCHAR Source,
IN ULONG SourceLength)
{
ULONG i, Length;
/* Get the actual length to copy */
Length = min(DestinationLength / sizeof(WCHAR), SourceLength);
for (i = 0; i < Length; i++)
{
/* Copy each character */
Destination[i] = (WCHAR)((PCHAR)Source)[i];
}
}
USHORT
NTAPI
CmpNameSize(IN PHHIVE Hive,
IN PUNICODE_STRING Name)
{
ULONG i;
/* For old hives, just retun the length */
if (Hive->Version == 1) return Name->Length;
/* For new versions, check for compressed name */
for (i = 0; i < (Name->Length / sizeof(WCHAR)); i++)
{
/* Check if the name is non compressed */
if (Name->Buffer[i] > (UCHAR)-1) return Name->Length;
}
/* Compressed name, return length */
return Name->Length / sizeof(WCHAR);
}
USHORT
NTAPI
CmpCompressedNameSize(IN PWCHAR Name,
IN ULONG Length)
{
/*
* Don't remove this: compressed names are "opaque" and just because
* the current implementation turns them into ansi-names doesn't mean
* that it will remain that way forever, so -never- assume this code
* below internally!
*/
return (USHORT)Length * sizeof(WCHAR);
}
LONG
NTAPI
CmpCompareCompressedName(IN PCUNICODE_STRING SearchName,
IN PWCHAR CompressedName,
IN ULONG NameLength)
{
WCHAR *p;
CHAR *pp;
WCHAR p1, p2;
USHORT SearchLength;
LONG Result;
/* Set the pointers and length and then loop */
p = SearchName->Buffer;
pp = (PCHAR)CompressedName;
SearchLength = (SearchName->Length / sizeof(WCHAR));
while ((SearchLength) && (NameLength))
{
/* Get the characters */
p1 = *p++;
p2 = (WCHAR)(*pp++);
/* Check if we have a direct match */
if (p1 != p2)
{
/* See if they match and return result if they don't */
Result = (LONG)RtlUpcaseUnicodeChar(p1) -
(LONG)RtlUpcaseUnicodeChar(p2);
if (Result) return Result;
}
/* Next chars */
SearchLength--;
NameLength--;
}
/* Return the difference directly */
return SearchLength - NameLength;
}
BOOLEAN
NTAPI
CmpFindNameInList(IN PHHIVE Hive,
IN PCHILD_LIST ChildList,
IN PUNICODE_STRING Name,
IN PULONG ChildIndex,
IN PHCELL_INDEX CellIndex)
{
PCELL_DATA CellData;
HCELL_INDEX CellToRelease = HCELL_NIL;
ULONG i;
PCM_KEY_VALUE KeyValue;
LONG Result;
UNICODE_STRING SearchName;
BOOLEAN Success;
/* Make sure there's actually something on the list */
if (ChildList->Count != 0)
{
/* Get the cell data */
CellData = (PCELL_DATA)HvGetCell(Hive, ChildList->List);
if (!CellData)
{
/* Couldn't get the cell... tell the caller */
*CellIndex = HCELL_NIL;
return FALSE;
}
/* Now loop every entry */
for (i = 0; i < ChildList->Count; i++)
{
/* Check if we have a cell to release */
if (CellToRelease != HCELL_NIL)
{
/* Release it */
HvReleaseCell(Hive, CellToRelease);
CellToRelease = HCELL_NIL;
}
/* Get this value */
KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellData->u.KeyList[i]);
if (!KeyValue)
{
/* Return with no data found */
*CellIndex = HCELL_NIL;
Success = FALSE;
goto Return;
}
/* Save the cell to release */
CellToRelease = CellData->u.KeyList[i];
/* Check if it's a compressed value name */
if (KeyValue->Flags & VALUE_COMP_NAME)
{
/* Use the compressed name check */
Result = CmpCompareCompressedName(Name,
KeyValue->Name,
KeyValue->NameLength);
}
else
{
/* Setup the Unicode string */
SearchName.Length = KeyValue->NameLength;
SearchName.MaximumLength = SearchName.Length;
SearchName.Buffer = KeyValue->Name;
Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
}
/* Check if we found it */
if (!Result)
{
/* We did...return info to caller */
if (ChildIndex) *ChildIndex = i;
*CellIndex = CellData->u.KeyList[i];
/* Set success state */
Success = TRUE;
goto Return;
}
}
/* Got to the end of the list */
if (ChildIndex) *ChildIndex = i;
*CellIndex = HCELL_NIL;
/* Nothing found if we got here */
Success = TRUE;
goto Return;
}
/* Nothing found...check if the caller wanted more info */
ASSERT(ChildList->Count == 0);
if (ChildIndex) *ChildIndex = 0;
*CellIndex = HCELL_NIL;
/* Nothing found if we got here */
return TRUE;
Return:
/* Release the first cell we got */
if (CellData) HvReleaseCell(Hive, ChildList->List);
/* Release the secondary one, if we have one */
if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
return Success;
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmname.c
* PURPOSE: Configuration Manager - Name Management
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
USHORT
NTAPI
CmpCopyName(IN PHHIVE Hive,
IN PWCHAR Destination,
IN PUNICODE_STRING Source)
{
ULONG i;
/* Check for old hives */
if (Hive->Version == 1)
{
/* Just copy the source directly */
RtlCopyMemory(Destination, Source->Buffer, Source->Length);
return Source->Length;
}
/* For new versions, check for compressed name */
for (i = 0; i < (Source->Length / sizeof(WCHAR)); i++)
{
/* Check if the name is non compressed */
if (Source->Buffer[i] > (UCHAR)-1)
{
/* Do the copy */
RtlCopyMemory(Destination, Source->Buffer, Source->Length);
return Source->Length;
}
/* Copy this character */
((PCHAR)Destination)[i] = (CHAR)(Source->Buffer[i]);
}
/* Compressed name, return length */
return Source->Length / sizeof(WCHAR);
}
VOID
NTAPI
CmpCopyCompressedName(IN PWCHAR Destination,
IN ULONG DestinationLength,
IN PWCHAR Source,
IN ULONG SourceLength)
{
ULONG i, Length;
/* Get the actual length to copy */
Length = min(DestinationLength / sizeof(WCHAR), SourceLength);
for (i = 0; i < Length; i++)
{
/* Copy each character */
Destination[i] = (WCHAR)((PCHAR)Source)[i];
}
}
USHORT
NTAPI
CmpNameSize(IN PHHIVE Hive,
IN PUNICODE_STRING Name)
{
ULONG i;
/* For old hives, just retun the length */
if (Hive->Version == 1) return Name->Length;
/* For new versions, check for compressed name */
for (i = 0; i < (Name->Length / sizeof(WCHAR)); i++)
{
/* Check if the name is non compressed */
if (Name->Buffer[i] > (UCHAR)-1) return Name->Length;
}
/* Compressed name, return length */
return Name->Length / sizeof(WCHAR);
}
USHORT
NTAPI
CmpCompressedNameSize(IN PWCHAR Name,
IN ULONG Length)
{
/*
* Don't remove this: compressed names are "opaque" and just because
* the current implementation turns them into ansi-names doesn't mean
* that it will remain that way forever, so -never- assume this code
* below internally!
*/
return (USHORT)Length * sizeof(WCHAR);
}
LONG
NTAPI
CmpCompareCompressedName(IN PCUNICODE_STRING SearchName,
IN PWCHAR CompressedName,
IN ULONG NameLength)
{
WCHAR *p;
CHAR *pp;
WCHAR p1, p2;
USHORT SearchLength;
LONG Result;
/* Set the pointers and length and then loop */
p = SearchName->Buffer;
pp = (PCHAR)CompressedName;
SearchLength = (SearchName->Length / sizeof(WCHAR));
while ((SearchLength) && (NameLength))
{
/* Get the characters */
p1 = *p++;
p2 = (WCHAR)(*pp++);
/* Check if we have a direct match */
if (p1 != p2)
{
/* See if they match and return result if they don't */
Result = (LONG)RtlUpcaseUnicodeChar(p1) -
(LONG)RtlUpcaseUnicodeChar(p2);
if (Result) return Result;
}
/* Next chars */
SearchLength--;
NameLength--;
}
/* Return the difference directly */
return SearchLength - NameLength;
}
BOOLEAN
NTAPI
CmpFindNameInList(IN PHHIVE Hive,
IN PCHILD_LIST ChildList,
IN PUNICODE_STRING Name,
IN PULONG ChildIndex,
IN PHCELL_INDEX CellIndex)
{
PCELL_DATA CellData;
HCELL_INDEX CellToRelease = HCELL_NIL;
ULONG i;
PCM_KEY_VALUE KeyValue;
LONG Result;
UNICODE_STRING SearchName;
BOOLEAN Success;
/* Make sure there's actually something on the list */
if (ChildList->Count != 0)
{
/* Get the cell data */
CellData = (PCELL_DATA)HvGetCell(Hive, ChildList->List);
if (!CellData)
{
/* Couldn't get the cell... tell the caller */
*CellIndex = HCELL_NIL;
return FALSE;
}
/* Now loop every entry */
for (i = 0; i < ChildList->Count; i++)
{
/* Check if we have a cell to release */
if (CellToRelease != HCELL_NIL)
{
/* Release it */
HvReleaseCell(Hive, CellToRelease);
CellToRelease = HCELL_NIL;
}
/* Get this value */
KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellData->u.KeyList[i]);
if (!KeyValue)
{
/* Return with no data found */
*CellIndex = HCELL_NIL;
Success = FALSE;
goto Return;
}
/* Save the cell to release */
CellToRelease = CellData->u.KeyList[i];
/* Check if it's a compressed value name */
if (KeyValue->Flags & VALUE_COMP_NAME)
{
/* Use the compressed name check */
Result = CmpCompareCompressedName(Name,
KeyValue->Name,
KeyValue->NameLength);
}
else
{
/* Setup the Unicode string */
SearchName.Length = KeyValue->NameLength;
SearchName.MaximumLength = SearchName.Length;
SearchName.Buffer = KeyValue->Name;
Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
}
/* Check if we found it */
if (!Result)
{
/* We did...return info to caller */
if (ChildIndex) *ChildIndex = i;
*CellIndex = CellData->u.KeyList[i];
/* Set success state */
Success = TRUE;
goto Return;
}
}
/* Got to the end of the list */
if (ChildIndex) *ChildIndex = i;
*CellIndex = HCELL_NIL;
/* Nothing found if we got here */
Success = TRUE;
goto Return;
}
/* Nothing found...check if the caller wanted more info */
ASSERT(ChildList->Count == 0);
if (ChildIndex) *ChildIndex = 0;
*CellIndex = HCELL_NIL;
/* Nothing found if we got here */
return TRUE;
Return:
/* Release the first cell we got */
if (CellData) HvReleaseCell(Hive, ChildList->List);
/* Release the secondary one, if we have one */
if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
return Success;
}

File diff suppressed because it is too large Load diff

View file

@ -1,153 +1,152 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmse.c
* PURPOSE: Configuration Manager - Security Subsystem Interface
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
PSECURITY_DESCRIPTOR
NTAPI
CmpHiveRootSecurityDescriptor(VOID)
{
NTSTATUS Status;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PACL Acl, AclCopy;
PSID Sid[4];
SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
ULONG AceLength, AclLength, SidLength;
PACE_HEADER AceHeader;
ULONG i;
PAGED_CODE();
/* Phase 1: Allocate SIDs */
SidLength = RtlLengthRequiredSid(1);
Sid[0] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
Sid[1] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
Sid[2] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
SidLength = RtlLengthRequiredSid(2);
Sid[3] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
/* Make sure all SIDs were allocated */
if (!(Sid[0]) || !(Sid[1]) || !(Sid[2]) || !(Sid[3]))
{
/* Bugcheck */
KEBUGCHECKEX(REGISTRY_ERROR, 11, 1, 0, 0);
}
/* Phase 2: Initialize all SIDs */
Status = RtlInitializeSid(Sid[0], &WorldAuthority, 1);
Status |= RtlInitializeSid(Sid[1], &NtAuthority, 1);
Status |= RtlInitializeSid(Sid[2], &NtAuthority, 1);
Status |= RtlInitializeSid(Sid[3], &NtAuthority, 2);
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 2, 0, 0);
/* Phase 2: Setup SID Sub Authorities */
*RtlSubAuthoritySid(Sid[0], 0) = SECURITY_WORLD_RID;
*RtlSubAuthoritySid(Sid[1], 0) = SECURITY_RESTRICTED_CODE_RID;
*RtlSubAuthoritySid(Sid[2], 0) = SECURITY_LOCAL_SYSTEM_RID;
*RtlSubAuthoritySid(Sid[3], 0) = SECURITY_BUILTIN_DOMAIN_RID;
*RtlSubAuthoritySid(Sid[3], 1) = DOMAIN_ALIAS_RID_ADMINS;
/* Make sure all SIDs are valid */
ASSERT(RtlValidSid(Sid[0]));
ASSERT(RtlValidSid(Sid[1]));
ASSERT(RtlValidSid(Sid[2]));
ASSERT(RtlValidSid(Sid[3]));
/* Phase 3: Calculate ACL Length */
AclLength = sizeof(ACL);
for (i = 0; i < 4; i++)
{
/* This is what MSDN says to do */
AceLength = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
AceLength += SeLengthSid(Sid[i]);
AclLength += AceLength;
}
/* Phase 3: Allocate the ACL */
Acl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_CM);
if (!Acl) KEBUGCHECKEX(REGISTRY_ERROR, 11, 3, 0, 0);
/* Phase 4: Create the ACL */
Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION);
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 4, Status, 0);
/* Phase 5: Build the ACL */
Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[0]);
Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[1]);
Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[2]);
Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[3]);
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 5, Status, 0);
/* Phase 5: Make the ACEs inheritable */
Status = RtlGetAce(Acl, 0,( PVOID*)&AceHeader);
ASSERT(NT_SUCCESS(Status));
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
Status = RtlGetAce(Acl, 1, (PVOID*)&AceHeader);
ASSERT(NT_SUCCESS(Status));
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
Status = RtlGetAce(Acl, 2, (PVOID*)&AceHeader);
ASSERT(NT_SUCCESS(Status));
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
Status = RtlGetAce(Acl, 3, (PVOID*)&AceHeader);
ASSERT(NT_SUCCESS(Status));
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
/* Phase 6: Allocate the security descriptor and make space for the ACL */
SecurityDescriptor = ExAllocatePoolWithTag(PagedPool,
sizeof(SECURITY_DESCRIPTOR) +
AclLength,
TAG_CM);
if (!SecurityDescriptor) KEBUGCHECKEX(REGISTRY_ERROR, 11, 6, 0, 0);
/* Phase 6: Make a copy of the ACL */
AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor + 1);
RtlCopyMemory(AclCopy, Acl, AclLength);
/* Phase 7: Create the security descriptor */
Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 7, Status, 0);
/* Phase 8: Set the ACL as a DACL */
Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
TRUE,
AclCopy,
FALSE);
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 8, Status, 0);
/* Free the SIDs and original ACL */
for (i = 0; i < 4; i++) ExFreePool(Sid[i]);
ExFreePool(Acl);
/* Return the security descriptor */
return SecurityDescriptor;
}
NTSTATUS
NTAPI
CmpSecurityMethod(IN PVOID ObjectBody,
IN SECURITY_OPERATION_CODE OperationCode,
IN PSECURITY_INFORMATION SecurityInformation,
IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
IN OUT PULONG BufferLength,
IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
IN POOL_TYPE PoolType,
IN PGENERIC_MAPPING GenericMapping)
{
/* HACK */
return STATUS_SUCCESS;
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmse.c
* PURPOSE: Configuration Manager - Security Subsystem Interface
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
PSECURITY_DESCRIPTOR
NTAPI
CmpHiveRootSecurityDescriptor(VOID)
{
NTSTATUS Status;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PACL Acl, AclCopy;
PSID Sid[4];
SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
ULONG AceLength, AclLength, SidLength;
PACE_HEADER AceHeader;
ULONG i;
PAGED_CODE();
/* Phase 1: Allocate SIDs */
SidLength = RtlLengthRequiredSid(1);
Sid[0] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
Sid[1] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
Sid[2] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
SidLength = RtlLengthRequiredSid(2);
Sid[3] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
/* Make sure all SIDs were allocated */
if (!(Sid[0]) || !(Sid[1]) || !(Sid[2]) || !(Sid[3]))
{
/* Bugcheck */
KEBUGCHECKEX(REGISTRY_ERROR, 11, 1, 0, 0);
}
/* Phase 2: Initialize all SIDs */
Status = RtlInitializeSid(Sid[0], &WorldAuthority, 1);
Status |= RtlInitializeSid(Sid[1], &NtAuthority, 1);
Status |= RtlInitializeSid(Sid[2], &NtAuthority, 1);
Status |= RtlInitializeSid(Sid[3], &NtAuthority, 2);
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 2, 0, 0);
/* Phase 2: Setup SID Sub Authorities */
*RtlSubAuthoritySid(Sid[0], 0) = SECURITY_WORLD_RID;
*RtlSubAuthoritySid(Sid[1], 0) = SECURITY_RESTRICTED_CODE_RID;
*RtlSubAuthoritySid(Sid[2], 0) = SECURITY_LOCAL_SYSTEM_RID;
*RtlSubAuthoritySid(Sid[3], 0) = SECURITY_BUILTIN_DOMAIN_RID;
*RtlSubAuthoritySid(Sid[3], 1) = DOMAIN_ALIAS_RID_ADMINS;
/* Make sure all SIDs are valid */
ASSERT(RtlValidSid(Sid[0]));
ASSERT(RtlValidSid(Sid[1]));
ASSERT(RtlValidSid(Sid[2]));
ASSERT(RtlValidSid(Sid[3]));
/* Phase 3: Calculate ACL Length */
AclLength = sizeof(ACL);
for (i = 0; i < 4; i++)
{
/* This is what MSDN says to do */
AceLength = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
AceLength += SeLengthSid(Sid[i]);
AclLength += AceLength;
}
/* Phase 3: Allocate the ACL */
Acl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_CM);
if (!Acl) KEBUGCHECKEX(REGISTRY_ERROR, 11, 3, 0, 0);
/* Phase 4: Create the ACL */
Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION);
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 4, Status, 0);
/* Phase 5: Build the ACL */
Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[0]);
Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[1]);
Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[2]);
Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[3]);
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 5, Status, 0);
/* Phase 5: Make the ACEs inheritable */
Status = RtlGetAce(Acl, 0,( PVOID*)&AceHeader);
ASSERT(NT_SUCCESS(Status));
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
Status = RtlGetAce(Acl, 1, (PVOID*)&AceHeader);
ASSERT(NT_SUCCESS(Status));
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
Status = RtlGetAce(Acl, 2, (PVOID*)&AceHeader);
ASSERT(NT_SUCCESS(Status));
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
Status = RtlGetAce(Acl, 3, (PVOID*)&AceHeader);
ASSERT(NT_SUCCESS(Status));
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
/* Phase 6: Allocate the security descriptor and make space for the ACL */
SecurityDescriptor = ExAllocatePoolWithTag(PagedPool,
sizeof(SECURITY_DESCRIPTOR) +
AclLength,
TAG_CM);
if (!SecurityDescriptor) KEBUGCHECKEX(REGISTRY_ERROR, 11, 6, 0, 0);
/* Phase 6: Make a copy of the ACL */
AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor + 1);
RtlCopyMemory(AclCopy, Acl, AclLength);
/* Phase 7: Create the security descriptor */
Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 7, Status, 0);
/* Phase 8: Set the ACL as a DACL */
Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
TRUE,
AclCopy,
FALSE);
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 8, Status, 0);
/* Free the SIDs and original ACL */
for (i = 0; i < 4; i++) ExFreePool(Sid[i]);
ExFreePool(Acl);
/* Return the security descriptor */
return SecurityDescriptor;
}
NTSTATUS
NTAPI
CmpSecurityMethod(IN PVOID ObjectBody,
IN SECURITY_OPERATION_CODE OperationCode,
IN PSECURITY_INFORMATION SecurityInformation,
IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
IN OUT PULONG BufferLength,
IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
IN POOL_TYPE PoolType,
IN PGENERIC_MAPPING GenericMapping)
{
/* HACK */
return STATUS_SUCCESS;
}

View file

@ -1,38 +1,37 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmsecach.c
* PURPOSE: Configuration Manager - Security Cache
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
CmpInitSecurityCache(IN PCMHIVE Hive)
{
ULONG i;
/* Reset data */
Hive->SecurityCount = 0;
Hive->SecurityCacheSize = 0;
Hive->SecurityHitHint = -1;
Hive->SecurityCache = NULL;
/* Loop every security hash */
for (i = 0; i < 64; i++)
{
/* Initialize it */
InitializeListHead(&Hive->SecurityHash[i]);
}
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmsecach.c
* PURPOSE: Configuration Manager - Security Cache
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* GLOBALS *******************************************************************/
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
CmpInitSecurityCache(IN PCMHIVE Hive)
{
ULONG i;
/* Reset data */
Hive->SecurityCount = 0;
Hive->SecurityCacheSize = 0;
Hive->SecurityHitHint = -1;
Hive->SecurityCache = NULL;
/* Loop every security hash */
for (i = 0; i < 64; i++)
{
/* Initialize it */
InitializeListHead(&Hive->SecurityHash[i]);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,364 +1,363 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmvalue.c
* PURPOSE: Configuration Manager - Cell Values
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
CmpMarkValueDataDirty(IN PHHIVE Hive,
IN PCM_KEY_VALUE Value)
{
ULONG KeySize;
PAGED_CODE();
/* Make sure there's actually any data */
if (Value->Data != HCELL_NIL)
{
/* If this is a small key, there's no need to have it dirty */
if (CmpIsKeyValueSmall(&KeySize, Value->DataLength)) return TRUE;
/* Check if this is a big key */
ASSERT_VALUE_BIG(Hive, KeySize);
/* Normal value, just mark it dirty */
HvMarkCellDirty(Hive, Value->Data, FALSE);
}
/* Operation complete */
return TRUE;
}
BOOLEAN
NTAPI
CmpFreeValueData(IN PHHIVE Hive,
IN HCELL_INDEX DataCell,
IN ULONG DataLength)
{
ULONG KeySize;
PAGED_CODE();
/* If this is a small key, the data is built-in */
if (!CmpIsKeyValueSmall(&KeySize, DataLength))
{
/* If there's no data cell, there's nothing to do */
if (DataCell == HCELL_NIL) return TRUE;
/* Make sure the data cell is allocated */
//ASSERT(HvIsCellAllocated(Hive, DataCell));
/* Unsupported value type */
ASSERT_VALUE_BIG(Hive, KeySize);
/* Normal value, just free the data cell */
HvFreeCell(Hive, DataCell);
}
/* Operation complete */
return TRUE;
}
BOOLEAN
NTAPI
CmpFreeValue(IN PHHIVE Hive,
IN HCELL_INDEX Cell)
{
PCM_KEY_VALUE Value;
PAGED_CODE();
/* Get the cell data */
Value = (PCM_KEY_VALUE)HvGetCell(Hive, Cell);
if (!Value) ASSERT(FALSE);
/* Free it */
if (!CmpFreeValueData(Hive, Value->Data, Value->DataLength))
{
/* We failed to free the data, return failure */
HvReleaseCell(Hive, Cell);
return FALSE;
}
/* Release the cell and free it */
HvReleaseCell(Hive, Cell);
HvFreeCell(Hive, Cell);
return TRUE;
}
HCELL_INDEX
NTAPI
CmpFindValueByName(IN PHHIVE Hive,
IN PCM_KEY_NODE KeyNode,
IN PUNICODE_STRING Name)
{
HCELL_INDEX CellIndex;
/* Call the main function */
if (!CmpFindNameInList(Hive,
&KeyNode->ValueList,
Name,
NULL,
&CellIndex))
{
/* Santy check */
ASSERT(CellIndex == HCELL_NIL);
}
/* Return the index */
return CellIndex;
}
BOOLEAN
NTAPI
CmpGetValueData(IN PHHIVE Hive,
IN PCM_KEY_VALUE Value,
IN PULONG Length,
OUT PVOID *Buffer,
OUT PBOOLEAN BufferAllocated,
OUT PHCELL_INDEX CellToRelease)
{
PAGED_CODE();
/* Sanity check */
ASSERT(Value->Signature == CM_KEY_VALUE_SIGNATURE);
/* Set failure defaults */
*BufferAllocated = FALSE;
*Buffer = NULL;
*CellToRelease = HCELL_NIL;
/* Check if this is a small key */
if (CmpIsKeyValueSmall(Length, Value->DataLength))
{
/* Return the data immediately */
*Buffer = &Value->Data;
return TRUE;
}
/* Unsupported */
ASSERT_VALUE_BIG(Hive, *Length);
/* Get the data from the cell */
*Buffer = HvGetCell(Hive, Value->Data);
if (!(*Buffer)) return FALSE;
/* Return success and the cell to be released */
*CellToRelease = Value->Data;
return TRUE;
}
PCELL_DATA
NTAPI
CmpValueToData(IN PHHIVE Hive,
IN PCM_KEY_VALUE Value,
OUT PULONG Length)
{
PCELL_DATA Buffer;
BOOLEAN BufferAllocated;
HCELL_INDEX CellToRelease;
PAGED_CODE();
/* Sanity check */
ASSERT(Hive->ReleaseCellRoutine == NULL);
/* Get the actual data */
if (!CmpGetValueData(Hive,
Value,
Length,
(PVOID)&Buffer,
&BufferAllocated,
&CellToRelease))
{
/* We failed */
ASSERT(BufferAllocated == FALSE);
ASSERT(Buffer == NULL);
return NULL;
}
/* This should never happen!*/
if (BufferAllocated)
{
/* Free the buffer and bugcheck */
ExFreePool(Buffer);
KEBUGCHECKEX(REGISTRY_ERROR, 8, 0, (ULONG_PTR)Hive, (ULONG_PTR)Value);
}
/* Otherwise, return the cell data */
return Buffer;
}
NTSTATUS
NTAPI
CmpAddValueToList(IN PHHIVE Hive,
IN HCELL_INDEX ValueCell,
IN ULONG Index,
IN ULONG Type,
IN OUT PCHILD_LIST ChildList)
{
HCELL_INDEX ListCell;
ULONG ChildCount, Length, i;
PCELL_DATA CellData;
PAGED_CODE();
/* Sanity check */
ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
/* Get the number of entries in the child list */
ChildCount = ChildList->Count;
ChildCount++;
if (ChildCount > 1)
{
/* The cell should be dirty at this point */
ASSERT(HvIsCellDirty(Hive, ChildList->List));
/* Check if we have less then 100 children */
if (ChildCount < 100)
{
/* Allocate just enough as requested */
Length = ChildCount * sizeof(HCELL_INDEX);
}
else
{
/* Otherwise, we have quite a few, so allocate a batch */
Length = ROUND_UP(ChildCount, 100) * sizeof(HCELL_INDEX);
if (Length > HBLOCK_SIZE)
{
/* But make sure we don't allocate beyond our block size */
Length = ROUND_UP(Length, HBLOCK_SIZE);
}
}
/* Perform the allocation */
ListCell = HvReallocateCell(Hive, ChildList->List, Length);
}
else
{
/* This is our first child, so allocate a single cell */
ListCell = HvAllocateCell(Hive, sizeof(HCELL_INDEX), Type, HCELL_NIL);
}
/* Fail if we couldn't get a cell */
if (ListCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
/* Set this cell as the child list's list cell */
ChildList->List = ListCell;
/* Get the actual key list memory */
CellData = HvGetCell(Hive, ListCell);
ASSERT(CellData != NULL);
/* Loop all the children */
for (i = ChildCount - 1; i > Index; i--)
{
/* Move them all down */
CellData->u.KeyList[i] = CellData->u.KeyList[i - 1];
}
/* Insert us on top now */
CellData->u.KeyList[Index] = ValueCell;
ChildList->Count = ChildCount;
/* Release the list cell and make sure the value cell is dirty */
HvReleaseCell(Hive, ListCell);
ASSERT(HvIsCellDirty(Hive, ValueCell));
/* We're done here */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpSetValueDataNew(IN PHHIVE Hive,
IN PVOID Data,
IN ULONG DataSize,
IN ULONG StorageType,
IN HCELL_INDEX ValueCell,
OUT PHCELL_INDEX DataCell)
{
PCELL_DATA CellData;
PAGED_CODE();
ASSERT(DataSize > CM_KEY_VALUE_SMALL);
/* Check if this is a big key */
ASSERT_VALUE_BIG(Hive, DataSize);
/* Allocate a data cell */
*DataCell = HvAllocateCell(Hive, DataSize, StorageType, HCELL_NIL);
if (*DataCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
/* Get the actual data */
CellData = HvGetCell(Hive, *DataCell);
if (!CellData) ASSERT(FALSE);
/* Copy our buffer into it */
RtlCopyMemory(CellData, Data, DataSize);
/* All done */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpRemoveValueFromList(IN PHHIVE Hive,
IN ULONG Index,
IN OUT PCHILD_LIST ChildList)
{
ULONG Count;
PCELL_DATA CellData;
HCELL_INDEX NewCell;
PAGED_CODE();
/* Sanity check */
ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
/* Get the new count after removal */
Count = ChildList->Count - 1;
if (Count > 0)
{
/* Get the actual list array */
CellData = HvGetCell(Hive, ChildList->List);
if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
/* Make sure cells data have been made dirty */
ASSERT(HvIsCellDirty(Hive, ChildList->List));
ASSERT(HvIsCellDirty(Hive, CellData->u.KeyList[Index]));
/* Loop the list */
while (Index < Count)
{
/* Move everything up */
CellData->u.KeyList[Index] = CellData->u.KeyList[Index + 1];
Index++;
}
/* Re-allocate the cell for the list by decreasing the count */
NewCell = HvReallocateCell(Hive,
ChildList->List,
Count * sizeof(HCELL_INDEX));
ASSERT(NewCell != HCELL_NIL);
HvReleaseCell(Hive,ChildList->List);
/* Update the list cell */
ChildList->List = NewCell;
}
else
{
/* Otherwise, we were the last entry, so free the list entirely */
HvFreeCell(Hive, ChildList->List);
ChildList->List = HCELL_NIL;
}
/* Update the child list with the new count */
ChildList->Count = Count;
return STATUS_SUCCESS;
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmvalue.c
* PURPOSE: Configuration Manager - Cell Values
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* FUNCTIONS *****************************************************************/
BOOLEAN
NTAPI
CmpMarkValueDataDirty(IN PHHIVE Hive,
IN PCM_KEY_VALUE Value)
{
ULONG KeySize;
PAGED_CODE();
/* Make sure there's actually any data */
if (Value->Data != HCELL_NIL)
{
/* If this is a small key, there's no need to have it dirty */
if (CmpIsKeyValueSmall(&KeySize, Value->DataLength)) return TRUE;
/* Check if this is a big key */
ASSERT_VALUE_BIG(Hive, KeySize);
/* Normal value, just mark it dirty */
HvMarkCellDirty(Hive, Value->Data, FALSE);
}
/* Operation complete */
return TRUE;
}
BOOLEAN
NTAPI
CmpFreeValueData(IN PHHIVE Hive,
IN HCELL_INDEX DataCell,
IN ULONG DataLength)
{
ULONG KeySize;
PAGED_CODE();
/* If this is a small key, the data is built-in */
if (!CmpIsKeyValueSmall(&KeySize, DataLength))
{
/* If there's no data cell, there's nothing to do */
if (DataCell == HCELL_NIL) return TRUE;
/* Make sure the data cell is allocated */
//ASSERT(HvIsCellAllocated(Hive, DataCell));
/* Unsupported value type */
ASSERT_VALUE_BIG(Hive, KeySize);
/* Normal value, just free the data cell */
HvFreeCell(Hive, DataCell);
}
/* Operation complete */
return TRUE;
}
BOOLEAN
NTAPI
CmpFreeValue(IN PHHIVE Hive,
IN HCELL_INDEX Cell)
{
PCM_KEY_VALUE Value;
PAGED_CODE();
/* Get the cell data */
Value = (PCM_KEY_VALUE)HvGetCell(Hive, Cell);
if (!Value) ASSERT(FALSE);
/* Free it */
if (!CmpFreeValueData(Hive, Value->Data, Value->DataLength))
{
/* We failed to free the data, return failure */
HvReleaseCell(Hive, Cell);
return FALSE;
}
/* Release the cell and free it */
HvReleaseCell(Hive, Cell);
HvFreeCell(Hive, Cell);
return TRUE;
}
HCELL_INDEX
NTAPI
CmpFindValueByName(IN PHHIVE Hive,
IN PCM_KEY_NODE KeyNode,
IN PUNICODE_STRING Name)
{
HCELL_INDEX CellIndex;
/* Call the main function */
if (!CmpFindNameInList(Hive,
&KeyNode->ValueList,
Name,
NULL,
&CellIndex))
{
/* Santy check */
ASSERT(CellIndex == HCELL_NIL);
}
/* Return the index */
return CellIndex;
}
BOOLEAN
NTAPI
CmpGetValueData(IN PHHIVE Hive,
IN PCM_KEY_VALUE Value,
IN PULONG Length,
OUT PVOID *Buffer,
OUT PBOOLEAN BufferAllocated,
OUT PHCELL_INDEX CellToRelease)
{
PAGED_CODE();
/* Sanity check */
ASSERT(Value->Signature == CM_KEY_VALUE_SIGNATURE);
/* Set failure defaults */
*BufferAllocated = FALSE;
*Buffer = NULL;
*CellToRelease = HCELL_NIL;
/* Check if this is a small key */
if (CmpIsKeyValueSmall(Length, Value->DataLength))
{
/* Return the data immediately */
*Buffer = &Value->Data;
return TRUE;
}
/* Unsupported */
ASSERT_VALUE_BIG(Hive, *Length);
/* Get the data from the cell */
*Buffer = HvGetCell(Hive, Value->Data);
if (!(*Buffer)) return FALSE;
/* Return success and the cell to be released */
*CellToRelease = Value->Data;
return TRUE;
}
PCELL_DATA
NTAPI
CmpValueToData(IN PHHIVE Hive,
IN PCM_KEY_VALUE Value,
OUT PULONG Length)
{
PCELL_DATA Buffer;
BOOLEAN BufferAllocated;
HCELL_INDEX CellToRelease;
PAGED_CODE();
/* Sanity check */
ASSERT(Hive->ReleaseCellRoutine == NULL);
/* Get the actual data */
if (!CmpGetValueData(Hive,
Value,
Length,
(PVOID)&Buffer,
&BufferAllocated,
&CellToRelease))
{
/* We failed */
ASSERT(BufferAllocated == FALSE);
ASSERT(Buffer == NULL);
return NULL;
}
/* This should never happen!*/
if (BufferAllocated)
{
/* Free the buffer and bugcheck */
ExFreePool(Buffer);
KEBUGCHECKEX(REGISTRY_ERROR, 8, 0, (ULONG_PTR)Hive, (ULONG_PTR)Value);
}
/* Otherwise, return the cell data */
return Buffer;
}
NTSTATUS
NTAPI
CmpAddValueToList(IN PHHIVE Hive,
IN HCELL_INDEX ValueCell,
IN ULONG Index,
IN ULONG Type,
IN OUT PCHILD_LIST ChildList)
{
HCELL_INDEX ListCell;
ULONG ChildCount, Length, i;
PCELL_DATA CellData;
PAGED_CODE();
/* Sanity check */
ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
/* Get the number of entries in the child list */
ChildCount = ChildList->Count;
ChildCount++;
if (ChildCount > 1)
{
/* The cell should be dirty at this point */
ASSERT(HvIsCellDirty(Hive, ChildList->List));
/* Check if we have less then 100 children */
if (ChildCount < 100)
{
/* Allocate just enough as requested */
Length = ChildCount * sizeof(HCELL_INDEX);
}
else
{
/* Otherwise, we have quite a few, so allocate a batch */
Length = ROUND_UP(ChildCount, 100) * sizeof(HCELL_INDEX);
if (Length > HBLOCK_SIZE)
{
/* But make sure we don't allocate beyond our block size */
Length = ROUND_UP(Length, HBLOCK_SIZE);
}
}
/* Perform the allocation */
ListCell = HvReallocateCell(Hive, ChildList->List, Length);
}
else
{
/* This is our first child, so allocate a single cell */
ListCell = HvAllocateCell(Hive, sizeof(HCELL_INDEX), Type, HCELL_NIL);
}
/* Fail if we couldn't get a cell */
if (ListCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
/* Set this cell as the child list's list cell */
ChildList->List = ListCell;
/* Get the actual key list memory */
CellData = HvGetCell(Hive, ListCell);
ASSERT(CellData != NULL);
/* Loop all the children */
for (i = ChildCount - 1; i > Index; i--)
{
/* Move them all down */
CellData->u.KeyList[i] = CellData->u.KeyList[i - 1];
}
/* Insert us on top now */
CellData->u.KeyList[Index] = ValueCell;
ChildList->Count = ChildCount;
/* Release the list cell and make sure the value cell is dirty */
HvReleaseCell(Hive, ListCell);
ASSERT(HvIsCellDirty(Hive, ValueCell));
/* We're done here */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpSetValueDataNew(IN PHHIVE Hive,
IN PVOID Data,
IN ULONG DataSize,
IN ULONG StorageType,
IN HCELL_INDEX ValueCell,
OUT PHCELL_INDEX DataCell)
{
PCELL_DATA CellData;
PAGED_CODE();
ASSERT(DataSize > CM_KEY_VALUE_SMALL);
/* Check if this is a big key */
ASSERT_VALUE_BIG(Hive, DataSize);
/* Allocate a data cell */
*DataCell = HvAllocateCell(Hive, DataSize, StorageType, HCELL_NIL);
if (*DataCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
/* Get the actual data */
CellData = HvGetCell(Hive, *DataCell);
if (!CellData) ASSERT(FALSE);
/* Copy our buffer into it */
RtlCopyMemory(CellData, Data, DataSize);
/* All done */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpRemoveValueFromList(IN PHHIVE Hive,
IN ULONG Index,
IN OUT PCHILD_LIST ChildList)
{
ULONG Count;
PCELL_DATA CellData;
HCELL_INDEX NewCell;
PAGED_CODE();
/* Sanity check */
ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
/* Get the new count after removal */
Count = ChildList->Count - 1;
if (Count > 0)
{
/* Get the actual list array */
CellData = HvGetCell(Hive, ChildList->List);
if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
/* Make sure cells data have been made dirty */
ASSERT(HvIsCellDirty(Hive, ChildList->List));
ASSERT(HvIsCellDirty(Hive, CellData->u.KeyList[Index]));
/* Loop the list */
while (Index < Count)
{
/* Move everything up */
CellData->u.KeyList[Index] = CellData->u.KeyList[Index + 1];
Index++;
}
/* Re-allocate the cell for the list by decreasing the count */
NewCell = HvReallocateCell(Hive,
ChildList->List,
Count * sizeof(HCELL_INDEX));
ASSERT(NewCell != HCELL_NIL);
HvReleaseCell(Hive,ChildList->List);
/* Update the list cell */
ChildList->List = NewCell;
}
else
{
/* Otherwise, we were the last entry, so free the list entirely */
HvFreeCell(Hive, ChildList->List);
ChildList->List = HCELL_NIL;
}
/* Update the child list with the new count */
ChildList->Count = Count;
return STATUS_SUCCESS;
}

View file

@ -1,159 +1,158 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmwraprs.c
* PURPOSE: Configuration Manager - Wrappers for Hive Operations
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
CmpCreateEvent(IN EVENT_TYPE EventType,
OUT PHANDLE EventHandle,
OUT PKEVENT *Event)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
/* Create the event */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwCreateEvent(EventHandle,
EVENT_ALL_ACCESS,
&ObjectAttributes,
EventType,
FALSE);
if (!NT_SUCCESS(Status)) return Status;
/* Get a pointer to the object itself */
Status = ObReferenceObjectByHandle(*EventHandle,
EVENT_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)Event,
NULL);
if (!NT_SUCCESS(Status)) ZwClose(*EventHandle);
/* Return status */
return Status;
}
PVOID
NTAPI
CmpAllocate(IN ULONG Size,
IN BOOLEAN Paged,
IN ULONG Tag)
{
return ExAllocatePoolWithTag(Paged ? PagedPool : NonPagedPool,
Size,
Tag);
}
VOID
NTAPI
CmpFree(IN PVOID Ptr,
IN ULONG Quota)
{
ExFreePool(Ptr);
}
BOOLEAN
NTAPI
CmpFileRead(IN PHHIVE RegistryHive,
IN ULONG FileType,
IN PULONG FileOffset,
OUT PVOID Buffer,
IN SIZE_T BufferLength)
{
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
HANDLE HiveHandle = CmHive->FileHandles[FileType];
LARGE_INTEGER _FileOffset;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
_FileOffset.QuadPart = *FileOffset;
Status = ZwReadFile(HiveHandle, 0, 0, 0, &IoStatusBlock,
Buffer, BufferLength, &_FileOffset, 0);
return NT_SUCCESS(Status) ? TRUE : FALSE;
}
BOOLEAN
NTAPI
CmpFileWrite(IN PHHIVE RegistryHive,
IN ULONG FileType,
IN PULONG FileOffset,
IN PVOID Buffer,
IN SIZE_T BufferLength)
{
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
HANDLE HiveHandle = CmHive->FileHandles[FileType];
LARGE_INTEGER _FileOffset;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
_FileOffset.QuadPart = *FileOffset;
Status = ZwWriteFile(HiveHandle, 0, 0, 0, &IoStatusBlock,
Buffer, BufferLength, &_FileOffset, 0);
return NT_SUCCESS(Status) ? TRUE : FALSE;
}
BOOLEAN
NTAPI
CmpFileSetSize(IN PHHIVE RegistryHive,
IN ULONG FileType,
IN ULONG FileSize,
IN ULONG OldFileSize)
{
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
HANDLE HiveHandle = CmHive->FileHandles[FileType];
FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
FILE_ALLOCATION_INFORMATION FileAllocationInfo;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
EndOfFileInfo.EndOfFile.QuadPart = FileSize;
Status = ZwSetInformationFile(HiveHandle,
&IoStatusBlock,
&EndOfFileInfo,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation);
if (!NT_SUCCESS(Status)) return FALSE;
FileAllocationInfo.AllocationSize.QuadPart = FileSize;
Status = ZwSetInformationFile(HiveHandle,
&IoStatusBlock,
&FileAllocationInfo,
sizeof(FILE_ALLOCATION_INFORMATION),
FileAllocationInformation);
if (!NT_SUCCESS(Status)) return FALSE;
return TRUE;
}
BOOLEAN
NTAPI
CmpFileFlush(IN PHHIVE RegistryHive,
IN ULONG FileType,
IN OUT PLARGE_INTEGER FileOffset,
IN ULONG Length)
{
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
HANDLE HiveHandle = CmHive->FileHandles[FileType];
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
Status = ZwFlushBuffersFile(HiveHandle, &IoStatusBlock);
return NT_SUCCESS(Status) ? TRUE : FALSE;
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/config/cmwraprs.c
* PURPOSE: Configuration Manager - Wrappers for Hive Operations
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#define NDEBUG
#include "debug.h"
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
CmpCreateEvent(IN EVENT_TYPE EventType,
OUT PHANDLE EventHandle,
OUT PKEVENT *Event)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
/* Create the event */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwCreateEvent(EventHandle,
EVENT_ALL_ACCESS,
&ObjectAttributes,
EventType,
FALSE);
if (!NT_SUCCESS(Status)) return Status;
/* Get a pointer to the object itself */
Status = ObReferenceObjectByHandle(*EventHandle,
EVENT_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)Event,
NULL);
if (!NT_SUCCESS(Status)) ZwClose(*EventHandle);
/* Return status */
return Status;
}
PVOID
NTAPI
CmpAllocate(IN ULONG Size,
IN BOOLEAN Paged,
IN ULONG Tag)
{
return ExAllocatePoolWithTag(Paged ? PagedPool : NonPagedPool,
Size,
Tag);
}
VOID
NTAPI
CmpFree(IN PVOID Ptr,
IN ULONG Quota)
{
ExFreePool(Ptr);
}
BOOLEAN
NTAPI
CmpFileRead(IN PHHIVE RegistryHive,
IN ULONG FileType,
IN PULONG FileOffset,
OUT PVOID Buffer,
IN SIZE_T BufferLength)
{
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
HANDLE HiveHandle = CmHive->FileHandles[FileType];
LARGE_INTEGER _FileOffset;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
_FileOffset.QuadPart = *FileOffset;
Status = ZwReadFile(HiveHandle, 0, 0, 0, &IoStatusBlock,
Buffer, BufferLength, &_FileOffset, 0);
return NT_SUCCESS(Status) ? TRUE : FALSE;
}
BOOLEAN
NTAPI
CmpFileWrite(IN PHHIVE RegistryHive,
IN ULONG FileType,
IN PULONG FileOffset,
IN PVOID Buffer,
IN SIZE_T BufferLength)
{
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
HANDLE HiveHandle = CmHive->FileHandles[FileType];
LARGE_INTEGER _FileOffset;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
_FileOffset.QuadPart = *FileOffset;
Status = ZwWriteFile(HiveHandle, 0, 0, 0, &IoStatusBlock,
Buffer, BufferLength, &_FileOffset, 0);
return NT_SUCCESS(Status) ? TRUE : FALSE;
}
BOOLEAN
NTAPI
CmpFileSetSize(IN PHHIVE RegistryHive,
IN ULONG FileType,
IN ULONG FileSize,
IN ULONG OldFileSize)
{
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
HANDLE HiveHandle = CmHive->FileHandles[FileType];
FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
FILE_ALLOCATION_INFORMATION FileAllocationInfo;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
EndOfFileInfo.EndOfFile.QuadPart = FileSize;
Status = ZwSetInformationFile(HiveHandle,
&IoStatusBlock,
&EndOfFileInfo,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation);
if (!NT_SUCCESS(Status)) return FALSE;
FileAllocationInfo.AllocationSize.QuadPart = FileSize;
Status = ZwSetInformationFile(HiveHandle,
&IoStatusBlock,
&FileAllocationInfo,
sizeof(FILE_ALLOCATION_INFORMATION),
FileAllocationInformation);
if (!NT_SUCCESS(Status)) return FALSE;
return TRUE;
}
BOOLEAN
NTAPI
CmpFileFlush(IN PHHIVE RegistryHive,
IN ULONG FileType,
IN OUT PLARGE_INTEGER FileOffset,
IN ULONG Length)
{
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
HANDLE HiveHandle = CmHive->FileHandles[FileType];
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
Status = ZwFlushBuffersFile(HiveHandle, &IoStatusBlock);
return NT_SUCCESS(Status) ? TRUE : FALSE;
}

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,6 @@
/* INCLUDES ******************************************************************/
#include "ntoskrnl.h"
#include "cm.h"
#define NDEBUG
#include "debug.h"
@ -18,7 +17,6 @@ BOOLEAN CmFirstTime = TRUE;
/* FUNCTIONS *****************************************************************/
#if 0
NTSTATUS
NTAPI
NtCreateKey(OUT PHANDLE KeyHandle,
@ -32,7 +30,9 @@ NtCreateKey(OUT PHANDLE KeyHandle,
NTSTATUS Status;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
CM_PARSE_CONTEXT ParseContext = {0};
HANDLE Handle;
PAGED_CODE();
DPRINT("NtCreateKey(OB 0x%wZ)\n", ObjectAttributes->ObjectName);
/* Setup the parse context */
ParseContext.CreateOperation = TRUE;
@ -46,13 +46,13 @@ NtCreateKey(OUT PHANDLE KeyHandle,
NULL,
DesiredAccess,
&ParseContext,
KeyHandle);
&Handle);
if (NT_SUCCESS(Status)) *KeyHandle = Handle;
/* Return data to user */
if (Disposition) *Disposition = ParseContext.Disposition;
return Status;
}
#endif
NTSTATUS
NTAPI
@ -61,18 +61,26 @@ NtOpenKey(OUT PHANDLE KeyHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
CM_PARSE_CONTEXT ParseContext = {0};
HANDLE Handle;
NTSTATUS Status;
PAGED_CODE();
DPRINT("NtOpenKey(OB 0x%wZ)\n", ObjectAttributes->ObjectName);
/* Just let the object manager handle this */
return ObOpenObjectByName(ObjectAttributes,
CmpKeyObjectType,
ExGetPreviousMode(),
NULL,
DesiredAccess,
&ParseContext,
KeyHandle);
Status = ObOpenObjectByName(ObjectAttributes,
CmpKeyObjectType,
ExGetPreviousMode(),
NULL,
DesiredAccess,
&ParseContext,
&Handle);
if (NT_SUCCESS(Status)) *KeyHandle = Handle;
/* Return status */
return Status;
}
NTSTATUS
NTAPI
NtDeleteKey(IN HANDLE KeyHandle)

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,6 @@
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#include "ntoskrnl/cm/cm.h"
#include "ntstrsafe.h"
typedef struct _INIT_BUFFER

View file

@ -1,248 +1,248 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/cm/cm_x.h
* PURPOSE: Inlined Functions for the Configuration Manager
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
//
// Returns whether or not this is a small valued key
//
BOOLEAN
FORCEINLINE
CmpIsKeyValueSmall(OUT PULONG RealLength,
IN ULONG Length)
{
/* Check if the length has the special size value */
if (Length >= CM_KEY_VALUE_SPECIAL_SIZE)
{
/* It does, so this is a small key: return the real length */
*RealLength = Length - CM_KEY_VALUE_SPECIAL_SIZE;
return TRUE;
}
/* This is not a small key, return the length we read */
*RealLength = Length;
return FALSE;
}
//
// Returns whether or not this is a big valued key
//
BOOLEAN
FORCEINLINE
CmpIsKeyValueBig(IN PHHIVE Hive,
IN ULONG Length)
{
/* Check if the hive is XP Beta 1 or newer */
if (Hive->Version >= HSYS_WHISTLER_BETA1)
{
/* Check if the key length is valid for a big value key */
if ((Length < CM_KEY_VALUE_SPECIAL_SIZE) && (Length > CM_KEY_VALUE_BIG))
{
/* Yes, this value is big */
return TRUE;
}
}
/* Not a big value key */
return FALSE;
}
//
// Returns the hashkey corresponding to a convkey
//
#define GET_HASH_KEY(ConvKey) \
((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
//
// Returns the index into the hash table, or the entry itself
//
#define GET_HASH_INDEX(ConvKey) \
GET_HASH_KEY(ConvKey) % CmpHashTableSize
#define GET_HASH_ENTRY(Table, ConvKey) \
(Table[GET_HASH_INDEX(ConvKey)])
//
// Returns whether or not the cell is cached
//
#define CMP_IS_CELL_CACHED(c) \
(((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
//
// Return data from a cached cell
//
#define CMP_GET_CACHED_CELL(c) \
(ULONG_PTR)((c) & ~HCELL_CACHED)
#define CMP_GET_CACHED_DATA(c) \
(&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData))
#define CMP_GET_CACHED_INDEX(c) \
(&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex))
#define CMP_GET_CACHED_VALUE(c) \
(&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
//
// Makes sure that the registry is locked
//
#define CMP_ASSERT_REGISTRY_LOCK() \
ASSERT((CmpSpecialBootCondition == TRUE) || \
(CmpTestRegistryLock() == TRUE))
//
// Makes sure that the registry is exclusively locked
//
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
ASSERT((CmpSpecialBootCondition == TRUE) || \
(CmpTestRegistryLockExclusive() == TRUE))
//
// Checks if a KCB is exclusively locked
//
#define CmpIsKcbLockedExclusive(k) \
(GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Owner == KeGetCurrentThread())
//
// Exclusively acquires a KCB
//
#define CmpAcquireKcbLockExclusive(k) \
{ \
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Lock); \
GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Owner = KeGetCurrentThread(); \
}
//
// Exclusively acquires a KCB by index
//
#define CmpAcquireKcbLockExclusiveByIndex(i) \
{ \
ExAcquirePushLockExclusive(&CmpCacheTable[(i)].Lock); \
CmpCacheTable[(i)].Owner = KeGetCurrentThread(); \
}
//
// Exclusively acquires a KCB by key
//
#define CmpAcquireKcbLockExclusiveByKey(k) \
{ \
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
(k)).Lock); \
GET_HASH_ENTRY(CmpCacheTable, \
(k)).Owner = KeGetCurrentThread(); \
}
//
// Shared acquires a KCB
//
#define CmpAcquireKcbLockShared(k) \
{ \
ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Lock); \
}
//
// Shared acquires a KCB by index
//
#define CmpAcquireKcbLockSharedByIndex(i) \
{ \
ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \
}
//
// Tries to convert a KCB lock
//
FORCEINLINE
BOOLEAN
CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
{
ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
if (ExConvertPushLockSharedToExclusive(
&GET_HASH_ENTRY(CmpCacheTable, k->ConvKey).Lock))
{
GET_HASH_ENTRY(CmpCacheTable,
k->ConvKey).Owner = KeGetCurrentThread();
return TRUE;
}
return FALSE;
}
//
// Releases an exlusively or shared acquired KCB
//
#define CmpReleaseKcbLock(k) \
{ \
GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Lock); \
}
//
// Releases an exlusively or shared acquired KCB by index
//
#define CmpReleaseKcbLockByIndex(i) \
{ \
CmpCacheTable[(i)].Owner = NULL; \
ExReleasePushLock(&CmpCacheTable[(i)].Lock); \
}
//
// Releases an exlusively or shared acquired KCB by key
//
#define CmpReleaseKcbLockByKey(k) \
{ \
GET_HASH_ENTRY(CmpCacheTable, (k)).Owner = NULL; \
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
(k)).Lock); \
}
//
// Converts a KCB lock
//
FORCEINLINE
VOID
CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
{
ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
CmpReleaseKcbLock(k);
CmpAcquireKcbLockExclusive(k);
}
//
// Exclusively acquires an NCB
//
#define CmpAcquireNcbLockExclusive(n) \
{ \
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
(n)->ConvKey).Lock); \
}
//
// Exclusively acquires an NCB by key
//
#define CmpAcquireNcbLockExclusiveByKey(k) \
{ \
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
(k)).Lock); \
}
//
// Releases an exlusively or shared acquired NCB
//
#define CmpReleaseNcbLock(k) \
{ \
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
(k)->ConvKey).Lock); \
}
//
// Releases an exlusively or shared acquired NCB by key
//
#define CmpReleaseNcbLockByKey(k) \
{ \
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
(k)).Lock); \
}
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/cm/cm_x.h
* PURPOSE: Inlined Functions for the Configuration Manager
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
//
// Returns whether or not this is a small valued key
//
BOOLEAN
FORCEINLINE
CmpIsKeyValueSmall(OUT PULONG RealLength,
IN ULONG Length)
{
/* Check if the length has the special size value */
if (Length >= CM_KEY_VALUE_SPECIAL_SIZE)
{
/* It does, so this is a small key: return the real length */
*RealLength = Length - CM_KEY_VALUE_SPECIAL_SIZE;
return TRUE;
}
/* This is not a small key, return the length we read */
*RealLength = Length;
return FALSE;
}
//
// Returns whether or not this is a big valued key
//
BOOLEAN
FORCEINLINE
CmpIsKeyValueBig(IN PHHIVE Hive,
IN ULONG Length)
{
/* Check if the hive is XP Beta 1 or newer */
if (Hive->Version >= HSYS_WHISTLER_BETA1)
{
/* Check if the key length is valid for a big value key */
if ((Length < CM_KEY_VALUE_SPECIAL_SIZE) && (Length > CM_KEY_VALUE_BIG))
{
/* Yes, this value is big */
return TRUE;
}
}
/* Not a big value key */
return FALSE;
}
//
// Returns the hashkey corresponding to a convkey
//
#define GET_HASH_KEY(ConvKey) \
((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
//
// Returns the index into the hash table, or the entry itself
//
#define GET_HASH_INDEX(ConvKey) \
GET_HASH_KEY(ConvKey) % CmpHashTableSize
#define GET_HASH_ENTRY(Table, ConvKey) \
(Table[GET_HASH_INDEX(ConvKey)])
//
// Returns whether or not the cell is cached
//
#define CMP_IS_CELL_CACHED(c) \
(((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
//
// Return data from a cached cell
//
#define CMP_GET_CACHED_CELL(c) \
(ULONG_PTR)((c) & ~HCELL_CACHED)
#define CMP_GET_CACHED_DATA(c) \
(&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData))
#define CMP_GET_CACHED_INDEX(c) \
(&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex))
#define CMP_GET_CACHED_VALUE(c) \
(&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
//
// Makes sure that the registry is locked
//
#define CMP_ASSERT_REGISTRY_LOCK() \
ASSERT((CmpSpecialBootCondition == TRUE) || \
(CmpTestRegistryLock() == TRUE))
//
// Makes sure that the registry is exclusively locked
//
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
ASSERT((CmpSpecialBootCondition == TRUE) || \
(CmpTestRegistryLockExclusive() == TRUE))
//
// Checks if a KCB is exclusively locked
//
#define CmpIsKcbLockedExclusive(k) \
(GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Owner == KeGetCurrentThread())
//
// Exclusively acquires a KCB
//
#define CmpAcquireKcbLockExclusive(k) \
{ \
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Lock); \
GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Owner = KeGetCurrentThread(); \
}
//
// Exclusively acquires a KCB by index
//
#define CmpAcquireKcbLockExclusiveByIndex(i) \
{ \
ExAcquirePushLockExclusive(&CmpCacheTable[(i)].Lock); \
CmpCacheTable[(i)].Owner = KeGetCurrentThread(); \
}
//
// Exclusively acquires a KCB by key
//
#define CmpAcquireKcbLockExclusiveByKey(k) \
{ \
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
(k)).Lock); \
GET_HASH_ENTRY(CmpCacheTable, \
(k)).Owner = KeGetCurrentThread(); \
}
//
// Shared acquires a KCB
//
#define CmpAcquireKcbLockShared(k) \
{ \
ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Lock); \
}
//
// Shared acquires a KCB by index
//
#define CmpAcquireKcbLockSharedByIndex(i) \
{ \
ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \
}
//
// Tries to convert a KCB lock
//
FORCEINLINE
BOOLEAN
CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
{
ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
if (ExConvertPushLockSharedToExclusive(
&GET_HASH_ENTRY(CmpCacheTable, k->ConvKey).Lock))
{
GET_HASH_ENTRY(CmpCacheTable,
k->ConvKey).Owner = KeGetCurrentThread();
return TRUE;
}
return FALSE;
}
//
// Releases an exlusively or shared acquired KCB
//
#define CmpReleaseKcbLock(k) \
{ \
GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
(k)->ConvKey).Lock); \
}
//
// Releases an exlusively or shared acquired KCB by index
//
#define CmpReleaseKcbLockByIndex(i) \
{ \
CmpCacheTable[(i)].Owner = NULL; \
ExReleasePushLock(&CmpCacheTable[(i)].Lock); \
}
//
// Releases an exlusively or shared acquired KCB by key
//
#define CmpReleaseKcbLockByKey(k) \
{ \
GET_HASH_ENTRY(CmpCacheTable, (k)).Owner = NULL; \
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
(k)).Lock); \
}
//
// Converts a KCB lock
//
FORCEINLINE
VOID
CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
{
ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
CmpReleaseKcbLock(k);
CmpAcquireKcbLockExclusive(k);
}
//
// Exclusively acquires an NCB
//
#define CmpAcquireNcbLockExclusive(n) \
{ \
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
(n)->ConvKey).Lock); \
}
//
// Exclusively acquires an NCB by key
//
#define CmpAcquireNcbLockExclusiveByKey(k) \
{ \
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
(k)).Lock); \
}
//
// Releases an exlusively or shared acquired NCB
//
#define CmpReleaseNcbLock(k) \
{ \
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
(k)->ConvKey).Lock); \
}
//
// Releases an exlusively or shared acquired NCB by key
//
#define CmpReleaseNcbLockByKey(k) \
{ \
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
(k)).Lock); \
}

View file

@ -30,6 +30,7 @@
#include "ob.h"
#include "mm.h"
#include "ex.h"
#include "cm.h"
#include "ps.h"
#include "cc.h"
#include "io.h"

View file

@ -142,12 +142,6 @@
<file>cmwraprs.c</file>
<file>ntapi.c</file>
</directory>
<directory name="cm">
<file>ntfunc.c</file>
<file>regfile.c</file>
<file>registry.c</file>
<file>regobj.c</file>
</directory>
<directory name="dbgk">
<file>dbgkutil.c</file>
<file>dbgkobj.c</file>

View file

@ -138,9 +138,6 @@
<file>cmwraprs.c</file>
<file>ntapi.c</file>
</directory>
<directory name="cm">
<file>regobj.c</file>
</directory>
<directory name="dbgk">
<file>dbgkutil.c</file>
<file>dbgkobj.c</file>