mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 02:25:40 +00:00
- 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:
parent
ffa5f05eca
commit
0b6a2fda00
34 changed files with 11540 additions and 12666 deletions
|
@ -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
|
@ -11,7 +11,6 @@
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include "cm.h"
|
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
|
@ -1,127 +1,126 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmboot.c
|
* FILE: ntoskrnl/config/cmboot.c
|
||||||
* PURPOSE: Configuration Manager - Boot Initialization
|
* PURPOSE: Configuration Manager - Boot Initialization
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* GLOBALS *******************************************************************/
|
||||||
/* GLOBALS *******************************************************************/
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
HCELL_INDEX
|
||||||
HCELL_INDEX
|
NTAPI
|
||||||
NTAPI
|
CmpFindControlSet(IN PHHIVE SystemHive,
|
||||||
CmpFindControlSet(IN PHHIVE SystemHive,
|
IN HCELL_INDEX RootCell,
|
||||||
IN HCELL_INDEX RootCell,
|
IN PUNICODE_STRING SelectKeyName,
|
||||||
IN PUNICODE_STRING SelectKeyName,
|
OUT PBOOLEAN AutoSelect)
|
||||||
OUT PBOOLEAN AutoSelect)
|
{
|
||||||
{
|
UNICODE_STRING KeyName;
|
||||||
UNICODE_STRING KeyName;
|
PCM_KEY_NODE Node;
|
||||||
PCM_KEY_NODE Node;
|
HCELL_INDEX SelectCell, AutoSelectCell, SelectValueCell, ControlSetCell;
|
||||||
HCELL_INDEX SelectCell, AutoSelectCell, SelectValueCell, ControlSetCell;
|
HCELL_INDEX CurrentValueCell;
|
||||||
HCELL_INDEX CurrentValueCell;
|
PCM_KEY_VALUE KeyValue;
|
||||||
PCM_KEY_VALUE KeyValue;
|
ULONG Length;
|
||||||
ULONG Length;
|
PULONG ControlSetId;
|
||||||
PULONG ControlSetId;
|
ANSI_STRING ControlSetAnsiName;
|
||||||
ANSI_STRING ControlSetAnsiName;
|
CHAR Buffer[128];
|
||||||
CHAR Buffer[128];
|
WCHAR WideBuffer[128];
|
||||||
WCHAR WideBuffer[128];
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
PULONG CurrentData;
|
||||||
PULONG CurrentData;
|
|
||||||
|
/* Sanity check */
|
||||||
/* Sanity check */
|
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
|
||||||
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
|
|
||||||
|
/* Get the Select subkey */
|
||||||
/* Get the Select subkey */
|
RtlInitUnicodeString(&KeyName, L"select");
|
||||||
RtlInitUnicodeString(&KeyName, L"select");
|
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
|
||||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
|
if (!Node) return HCELL_NIL;
|
||||||
if (!Node) return HCELL_NIL;
|
SelectCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
|
||||||
SelectCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
|
if (SelectCell == HCELL_NIL) return SelectCell;
|
||||||
if (SelectCell == HCELL_NIL) return SelectCell;
|
|
||||||
|
/* Get AutoSelect value */
|
||||||
/* Get AutoSelect value */
|
RtlInitUnicodeString(&KeyName, L"AutoSelect");
|
||||||
RtlInitUnicodeString(&KeyName, L"AutoSelect");
|
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
|
||||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
|
if (!Node) return HCELL_NIL;
|
||||||
if (!Node) return HCELL_NIL;
|
AutoSelectCell = CmpFindValueByName(SystemHive, Node, &KeyName);
|
||||||
AutoSelectCell = CmpFindValueByName(SystemHive, Node, &KeyName);
|
if (AutoSelectCell == HCELL_NIL)
|
||||||
if (AutoSelectCell == HCELL_NIL)
|
{
|
||||||
{
|
/* Assume TRUE if the value is missing. */
|
||||||
/* Assume TRUE if the value is missing. */
|
*AutoSelect = TRUE;
|
||||||
*AutoSelect = TRUE;
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Read the value */
|
||||||
/* Read the value */
|
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
|
||||||
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, AutoSelectCell);
|
if (KeyValue == NULL) return HCELL_NIL;
|
||||||
if (KeyValue == NULL) return HCELL_NIL;
|
|
||||||
|
/* Convert it to a boolean */
|
||||||
/* Convert it to a boolean */
|
*AutoSelect = *(PBOOLEAN)CmpValueToData(SystemHive, KeyValue, &Length);
|
||||||
*AutoSelect = *(PBOOLEAN)CmpValueToData(SystemHive, KeyValue, &Length);
|
}
|
||||||
}
|
|
||||||
|
/* Now find the control set being looked up */
|
||||||
/* Now find the control set being looked up */
|
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
|
||||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
|
if (!Node) return HCELL_NIL;
|
||||||
if (!Node) return HCELL_NIL;
|
SelectValueCell = CmpFindValueByName(SystemHive, Node, SelectKeyName);
|
||||||
SelectValueCell = CmpFindValueByName(SystemHive, Node, SelectKeyName);
|
if (SelectValueCell == HCELL_NIL) return SelectValueCell;
|
||||||
if (SelectValueCell == HCELL_NIL) return SelectValueCell;
|
|
||||||
|
/* Read the value (corresponding to the CCS ID) */
|
||||||
/* Read the value (corresponding to the CCS ID) */
|
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, SelectValueCell);
|
||||||
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, SelectValueCell);
|
if (!KeyValue) return HCELL_NIL;
|
||||||
if (!KeyValue) return HCELL_NIL;
|
if (KeyValue->Type != REG_DWORD) return HCELL_NIL;
|
||||||
if (KeyValue->Type != REG_DWORD) return HCELL_NIL;
|
ControlSetId = (PULONG)CmpValueToData(SystemHive, KeyValue, &Length);
|
||||||
ControlSetId = (PULONG)CmpValueToData(SystemHive, KeyValue, &Length);
|
|
||||||
|
/* Now build an Ansi String for the CCS's Name */
|
||||||
/* Now build an Ansi String for the CCS's Name */
|
sprintf(Buffer, "ControlSet%03lu", *ControlSetId);
|
||||||
sprintf(Buffer, "ControlSet%03lu", *ControlSetId);
|
ControlSetAnsiName.Length = (USHORT)strlen(Buffer);
|
||||||
ControlSetAnsiName.Length = (USHORT)strlen(Buffer);
|
ControlSetAnsiName.MaximumLength = (USHORT)strlen(Buffer);
|
||||||
ControlSetAnsiName.MaximumLength = (USHORT)strlen(Buffer);
|
ControlSetAnsiName.Buffer = Buffer;
|
||||||
ControlSetAnsiName.Buffer = Buffer;
|
|
||||||
|
/* And convert it to Unicode... */
|
||||||
/* And convert it to Unicode... */
|
KeyName.MaximumLength = 256;
|
||||||
KeyName.MaximumLength = 256;
|
KeyName.Buffer = WideBuffer;
|
||||||
KeyName.Buffer = WideBuffer;
|
Status = RtlAnsiStringToUnicodeString(&KeyName,
|
||||||
Status = RtlAnsiStringToUnicodeString(&KeyName,
|
&ControlSetAnsiName,
|
||||||
&ControlSetAnsiName,
|
FALSE);
|
||||||
FALSE);
|
if (!NT_SUCCESS(Status)) return HCELL_NIL;
|
||||||
if (!NT_SUCCESS(Status)) return HCELL_NIL;
|
|
||||||
|
/* Now open it */
|
||||||
/* Now open it */
|
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
|
||||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, RootCell);
|
if (!Node) return HCELL_NIL;
|
||||||
if (!Node) return HCELL_NIL;
|
ControlSetCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
|
||||||
ControlSetCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
|
if (ControlSetCell == HCELL_NIL) return ControlSetCell;
|
||||||
if (ControlSetCell == HCELL_NIL) return ControlSetCell;
|
|
||||||
|
/* Get the value of the "Current" CCS */
|
||||||
/* Get the value of the "Current" CCS */
|
RtlInitUnicodeString(&KeyName, L"Current");
|
||||||
RtlInitUnicodeString(&KeyName, L"Current");
|
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
|
||||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, SelectCell);
|
if (!Node) return HCELL_NIL;
|
||||||
if (!Node) return HCELL_NIL;
|
CurrentValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
|
||||||
CurrentValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
|
|
||||||
|
/* Make sure it exists */
|
||||||
/* Make sure it exists */
|
if (CurrentValueCell != HCELL_NIL)
|
||||||
if (CurrentValueCell != HCELL_NIL)
|
{
|
||||||
{
|
/* Get the current value and make sure its a ULONG */
|
||||||
/* Get the current value and make sure its a ULONG */
|
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, CurrentValueCell);
|
||||||
KeyValue = (PCM_KEY_VALUE)HvGetCell(SystemHive, CurrentValueCell);
|
if (!KeyValue) return HCELL_NIL;
|
||||||
if (!KeyValue) return HCELL_NIL;
|
if (KeyValue->Type == REG_DWORD)
|
||||||
if (KeyValue->Type == REG_DWORD)
|
{
|
||||||
{
|
/* Get the data and update it */
|
||||||
/* Get the data and update it */
|
CurrentData = (PULONG)CmpValueToData(SystemHive,
|
||||||
CurrentData = (PULONG)CmpValueToData(SystemHive,
|
KeyValue,
|
||||||
KeyValue,
|
&Length);
|
||||||
&Length);
|
if (!CurrentData) return HCELL_NIL;
|
||||||
if (!CurrentData) return HCELL_NIL;
|
*CurrentData = *ControlSetId;
|
||||||
*CurrentData = *ControlSetId;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Return the CCS Cell */
|
||||||
/* Return the CCS Cell */
|
return ControlSetCell;
|
||||||
return ControlSetCell;
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,27 +1,26 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmcheck.c
|
* FILE: ntoskrnl/config/cmcheck.c
|
||||||
* PURPOSE: Configuration Manager - Hive and Key Validation
|
* PURPOSE: Configuration Manager - Hive and Key Validation
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* GLOBALS *******************************************************************/
|
||||||
/* GLOBALS *******************************************************************/
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
ULONG
|
||||||
ULONG
|
NTAPI
|
||||||
NTAPI
|
CmCheckRegistry(IN PCMHIVE RegistryHive,
|
||||||
CmCheckRegistry(IN PCMHIVE RegistryHive,
|
IN ULONG Flags)
|
||||||
IN ULONG Flags)
|
{
|
||||||
{
|
/* FIXME: HACK! */
|
||||||
/* FIXME: HACK! */
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,399 +1,398 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmconfig.c
|
* FILE: ntoskrnl/config/cmconfig.c
|
||||||
* PURPOSE: Configuration Manager - System Configuration Routines
|
* PURPOSE: Configuration Manager - System Configuration Routines
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
|
||||||
CmpInitializeRegistryNode(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
|
IN HANDLE NodeHandle,
|
||||||
IN HANDLE NodeHandle,
|
OUT PHANDLE NewHandle,
|
||||||
OUT PHANDLE NewHandle,
|
IN INTERFACE_TYPE InterfaceType,
|
||||||
IN INTERFACE_TYPE InterfaceType,
|
IN ULONG BusNumber,
|
||||||
IN ULONG BusNumber,
|
IN PUSHORT DeviceIndexTable)
|
||||||
IN PUSHORT DeviceIndexTable)
|
{
|
||||||
{
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
UNICODE_STRING KeyName, ValueName, ValueData;
|
||||||
UNICODE_STRING KeyName, ValueName, ValueData;
|
HANDLE KeyHandle, ParentHandle;
|
||||||
HANDLE KeyHandle, ParentHandle;
|
ANSI_STRING TempString;
|
||||||
ANSI_STRING TempString;
|
CHAR TempBuffer[12];
|
||||||
CHAR TempBuffer[12];
|
WCHAR Buffer[12];
|
||||||
WCHAR Buffer[12];
|
PCONFIGURATION_COMPONENT Component;
|
||||||
PCONFIGURATION_COMPONENT Component;
|
ULONG Disposition, Length = 0;
|
||||||
ULONG Disposition, Length = 0;
|
|
||||||
|
/* Get the component */
|
||||||
/* Get the component */
|
Component = &CurrentEntry->ComponentEntry;
|
||||||
Component = &CurrentEntry->ComponentEntry;
|
|
||||||
|
/* Set system class components to ARC system type */
|
||||||
/* Set system class components to ARC system type */
|
if (Component->Class == SystemClass) Component->Type = ArcSystem;
|
||||||
if (Component->Class == SystemClass) Component->Type = ArcSystem;
|
|
||||||
|
/* Create a key for the component */
|
||||||
/* Create a key for the component */
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
&CmTypeName[Component->Type],
|
||||||
&CmTypeName[Component->Type],
|
OBJ_CASE_INSENSITIVE,
|
||||||
OBJ_CASE_INSENSITIVE,
|
NodeHandle,
|
||||||
NodeHandle,
|
NULL);
|
||||||
NULL);
|
Status = NtCreateKey(&KeyHandle,
|
||||||
Status = NtCreateKey(&KeyHandle,
|
KEY_READ | KEY_WRITE,
|
||||||
KEY_READ | KEY_WRITE,
|
&ObjectAttributes,
|
||||||
&ObjectAttributes,
|
0,
|
||||||
0,
|
NULL,
|
||||||
NULL,
|
0,
|
||||||
0,
|
&Disposition);
|
||||||
&Disposition);
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
|
||||||
|
/* Check if this is anything but a system class component */
|
||||||
/* Check if this is anything but a system class component */
|
if (Component->Class != SystemClass)
|
||||||
if (Component->Class != SystemClass)
|
{
|
||||||
{
|
/* Build the sub-component string */
|
||||||
/* Build the sub-component string */
|
RtlIntegerToChar(DeviceIndexTable[Component->Type]++,
|
||||||
RtlIntegerToChar(DeviceIndexTable[Component->Type]++,
|
10,
|
||||||
10,
|
12,
|
||||||
12,
|
TempBuffer);
|
||||||
TempBuffer);
|
RtlInitAnsiString(&TempString, TempBuffer);
|
||||||
RtlInitAnsiString(&TempString, TempBuffer);
|
|
||||||
|
/* Convert it to Unicode */
|
||||||
/* Convert it to Unicode */
|
RtlInitEmptyUnicodeString(&KeyName, Buffer, sizeof(Buffer));
|
||||||
RtlInitEmptyUnicodeString(&KeyName, Buffer, sizeof(Buffer));
|
RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE);
|
||||||
RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE);
|
|
||||||
|
/* Create the key */
|
||||||
/* Create the key */
|
ParentHandle = KeyHandle;
|
||||||
ParentHandle = KeyHandle;
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
&KeyName,
|
||||||
&KeyName,
|
OBJ_CASE_INSENSITIVE,
|
||||||
OBJ_CASE_INSENSITIVE,
|
ParentHandle,
|
||||||
ParentHandle,
|
NULL);
|
||||||
NULL);
|
Status = NtCreateKey(&KeyHandle,
|
||||||
Status = NtCreateKey(&KeyHandle,
|
KEY_READ | KEY_WRITE,
|
||||||
KEY_READ | KEY_WRITE,
|
&ObjectAttributes,
|
||||||
&ObjectAttributes,
|
0,
|
||||||
0,
|
NULL,
|
||||||
NULL,
|
0,
|
||||||
0,
|
&Disposition);
|
||||||
&Disposition);
|
NtClose(ParentHandle);
|
||||||
NtClose(ParentHandle);
|
|
||||||
|
/* Fail if the key couldn't be created, and make sure it's a new key */
|
||||||
/* Fail if the key couldn't be created, and make sure it's a new key */
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
ASSERT(Disposition == REG_CREATED_NEW_KEY);
|
||||||
ASSERT(Disposition == REG_CREATED_NEW_KEY);
|
}
|
||||||
}
|
|
||||||
|
/* Setup the component information key */
|
||||||
/* Setup the component information key */
|
RtlInitUnicodeString(&ValueName, L"Component Information");
|
||||||
RtlInitUnicodeString(&ValueName, L"Component Information");
|
Status = NtSetValueKey(KeyHandle,
|
||||||
Status = NtSetValueKey(KeyHandle,
|
&ValueName,
|
||||||
&ValueName,
|
0,
|
||||||
0,
|
REG_BINARY,
|
||||||
REG_BINARY,
|
&Component->Flags,
|
||||||
&Component->Flags,
|
FIELD_OFFSET(CONFIGURATION_COMPONENT,
|
||||||
FIELD_OFFSET(CONFIGURATION_COMPONENT,
|
ConfigurationDataLength) -
|
||||||
ConfigurationDataLength) -
|
FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags));
|
||||||
FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags));
|
if (!NT_SUCCESS(Status))
|
||||||
if (!NT_SUCCESS(Status))
|
{
|
||||||
{
|
/* Fail */
|
||||||
/* Fail */
|
NtClose(KeyHandle);
|
||||||
NtClose(KeyHandle);
|
return Status;
|
||||||
return Status;
|
}
|
||||||
}
|
|
||||||
|
/* Check if we have an identifier */
|
||||||
/* Check if we have an identifier */
|
if (Component->IdentifierLength)
|
||||||
if (Component->IdentifierLength)
|
{
|
||||||
{
|
/* Build the string and convert it to Unicode */
|
||||||
/* Build the string and convert it to Unicode */
|
RtlInitUnicodeString(&ValueName, L"Identifier");
|
||||||
RtlInitUnicodeString(&ValueName, L"Identifier");
|
RtlInitAnsiString(&TempString, Component->Identifier);
|
||||||
RtlInitAnsiString(&TempString, Component->Identifier);
|
Status = RtlAnsiStringToUnicodeString(&ValueData,
|
||||||
Status = RtlAnsiStringToUnicodeString(&ValueData,
|
&TempString,
|
||||||
&TempString,
|
TRUE);
|
||||||
TRUE);
|
RtlCreateUnicodeString(&ValueData, (PWCHAR)Component->Identifier);
|
||||||
RtlCreateUnicodeString(&ValueData, (PWCHAR)Component->Identifier);
|
if (NT_SUCCESS(Status))
|
||||||
if (NT_SUCCESS(Status))
|
{
|
||||||
{
|
/* Save the identifier in the registry */
|
||||||
/* Save the identifier in the registry */
|
Status = NtSetValueKey(KeyHandle,
|
||||||
Status = NtSetValueKey(KeyHandle,
|
&ValueName,
|
||||||
&ValueName,
|
0,
|
||||||
0,
|
REG_SZ,
|
||||||
REG_SZ,
|
ValueData.Buffer,
|
||||||
ValueData.Buffer,
|
ValueData.Length + sizeof(UNICODE_NULL));
|
||||||
ValueData.Length + sizeof(UNICODE_NULL));
|
RtlFreeUnicodeString(&ValueData);
|
||||||
RtlFreeUnicodeString(&ValueData);
|
}
|
||||||
}
|
|
||||||
|
/* Check for failure during conversion or registry write */
|
||||||
/* Check for failure during conversion or registry write */
|
if (!NT_SUCCESS(Status))
|
||||||
if (!NT_SUCCESS(Status))
|
{
|
||||||
{
|
/* Fail */
|
||||||
/* Fail */
|
NtClose(KeyHandle);
|
||||||
NtClose(KeyHandle);
|
return Status;
|
||||||
return Status;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Setup the configuration data string */
|
||||||
/* Setup the configuration data string */
|
RtlInitUnicodeString(&ValueName, L"Configuration Data");
|
||||||
RtlInitUnicodeString(&ValueName, L"Configuration Data");
|
|
||||||
|
/* Check if we got configuration data */
|
||||||
/* Check if we got configuration data */
|
if (CurrentEntry->ConfigurationData)
|
||||||
if (CurrentEntry->ConfigurationData)
|
{
|
||||||
{
|
/* Calculate the total length and check if it fits into our buffer */
|
||||||
/* Calculate the total length and check if it fits into our buffer */
|
Length = Component->ConfigurationDataLength +
|
||||||
Length = Component->ConfigurationDataLength +
|
FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList);
|
||||||
FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList);
|
if (Length > CmpConfigurationAreaSize)
|
||||||
if (Length > CmpConfigurationAreaSize)
|
{
|
||||||
{
|
ASSERTMSG("Component too large -- need reallocation!", FALSE);
|
||||||
ASSERTMSG("Component too large -- need reallocation!", FALSE);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Copy the data */
|
||||||
/* Copy the data */
|
RtlCopyMemory(&CmpConfigurationData->PartialResourceList.Version,
|
||||||
RtlCopyMemory(&CmpConfigurationData->PartialResourceList.Version,
|
CurrentEntry->ConfigurationData,
|
||||||
CurrentEntry->ConfigurationData,
|
Component->ConfigurationDataLength);
|
||||||
Component->ConfigurationDataLength);
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* No configuration data, setup defaults */
|
||||||
/* No configuration data, setup defaults */
|
CmpConfigurationData->PartialResourceList.Version = 0;
|
||||||
CmpConfigurationData->PartialResourceList.Version = 0;
|
CmpConfigurationData->PartialResourceList.Revision = 0;
|
||||||
CmpConfigurationData->PartialResourceList.Revision = 0;
|
CmpConfigurationData->PartialResourceList.Count = 0;
|
||||||
CmpConfigurationData->PartialResourceList.Count = 0;
|
Length = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
|
||||||
Length = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
|
FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList);
|
||||||
FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList);
|
}
|
||||||
}
|
|
||||||
|
/* Set the interface type and bus number */
|
||||||
/* Set the interface type and bus number */
|
CmpConfigurationData->InterfaceType = InterfaceType;
|
||||||
CmpConfigurationData->InterfaceType = InterfaceType;
|
CmpConfigurationData->BusNumber = BusNumber;
|
||||||
CmpConfigurationData->BusNumber = BusNumber;
|
|
||||||
|
/* Save the actual data */
|
||||||
/* Save the actual data */
|
Status = NtSetValueKey(KeyHandle,
|
||||||
Status = NtSetValueKey(KeyHandle,
|
&ValueName,
|
||||||
&ValueName,
|
0,
|
||||||
0,
|
REG_FULL_RESOURCE_DESCRIPTOR,
|
||||||
REG_FULL_RESOURCE_DESCRIPTOR,
|
CmpConfigurationData,
|
||||||
CmpConfigurationData,
|
Length);
|
||||||
Length);
|
if (!NT_SUCCESS(Status))
|
||||||
if (!NT_SUCCESS(Status))
|
{
|
||||||
{
|
/* Fail */
|
||||||
/* Fail */
|
NtClose(KeyHandle);
|
||||||
NtClose(KeyHandle);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Return the new handle */
|
||||||
/* Return the new handle */
|
*NewHandle = KeyHandle;
|
||||||
*NewHandle = KeyHandle;
|
}
|
||||||
}
|
|
||||||
|
/* Return status */
|
||||||
/* Return status */
|
return Status;
|
||||||
return Status;
|
}
|
||||||
}
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
|
||||||
CmpSetupConfigurationTree(IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
|
IN HANDLE ParentHandle,
|
||||||
IN HANDLE ParentHandle,
|
IN INTERFACE_TYPE InterfaceType,
|
||||||
IN INTERFACE_TYPE InterfaceType,
|
IN ULONG BusNumber)
|
||||||
IN ULONG BusNumber)
|
{
|
||||||
{
|
PCONFIGURATION_COMPONENT Component;
|
||||||
PCONFIGURATION_COMPONENT Component;
|
USHORT DeviceIndexTable[MaximumType + 1] = {0};
|
||||||
USHORT DeviceIndexTable[MaximumType + 1] = {0};
|
ULONG Interface = InterfaceType, Bus = BusNumber, i;
|
||||||
ULONG Interface = InterfaceType, Bus = BusNumber, i;
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
HANDLE NewHandle;
|
||||||
HANDLE NewHandle;
|
|
||||||
|
/* Loop each entry */
|
||||||
/* Loop each entry */
|
while (CurrentEntry)
|
||||||
while (CurrentEntry)
|
{
|
||||||
{
|
/* Check if this is an adapter */
|
||||||
/* Check if this is an adapter */
|
Component = &CurrentEntry->ComponentEntry;
|
||||||
Component = &CurrentEntry->ComponentEntry;
|
if ((Component->Class == AdapterClass) &&
|
||||||
if ((Component->Class == AdapterClass) &&
|
(CurrentEntry->Parent->ComponentEntry.Class == SystemClass))
|
||||||
(CurrentEntry->Parent->ComponentEntry.Class == SystemClass))
|
{
|
||||||
{
|
/* Check what kind of adapter it is */
|
||||||
/* Check what kind of adapter it is */
|
switch (Component->Type)
|
||||||
switch (Component->Type)
|
{
|
||||||
{
|
/* EISA */
|
||||||
/* EISA */
|
case EisaAdapter:
|
||||||
case EisaAdapter:
|
|
||||||
|
/* Fixup information */
|
||||||
/* Fixup information */
|
Interface = Eisa;
|
||||||
Interface = Eisa;
|
Bus = CmpTypeCount[EisaAdapter]++;
|
||||||
Bus = CmpTypeCount[EisaAdapter]++;
|
break;
|
||||||
break;
|
|
||||||
|
/* Turbo-channel */
|
||||||
/* Turbo-channel */
|
case TcAdapter:
|
||||||
case TcAdapter:
|
|
||||||
|
/* Fixup information */
|
||||||
/* Fixup information */
|
Interface = TurboChannel;
|
||||||
Interface = TurboChannel;
|
Bus = CmpTypeCount[TurboChannel]++;
|
||||||
Bus = CmpTypeCount[TurboChannel]++;
|
break;
|
||||||
break;
|
|
||||||
|
/* ISA, PCI, etc busses */
|
||||||
/* ISA, PCI, etc busses */
|
case MultiFunctionAdapter:
|
||||||
case MultiFunctionAdapter:
|
|
||||||
|
/* Check if we have an identifier */
|
||||||
/* Check if we have an identifier */
|
if (Component->Identifier)
|
||||||
if (Component->Identifier)
|
{
|
||||||
{
|
/* Loop each multi-function adapter type */
|
||||||
/* Loop each multi-function adapter type */
|
for (i = 0; CmpMultifunctionTypes[i].Identifier; i++)
|
||||||
for (i = 0; CmpMultifunctionTypes[i].Identifier; i++)
|
{
|
||||||
{
|
/* Check for a name match */
|
||||||
/* Check for a name match */
|
if (!_wcsicmp(CmpMultifunctionTypes[i].Identifier,
|
||||||
if (!_wcsicmp(CmpMultifunctionTypes[i].Identifier,
|
(PWCHAR)Component->Identifier))
|
||||||
(PWCHAR)Component->Identifier))
|
{
|
||||||
{
|
/* Match found */
|
||||||
/* Match found */
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Fix up information */
|
||||||
/* Fix up information */
|
Interface = CmpMultifunctionTypes[i].InterfaceType;
|
||||||
Interface = CmpMultifunctionTypes[i].InterfaceType;
|
Bus = CmpMultifunctionTypes[i].Count++;
|
||||||
Bus = CmpMultifunctionTypes[i].Count++;
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
|
/* SCSI Bus */
|
||||||
/* SCSI Bus */
|
case ScsiAdapter:
|
||||||
case ScsiAdapter:
|
|
||||||
|
/* Fix up */
|
||||||
/* Fix up */
|
Interface = Internal;
|
||||||
Interface = Internal;
|
Bus = CmpTypeCount[ScsiAdapter]++;
|
||||||
Bus = CmpTypeCount[ScsiAdapter]++;
|
break;
|
||||||
break;
|
|
||||||
|
/* Unknown */
|
||||||
/* Unknown */
|
default:
|
||||||
default:
|
Interface = -1;
|
||||||
Interface = -1;
|
Bus = CmpUnknownBusCount++;
|
||||||
Bus = CmpUnknownBusCount++;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Dump information on the component */
|
||||||
/* Dump information on the component */
|
|
||||||
|
/* Setup the hardware node */
|
||||||
/* Setup the hardware node */
|
Status = CmpInitializeRegistryNode(CurrentEntry,
|
||||||
Status = CmpInitializeRegistryNode(CurrentEntry,
|
ParentHandle,
|
||||||
ParentHandle,
|
&NewHandle,
|
||||||
&NewHandle,
|
Interface,
|
||||||
Interface,
|
Bus,
|
||||||
Bus,
|
DeviceIndexTable);
|
||||||
DeviceIndexTable);
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
|
||||||
|
/* Check for children */
|
||||||
/* Check for children */
|
if (CurrentEntry->Child)
|
||||||
if (CurrentEntry->Child)
|
{
|
||||||
{
|
/* Recurse child */
|
||||||
/* Recurse child */
|
Status = CmpSetupConfigurationTree(CurrentEntry->Child,
|
||||||
Status = CmpSetupConfigurationTree(CurrentEntry->Child,
|
NewHandle,
|
||||||
NewHandle,
|
Interface,
|
||||||
Interface,
|
Bus);
|
||||||
Bus);
|
if (!NT_SUCCESS(Status))
|
||||||
if (!NT_SUCCESS(Status))
|
{
|
||||||
{
|
/* Fail */
|
||||||
/* Fail */
|
NtClose(NewHandle);
|
||||||
NtClose(NewHandle);
|
return Status;
|
||||||
return Status;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Get to the next entry */
|
||||||
/* Get to the next entry */
|
NtClose(NewHandle);
|
||||||
NtClose(NewHandle);
|
CurrentEntry = CurrentEntry->Sibling;
|
||||||
CurrentEntry = CurrentEntry->Sibling;
|
}
|
||||||
}
|
|
||||||
|
/* We're done */
|
||||||
/* We're done */
|
return STATUS_SUCCESS;
|
||||||
return STATUS_SUCCESS;
|
}
|
||||||
}
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
CmpInitializeHardwareConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
{
|
||||||
{
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
HANDLE KeyHandle;
|
||||||
HANDLE KeyHandle;
|
ULONG Disposition;
|
||||||
ULONG Disposition;
|
UNICODE_STRING KeyName;
|
||||||
UNICODE_STRING KeyName;
|
|
||||||
|
/* Setup the key name */
|
||||||
/* Setup the key name */
|
RtlInitUnicodeString(&KeyName,
|
||||||
RtlInitUnicodeString(&KeyName,
|
L"\\Registry\\Machine\\Hardware\\DeviceMap");
|
||||||
L"\\Registry\\Machine\\Hardware\\DeviceMap");
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
&KeyName,
|
||||||
&KeyName,
|
OBJ_CASE_INSENSITIVE,
|
||||||
OBJ_CASE_INSENSITIVE,
|
NULL,
|
||||||
NULL,
|
NULL);
|
||||||
NULL);
|
|
||||||
|
/* Create the device map key */
|
||||||
/* Create the device map key */
|
Status = NtCreateKey(&KeyHandle,
|
||||||
Status = NtCreateKey(&KeyHandle,
|
KEY_READ | KEY_WRITE,
|
||||||
KEY_READ | KEY_WRITE,
|
&ObjectAttributes,
|
||||||
&ObjectAttributes,
|
0,
|
||||||
0,
|
NULL,
|
||||||
NULL,
|
0,
|
||||||
0,
|
&Disposition);
|
||||||
&Disposition);
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
NtClose(KeyHandle);
|
||||||
NtClose(KeyHandle);
|
|
||||||
|
/* Nobody should've created this key yet! */
|
||||||
/* Nobody should've created this key yet! */
|
ASSERT(Disposition == REG_CREATED_NEW_KEY);
|
||||||
ASSERT(Disposition == REG_CREATED_NEW_KEY);
|
|
||||||
|
/* Setup the key name */
|
||||||
/* Setup the key name */
|
RtlInitUnicodeString(&KeyName,
|
||||||
RtlInitUnicodeString(&KeyName,
|
L"\\Registry\\Machine\\Hardware\\Description");
|
||||||
L"\\Registry\\Machine\\Hardware\\Description");
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
&KeyName,
|
||||||
&KeyName,
|
OBJ_CASE_INSENSITIVE,
|
||||||
OBJ_CASE_INSENSITIVE,
|
NULL,
|
||||||
NULL,
|
NULL);
|
||||||
NULL);
|
|
||||||
|
/* Create the description key */
|
||||||
/* Create the description key */
|
Status = NtCreateKey(&KeyHandle,
|
||||||
Status = NtCreateKey(&KeyHandle,
|
KEY_READ | KEY_WRITE,
|
||||||
KEY_READ | KEY_WRITE,
|
&ObjectAttributes,
|
||||||
&ObjectAttributes,
|
0,
|
||||||
0,
|
NULL,
|
||||||
NULL,
|
0,
|
||||||
0,
|
&Disposition);
|
||||||
&Disposition);
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
|
||||||
|
/* Nobody should've created this key yet! */
|
||||||
/* Nobody should've created this key yet! */
|
ASSERT(Disposition == REG_CREATED_NEW_KEY);
|
||||||
ASSERT(Disposition == REG_CREATED_NEW_KEY);
|
|
||||||
|
/* Allocate the configuration data buffer */
|
||||||
/* Allocate the configuration data buffer */
|
CmpConfigurationData = ExAllocatePoolWithTag(PagedPool,
|
||||||
CmpConfigurationData = ExAllocatePoolWithTag(PagedPool,
|
CmpConfigurationAreaSize,
|
||||||
CmpConfigurationAreaSize,
|
TAG_CM);
|
||||||
TAG_CM);
|
if (!CmpConfigurationData) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
if (!CmpConfigurationData) return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
/* Check if we got anything from NTLDR */
|
||||||
/* Check if we got anything from NTLDR */
|
if (LoaderBlock->ConfigurationRoot)
|
||||||
if (LoaderBlock->ConfigurationRoot)
|
{
|
||||||
{
|
/* Setup the configuration tree */
|
||||||
/* Setup the configuration tree */
|
Status = CmpSetupConfigurationTree(LoaderBlock->ConfigurationRoot,
|
||||||
Status = CmpSetupConfigurationTree(LoaderBlock->ConfigurationRoot,
|
KeyHandle,
|
||||||
KeyHandle,
|
-1,
|
||||||
-1,
|
-1);
|
||||||
-1);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Nothing else to do */
|
||||||
/* Nothing else to do */
|
Status = STATUS_SUCCESS;
|
||||||
Status = STATUS_SUCCESS;
|
}
|
||||||
}
|
|
||||||
|
/* Close our handle, free the buffer and return status */
|
||||||
/* Close our handle, free the buffer and return status */
|
ExFreePool(CmpConfigurationData);
|
||||||
ExFreePool(CmpConfigurationData);
|
NtClose(KeyHandle);
|
||||||
NtClose(KeyHandle);
|
return Status;
|
||||||
return Status;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,265 +1,264 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmcontrl.c
|
* FILE: ntoskrnl/config/cmcontrl.c
|
||||||
* PURPOSE: Configuration Manager - Control Set Management
|
* PURPOSE: Configuration Manager - Control Set Management
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* GLOBALS *******************************************************************/
|
||||||
/* GLOBALS *******************************************************************/
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
LANGID
|
||||||
LANGID
|
NTAPI
|
||||||
NTAPI
|
CmpConvertLangId(IN LPWSTR Name,
|
||||||
CmpConvertLangId(IN LPWSTR Name,
|
IN ULONG NameLength)
|
||||||
IN ULONG NameLength)
|
{
|
||||||
{
|
ULONG i;
|
||||||
ULONG i;
|
WCHAR p;
|
||||||
WCHAR p;
|
LANGID LangId = 0;
|
||||||
LANGID LangId = 0;
|
ULONG IdCode;
|
||||||
ULONG IdCode;
|
|
||||||
|
/* Convert the length in chars and loop */
|
||||||
/* Convert the length in chars and loop */
|
NameLength = NameLength / sizeof(WCHAR);
|
||||||
NameLength = NameLength / sizeof(WCHAR);
|
for (i = 0; i < NameLength; i++)
|
||||||
for (i = 0; i < NameLength; i++)
|
{
|
||||||
{
|
/* Get the character */
|
||||||
/* Get the character */
|
p = Name[i];
|
||||||
p = Name[i];
|
|
||||||
|
/* Handle each case */
|
||||||
/* Handle each case */
|
if ((p >= L'0') && (p <= L'9'))
|
||||||
if ((p >= L'0') && (p <= L'9'))
|
{
|
||||||
{
|
/* Handle digits*/
|
||||||
/* Handle digits*/
|
IdCode = p - L'0';
|
||||||
IdCode = p - L'0';
|
}
|
||||||
}
|
else if ((p >= L'A') && (p <= L'F'))
|
||||||
else if ((p >= L'A') && (p <= L'F'))
|
{
|
||||||
{
|
/* Handle upper-case letters */
|
||||||
/* Handle upper-case letters */
|
IdCode = p - L'A' + 10;
|
||||||
IdCode = p - L'A' + 10;
|
}
|
||||||
}
|
else if ((p >= L'a') && (p <= L'f'))
|
||||||
else if ((p >= L'a') && (p <= L'f'))
|
{
|
||||||
{
|
/* Handle lower-case letters */
|
||||||
/* Handle lower-case letters */
|
IdCode = p - L'a' + 10;
|
||||||
IdCode = p - L'a' + 10;
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Unhandled case, return what we have till now */
|
||||||
/* Unhandled case, return what we have till now */
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
/* If the ID Code is >= 16, then we're done */
|
||||||
/* If the ID Code is >= 16, then we're done */
|
if (IdCode >= 16) break;
|
||||||
if (IdCode >= 16) break;
|
|
||||||
|
/* Build the Language ID */
|
||||||
/* Build the Language ID */
|
LangId = (LangId << 4) | (LANGID)IdCode;
|
||||||
LangId = (LangId << 4) | (LANGID)IdCode;
|
}
|
||||||
}
|
|
||||||
|
/* Return the Language ID */
|
||||||
/* Return the Language ID */
|
return LangId;
|
||||||
return LangId;
|
}
|
||||||
}
|
|
||||||
|
HCELL_INDEX
|
||||||
HCELL_INDEX
|
NTAPI
|
||||||
NTAPI
|
CmpWalkPath(IN PHHIVE SystemHive,
|
||||||
CmpWalkPath(IN PHHIVE SystemHive,
|
IN HCELL_INDEX ParentCell,
|
||||||
IN HCELL_INDEX ParentCell,
|
IN LPWSTR Path)
|
||||||
IN LPWSTR Path)
|
{
|
||||||
{
|
UNICODE_STRING UnicodePath, NextName;
|
||||||
UNICODE_STRING UnicodePath, NextName;
|
BOOLEAN LastName;
|
||||||
BOOLEAN LastName;
|
HCELL_INDEX CurrentCell = ParentCell;
|
||||||
HCELL_INDEX CurrentCell = ParentCell;
|
PCM_KEY_NODE Node;
|
||||||
PCM_KEY_NODE Node;
|
|
||||||
|
/* We shouldn't have a release routine at this point */
|
||||||
/* We shouldn't have a release routine at this point */
|
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
|
||||||
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
|
|
||||||
|
/* Initialize the Unicode path and start looping */
|
||||||
/* Initialize the Unicode path and start looping */
|
RtlInitUnicodeString(&UnicodePath, Path);
|
||||||
RtlInitUnicodeString(&UnicodePath, Path);
|
while (TRUE)
|
||||||
while (TRUE)
|
{
|
||||||
{
|
/* Get the next name */
|
||||||
/* Get the next name */
|
CmpGetNextName(&UnicodePath, &NextName, &LastName);
|
||||||
CmpGetNextName(&UnicodePath, &NextName, &LastName);
|
if (!NextName.Length) return CurrentCell;
|
||||||
if (!NextName.Length) return CurrentCell;
|
|
||||||
|
/* Get the subkey */
|
||||||
/* Get the subkey */
|
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, CurrentCell);
|
||||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, CurrentCell);
|
if (!Node) return HCELL_NIL;
|
||||||
if (!Node) return HCELL_NIL;
|
CurrentCell = CmpFindSubKeyByName(SystemHive, Node, &NextName);
|
||||||
CurrentCell = CmpFindSubKeyByName(SystemHive, Node, &NextName);
|
if (CurrentCell == HCELL_NIL) return CurrentCell;
|
||||||
if (CurrentCell == HCELL_NIL) return CurrentCell;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
VOID
|
||||||
VOID
|
NTAPI
|
||||||
NTAPI
|
CmGetSystemControlValues(IN PVOID SystemHiveData,
|
||||||
CmGetSystemControlValues(IN PVOID SystemHiveData,
|
IN PCM_SYSTEM_CONTROL_VECTOR ControlVector)
|
||||||
IN PCM_SYSTEM_CONTROL_VECTOR ControlVector)
|
{
|
||||||
{
|
PHHIVE SystemHive = (PHHIVE)&CmControlHive;
|
||||||
PHHIVE SystemHive = (PHHIVE)&CmControlHive;
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
HCELL_INDEX RootCell, BaseCell, KeyCell, ValueCell;
|
||||||
HCELL_INDEX RootCell, BaseCell, KeyCell, ValueCell;
|
ULONG Length, DataSize;
|
||||||
ULONG Length, DataSize;
|
PCM_KEY_NODE Node;
|
||||||
PCM_KEY_NODE Node;
|
PCM_KEY_VALUE ValueData;
|
||||||
PCM_KEY_VALUE ValueData;
|
UNICODE_STRING KeyName;
|
||||||
UNICODE_STRING KeyName;
|
BOOLEAN Auto, IsSmallKey;
|
||||||
BOOLEAN Auto, IsSmallKey;
|
PVOID Buffer;
|
||||||
PVOID Buffer;
|
|
||||||
|
/* LUDDDIIIICRROOOUUSSSS KI^H^H HACKKKK */
|
||||||
/* LUDDDIIIICRROOOUUSSSS KI^H^H HACKKKK */
|
if (!SystemHiveData) return;
|
||||||
if (!SystemHiveData) return;
|
|
||||||
|
/* Initialize the Hive View List and the security cache */
|
||||||
/* Initialize the Hive View List and the security cache */
|
RtlZeroMemory(SystemHive, sizeof(SystemHive));
|
||||||
RtlZeroMemory(SystemHive, sizeof(SystemHive));
|
CmpInitHiveViewList((PCMHIVE)SystemHive);
|
||||||
CmpInitHiveViewList((PCMHIVE)SystemHive);
|
CmpInitSecurityCache((PCMHIVE)SystemHive);
|
||||||
CmpInitSecurityCache((PCMHIVE)SystemHive);
|
|
||||||
|
/* Initialize the Hive */
|
||||||
/* Initialize the Hive */
|
Status = HvInitialize(SystemHive,
|
||||||
Status = HvInitialize(SystemHive,
|
HINIT_FLAT,
|
||||||
HINIT_FLAT,
|
HIVE_VOLATILE,
|
||||||
HIVE_VOLATILE,
|
HFILE_TYPE_PRIMARY,
|
||||||
HFILE_TYPE_PRIMARY,
|
SystemHiveData,
|
||||||
SystemHiveData,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
1,
|
||||||
1,
|
NULL);
|
||||||
NULL);
|
if (!NT_SUCCESS(Status)) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 1, 0, 0);
|
||||||
if (!NT_SUCCESS(Status)) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 1, 0, 0);
|
|
||||||
|
/* Sanity check, flat hives don't have release routines */
|
||||||
/* Sanity check, flat hives don't have release routines */
|
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
|
||||||
ASSERT(SystemHive->ReleaseCellRoutine == NULL);
|
|
||||||
|
/* FIXME: Prepare it */
|
||||||
/* FIXME: Prepare it */
|
CmPrepareHive(SystemHive);
|
||||||
CmPrepareHive(SystemHive);
|
|
||||||
|
/* Set the Root Cell */
|
||||||
/* Set the Root Cell */
|
RootCell = ((PHBASE_BLOCK)SystemHiveData)->RootCell;
|
||||||
RootCell = ((PHBASE_BLOCK)SystemHiveData)->RootCell;
|
|
||||||
|
/* Find the current control set */
|
||||||
/* Find the current control set */
|
RtlInitUnicodeString(&KeyName, L"current");
|
||||||
RtlInitUnicodeString(&KeyName, L"current");
|
BaseCell = CmpFindControlSet(SystemHive, RootCell, &KeyName, &Auto);
|
||||||
BaseCell = CmpFindControlSet(SystemHive, RootCell, &KeyName, &Auto);
|
if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 2, 0, 0);
|
||||||
if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 1, 2, 0, 0);
|
|
||||||
|
/* Find the control subkey */
|
||||||
/* Find the control subkey */
|
RtlInitUnicodeString(&KeyName, L"control");
|
||||||
RtlInitUnicodeString(&KeyName, L"control");
|
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, BaseCell);
|
||||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, BaseCell);
|
BaseCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
|
||||||
BaseCell = CmpFindSubKeyByName(SystemHive, Node, &KeyName);
|
if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO,1 , 3, 0, 0);
|
||||||
if (BaseCell == HCELL_NIL) KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO,1 , 3, 0, 0);
|
|
||||||
|
/* Loop each key */
|
||||||
/* Loop each key */
|
while (ControlVector->KeyPath)
|
||||||
while (ControlVector->KeyPath)
|
{
|
||||||
{
|
/* Assume failure */
|
||||||
/* Assume failure */
|
Length = -1;
|
||||||
Length = -1;
|
|
||||||
|
/* Get the cell for this key */
|
||||||
/* Get the cell for this key */
|
KeyCell = CmpWalkPath(SystemHive, BaseCell, ControlVector->KeyPath);
|
||||||
KeyCell = CmpWalkPath(SystemHive, BaseCell, ControlVector->KeyPath);
|
if (KeyCell != HCELL_NIL)
|
||||||
if (KeyCell != HCELL_NIL)
|
{
|
||||||
{
|
/* Now get the cell for the value */
|
||||||
/* Now get the cell for the value */
|
RtlInitUnicodeString(&KeyName, ControlVector->ValueName);
|
||||||
RtlInitUnicodeString(&KeyName, ControlVector->ValueName);
|
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, KeyCell);
|
||||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive, KeyCell);
|
ValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
|
||||||
ValueCell = CmpFindValueByName(SystemHive, Node, &KeyName);
|
if (ValueCell != HCELL_NIL)
|
||||||
if (ValueCell != HCELL_NIL)
|
{
|
||||||
{
|
/* Check if there's any data */
|
||||||
/* Check if there's any data */
|
if (!ControlVector->BufferLength)
|
||||||
if (!ControlVector->BufferLength)
|
{
|
||||||
{
|
/* No, the buffer will only be large enough for a ULONG */
|
||||||
/* No, the buffer will only be large enough for a ULONG */
|
DataSize = sizeof(ULONG);
|
||||||
DataSize = sizeof(ULONG);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Yes, save the data size */
|
||||||
/* Yes, save the data size */
|
DataSize = *ControlVector->BufferLength;
|
||||||
DataSize = *ControlVector->BufferLength;
|
}
|
||||||
}
|
|
||||||
|
/* Get the actual data */
|
||||||
/* Get the actual data */
|
ValueData = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
|
||||||
ValueData = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
|
|
||||||
|
/* Check if this is a small key */
|
||||||
/* Check if this is a small key */
|
IsSmallKey = CmpIsKeyValueSmall(&Length, ValueData->DataLength);
|
||||||
IsSmallKey = CmpIsKeyValueSmall(&Length, ValueData->DataLength);
|
|
||||||
|
/* If the length is bigger then our buffer, normalize it */
|
||||||
/* If the length is bigger then our buffer, normalize it */
|
if (DataSize < Length) Length = DataSize;
|
||||||
if (DataSize < Length) Length = DataSize;
|
|
||||||
|
/* Make sure we have some data */
|
||||||
/* Make sure we have some data */
|
if (Length > 0)
|
||||||
if (Length > 0)
|
{
|
||||||
{
|
/* Check if this was a small key */
|
||||||
/* Check if this was a small key */
|
if (IsSmallKey)
|
||||||
if (IsSmallKey)
|
{
|
||||||
{
|
/* The buffer is directly safe to read */
|
||||||
/* The buffer is directly safe to read */
|
Buffer = (PVOID)(&(ValueData->Data));
|
||||||
Buffer = (PVOID)(&(ValueData->Data));
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Use the longer path */
|
||||||
/* Use the longer path */
|
Buffer = (PVOID)HvGetCell(SystemHive, ValueData->Data);
|
||||||
Buffer = (PVOID)HvGetCell(SystemHive, ValueData->Data);
|
}
|
||||||
}
|
|
||||||
|
/* Sanity check if this is a small key */
|
||||||
/* Sanity check if this is a small key */
|
ASSERT((IsSmallKey ?
|
||||||
ASSERT((IsSmallKey ?
|
(Length <= CM_KEY_VALUE_SMALL) : TRUE));
|
||||||
(Length <= CM_KEY_VALUE_SMALL) : TRUE));
|
|
||||||
|
/* Copy the data in the buffer */
|
||||||
/* Copy the data in the buffer */
|
RtlCopyMemory(ControlVector->Buffer, Buffer, Length);
|
||||||
RtlCopyMemory(ControlVector->Buffer, Buffer, Length);
|
}
|
||||||
}
|
|
||||||
|
/* Check if we should return the data type */
|
||||||
/* Check if we should return the data type */
|
if (ControlVector->Type)
|
||||||
if (ControlVector->Type)
|
{
|
||||||
{
|
/* Return the type that we read */
|
||||||
/* Return the type that we read */
|
*ControlVector->Type = ValueData->Type;
|
||||||
*ControlVector->Type = ValueData->Type;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Return the size that we read */
|
||||||
/* Return the size that we read */
|
if (ControlVector->BufferLength) *ControlVector->BufferLength = Length;
|
||||||
if (ControlVector->BufferLength) *ControlVector->BufferLength = Length;
|
|
||||||
|
/* Go to the next entry */
|
||||||
/* Go to the next entry */
|
ControlVector++;
|
||||||
ControlVector++;
|
}
|
||||||
}
|
|
||||||
|
/* Check if the ID is in the registry */
|
||||||
/* Check if the ID is in the registry */
|
if (CmDefaultLanguageIdType == REG_SZ)
|
||||||
if (CmDefaultLanguageIdType == REG_SZ)
|
{
|
||||||
{
|
/* Read it */
|
||||||
/* Read it */
|
PsDefaultSystemLocaleId =
|
||||||
PsDefaultSystemLocaleId =
|
(LCID)CmpConvertLangId(CmDefaultLanguageId,
|
||||||
(LCID)CmpConvertLangId(CmDefaultLanguageId,
|
CmDefaultLanguageIdLength);
|
||||||
CmDefaultLanguageIdLength);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Use EN_US by default */
|
||||||
/* Use EN_US by default */
|
PsDefaultSystemLocaleId = 0x409;
|
||||||
PsDefaultSystemLocaleId = 0x409;
|
}
|
||||||
}
|
|
||||||
|
/* Check if the ID Is in the registry */
|
||||||
/* Check if the ID Is in the registry */
|
if (CmInstallUILanguageIdType == REG_SZ)
|
||||||
if (CmInstallUILanguageIdType == REG_SZ)
|
{
|
||||||
{
|
/* Read it */
|
||||||
/* Read it */
|
PsInstallUILanguageId = CmpConvertLangId(CmInstallUILanguageId,
|
||||||
PsInstallUILanguageId = CmpConvertLangId(CmInstallUILanguageId,
|
CmInstallUILanguageIdLength);
|
||||||
CmInstallUILanguageIdLength);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Otherwise, use the default */
|
||||||
/* Otherwise, use the default */
|
PsInstallUILanguageId = LANGIDFROMLCID(PsDefaultSystemLocaleId);
|
||||||
PsInstallUILanguageId = LANGIDFROMLCID(PsDefaultSystemLocaleId);
|
}
|
||||||
}
|
|
||||||
|
/* Set the defaults for the Thread UI */
|
||||||
/* Set the defaults for the Thread UI */
|
PsDefaultThreadLocaleId = PsDefaultSystemLocaleId;
|
||||||
PsDefaultThreadLocaleId = PsDefaultSystemLocaleId;
|
PsDefaultUILanguageId = PsInstallUILanguageId;
|
||||||
PsDefaultUILanguageId = PsInstallUILanguageId;
|
}
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -11,7 +11,6 @@
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include "cm.h"
|
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -1,198 +1,197 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmhook.c
|
* FILE: ntoskrnl/config/cmhook.c
|
||||||
* PURPOSE: Configuration Manager - Registry Notifications/Callbacks
|
* PURPOSE: Configuration Manager - Registry Notifications/Callbacks
|
||||||
* PROGRAMMERS: Thomas Weidenmueller (w3seek@reactos.org)
|
* PROGRAMMERS: Thomas Weidenmueller (w3seek@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* GLOBALS *******************************************************************/
|
||||||
/* GLOBALS *******************************************************************/
|
|
||||||
|
ULONG CmpCallBackCount = 0;
|
||||||
ULONG CmpCallBackCount = 0;
|
EX_CALLBACK CmpCallBackVector[100];
|
||||||
EX_CALLBACK CmpCallBackVector[100];
|
|
||||||
|
LIST_ENTRY CmiCallbackHead;
|
||||||
LIST_ENTRY CmiCallbackHead;
|
FAST_MUTEX CmiCallbackLock;
|
||||||
FAST_MUTEX CmiCallbackLock;
|
|
||||||
|
typedef struct _REGISTRY_CALLBACK
|
||||||
typedef struct _REGISTRY_CALLBACK
|
{
|
||||||
{
|
LIST_ENTRY ListEntry;
|
||||||
LIST_ENTRY ListEntry;
|
EX_RUNDOWN_REF RundownRef;
|
||||||
EX_RUNDOWN_REF RundownRef;
|
PEX_CALLBACK_FUNCTION Function;
|
||||||
PEX_CALLBACK_FUNCTION Function;
|
PVOID Context;
|
||||||
PVOID Context;
|
LARGE_INTEGER Cookie;
|
||||||
LARGE_INTEGER Cookie;
|
BOOLEAN PendingDelete;
|
||||||
BOOLEAN PendingDelete;
|
} REGISTRY_CALLBACK, *PREGISTRY_CALLBACK;
|
||||||
} REGISTRY_CALLBACK, *PREGISTRY_CALLBACK;
|
|
||||||
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
|
||||||
|
VOID
|
||||||
VOID
|
NTAPI
|
||||||
NTAPI
|
CmpInitCallback(VOID)
|
||||||
CmpInitCallback(VOID)
|
{
|
||||||
{
|
ULONG i;
|
||||||
ULONG i;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
/* Reset counter */
|
||||||
/* Reset counter */
|
CmpCallBackCount = 0;
|
||||||
CmpCallBackCount = 0;
|
|
||||||
|
/* Loop all the callbacks */
|
||||||
/* Loop all the callbacks */
|
for (i = 0; i < CMP_MAX_CALLBACKS; i++)
|
||||||
for (i = 0; i < CMP_MAX_CALLBACKS; i++)
|
{
|
||||||
{
|
/* Initialize this one */
|
||||||
/* Initialize this one */
|
ExInitializeCallBack(&CmpCallBackVector[i]);
|
||||||
ExInitializeCallBack(&CmpCallBackVector[i]);
|
}
|
||||||
}
|
|
||||||
|
/* ROS: Initialize old-style callbacks for now */
|
||||||
/* ROS: Initialize old-style callbacks for now */
|
InitializeListHead(&CmiCallbackHead);
|
||||||
InitializeListHead(&CmiCallbackHead);
|
ExInitializeFastMutex(&CmiCallbackLock);
|
||||||
ExInitializeFastMutex(&CmiCallbackLock);
|
}
|
||||||
}
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS
|
CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
|
||||||
CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
|
IN PVOID Argument2)
|
||||||
IN PVOID Argument2)
|
{
|
||||||
{
|
PLIST_ENTRY CurrentEntry;
|
||||||
PLIST_ENTRY CurrentEntry;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
PREGISTRY_CALLBACK CurrentCallback;
|
||||||
PREGISTRY_CALLBACK CurrentCallback;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
ExAcquireFastMutex(&CmiCallbackLock);
|
||||||
ExAcquireFastMutex(&CmiCallbackLock);
|
|
||||||
|
for (CurrentEntry = CmiCallbackHead.Flink;
|
||||||
for (CurrentEntry = CmiCallbackHead.Flink;
|
CurrentEntry != &CmiCallbackHead;
|
||||||
CurrentEntry != &CmiCallbackHead;
|
CurrentEntry = CurrentEntry->Flink)
|
||||||
CurrentEntry = CurrentEntry->Flink)
|
{
|
||||||
{
|
CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
|
||||||
CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
|
if (!CurrentCallback->PendingDelete &&
|
||||||
if (!CurrentCallback->PendingDelete &&
|
ExAcquireRundownProtection(&CurrentCallback->RundownRef))
|
||||||
ExAcquireRundownProtection(&CurrentCallback->RundownRef))
|
{
|
||||||
{
|
/* don't hold locks during the callbacks! */
|
||||||
/* don't hold locks during the callbacks! */
|
ExReleaseFastMutex(&CmiCallbackLock);
|
||||||
ExReleaseFastMutex(&CmiCallbackLock);
|
|
||||||
|
Status = CurrentCallback->Function(CurrentCallback->Context,
|
||||||
Status = CurrentCallback->Function(CurrentCallback->Context,
|
(PVOID)Argument1,
|
||||||
(PVOID)Argument1,
|
Argument2);
|
||||||
Argument2);
|
|
||||||
|
ExAcquireFastMutex(&CmiCallbackLock);
|
||||||
ExAcquireFastMutex(&CmiCallbackLock);
|
|
||||||
|
/* don't release the rundown protection before holding the callback lock
|
||||||
/* 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
|
||||||
so the pointer to the next callback isn't cleared in case this callback
|
get's deleted */
|
||||||
get's deleted */
|
ExReleaseRundownProtection(&CurrentCallback->RundownRef);
|
||||||
ExReleaseRundownProtection(&CurrentCallback->RundownRef);
|
if(!NT_SUCCESS(Status))
|
||||||
if(!NT_SUCCESS(Status))
|
{
|
||||||
{
|
/* one callback returned failure, don't call any more callbacks */
|
||||||
/* one callback returned failure, don't call any more callbacks */
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
ExReleaseFastMutex(&CmiCallbackLock);
|
||||||
ExReleaseFastMutex(&CmiCallbackLock);
|
|
||||||
|
return Status;
|
||||||
return Status;
|
}
|
||||||
}
|
|
||||||
|
/* PUBLIC FUNCTIONS **********************************************************/
|
||||||
/* PUBLIC FUNCTIONS **********************************************************/
|
|
||||||
|
/*
|
||||||
/*
|
* @implemented
|
||||||
* @implemented
|
*/
|
||||||
*/
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
|
||||||
CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
|
IN PVOID Context,
|
||||||
IN PVOID Context,
|
IN OUT PLARGE_INTEGER Cookie)
|
||||||
IN OUT PLARGE_INTEGER Cookie)
|
{
|
||||||
{
|
PREGISTRY_CALLBACK Callback;
|
||||||
PREGISTRY_CALLBACK Callback;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
ASSERT(Function && Cookie);
|
||||||
ASSERT(Function && Cookie);
|
|
||||||
|
Callback = ExAllocatePoolWithTag(PagedPool,
|
||||||
Callback = ExAllocatePoolWithTag(PagedPool,
|
sizeof(REGISTRY_CALLBACK),
|
||||||
sizeof(REGISTRY_CALLBACK),
|
TAG('C', 'M', 'c', 'b'));
|
||||||
TAG('C', 'M', 'c', 'b'));
|
if (Callback != NULL)
|
||||||
if (Callback != NULL)
|
{
|
||||||
{
|
/* initialize the callback */
|
||||||
/* initialize the callback */
|
ExInitializeRundownProtection(&Callback->RundownRef);
|
||||||
ExInitializeRundownProtection(&Callback->RundownRef);
|
Callback->Function = Function;
|
||||||
Callback->Function = Function;
|
Callback->Context = Context;
|
||||||
Callback->Context = Context;
|
Callback->PendingDelete = FALSE;
|
||||||
Callback->PendingDelete = FALSE;
|
|
||||||
|
/* add it to the callback list and receive a cookie for the callback */
|
||||||
/* add it to the callback list and receive a cookie for the callback */
|
ExAcquireFastMutex(&CmiCallbackLock);
|
||||||
ExAcquireFastMutex(&CmiCallbackLock);
|
|
||||||
|
/* FIXME - to receive a unique cookie we'll just return the pointer to the
|
||||||
/* FIXME - to receive a unique cookie we'll just return the pointer to the
|
callback object */
|
||||||
callback object */
|
Callback->Cookie.QuadPart = (ULONG_PTR)Callback;
|
||||||
Callback->Cookie.QuadPart = (ULONG_PTR)Callback;
|
InsertTailList(&CmiCallbackHead, &Callback->ListEntry);
|
||||||
InsertTailList(&CmiCallbackHead, &Callback->ListEntry);
|
|
||||||
|
ExReleaseFastMutex(&CmiCallbackLock);
|
||||||
ExReleaseFastMutex(&CmiCallbackLock);
|
|
||||||
|
*Cookie = Callback->Cookie;
|
||||||
*Cookie = Callback->Cookie;
|
return STATUS_SUCCESS;
|
||||||
return STATUS_SUCCESS;
|
}
|
||||||
}
|
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
}
|
||||||
}
|
|
||||||
|
/*
|
||||||
/*
|
* @implemented
|
||||||
* @implemented
|
*/
|
||||||
*/
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
|
||||||
CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
|
{
|
||||||
{
|
PLIST_ENTRY CurrentEntry;
|
||||||
PLIST_ENTRY CurrentEntry;
|
PREGISTRY_CALLBACK CurrentCallback;
|
||||||
PREGISTRY_CALLBACK CurrentCallback;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
ExAcquireFastMutex(&CmiCallbackLock);
|
||||||
ExAcquireFastMutex(&CmiCallbackLock);
|
|
||||||
|
for (CurrentEntry = CmiCallbackHead.Flink;
|
||||||
for (CurrentEntry = CmiCallbackHead.Flink;
|
CurrentEntry != &CmiCallbackHead;
|
||||||
CurrentEntry != &CmiCallbackHead;
|
CurrentEntry = CurrentEntry->Flink)
|
||||||
CurrentEntry = CurrentEntry->Flink)
|
{
|
||||||
{
|
CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
|
||||||
CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
|
if (CurrentCallback->Cookie.QuadPart == Cookie.QuadPart)
|
||||||
if (CurrentCallback->Cookie.QuadPart == Cookie.QuadPart)
|
{
|
||||||
{
|
if (!CurrentCallback->PendingDelete)
|
||||||
if (!CurrentCallback->PendingDelete)
|
{
|
||||||
{
|
/* found the callback, don't unlink it from the list yet so we don't screw
|
||||||
/* found the callback, don't unlink it from the list yet so we don't screw
|
the calling loop */
|
||||||
the calling loop */
|
CurrentCallback->PendingDelete = TRUE;
|
||||||
CurrentCallback->PendingDelete = TRUE;
|
ExReleaseFastMutex(&CmiCallbackLock);
|
||||||
ExReleaseFastMutex(&CmiCallbackLock);
|
|
||||||
|
/* if the callback is currently executing, wait until it finished */
|
||||||
/* if the callback is currently executing, wait until it finished */
|
ExWaitForRundownProtectionRelease(&CurrentCallback->RundownRef);
|
||||||
ExWaitForRundownProtectionRelease(&CurrentCallback->RundownRef);
|
|
||||||
|
/* time to unlink it. It's now safe because every attempt to acquire a
|
||||||
/* time to unlink it. It's now safe because every attempt to acquire a
|
runtime protection on this callback will fail */
|
||||||
runtime protection on this callback will fail */
|
ExAcquireFastMutex(&CmiCallbackLock);
|
||||||
ExAcquireFastMutex(&CmiCallbackLock);
|
RemoveEntryList(&CurrentCallback->ListEntry);
|
||||||
RemoveEntryList(&CurrentCallback->ListEntry);
|
ExReleaseFastMutex(&CmiCallbackLock);
|
||||||
ExReleaseFastMutex(&CmiCallbackLock);
|
|
||||||
|
/* free the callback */
|
||||||
/* free the callback */
|
ExFreePool(CurrentCallback);
|
||||||
ExFreePool(CurrentCallback);
|
return STATUS_SUCCESS;
|
||||||
return STATUS_SUCCESS;
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* pending delete, pretend like it already is deleted */
|
||||||
/* pending delete, pretend like it already is deleted */
|
ExReleaseFastMutex(&CmiCallbackLock);
|
||||||
ExReleaseFastMutex(&CmiCallbackLock);
|
return STATUS_UNSUCCESSFUL;
|
||||||
return STATUS_UNSUCCESSFUL;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
ExReleaseFastMutex(&CmiCallbackLock);
|
||||||
ExReleaseFastMutex(&CmiCallbackLock);
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
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
|
@ -1,221 +1,220 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmkeydel.c
|
* FILE: ntoskrnl/config/cmkeydel.c
|
||||||
* PURPOSE: Configuration Manager - Key Body Deletion
|
* PURPOSE: Configuration Manager - Key Body Deletion
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpMarkKeyDirty(IN PHHIVE Hive,
|
||||||
CmpMarkKeyDirty(IN PHHIVE Hive,
|
IN HCELL_INDEX Cell,
|
||||||
IN HCELL_INDEX Cell,
|
IN BOOLEAN CheckNoSubkeys)
|
||||||
IN BOOLEAN CheckNoSubkeys)
|
{
|
||||||
{
|
PCELL_DATA CellData, ListData, SecurityData, ValueData;
|
||||||
PCELL_DATA CellData, ListData, SecurityData, ValueData;
|
ULONG i;
|
||||||
ULONG i;
|
|
||||||
|
/* Get the cell data for our target */
|
||||||
/* Get the cell data for our target */
|
CellData = HvGetCell(Hive, Cell);
|
||||||
CellData = HvGetCell(Hive, Cell);
|
if (!CellData) return FALSE;
|
||||||
if (!CellData) return FALSE;
|
|
||||||
|
/* Check if sanity checks requested */
|
||||||
/* Check if sanity checks requested */
|
if (CheckNoSubkeys)
|
||||||
if (CheckNoSubkeys)
|
{
|
||||||
{
|
/* Do them */
|
||||||
/* Do them */
|
ASSERT(CellData->u.KeyNode.SubKeyCounts[Stable] == 0);
|
||||||
ASSERT(CellData->u.KeyNode.SubKeyCounts[Stable] == 0);
|
ASSERT(CellData->u.KeyNode.SubKeyCounts[Volatile] == 0);
|
||||||
ASSERT(CellData->u.KeyNode.SubKeyCounts[Volatile] == 0);
|
}
|
||||||
}
|
|
||||||
|
/* If this is an exit hive, there's nothing to do */
|
||||||
/* If this is an exit hive, there's nothing to do */
|
if (CellData->u.KeyNode.Flags & KEY_HIVE_EXIT)
|
||||||
if (CellData->u.KeyNode.Flags & KEY_HIVE_EXIT)
|
{
|
||||||
{
|
/* Release the cell and get out */
|
||||||
/* Release the cell and get out */
|
HvReleaseCell(Hive, Cell);
|
||||||
HvReleaseCell(Hive, Cell);
|
return TRUE;
|
||||||
return TRUE;
|
}
|
||||||
}
|
|
||||||
|
/* Otherwise, mark it dirty and release it */
|
||||||
/* Otherwise, mark it dirty and release it */
|
HvMarkCellDirty(Hive, Cell, FALSE);
|
||||||
HvMarkCellDirty(Hive, Cell, FALSE);
|
HvReleaseCell(Hive, Cell);
|
||||||
HvReleaseCell(Hive, Cell);
|
|
||||||
|
/* Check if we have a class */
|
||||||
/* Check if we have a class */
|
if (CellData->u.KeyNode.Class != HCELL_NIL)
|
||||||
if (CellData->u.KeyNode.Class != HCELL_NIL)
|
{
|
||||||
{
|
/* Mark it dirty */
|
||||||
/* Mark it dirty */
|
HvMarkCellDirty(Hive, CellData->u.KeyNode.Class, FALSE);
|
||||||
HvMarkCellDirty(Hive, CellData->u.KeyNode.Class, FALSE);
|
}
|
||||||
}
|
|
||||||
|
/* Check if we have security */
|
||||||
/* Check if we have security */
|
if (CellData->u.KeyNode.Security != HCELL_NIL)
|
||||||
if (CellData->u.KeyNode.Security != HCELL_NIL)
|
{
|
||||||
{
|
/* Mark it dirty */
|
||||||
/* Mark it dirty */
|
HvMarkCellDirty(Hive, CellData->u.KeyNode.Security, FALSE);
|
||||||
HvMarkCellDirty(Hive, CellData->u.KeyNode.Security, FALSE);
|
|
||||||
|
/* Get the security data and release it */
|
||||||
/* Get the security data and release it */
|
SecurityData = HvGetCell(Hive, CellData->u.KeyNode.Security);
|
||||||
SecurityData = HvGetCell(Hive, CellData->u.KeyNode.Security);
|
if (!SecurityData) ASSERT(FALSE);
|
||||||
if (!SecurityData) ASSERT(FALSE);
|
HvReleaseCell(Hive, CellData->u.KeyNode.Security);
|
||||||
HvReleaseCell(Hive, CellData->u.KeyNode.Security);
|
|
||||||
|
/* Mark the security links dirty too */
|
||||||
/* Mark the security links dirty too */
|
HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Flink, FALSE);
|
||||||
HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Flink, FALSE);
|
HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Blink, FALSE);
|
||||||
HvMarkCellDirty(Hive, SecurityData->u.KeySecurity.Blink, FALSE);
|
}
|
||||||
}
|
|
||||||
|
/* Check if we have any values */
|
||||||
/* Check if we have any values */
|
if (CellData->u.KeyNode.ValueList.Count > 0)
|
||||||
if (CellData->u.KeyNode.ValueList.Count > 0)
|
{
|
||||||
{
|
/* Dirty the value list */
|
||||||
/* Dirty the value list */
|
HvMarkCellDirty(Hive, CellData->u.KeyNode.ValueList.List, FALSE);
|
||||||
HvMarkCellDirty(Hive, CellData->u.KeyNode.ValueList.List, FALSE);
|
|
||||||
|
/* Get the list data itself, and release it */
|
||||||
/* Get the list data itself, and release it */
|
ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
|
if (!ListData) ASSERT(FALSE);
|
||||||
if (!ListData) ASSERT(FALSE);
|
HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
|
|
||||||
|
/* Loop all values */
|
||||||
/* Loop all values */
|
for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
|
||||||
for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
|
{
|
||||||
{
|
/* Dirty each value */
|
||||||
/* Dirty each value */
|
HvMarkCellDirty(Hive, ListData->u.KeyList[i], FALSE);
|
||||||
HvMarkCellDirty(Hive, ListData->u.KeyList[i], FALSE);
|
|
||||||
|
/* Get the value data and release it */
|
||||||
/* Get the value data and release it */
|
ValueData = HvGetCell(Hive, ListData->u.KeyList[i]);
|
||||||
ValueData = HvGetCell(Hive, ListData->u.KeyList[i]);
|
ASSERT(ValueData);
|
||||||
ASSERT(ValueData);
|
HvReleaseCell(Hive,ListData->u.KeyList[i]);
|
||||||
HvReleaseCell(Hive,ListData->u.KeyList[i]);
|
|
||||||
|
/* Mark the value data dirty too */
|
||||||
/* Mark the value data dirty too */
|
if (!CmpMarkValueDataDirty(Hive, &ValueData->u.KeyValue))
|
||||||
if (!CmpMarkValueDataDirty(Hive, &ValueData->u.KeyValue))
|
{
|
||||||
{
|
/* Failure */
|
||||||
/* Failure */
|
return FALSE;
|
||||||
return FALSE;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* If this is an entry hive, we're done */
|
||||||
/* If this is an entry hive, we're done */
|
if (CellData->u.KeyNode.Flags & KEY_HIVE_ENTRY) return TRUE;
|
||||||
if (CellData->u.KeyNode.Flags & KEY_HIVE_ENTRY) return TRUE;
|
|
||||||
|
/* Otherwise mark the index dirty too */
|
||||||
/* Otherwise mark the index dirty too */
|
if (!CmpMarkIndexDirty(Hive, CellData->u.KeyNode.Parent, Cell))
|
||||||
if (!CmpMarkIndexDirty(Hive, CellData->u.KeyNode.Parent, Cell))
|
{
|
||||||
{
|
/* Failure */
|
||||||
/* Failure */
|
return FALSE;
|
||||||
return FALSE;
|
}
|
||||||
}
|
|
||||||
|
/* Finally, mark the parent dirty */
|
||||||
/* Finally, mark the parent dirty */
|
HvMarkCellDirty(Hive, CellData->u.KeyNode.Parent, FALSE);
|
||||||
HvMarkCellDirty(Hive, CellData->u.KeyNode.Parent, FALSE);
|
return TRUE;
|
||||||
return TRUE;
|
}
|
||||||
}
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpFreeKeyBody(IN PHHIVE Hive,
|
||||||
CmpFreeKeyBody(IN PHHIVE Hive,
|
IN HCELL_INDEX Cell)
|
||||||
IN HCELL_INDEX Cell)
|
{
|
||||||
{
|
PCELL_DATA CellData;
|
||||||
PCELL_DATA CellData;
|
|
||||||
|
/* Get the key node */
|
||||||
/* Get the key node */
|
CellData = HvGetCell(Hive, Cell);
|
||||||
CellData = HvGetCell(Hive, Cell);
|
if (!CellData) ASSERT(FALSE);
|
||||||
if (!CellData) ASSERT(FALSE);
|
|
||||||
|
/* Check if we can delete the child cells */
|
||||||
/* Check if we can delete the child cells */
|
if (!(CellData->u.KeyNode.Flags & KEY_HIVE_EXIT))
|
||||||
if (!(CellData->u.KeyNode.Flags & KEY_HIVE_EXIT))
|
{
|
||||||
{
|
/* Check if we have a security cell */
|
||||||
/* Check if we have a security cell */
|
if (CellData->u.KeyNode.Security != HCELL_NIL)
|
||||||
if (CellData->u.KeyNode.Security != HCELL_NIL)
|
{
|
||||||
{
|
/* Free the security cell */
|
||||||
/* Free the security cell */
|
HvFreeCell(Hive, CellData->u.KeyNode.Security);
|
||||||
HvFreeCell(Hive, CellData->u.KeyNode.Security);
|
}
|
||||||
}
|
|
||||||
|
/* Check if we have a class */
|
||||||
/* Check if we have a class */
|
if (CellData->u.KeyNode.ClassLength > 0)
|
||||||
if (CellData->u.KeyNode.ClassLength > 0)
|
{
|
||||||
{
|
/* Free it */
|
||||||
/* Free it */
|
HvFreeCell(Hive, CellData->u.KeyNode.Class);
|
||||||
HvFreeCell(Hive, CellData->u.KeyNode.Class);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Release and free the cell */
|
||||||
/* Release and free the cell */
|
HvReleaseCell(Hive, Cell);
|
||||||
HvReleaseCell(Hive, Cell);
|
HvFreeCell(Hive, Cell);
|
||||||
HvFreeCell(Hive, Cell);
|
return TRUE;
|
||||||
return TRUE;
|
}
|
||||||
}
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmpFreeKeyByCell(IN PHHIVE Hive,
|
||||||
CmpFreeKeyByCell(IN PHHIVE Hive,
|
IN HCELL_INDEX Cell,
|
||||||
IN HCELL_INDEX Cell,
|
IN BOOLEAN Unlink)
|
||||||
IN BOOLEAN Unlink)
|
{
|
||||||
{
|
PCELL_DATA CellData, ParentData, ListData;
|
||||||
PCELL_DATA CellData, ParentData, ListData;
|
ULONG i;
|
||||||
ULONG i;
|
BOOLEAN Result;
|
||||||
BOOLEAN Result;
|
|
||||||
|
/* Mark the entire key dirty */
|
||||||
/* Mark the entire key dirty */
|
CmpMarkKeyDirty(Hive, Cell ,TRUE);
|
||||||
CmpMarkKeyDirty(Hive, Cell ,TRUE);
|
|
||||||
|
/* Get the target node and release it */
|
||||||
/* Get the target node and release it */
|
CellData = HvGetCell(Hive, Cell);
|
||||||
CellData = HvGetCell(Hive, Cell);
|
if (!CellData) ASSERT(FALSE);
|
||||||
if (!CellData) ASSERT(FALSE);
|
HvReleaseCell(Hive, Cell);
|
||||||
HvReleaseCell(Hive, Cell);
|
|
||||||
|
/* Make sure we don't have subkeys */
|
||||||
/* Make sure we don't have subkeys */
|
ASSERT((CellData->u.KeyNode.SubKeyCounts[Stable] +
|
||||||
ASSERT((CellData->u.KeyNode.SubKeyCounts[Stable] +
|
CellData->u.KeyNode.SubKeyCounts[Volatile]) == 0);
|
||||||
CellData->u.KeyNode.SubKeyCounts[Volatile]) == 0);
|
|
||||||
|
/* Check if we have to unlink */
|
||||||
/* Check if we have to unlink */
|
if (Unlink)
|
||||||
if (Unlink)
|
{
|
||||||
{
|
/* Remove the subkey */
|
||||||
/* Remove the subkey */
|
Result = CmpRemoveSubKey(Hive, CellData->u.KeyNode.Parent, Cell);
|
||||||
Result = CmpRemoveSubKey(Hive, CellData->u.KeyNode.Parent, Cell);
|
if (!Result) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
if (!Result) return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
/* Get the parent node and release it */
|
||||||
/* Get the parent node and release it */
|
ParentData = HvGetCell(Hive, CellData->u.KeyNode.Parent);
|
||||||
ParentData = HvGetCell(Hive, CellData->u.KeyNode.Parent);
|
if (!ParentData) ASSERT(FALSE);
|
||||||
if (!ParentData) ASSERT(FALSE);
|
HvReleaseCell(Hive, CellData->u.KeyNode.Parent);
|
||||||
HvReleaseCell(Hive, CellData->u.KeyNode.Parent);
|
|
||||||
|
/* Check if the parent node has no more subkeys */
|
||||||
/* Check if the parent node has no more subkeys */
|
if (!(ParentData->u.KeyNode.SubKeyCounts[Stable] +
|
||||||
if (!(ParentData->u.KeyNode.SubKeyCounts[Stable] +
|
ParentData->u.KeyNode.SubKeyCounts[Volatile]))
|
||||||
ParentData->u.KeyNode.SubKeyCounts[Volatile]))
|
{
|
||||||
{
|
/* Then free the cached name/class lengths */
|
||||||
/* Then free the cached name/class lengths */
|
ParentData->u.KeyNode.MaxNameLen = 0;
|
||||||
ParentData->u.KeyNode.MaxNameLen = 0;
|
ParentData->u.KeyNode.MaxClassLen = 0;
|
||||||
ParentData->u.KeyNode.MaxClassLen = 0;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Check if we have any values */
|
||||||
/* Check if we have any values */
|
if (CellData->u.KeyNode.ValueList.Count > 0)
|
||||||
if (CellData->u.KeyNode.ValueList.Count > 0)
|
{
|
||||||
{
|
/* Get the value list and release it */
|
||||||
/* Get the value list and release it */
|
ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
ListData = HvGetCell(Hive, CellData->u.KeyNode.ValueList.List);
|
if (!ListData) ASSERT(FALSE);
|
||||||
if (!ListData) ASSERT(FALSE);
|
HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
HvReleaseCell(Hive, CellData->u.KeyNode.ValueList.List);
|
|
||||||
|
/* Loop every value */
|
||||||
/* Loop every value */
|
for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
|
||||||
for (i = 0; i < CellData->u.KeyNode.ValueList.Count; i++)
|
{
|
||||||
{
|
/* Free it */
|
||||||
/* Free it */
|
if (!CmpFreeValue(Hive, ListData->u.KeyList[i])) ASSERT(FALSE);
|
||||||
if (!CmpFreeValue(Hive, ListData->u.KeyList[i])) ASSERT(FALSE);
|
}
|
||||||
}
|
|
||||||
|
/* Free the value list */
|
||||||
/* Free the value list */
|
HvFreeCell(Hive, CellData->u.KeyNode.ValueList.List);
|
||||||
HvFreeCell(Hive, CellData->u.KeyNode.ValueList.List);
|
}
|
||||||
}
|
|
||||||
|
/* Free the key body itself, and then return our status */
|
||||||
/* Free the key body itself, and then return our status */
|
if (!CmpFreeKeyBody(Hive, Cell)) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
if (!CmpFreeKeyBody(Hive, Cell)) return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_SUCCESS;
|
||||||
return STATUS_SUCCESS;
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
/* INCLUDES *******************************************************************/
|
/* INCLUDES *******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
|
@ -1,33 +1,32 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmmapvw.c
|
* FILE: ntoskrnl/config/cmmapvw.c
|
||||||
* PURPOSE: Configuration Manager - Map-Viewed Hive Support
|
* PURPOSE: Configuration Manager - Map-Viewed Hive Support
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* GLOBALS *******************************************************************/
|
||||||
/* GLOBALS *******************************************************************/
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
VOID
|
||||||
VOID
|
NTAPI
|
||||||
NTAPI
|
CmpInitHiveViewList(IN PCMHIVE Hive)
|
||||||
CmpInitHiveViewList(IN PCMHIVE Hive)
|
{
|
||||||
{
|
/* Initialize the list heads */
|
||||||
/* Initialize the list heads */
|
InitializeListHead(&Hive->LRUViewListHead);
|
||||||
InitializeListHead(&Hive->LRUViewListHead);
|
InitializeListHead(&Hive->PinViewListHead);
|
||||||
InitializeListHead(&Hive->PinViewListHead);
|
|
||||||
|
/* Reset data */
|
||||||
/* Reset data */
|
Hive->MappedViews = 0;
|
||||||
Hive->MappedViews = 0;
|
Hive->PinnedViews = 0;
|
||||||
Hive->PinnedViews = 0;
|
Hive->UseCount = 0;
|
||||||
Hive->UseCount = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,254 +1,253 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmname.c
|
* FILE: ntoskrnl/config/cmname.c
|
||||||
* PURPOSE: Configuration Manager - Name Management
|
* PURPOSE: Configuration Manager - Name Management
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* GLOBALS *******************************************************************/
|
||||||
/* GLOBALS *******************************************************************/
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
USHORT
|
||||||
USHORT
|
NTAPI
|
||||||
NTAPI
|
CmpCopyName(IN PHHIVE Hive,
|
||||||
CmpCopyName(IN PHHIVE Hive,
|
IN PWCHAR Destination,
|
||||||
IN PWCHAR Destination,
|
IN PUNICODE_STRING Source)
|
||||||
IN PUNICODE_STRING Source)
|
{
|
||||||
{
|
ULONG i;
|
||||||
ULONG i;
|
|
||||||
|
/* Check for old hives */
|
||||||
/* Check for old hives */
|
if (Hive->Version == 1)
|
||||||
if (Hive->Version == 1)
|
{
|
||||||
{
|
/* Just copy the source directly */
|
||||||
/* Just copy the source directly */
|
RtlCopyMemory(Destination, Source->Buffer, Source->Length);
|
||||||
RtlCopyMemory(Destination, Source->Buffer, Source->Length);
|
return Source->Length;
|
||||||
return Source->Length;
|
}
|
||||||
}
|
|
||||||
|
/* For new versions, check for compressed name */
|
||||||
/* For new versions, check for compressed name */
|
for (i = 0; i < (Source->Length / sizeof(WCHAR)); i++)
|
||||||
for (i = 0; i < (Source->Length / sizeof(WCHAR)); i++)
|
{
|
||||||
{
|
/* Check if the name is non compressed */
|
||||||
/* Check if the name is non compressed */
|
if (Source->Buffer[i] > (UCHAR)-1)
|
||||||
if (Source->Buffer[i] > (UCHAR)-1)
|
{
|
||||||
{
|
/* Do the copy */
|
||||||
/* Do the copy */
|
RtlCopyMemory(Destination, Source->Buffer, Source->Length);
|
||||||
RtlCopyMemory(Destination, Source->Buffer, Source->Length);
|
return Source->Length;
|
||||||
return Source->Length;
|
}
|
||||||
}
|
|
||||||
|
/* Copy this character */
|
||||||
/* Copy this character */
|
((PCHAR)Destination)[i] = (CHAR)(Source->Buffer[i]);
|
||||||
((PCHAR)Destination)[i] = (CHAR)(Source->Buffer[i]);
|
}
|
||||||
}
|
|
||||||
|
/* Compressed name, return length */
|
||||||
/* Compressed name, return length */
|
return Source->Length / sizeof(WCHAR);
|
||||||
return Source->Length / sizeof(WCHAR);
|
}
|
||||||
}
|
|
||||||
|
VOID
|
||||||
VOID
|
NTAPI
|
||||||
NTAPI
|
CmpCopyCompressedName(IN PWCHAR Destination,
|
||||||
CmpCopyCompressedName(IN PWCHAR Destination,
|
IN ULONG DestinationLength,
|
||||||
IN ULONG DestinationLength,
|
IN PWCHAR Source,
|
||||||
IN PWCHAR Source,
|
IN ULONG SourceLength)
|
||||||
IN ULONG SourceLength)
|
{
|
||||||
{
|
ULONG i, Length;
|
||||||
ULONG i, Length;
|
|
||||||
|
/* Get the actual length to copy */
|
||||||
/* Get the actual length to copy */
|
Length = min(DestinationLength / sizeof(WCHAR), SourceLength);
|
||||||
Length = min(DestinationLength / sizeof(WCHAR), SourceLength);
|
for (i = 0; i < Length; i++)
|
||||||
for (i = 0; i < Length; i++)
|
{
|
||||||
{
|
/* Copy each character */
|
||||||
/* Copy each character */
|
Destination[i] = (WCHAR)((PCHAR)Source)[i];
|
||||||
Destination[i] = (WCHAR)((PCHAR)Source)[i];
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
USHORT
|
||||||
USHORT
|
NTAPI
|
||||||
NTAPI
|
CmpNameSize(IN PHHIVE Hive,
|
||||||
CmpNameSize(IN PHHIVE Hive,
|
IN PUNICODE_STRING Name)
|
||||||
IN PUNICODE_STRING Name)
|
{
|
||||||
{
|
ULONG i;
|
||||||
ULONG i;
|
|
||||||
|
/* For old hives, just retun the length */
|
||||||
/* For old hives, just retun the length */
|
if (Hive->Version == 1) return Name->Length;
|
||||||
if (Hive->Version == 1) return Name->Length;
|
|
||||||
|
/* For new versions, check for compressed name */
|
||||||
/* For new versions, check for compressed name */
|
for (i = 0; i < (Name->Length / sizeof(WCHAR)); i++)
|
||||||
for (i = 0; i < (Name->Length / sizeof(WCHAR)); i++)
|
{
|
||||||
{
|
/* Check if the name is non compressed */
|
||||||
/* Check if the name is non compressed */
|
if (Name->Buffer[i] > (UCHAR)-1) return Name->Length;
|
||||||
if (Name->Buffer[i] > (UCHAR)-1) return Name->Length;
|
}
|
||||||
}
|
|
||||||
|
/* Compressed name, return length */
|
||||||
/* Compressed name, return length */
|
return Name->Length / sizeof(WCHAR);
|
||||||
return Name->Length / sizeof(WCHAR);
|
}
|
||||||
}
|
|
||||||
|
USHORT
|
||||||
USHORT
|
NTAPI
|
||||||
NTAPI
|
CmpCompressedNameSize(IN PWCHAR Name,
|
||||||
CmpCompressedNameSize(IN PWCHAR Name,
|
IN ULONG Length)
|
||||||
IN ULONG Length)
|
{
|
||||||
{
|
/*
|
||||||
/*
|
* Don't remove this: compressed names are "opaque" and just because
|
||||||
* Don't remove this: compressed names are "opaque" and just because
|
* the current implementation turns them into ansi-names doesn't mean
|
||||||
* the current implementation turns them into ansi-names doesn't mean
|
* that it will remain that way forever, so -never- assume this code
|
||||||
* that it will remain that way forever, so -never- assume this code
|
* below internally!
|
||||||
* below internally!
|
*/
|
||||||
*/
|
return (USHORT)Length * sizeof(WCHAR);
|
||||||
return (USHORT)Length * sizeof(WCHAR);
|
}
|
||||||
}
|
|
||||||
|
LONG
|
||||||
LONG
|
NTAPI
|
||||||
NTAPI
|
CmpCompareCompressedName(IN PCUNICODE_STRING SearchName,
|
||||||
CmpCompareCompressedName(IN PCUNICODE_STRING SearchName,
|
IN PWCHAR CompressedName,
|
||||||
IN PWCHAR CompressedName,
|
IN ULONG NameLength)
|
||||||
IN ULONG NameLength)
|
{
|
||||||
{
|
WCHAR *p;
|
||||||
WCHAR *p;
|
CHAR *pp;
|
||||||
CHAR *pp;
|
WCHAR p1, p2;
|
||||||
WCHAR p1, p2;
|
USHORT SearchLength;
|
||||||
USHORT SearchLength;
|
LONG Result;
|
||||||
LONG Result;
|
|
||||||
|
/* Set the pointers and length and then loop */
|
||||||
/* Set the pointers and length and then loop */
|
p = SearchName->Buffer;
|
||||||
p = SearchName->Buffer;
|
pp = (PCHAR)CompressedName;
|
||||||
pp = (PCHAR)CompressedName;
|
SearchLength = (SearchName->Length / sizeof(WCHAR));
|
||||||
SearchLength = (SearchName->Length / sizeof(WCHAR));
|
while ((SearchLength) && (NameLength))
|
||||||
while ((SearchLength) && (NameLength))
|
{
|
||||||
{
|
/* Get the characters */
|
||||||
/* Get the characters */
|
p1 = *p++;
|
||||||
p1 = *p++;
|
p2 = (WCHAR)(*pp++);
|
||||||
p2 = (WCHAR)(*pp++);
|
|
||||||
|
/* Check if we have a direct match */
|
||||||
/* Check if we have a direct match */
|
if (p1 != p2)
|
||||||
if (p1 != p2)
|
{
|
||||||
{
|
/* See if they match and return result if they don't */
|
||||||
/* See if they match and return result if they don't */
|
Result = (LONG)RtlUpcaseUnicodeChar(p1) -
|
||||||
Result = (LONG)RtlUpcaseUnicodeChar(p1) -
|
(LONG)RtlUpcaseUnicodeChar(p2);
|
||||||
(LONG)RtlUpcaseUnicodeChar(p2);
|
if (Result) return Result;
|
||||||
if (Result) return Result;
|
}
|
||||||
}
|
|
||||||
|
/* Next chars */
|
||||||
/* Next chars */
|
SearchLength--;
|
||||||
SearchLength--;
|
NameLength--;
|
||||||
NameLength--;
|
}
|
||||||
}
|
|
||||||
|
/* Return the difference directly */
|
||||||
/* Return the difference directly */
|
return SearchLength - NameLength;
|
||||||
return SearchLength - NameLength;
|
}
|
||||||
}
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpFindNameInList(IN PHHIVE Hive,
|
||||||
CmpFindNameInList(IN PHHIVE Hive,
|
IN PCHILD_LIST ChildList,
|
||||||
IN PCHILD_LIST ChildList,
|
IN PUNICODE_STRING Name,
|
||||||
IN PUNICODE_STRING Name,
|
IN PULONG ChildIndex,
|
||||||
IN PULONG ChildIndex,
|
IN PHCELL_INDEX CellIndex)
|
||||||
IN PHCELL_INDEX CellIndex)
|
{
|
||||||
{
|
PCELL_DATA CellData;
|
||||||
PCELL_DATA CellData;
|
HCELL_INDEX CellToRelease = HCELL_NIL;
|
||||||
HCELL_INDEX CellToRelease = HCELL_NIL;
|
ULONG i;
|
||||||
ULONG i;
|
PCM_KEY_VALUE KeyValue;
|
||||||
PCM_KEY_VALUE KeyValue;
|
LONG Result;
|
||||||
LONG Result;
|
UNICODE_STRING SearchName;
|
||||||
UNICODE_STRING SearchName;
|
BOOLEAN Success;
|
||||||
BOOLEAN Success;
|
|
||||||
|
/* Make sure there's actually something on the list */
|
||||||
/* Make sure there's actually something on the list */
|
if (ChildList->Count != 0)
|
||||||
if (ChildList->Count != 0)
|
{
|
||||||
{
|
/* Get the cell data */
|
||||||
/* Get the cell data */
|
CellData = (PCELL_DATA)HvGetCell(Hive, ChildList->List);
|
||||||
CellData = (PCELL_DATA)HvGetCell(Hive, ChildList->List);
|
if (!CellData)
|
||||||
if (!CellData)
|
{
|
||||||
{
|
/* Couldn't get the cell... tell the caller */
|
||||||
/* Couldn't get the cell... tell the caller */
|
*CellIndex = HCELL_NIL;
|
||||||
*CellIndex = HCELL_NIL;
|
return FALSE;
|
||||||
return FALSE;
|
}
|
||||||
}
|
|
||||||
|
/* Now loop every entry */
|
||||||
/* Now loop every entry */
|
for (i = 0; i < ChildList->Count; i++)
|
||||||
for (i = 0; i < ChildList->Count; i++)
|
{
|
||||||
{
|
/* Check if we have a cell to release */
|
||||||
/* Check if we have a cell to release */
|
if (CellToRelease != HCELL_NIL)
|
||||||
if (CellToRelease != HCELL_NIL)
|
{
|
||||||
{
|
/* Release it */
|
||||||
/* Release it */
|
HvReleaseCell(Hive, CellToRelease);
|
||||||
HvReleaseCell(Hive, CellToRelease);
|
CellToRelease = HCELL_NIL;
|
||||||
CellToRelease = HCELL_NIL;
|
}
|
||||||
}
|
|
||||||
|
/* Get this value */
|
||||||
/* Get this value */
|
KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellData->u.KeyList[i]);
|
||||||
KeyValue = (PCM_KEY_VALUE)HvGetCell(Hive, CellData->u.KeyList[i]);
|
if (!KeyValue)
|
||||||
if (!KeyValue)
|
{
|
||||||
{
|
/* Return with no data found */
|
||||||
/* Return with no data found */
|
*CellIndex = HCELL_NIL;
|
||||||
*CellIndex = HCELL_NIL;
|
Success = FALSE;
|
||||||
Success = FALSE;
|
goto Return;
|
||||||
goto Return;
|
}
|
||||||
}
|
|
||||||
|
/* Save the cell to release */
|
||||||
/* Save the cell to release */
|
CellToRelease = CellData->u.KeyList[i];
|
||||||
CellToRelease = CellData->u.KeyList[i];
|
|
||||||
|
/* Check if it's a compressed value name */
|
||||||
/* Check if it's a compressed value name */
|
if (KeyValue->Flags & VALUE_COMP_NAME)
|
||||||
if (KeyValue->Flags & VALUE_COMP_NAME)
|
{
|
||||||
{
|
/* Use the compressed name check */
|
||||||
/* Use the compressed name check */
|
Result = CmpCompareCompressedName(Name,
|
||||||
Result = CmpCompareCompressedName(Name,
|
KeyValue->Name,
|
||||||
KeyValue->Name,
|
KeyValue->NameLength);
|
||||||
KeyValue->NameLength);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Setup the Unicode string */
|
||||||
/* Setup the Unicode string */
|
SearchName.Length = KeyValue->NameLength;
|
||||||
SearchName.Length = KeyValue->NameLength;
|
SearchName.MaximumLength = SearchName.Length;
|
||||||
SearchName.MaximumLength = SearchName.Length;
|
SearchName.Buffer = KeyValue->Name;
|
||||||
SearchName.Buffer = KeyValue->Name;
|
Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
|
||||||
Result = RtlCompareUnicodeString(Name, &SearchName, TRUE);
|
}
|
||||||
}
|
|
||||||
|
/* Check if we found it */
|
||||||
/* Check if we found it */
|
if (!Result)
|
||||||
if (!Result)
|
{
|
||||||
{
|
/* We did...return info to caller */
|
||||||
/* We did...return info to caller */
|
if (ChildIndex) *ChildIndex = i;
|
||||||
if (ChildIndex) *ChildIndex = i;
|
*CellIndex = CellData->u.KeyList[i];
|
||||||
*CellIndex = CellData->u.KeyList[i];
|
|
||||||
|
/* Set success state */
|
||||||
/* Set success state */
|
Success = TRUE;
|
||||||
Success = TRUE;
|
goto Return;
|
||||||
goto Return;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Got to the end of the list */
|
||||||
/* Got to the end of the list */
|
if (ChildIndex) *ChildIndex = i;
|
||||||
if (ChildIndex) *ChildIndex = i;
|
*CellIndex = HCELL_NIL;
|
||||||
*CellIndex = HCELL_NIL;
|
|
||||||
|
/* Nothing found if we got here */
|
||||||
/* Nothing found if we got here */
|
Success = TRUE;
|
||||||
Success = TRUE;
|
goto Return;
|
||||||
goto Return;
|
}
|
||||||
}
|
|
||||||
|
/* Nothing found...check if the caller wanted more info */
|
||||||
/* Nothing found...check if the caller wanted more info */
|
ASSERT(ChildList->Count == 0);
|
||||||
ASSERT(ChildList->Count == 0);
|
if (ChildIndex) *ChildIndex = 0;
|
||||||
if (ChildIndex) *ChildIndex = 0;
|
*CellIndex = HCELL_NIL;
|
||||||
*CellIndex = HCELL_NIL;
|
|
||||||
|
/* Nothing found if we got here */
|
||||||
/* Nothing found if we got here */
|
return TRUE;
|
||||||
return TRUE;
|
|
||||||
|
Return:
|
||||||
Return:
|
/* Release the first cell we got */
|
||||||
/* Release the first cell we got */
|
if (CellData) HvReleaseCell(Hive, ChildList->List);
|
||||||
if (CellData) HvReleaseCell(Hive, ChildList->List);
|
|
||||||
|
/* Release the secondary one, if we have one */
|
||||||
/* Release the secondary one, if we have one */
|
if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
|
||||||
if (CellToRelease) HvReleaseCell(Hive, CellToRelease);
|
return Success;
|
||||||
return Success;
|
}
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,153 +1,152 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmse.c
|
* FILE: ntoskrnl/config/cmse.c
|
||||||
* PURPOSE: Configuration Manager - Security Subsystem Interface
|
* PURPOSE: Configuration Manager - Security Subsystem Interface
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* GLOBALS *******************************************************************/
|
||||||
/* GLOBALS *******************************************************************/
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
PSECURITY_DESCRIPTOR
|
||||||
PSECURITY_DESCRIPTOR
|
NTAPI
|
||||||
NTAPI
|
CmpHiveRootSecurityDescriptor(VOID)
|
||||||
CmpHiveRootSecurityDescriptor(VOID)
|
{
|
||||||
{
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
PACL Acl, AclCopy;
|
||||||
PACL Acl, AclCopy;
|
PSID Sid[4];
|
||||||
PSID Sid[4];
|
SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
|
||||||
SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
|
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
|
||||||
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
|
ULONG AceLength, AclLength, SidLength;
|
||||||
ULONG AceLength, AclLength, SidLength;
|
PACE_HEADER AceHeader;
|
||||||
PACE_HEADER AceHeader;
|
ULONG i;
|
||||||
ULONG i;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
/* Phase 1: Allocate SIDs */
|
||||||
/* Phase 1: Allocate SIDs */
|
SidLength = RtlLengthRequiredSid(1);
|
||||||
SidLength = RtlLengthRequiredSid(1);
|
Sid[0] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
|
||||||
Sid[0] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
|
Sid[1] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
|
||||||
Sid[1] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
|
Sid[2] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
|
||||||
Sid[2] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
|
SidLength = RtlLengthRequiredSid(2);
|
||||||
SidLength = RtlLengthRequiredSid(2);
|
Sid[3] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
|
||||||
Sid[3] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
|
|
||||||
|
/* Make sure all SIDs were allocated */
|
||||||
/* Make sure all SIDs were allocated */
|
if (!(Sid[0]) || !(Sid[1]) || !(Sid[2]) || !(Sid[3]))
|
||||||
if (!(Sid[0]) || !(Sid[1]) || !(Sid[2]) || !(Sid[3]))
|
{
|
||||||
{
|
/* Bugcheck */
|
||||||
/* Bugcheck */
|
KEBUGCHECKEX(REGISTRY_ERROR, 11, 1, 0, 0);
|
||||||
KEBUGCHECKEX(REGISTRY_ERROR, 11, 1, 0, 0);
|
}
|
||||||
}
|
|
||||||
|
/* Phase 2: Initialize all SIDs */
|
||||||
/* Phase 2: Initialize all SIDs */
|
Status = RtlInitializeSid(Sid[0], &WorldAuthority, 1);
|
||||||
Status = RtlInitializeSid(Sid[0], &WorldAuthority, 1);
|
Status |= RtlInitializeSid(Sid[1], &NtAuthority, 1);
|
||||||
Status |= RtlInitializeSid(Sid[1], &NtAuthority, 1);
|
Status |= RtlInitializeSid(Sid[2], &NtAuthority, 1);
|
||||||
Status |= RtlInitializeSid(Sid[2], &NtAuthority, 1);
|
Status |= RtlInitializeSid(Sid[3], &NtAuthority, 2);
|
||||||
Status |= RtlInitializeSid(Sid[3], &NtAuthority, 2);
|
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 2, 0, 0);
|
||||||
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 2, 0, 0);
|
|
||||||
|
/* Phase 2: Setup SID Sub Authorities */
|
||||||
/* Phase 2: Setup SID Sub Authorities */
|
*RtlSubAuthoritySid(Sid[0], 0) = SECURITY_WORLD_RID;
|
||||||
*RtlSubAuthoritySid(Sid[0], 0) = SECURITY_WORLD_RID;
|
*RtlSubAuthoritySid(Sid[1], 0) = SECURITY_RESTRICTED_CODE_RID;
|
||||||
*RtlSubAuthoritySid(Sid[1], 0) = SECURITY_RESTRICTED_CODE_RID;
|
*RtlSubAuthoritySid(Sid[2], 0) = SECURITY_LOCAL_SYSTEM_RID;
|
||||||
*RtlSubAuthoritySid(Sid[2], 0) = SECURITY_LOCAL_SYSTEM_RID;
|
*RtlSubAuthoritySid(Sid[3], 0) = SECURITY_BUILTIN_DOMAIN_RID;
|
||||||
*RtlSubAuthoritySid(Sid[3], 0) = SECURITY_BUILTIN_DOMAIN_RID;
|
*RtlSubAuthoritySid(Sid[3], 1) = DOMAIN_ALIAS_RID_ADMINS;
|
||||||
*RtlSubAuthoritySid(Sid[3], 1) = DOMAIN_ALIAS_RID_ADMINS;
|
|
||||||
|
/* Make sure all SIDs are valid */
|
||||||
/* Make sure all SIDs are valid */
|
ASSERT(RtlValidSid(Sid[0]));
|
||||||
ASSERT(RtlValidSid(Sid[0]));
|
ASSERT(RtlValidSid(Sid[1]));
|
||||||
ASSERT(RtlValidSid(Sid[1]));
|
ASSERT(RtlValidSid(Sid[2]));
|
||||||
ASSERT(RtlValidSid(Sid[2]));
|
ASSERT(RtlValidSid(Sid[3]));
|
||||||
ASSERT(RtlValidSid(Sid[3]));
|
|
||||||
|
/* Phase 3: Calculate ACL Length */
|
||||||
/* Phase 3: Calculate ACL Length */
|
AclLength = sizeof(ACL);
|
||||||
AclLength = sizeof(ACL);
|
for (i = 0; i < 4; i++)
|
||||||
for (i = 0; i < 4; i++)
|
{
|
||||||
{
|
/* This is what MSDN says to do */
|
||||||
/* This is what MSDN says to do */
|
AceLength = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
|
||||||
AceLength = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
|
AceLength += SeLengthSid(Sid[i]);
|
||||||
AceLength += SeLengthSid(Sid[i]);
|
AclLength += AceLength;
|
||||||
AclLength += AceLength;
|
}
|
||||||
}
|
|
||||||
|
/* Phase 3: Allocate the ACL */
|
||||||
/* Phase 3: Allocate the ACL */
|
Acl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_CM);
|
||||||
Acl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_CM);
|
if (!Acl) KEBUGCHECKEX(REGISTRY_ERROR, 11, 3, 0, 0);
|
||||||
if (!Acl) KEBUGCHECKEX(REGISTRY_ERROR, 11, 3, 0, 0);
|
|
||||||
|
/* Phase 4: Create the ACL */
|
||||||
/* Phase 4: Create the ACL */
|
Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION);
|
||||||
Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION);
|
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 4, Status, 0);
|
||||||
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 4, Status, 0);
|
|
||||||
|
/* Phase 5: Build the ACL */
|
||||||
/* Phase 5: Build the ACL */
|
Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[0]);
|
||||||
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_ALL_ACCESS, Sid[1]);
|
Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[2]);
|
||||||
Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[2]);
|
Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[3]);
|
||||||
Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[3]);
|
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 5, Status, 0);
|
||||||
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 5, Status, 0);
|
|
||||||
|
/* Phase 5: Make the ACEs inheritable */
|
||||||
/* Phase 5: Make the ACEs inheritable */
|
Status = RtlGetAce(Acl, 0,( PVOID*)&AceHeader);
|
||||||
Status = RtlGetAce(Acl, 0,( PVOID*)&AceHeader);
|
ASSERT(NT_SUCCESS(Status));
|
||||||
ASSERT(NT_SUCCESS(Status));
|
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
|
||||||
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
|
Status = RtlGetAce(Acl, 1, (PVOID*)&AceHeader);
|
||||||
Status = RtlGetAce(Acl, 1, (PVOID*)&AceHeader);
|
ASSERT(NT_SUCCESS(Status));
|
||||||
ASSERT(NT_SUCCESS(Status));
|
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
|
||||||
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
|
Status = RtlGetAce(Acl, 2, (PVOID*)&AceHeader);
|
||||||
Status = RtlGetAce(Acl, 2, (PVOID*)&AceHeader);
|
ASSERT(NT_SUCCESS(Status));
|
||||||
ASSERT(NT_SUCCESS(Status));
|
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
|
||||||
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
|
Status = RtlGetAce(Acl, 3, (PVOID*)&AceHeader);
|
||||||
Status = RtlGetAce(Acl, 3, (PVOID*)&AceHeader);
|
ASSERT(NT_SUCCESS(Status));
|
||||||
ASSERT(NT_SUCCESS(Status));
|
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
|
||||||
AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
|
|
||||||
|
/* Phase 6: Allocate the security descriptor and make space for the ACL */
|
||||||
/* Phase 6: Allocate the security descriptor and make space for the ACL */
|
SecurityDescriptor = ExAllocatePoolWithTag(PagedPool,
|
||||||
SecurityDescriptor = ExAllocatePoolWithTag(PagedPool,
|
sizeof(SECURITY_DESCRIPTOR) +
|
||||||
sizeof(SECURITY_DESCRIPTOR) +
|
AclLength,
|
||||||
AclLength,
|
TAG_CM);
|
||||||
TAG_CM);
|
if (!SecurityDescriptor) KEBUGCHECKEX(REGISTRY_ERROR, 11, 6, 0, 0);
|
||||||
if (!SecurityDescriptor) KEBUGCHECKEX(REGISTRY_ERROR, 11, 6, 0, 0);
|
|
||||||
|
/* Phase 6: Make a copy of the ACL */
|
||||||
/* Phase 6: Make a copy of the ACL */
|
AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor + 1);
|
||||||
AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor + 1);
|
RtlCopyMemory(AclCopy, Acl, AclLength);
|
||||||
RtlCopyMemory(AclCopy, Acl, AclLength);
|
|
||||||
|
/* Phase 7: Create the security descriptor */
|
||||||
/* Phase 7: Create the security descriptor */
|
Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
|
||||||
Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
|
SECURITY_DESCRIPTOR_REVISION);
|
||||||
SECURITY_DESCRIPTOR_REVISION);
|
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 7, Status, 0);
|
||||||
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 7, Status, 0);
|
|
||||||
|
/* Phase 8: Set the ACL as a DACL */
|
||||||
/* Phase 8: Set the ACL as a DACL */
|
Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
|
||||||
Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
|
TRUE,
|
||||||
TRUE,
|
AclCopy,
|
||||||
AclCopy,
|
FALSE);
|
||||||
FALSE);
|
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 8, Status, 0);
|
||||||
if (!NT_SUCCESS(Status)) KEBUGCHECKEX(REGISTRY_ERROR, 11, 8, Status, 0);
|
|
||||||
|
/* Free the SIDs and original ACL */
|
||||||
/* Free the SIDs and original ACL */
|
for (i = 0; i < 4; i++) ExFreePool(Sid[i]);
|
||||||
for (i = 0; i < 4; i++) ExFreePool(Sid[i]);
|
ExFreePool(Acl);
|
||||||
ExFreePool(Acl);
|
|
||||||
|
/* Return the security descriptor */
|
||||||
/* Return the security descriptor */
|
return SecurityDescriptor;
|
||||||
return SecurityDescriptor;
|
}
|
||||||
}
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmpSecurityMethod(IN PVOID ObjectBody,
|
||||||
CmpSecurityMethod(IN PVOID ObjectBody,
|
IN SECURITY_OPERATION_CODE OperationCode,
|
||||||
IN SECURITY_OPERATION_CODE OperationCode,
|
IN PSECURITY_INFORMATION SecurityInformation,
|
||||||
IN PSECURITY_INFORMATION SecurityInformation,
|
IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||||
IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
IN OUT PULONG BufferLength,
|
||||||
IN OUT PULONG BufferLength,
|
IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
|
||||||
IN OUT PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
|
IN POOL_TYPE PoolType,
|
||||||
IN POOL_TYPE PoolType,
|
IN PGENERIC_MAPPING GenericMapping)
|
||||||
IN PGENERIC_MAPPING GenericMapping)
|
{
|
||||||
{
|
/* HACK */
|
||||||
/* HACK */
|
return STATUS_SUCCESS;
|
||||||
return STATUS_SUCCESS;
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,38 +1,37 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmsecach.c
|
* FILE: ntoskrnl/config/cmsecach.c
|
||||||
* PURPOSE: Configuration Manager - Security Cache
|
* PURPOSE: Configuration Manager - Security Cache
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* GLOBALS *******************************************************************/
|
||||||
/* GLOBALS *******************************************************************/
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
VOID
|
||||||
VOID
|
NTAPI
|
||||||
NTAPI
|
CmpInitSecurityCache(IN PCMHIVE Hive)
|
||||||
CmpInitSecurityCache(IN PCMHIVE Hive)
|
{
|
||||||
{
|
ULONG i;
|
||||||
ULONG i;
|
|
||||||
|
/* Reset data */
|
||||||
/* Reset data */
|
Hive->SecurityCount = 0;
|
||||||
Hive->SecurityCount = 0;
|
Hive->SecurityCacheSize = 0;
|
||||||
Hive->SecurityCacheSize = 0;
|
Hive->SecurityHitHint = -1;
|
||||||
Hive->SecurityHitHint = -1;
|
Hive->SecurityCache = NULL;
|
||||||
Hive->SecurityCache = NULL;
|
|
||||||
|
/* Loop every security hash */
|
||||||
/* Loop every security hash */
|
for (i = 0; i < 64; i++)
|
||||||
for (i = 0; i < 64; i++)
|
{
|
||||||
{
|
/* Initialize it */
|
||||||
/* Initialize it */
|
InitializeListHead(&Hive->SecurityHash[i]);
|
||||||
InitializeListHead(&Hive->SecurityHash[i]);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,364 +1,363 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmvalue.c
|
* FILE: ntoskrnl/config/cmvalue.c
|
||||||
* PURPOSE: Configuration Manager - Cell Values
|
* PURPOSE: Configuration Manager - Cell Values
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpMarkValueDataDirty(IN PHHIVE Hive,
|
||||||
CmpMarkValueDataDirty(IN PHHIVE Hive,
|
IN PCM_KEY_VALUE Value)
|
||||||
IN PCM_KEY_VALUE Value)
|
{
|
||||||
{
|
ULONG KeySize;
|
||||||
ULONG KeySize;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
/* Make sure there's actually any data */
|
||||||
/* Make sure there's actually any data */
|
if (Value->Data != HCELL_NIL)
|
||||||
if (Value->Data != HCELL_NIL)
|
{
|
||||||
{
|
/* If this is a small key, there's no need to have it dirty */
|
||||||
/* If this is a small key, there's no need to have it dirty */
|
if (CmpIsKeyValueSmall(&KeySize, Value->DataLength)) return TRUE;
|
||||||
if (CmpIsKeyValueSmall(&KeySize, Value->DataLength)) return TRUE;
|
|
||||||
|
/* Check if this is a big key */
|
||||||
/* Check if this is a big key */
|
ASSERT_VALUE_BIG(Hive, KeySize);
|
||||||
ASSERT_VALUE_BIG(Hive, KeySize);
|
|
||||||
|
/* Normal value, just mark it dirty */
|
||||||
/* Normal value, just mark it dirty */
|
HvMarkCellDirty(Hive, Value->Data, FALSE);
|
||||||
HvMarkCellDirty(Hive, Value->Data, FALSE);
|
}
|
||||||
}
|
|
||||||
|
/* Operation complete */
|
||||||
/* Operation complete */
|
return TRUE;
|
||||||
return TRUE;
|
}
|
||||||
}
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpFreeValueData(IN PHHIVE Hive,
|
||||||
CmpFreeValueData(IN PHHIVE Hive,
|
IN HCELL_INDEX DataCell,
|
||||||
IN HCELL_INDEX DataCell,
|
IN ULONG DataLength)
|
||||||
IN ULONG DataLength)
|
{
|
||||||
{
|
ULONG KeySize;
|
||||||
ULONG KeySize;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
/* If this is a small key, the data is built-in */
|
||||||
/* If this is a small key, the data is built-in */
|
if (!CmpIsKeyValueSmall(&KeySize, DataLength))
|
||||||
if (!CmpIsKeyValueSmall(&KeySize, DataLength))
|
{
|
||||||
{
|
/* If there's no data cell, there's nothing to do */
|
||||||
/* If there's no data cell, there's nothing to do */
|
if (DataCell == HCELL_NIL) return TRUE;
|
||||||
if (DataCell == HCELL_NIL) return TRUE;
|
|
||||||
|
/* Make sure the data cell is allocated */
|
||||||
/* Make sure the data cell is allocated */
|
//ASSERT(HvIsCellAllocated(Hive, DataCell));
|
||||||
//ASSERT(HvIsCellAllocated(Hive, DataCell));
|
|
||||||
|
/* Unsupported value type */
|
||||||
/* Unsupported value type */
|
ASSERT_VALUE_BIG(Hive, KeySize);
|
||||||
ASSERT_VALUE_BIG(Hive, KeySize);
|
|
||||||
|
/* Normal value, just free the data cell */
|
||||||
/* Normal value, just free the data cell */
|
HvFreeCell(Hive, DataCell);
|
||||||
HvFreeCell(Hive, DataCell);
|
}
|
||||||
}
|
|
||||||
|
/* Operation complete */
|
||||||
/* Operation complete */
|
return TRUE;
|
||||||
return TRUE;
|
}
|
||||||
}
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpFreeValue(IN PHHIVE Hive,
|
||||||
CmpFreeValue(IN PHHIVE Hive,
|
IN HCELL_INDEX Cell)
|
||||||
IN HCELL_INDEX Cell)
|
{
|
||||||
{
|
PCM_KEY_VALUE Value;
|
||||||
PCM_KEY_VALUE Value;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
/* Get the cell data */
|
||||||
/* Get the cell data */
|
Value = (PCM_KEY_VALUE)HvGetCell(Hive, Cell);
|
||||||
Value = (PCM_KEY_VALUE)HvGetCell(Hive, Cell);
|
if (!Value) ASSERT(FALSE);
|
||||||
if (!Value) ASSERT(FALSE);
|
|
||||||
|
/* Free it */
|
||||||
/* Free it */
|
if (!CmpFreeValueData(Hive, Value->Data, Value->DataLength))
|
||||||
if (!CmpFreeValueData(Hive, Value->Data, Value->DataLength))
|
{
|
||||||
{
|
/* We failed to free the data, return failure */
|
||||||
/* We failed to free the data, return failure */
|
HvReleaseCell(Hive, Cell);
|
||||||
HvReleaseCell(Hive, Cell);
|
return FALSE;
|
||||||
return FALSE;
|
}
|
||||||
}
|
|
||||||
|
/* Release the cell and free it */
|
||||||
/* Release the cell and free it */
|
HvReleaseCell(Hive, Cell);
|
||||||
HvReleaseCell(Hive, Cell);
|
HvFreeCell(Hive, Cell);
|
||||||
HvFreeCell(Hive, Cell);
|
return TRUE;
|
||||||
return TRUE;
|
}
|
||||||
}
|
|
||||||
|
HCELL_INDEX
|
||||||
HCELL_INDEX
|
NTAPI
|
||||||
NTAPI
|
CmpFindValueByName(IN PHHIVE Hive,
|
||||||
CmpFindValueByName(IN PHHIVE Hive,
|
IN PCM_KEY_NODE KeyNode,
|
||||||
IN PCM_KEY_NODE KeyNode,
|
IN PUNICODE_STRING Name)
|
||||||
IN PUNICODE_STRING Name)
|
{
|
||||||
{
|
HCELL_INDEX CellIndex;
|
||||||
HCELL_INDEX CellIndex;
|
|
||||||
|
/* Call the main function */
|
||||||
/* Call the main function */
|
if (!CmpFindNameInList(Hive,
|
||||||
if (!CmpFindNameInList(Hive,
|
&KeyNode->ValueList,
|
||||||
&KeyNode->ValueList,
|
Name,
|
||||||
Name,
|
NULL,
|
||||||
NULL,
|
&CellIndex))
|
||||||
&CellIndex))
|
{
|
||||||
{
|
/* Santy check */
|
||||||
/* Santy check */
|
ASSERT(CellIndex == HCELL_NIL);
|
||||||
ASSERT(CellIndex == HCELL_NIL);
|
}
|
||||||
}
|
|
||||||
|
/* Return the index */
|
||||||
/* Return the index */
|
return CellIndex;
|
||||||
return CellIndex;
|
}
|
||||||
}
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpGetValueData(IN PHHIVE Hive,
|
||||||
CmpGetValueData(IN PHHIVE Hive,
|
IN PCM_KEY_VALUE Value,
|
||||||
IN PCM_KEY_VALUE Value,
|
IN PULONG Length,
|
||||||
IN PULONG Length,
|
OUT PVOID *Buffer,
|
||||||
OUT PVOID *Buffer,
|
OUT PBOOLEAN BufferAllocated,
|
||||||
OUT PBOOLEAN BufferAllocated,
|
OUT PHCELL_INDEX CellToRelease)
|
||||||
OUT PHCELL_INDEX CellToRelease)
|
{
|
||||||
{
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
/* Sanity check */
|
||||||
/* Sanity check */
|
ASSERT(Value->Signature == CM_KEY_VALUE_SIGNATURE);
|
||||||
ASSERT(Value->Signature == CM_KEY_VALUE_SIGNATURE);
|
|
||||||
|
/* Set failure defaults */
|
||||||
/* Set failure defaults */
|
*BufferAllocated = FALSE;
|
||||||
*BufferAllocated = FALSE;
|
*Buffer = NULL;
|
||||||
*Buffer = NULL;
|
*CellToRelease = HCELL_NIL;
|
||||||
*CellToRelease = HCELL_NIL;
|
|
||||||
|
/* Check if this is a small key */
|
||||||
/* Check if this is a small key */
|
if (CmpIsKeyValueSmall(Length, Value->DataLength))
|
||||||
if (CmpIsKeyValueSmall(Length, Value->DataLength))
|
{
|
||||||
{
|
/* Return the data immediately */
|
||||||
/* Return the data immediately */
|
*Buffer = &Value->Data;
|
||||||
*Buffer = &Value->Data;
|
return TRUE;
|
||||||
return TRUE;
|
}
|
||||||
}
|
|
||||||
|
/* Unsupported */
|
||||||
/* Unsupported */
|
ASSERT_VALUE_BIG(Hive, *Length);
|
||||||
ASSERT_VALUE_BIG(Hive, *Length);
|
|
||||||
|
/* Get the data from the cell */
|
||||||
/* Get the data from the cell */
|
*Buffer = HvGetCell(Hive, Value->Data);
|
||||||
*Buffer = HvGetCell(Hive, Value->Data);
|
if (!(*Buffer)) return FALSE;
|
||||||
if (!(*Buffer)) return FALSE;
|
|
||||||
|
/* Return success and the cell to be released */
|
||||||
/* Return success and the cell to be released */
|
*CellToRelease = Value->Data;
|
||||||
*CellToRelease = Value->Data;
|
return TRUE;
|
||||||
return TRUE;
|
}
|
||||||
}
|
|
||||||
|
PCELL_DATA
|
||||||
PCELL_DATA
|
NTAPI
|
||||||
NTAPI
|
CmpValueToData(IN PHHIVE Hive,
|
||||||
CmpValueToData(IN PHHIVE Hive,
|
IN PCM_KEY_VALUE Value,
|
||||||
IN PCM_KEY_VALUE Value,
|
OUT PULONG Length)
|
||||||
OUT PULONG Length)
|
{
|
||||||
{
|
PCELL_DATA Buffer;
|
||||||
PCELL_DATA Buffer;
|
BOOLEAN BufferAllocated;
|
||||||
BOOLEAN BufferAllocated;
|
HCELL_INDEX CellToRelease;
|
||||||
HCELL_INDEX CellToRelease;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
/* Sanity check */
|
||||||
/* Sanity check */
|
ASSERT(Hive->ReleaseCellRoutine == NULL);
|
||||||
ASSERT(Hive->ReleaseCellRoutine == NULL);
|
|
||||||
|
/* Get the actual data */
|
||||||
/* Get the actual data */
|
if (!CmpGetValueData(Hive,
|
||||||
if (!CmpGetValueData(Hive,
|
Value,
|
||||||
Value,
|
Length,
|
||||||
Length,
|
(PVOID)&Buffer,
|
||||||
(PVOID)&Buffer,
|
&BufferAllocated,
|
||||||
&BufferAllocated,
|
&CellToRelease))
|
||||||
&CellToRelease))
|
{
|
||||||
{
|
/* We failed */
|
||||||
/* We failed */
|
ASSERT(BufferAllocated == FALSE);
|
||||||
ASSERT(BufferAllocated == FALSE);
|
ASSERT(Buffer == NULL);
|
||||||
ASSERT(Buffer == NULL);
|
return NULL;
|
||||||
return NULL;
|
}
|
||||||
}
|
|
||||||
|
/* This should never happen!*/
|
||||||
/* This should never happen!*/
|
if (BufferAllocated)
|
||||||
if (BufferAllocated)
|
{
|
||||||
{
|
/* Free the buffer and bugcheck */
|
||||||
/* Free the buffer and bugcheck */
|
ExFreePool(Buffer);
|
||||||
ExFreePool(Buffer);
|
KEBUGCHECKEX(REGISTRY_ERROR, 8, 0, (ULONG_PTR)Hive, (ULONG_PTR)Value);
|
||||||
KEBUGCHECKEX(REGISTRY_ERROR, 8, 0, (ULONG_PTR)Hive, (ULONG_PTR)Value);
|
}
|
||||||
}
|
|
||||||
|
/* Otherwise, return the cell data */
|
||||||
/* Otherwise, return the cell data */
|
return Buffer;
|
||||||
return Buffer;
|
}
|
||||||
}
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmpAddValueToList(IN PHHIVE Hive,
|
||||||
CmpAddValueToList(IN PHHIVE Hive,
|
IN HCELL_INDEX ValueCell,
|
||||||
IN HCELL_INDEX ValueCell,
|
IN ULONG Index,
|
||||||
IN ULONG Index,
|
IN ULONG Type,
|
||||||
IN ULONG Type,
|
IN OUT PCHILD_LIST ChildList)
|
||||||
IN OUT PCHILD_LIST ChildList)
|
{
|
||||||
{
|
HCELL_INDEX ListCell;
|
||||||
HCELL_INDEX ListCell;
|
ULONG ChildCount, Length, i;
|
||||||
ULONG ChildCount, Length, i;
|
PCELL_DATA CellData;
|
||||||
PCELL_DATA CellData;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
/* Sanity check */
|
||||||
/* Sanity check */
|
ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
|
||||||
ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
|
|
||||||
|
/* Get the number of entries in the child list */
|
||||||
/* Get the number of entries in the child list */
|
ChildCount = ChildList->Count;
|
||||||
ChildCount = ChildList->Count;
|
ChildCount++;
|
||||||
ChildCount++;
|
if (ChildCount > 1)
|
||||||
if (ChildCount > 1)
|
{
|
||||||
{
|
/* The cell should be dirty at this point */
|
||||||
/* The cell should be dirty at this point */
|
ASSERT(HvIsCellDirty(Hive, ChildList->List));
|
||||||
ASSERT(HvIsCellDirty(Hive, ChildList->List));
|
|
||||||
|
/* Check if we have less then 100 children */
|
||||||
/* Check if we have less then 100 children */
|
if (ChildCount < 100)
|
||||||
if (ChildCount < 100)
|
{
|
||||||
{
|
/* Allocate just enough as requested */
|
||||||
/* Allocate just enough as requested */
|
Length = ChildCount * sizeof(HCELL_INDEX);
|
||||||
Length = ChildCount * sizeof(HCELL_INDEX);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Otherwise, we have quite a few, so allocate a batch */
|
||||||
/* Otherwise, we have quite a few, so allocate a batch */
|
Length = ROUND_UP(ChildCount, 100) * sizeof(HCELL_INDEX);
|
||||||
Length = ROUND_UP(ChildCount, 100) * sizeof(HCELL_INDEX);
|
if (Length > HBLOCK_SIZE)
|
||||||
if (Length > HBLOCK_SIZE)
|
{
|
||||||
{
|
/* But make sure we don't allocate beyond our block size */
|
||||||
/* But make sure we don't allocate beyond our block size */
|
Length = ROUND_UP(Length, HBLOCK_SIZE);
|
||||||
Length = ROUND_UP(Length, HBLOCK_SIZE);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* Perform the allocation */
|
||||||
/* Perform the allocation */
|
ListCell = HvReallocateCell(Hive, ChildList->List, Length);
|
||||||
ListCell = HvReallocateCell(Hive, ChildList->List, Length);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* This is our first child, so allocate a single cell */
|
||||||
/* This is our first child, so allocate a single cell */
|
ListCell = HvAllocateCell(Hive, sizeof(HCELL_INDEX), Type, HCELL_NIL);
|
||||||
ListCell = HvAllocateCell(Hive, sizeof(HCELL_INDEX), Type, HCELL_NIL);
|
}
|
||||||
}
|
|
||||||
|
/* Fail if we couldn't get a cell */
|
||||||
/* Fail if we couldn't get a cell */
|
if (ListCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
if (ListCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
/* Set this cell as the child list's list cell */
|
||||||
/* Set this cell as the child list's list cell */
|
ChildList->List = ListCell;
|
||||||
ChildList->List = ListCell;
|
|
||||||
|
/* Get the actual key list memory */
|
||||||
/* Get the actual key list memory */
|
CellData = HvGetCell(Hive, ListCell);
|
||||||
CellData = HvGetCell(Hive, ListCell);
|
ASSERT(CellData != NULL);
|
||||||
ASSERT(CellData != NULL);
|
|
||||||
|
/* Loop all the children */
|
||||||
/* Loop all the children */
|
for (i = ChildCount - 1; i > Index; i--)
|
||||||
for (i = ChildCount - 1; i > Index; i--)
|
{
|
||||||
{
|
/* Move them all down */
|
||||||
/* Move them all down */
|
CellData->u.KeyList[i] = CellData->u.KeyList[i - 1];
|
||||||
CellData->u.KeyList[i] = CellData->u.KeyList[i - 1];
|
}
|
||||||
}
|
|
||||||
|
/* Insert us on top now */
|
||||||
/* Insert us on top now */
|
CellData->u.KeyList[Index] = ValueCell;
|
||||||
CellData->u.KeyList[Index] = ValueCell;
|
ChildList->Count = ChildCount;
|
||||||
ChildList->Count = ChildCount;
|
|
||||||
|
/* Release the list cell and make sure the value cell is dirty */
|
||||||
/* Release the list cell and make sure the value cell is dirty */
|
HvReleaseCell(Hive, ListCell);
|
||||||
HvReleaseCell(Hive, ListCell);
|
ASSERT(HvIsCellDirty(Hive, ValueCell));
|
||||||
ASSERT(HvIsCellDirty(Hive, ValueCell));
|
|
||||||
|
/* We're done here */
|
||||||
/* We're done here */
|
return STATUS_SUCCESS;
|
||||||
return STATUS_SUCCESS;
|
}
|
||||||
}
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmpSetValueDataNew(IN PHHIVE Hive,
|
||||||
CmpSetValueDataNew(IN PHHIVE Hive,
|
IN PVOID Data,
|
||||||
IN PVOID Data,
|
IN ULONG DataSize,
|
||||||
IN ULONG DataSize,
|
IN ULONG StorageType,
|
||||||
IN ULONG StorageType,
|
IN HCELL_INDEX ValueCell,
|
||||||
IN HCELL_INDEX ValueCell,
|
OUT PHCELL_INDEX DataCell)
|
||||||
OUT PHCELL_INDEX DataCell)
|
{
|
||||||
{
|
PCELL_DATA CellData;
|
||||||
PCELL_DATA CellData;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
ASSERT(DataSize > CM_KEY_VALUE_SMALL);
|
||||||
ASSERT(DataSize > CM_KEY_VALUE_SMALL);
|
|
||||||
|
/* Check if this is a big key */
|
||||||
/* Check if this is a big key */
|
ASSERT_VALUE_BIG(Hive, DataSize);
|
||||||
ASSERT_VALUE_BIG(Hive, DataSize);
|
|
||||||
|
/* Allocate a data cell */
|
||||||
/* Allocate a data cell */
|
*DataCell = HvAllocateCell(Hive, DataSize, StorageType, HCELL_NIL);
|
||||||
*DataCell = HvAllocateCell(Hive, DataSize, StorageType, HCELL_NIL);
|
if (*DataCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
if (*DataCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
/* Get the actual data */
|
||||||
/* Get the actual data */
|
CellData = HvGetCell(Hive, *DataCell);
|
||||||
CellData = HvGetCell(Hive, *DataCell);
|
if (!CellData) ASSERT(FALSE);
|
||||||
if (!CellData) ASSERT(FALSE);
|
|
||||||
|
/* Copy our buffer into it */
|
||||||
/* Copy our buffer into it */
|
RtlCopyMemory(CellData, Data, DataSize);
|
||||||
RtlCopyMemory(CellData, Data, DataSize);
|
|
||||||
|
/* All done */
|
||||||
/* All done */
|
return STATUS_SUCCESS;
|
||||||
return STATUS_SUCCESS;
|
}
|
||||||
}
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmpRemoveValueFromList(IN PHHIVE Hive,
|
||||||
CmpRemoveValueFromList(IN PHHIVE Hive,
|
IN ULONG Index,
|
||||||
IN ULONG Index,
|
IN OUT PCHILD_LIST ChildList)
|
||||||
IN OUT PCHILD_LIST ChildList)
|
{
|
||||||
{
|
ULONG Count;
|
||||||
ULONG Count;
|
PCELL_DATA CellData;
|
||||||
PCELL_DATA CellData;
|
HCELL_INDEX NewCell;
|
||||||
HCELL_INDEX NewCell;
|
PAGED_CODE();
|
||||||
PAGED_CODE();
|
|
||||||
|
/* Sanity check */
|
||||||
/* Sanity check */
|
ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
|
||||||
ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
|
|
||||||
|
/* Get the new count after removal */
|
||||||
/* Get the new count after removal */
|
Count = ChildList->Count - 1;
|
||||||
Count = ChildList->Count - 1;
|
if (Count > 0)
|
||||||
if (Count > 0)
|
{
|
||||||
{
|
/* Get the actual list array */
|
||||||
/* Get the actual list array */
|
CellData = HvGetCell(Hive, ChildList->List);
|
||||||
CellData = HvGetCell(Hive, ChildList->List);
|
if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
/* Make sure cells data have been made dirty */
|
||||||
/* Make sure cells data have been made dirty */
|
ASSERT(HvIsCellDirty(Hive, ChildList->List));
|
||||||
ASSERT(HvIsCellDirty(Hive, ChildList->List));
|
ASSERT(HvIsCellDirty(Hive, CellData->u.KeyList[Index]));
|
||||||
ASSERT(HvIsCellDirty(Hive, CellData->u.KeyList[Index]));
|
|
||||||
|
/* Loop the list */
|
||||||
/* Loop the list */
|
while (Index < Count)
|
||||||
while (Index < Count)
|
{
|
||||||
{
|
/* Move everything up */
|
||||||
/* Move everything up */
|
CellData->u.KeyList[Index] = CellData->u.KeyList[Index + 1];
|
||||||
CellData->u.KeyList[Index] = CellData->u.KeyList[Index + 1];
|
Index++;
|
||||||
Index++;
|
}
|
||||||
}
|
|
||||||
|
/* Re-allocate the cell for the list by decreasing the count */
|
||||||
/* Re-allocate the cell for the list by decreasing the count */
|
NewCell = HvReallocateCell(Hive,
|
||||||
NewCell = HvReallocateCell(Hive,
|
ChildList->List,
|
||||||
ChildList->List,
|
Count * sizeof(HCELL_INDEX));
|
||||||
Count * sizeof(HCELL_INDEX));
|
ASSERT(NewCell != HCELL_NIL);
|
||||||
ASSERT(NewCell != HCELL_NIL);
|
HvReleaseCell(Hive,ChildList->List);
|
||||||
HvReleaseCell(Hive,ChildList->List);
|
|
||||||
|
/* Update the list cell */
|
||||||
/* Update the list cell */
|
ChildList->List = NewCell;
|
||||||
ChildList->List = NewCell;
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
/* Otherwise, we were the last entry, so free the list entirely */
|
||||||
/* Otherwise, we were the last entry, so free the list entirely */
|
HvFreeCell(Hive, ChildList->List);
|
||||||
HvFreeCell(Hive, ChildList->List);
|
ChildList->List = HCELL_NIL;
|
||||||
ChildList->List = HCELL_NIL;
|
}
|
||||||
}
|
|
||||||
|
/* Update the child list with the new count */
|
||||||
/* Update the child list with the new count */
|
ChildList->Count = Count;
|
||||||
ChildList->Count = Count;
|
return STATUS_SUCCESS;
|
||||||
return STATUS_SUCCESS;
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,159 +1,158 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/config/cmwraprs.c
|
* FILE: ntoskrnl/config/cmwraprs.c
|
||||||
* PURPOSE: Configuration Manager - Wrappers for Hive Operations
|
* PURPOSE: Configuration Manager - Wrappers for Hive Operations
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
#define NDEBUG
|
||||||
#define NDEBUG
|
#include "debug.h"
|
||||||
#include "debug.h"
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS
|
NTAPI
|
||||||
NTAPI
|
CmpCreateEvent(IN EVENT_TYPE EventType,
|
||||||
CmpCreateEvent(IN EVENT_TYPE EventType,
|
OUT PHANDLE EventHandle,
|
||||||
OUT PHANDLE EventHandle,
|
OUT PKEVENT *Event)
|
||||||
OUT PKEVENT *Event)
|
{
|
||||||
{
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
||||||
|
/* Create the event */
|
||||||
/* Create the event */
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
NULL,
|
||||||
NULL,
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
NULL,
|
||||||
NULL,
|
NULL);
|
||||||
NULL);
|
Status = ZwCreateEvent(EventHandle,
|
||||||
Status = ZwCreateEvent(EventHandle,
|
EVENT_ALL_ACCESS,
|
||||||
EVENT_ALL_ACCESS,
|
&ObjectAttributes,
|
||||||
&ObjectAttributes,
|
EventType,
|
||||||
EventType,
|
FALSE);
|
||||||
FALSE);
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
|
||||||
|
/* Get a pointer to the object itself */
|
||||||
/* Get a pointer to the object itself */
|
Status = ObReferenceObjectByHandle(*EventHandle,
|
||||||
Status = ObReferenceObjectByHandle(*EventHandle,
|
EVENT_ALL_ACCESS,
|
||||||
EVENT_ALL_ACCESS,
|
NULL,
|
||||||
NULL,
|
KernelMode,
|
||||||
KernelMode,
|
(PVOID*)Event,
|
||||||
(PVOID*)Event,
|
NULL);
|
||||||
NULL);
|
if (!NT_SUCCESS(Status)) ZwClose(*EventHandle);
|
||||||
if (!NT_SUCCESS(Status)) ZwClose(*EventHandle);
|
|
||||||
|
/* Return status */
|
||||||
/* Return status */
|
return Status;
|
||||||
return Status;
|
}
|
||||||
}
|
|
||||||
|
PVOID
|
||||||
PVOID
|
NTAPI
|
||||||
NTAPI
|
CmpAllocate(IN ULONG Size,
|
||||||
CmpAllocate(IN ULONG Size,
|
IN BOOLEAN Paged,
|
||||||
IN BOOLEAN Paged,
|
IN ULONG Tag)
|
||||||
IN ULONG Tag)
|
{
|
||||||
{
|
return ExAllocatePoolWithTag(Paged ? PagedPool : NonPagedPool,
|
||||||
return ExAllocatePoolWithTag(Paged ? PagedPool : NonPagedPool,
|
Size,
|
||||||
Size,
|
Tag);
|
||||||
Tag);
|
}
|
||||||
}
|
|
||||||
|
VOID
|
||||||
VOID
|
NTAPI
|
||||||
NTAPI
|
CmpFree(IN PVOID Ptr,
|
||||||
CmpFree(IN PVOID Ptr,
|
IN ULONG Quota)
|
||||||
IN ULONG Quota)
|
{
|
||||||
{
|
ExFreePool(Ptr);
|
||||||
ExFreePool(Ptr);
|
}
|
||||||
}
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpFileRead(IN PHHIVE RegistryHive,
|
||||||
CmpFileRead(IN PHHIVE RegistryHive,
|
IN ULONG FileType,
|
||||||
IN ULONG FileType,
|
IN PULONG FileOffset,
|
||||||
IN PULONG FileOffset,
|
OUT PVOID Buffer,
|
||||||
OUT PVOID Buffer,
|
IN SIZE_T BufferLength)
|
||||||
IN SIZE_T BufferLength)
|
{
|
||||||
{
|
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
|
||||||
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
|
HANDLE HiveHandle = CmHive->FileHandles[FileType];
|
||||||
HANDLE HiveHandle = CmHive->FileHandles[FileType];
|
LARGE_INTEGER _FileOffset;
|
||||||
LARGE_INTEGER _FileOffset;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
|
||||||
|
_FileOffset.QuadPart = *FileOffset;
|
||||||
_FileOffset.QuadPart = *FileOffset;
|
Status = ZwReadFile(HiveHandle, 0, 0, 0, &IoStatusBlock,
|
||||||
Status = ZwReadFile(HiveHandle, 0, 0, 0, &IoStatusBlock,
|
Buffer, BufferLength, &_FileOffset, 0);
|
||||||
Buffer, BufferLength, &_FileOffset, 0);
|
return NT_SUCCESS(Status) ? TRUE : FALSE;
|
||||||
return NT_SUCCESS(Status) ? TRUE : FALSE;
|
}
|
||||||
}
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpFileWrite(IN PHHIVE RegistryHive,
|
||||||
CmpFileWrite(IN PHHIVE RegistryHive,
|
IN ULONG FileType,
|
||||||
IN ULONG FileType,
|
IN PULONG FileOffset,
|
||||||
IN PULONG FileOffset,
|
IN PVOID Buffer,
|
||||||
IN PVOID Buffer,
|
IN SIZE_T BufferLength)
|
||||||
IN SIZE_T BufferLength)
|
{
|
||||||
{
|
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
|
||||||
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
|
HANDLE HiveHandle = CmHive->FileHandles[FileType];
|
||||||
HANDLE HiveHandle = CmHive->FileHandles[FileType];
|
LARGE_INTEGER _FileOffset;
|
||||||
LARGE_INTEGER _FileOffset;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
|
||||||
|
_FileOffset.QuadPart = *FileOffset;
|
||||||
_FileOffset.QuadPart = *FileOffset;
|
Status = ZwWriteFile(HiveHandle, 0, 0, 0, &IoStatusBlock,
|
||||||
Status = ZwWriteFile(HiveHandle, 0, 0, 0, &IoStatusBlock,
|
Buffer, BufferLength, &_FileOffset, 0);
|
||||||
Buffer, BufferLength, &_FileOffset, 0);
|
return NT_SUCCESS(Status) ? TRUE : FALSE;
|
||||||
return NT_SUCCESS(Status) ? TRUE : FALSE;
|
}
|
||||||
}
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpFileSetSize(IN PHHIVE RegistryHive,
|
||||||
CmpFileSetSize(IN PHHIVE RegistryHive,
|
IN ULONG FileType,
|
||||||
IN ULONG FileType,
|
IN ULONG FileSize,
|
||||||
IN ULONG FileSize,
|
IN ULONG OldFileSize)
|
||||||
IN ULONG OldFileSize)
|
{
|
||||||
{
|
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
|
||||||
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
|
HANDLE HiveHandle = CmHive->FileHandles[FileType];
|
||||||
HANDLE HiveHandle = CmHive->FileHandles[FileType];
|
FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
|
||||||
FILE_END_OF_FILE_INFORMATION EndOfFileInfo;
|
FILE_ALLOCATION_INFORMATION FileAllocationInfo;
|
||||||
FILE_ALLOCATION_INFORMATION FileAllocationInfo;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
|
||||||
|
EndOfFileInfo.EndOfFile.QuadPart = FileSize;
|
||||||
EndOfFileInfo.EndOfFile.QuadPart = FileSize;
|
Status = ZwSetInformationFile(HiveHandle,
|
||||||
Status = ZwSetInformationFile(HiveHandle,
|
&IoStatusBlock,
|
||||||
&IoStatusBlock,
|
&EndOfFileInfo,
|
||||||
&EndOfFileInfo,
|
sizeof(FILE_END_OF_FILE_INFORMATION),
|
||||||
sizeof(FILE_END_OF_FILE_INFORMATION),
|
FileEndOfFileInformation);
|
||||||
FileEndOfFileInformation);
|
if (!NT_SUCCESS(Status)) return FALSE;
|
||||||
if (!NT_SUCCESS(Status)) return FALSE;
|
|
||||||
|
FileAllocationInfo.AllocationSize.QuadPart = FileSize;
|
||||||
FileAllocationInfo.AllocationSize.QuadPart = FileSize;
|
Status = ZwSetInformationFile(HiveHandle,
|
||||||
Status = ZwSetInformationFile(HiveHandle,
|
&IoStatusBlock,
|
||||||
&IoStatusBlock,
|
&FileAllocationInfo,
|
||||||
&FileAllocationInfo,
|
sizeof(FILE_ALLOCATION_INFORMATION),
|
||||||
sizeof(FILE_ALLOCATION_INFORMATION),
|
FileAllocationInformation);
|
||||||
FileAllocationInformation);
|
if (!NT_SUCCESS(Status)) return FALSE;
|
||||||
if (!NT_SUCCESS(Status)) return FALSE;
|
|
||||||
|
return TRUE;
|
||||||
return TRUE;
|
}
|
||||||
}
|
|
||||||
|
BOOLEAN
|
||||||
BOOLEAN
|
NTAPI
|
||||||
NTAPI
|
CmpFileFlush(IN PHHIVE RegistryHive,
|
||||||
CmpFileFlush(IN PHHIVE RegistryHive,
|
IN ULONG FileType,
|
||||||
IN ULONG FileType,
|
IN OUT PLARGE_INTEGER FileOffset,
|
||||||
IN OUT PLARGE_INTEGER FileOffset,
|
IN ULONG Length)
|
||||||
IN ULONG Length)
|
{
|
||||||
{
|
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
|
||||||
PCMHIVE CmHive = (PCMHIVE)RegistryHive;
|
HANDLE HiveHandle = CmHive->FileHandles[FileType];
|
||||||
HANDLE HiveHandle = CmHive->FileHandles[FileType];
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
|
||||||
|
Status = ZwFlushBuffersFile(HiveHandle, &IoStatusBlock);
|
||||||
Status = ZwFlushBuffersFile(HiveHandle, &IoStatusBlock);
|
return NT_SUCCESS(Status) ? TRUE : FALSE;
|
||||||
return NT_SUCCESS(Status) ? TRUE : FALSE;
|
}
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,7 +9,6 @@
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include "ntoskrnl.h"
|
#include "ntoskrnl.h"
|
||||||
#include "cm.h"
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
@ -18,7 +17,6 @@ BOOLEAN CmFirstTime = TRUE;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
#if 0
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NtCreateKey(OUT PHANDLE KeyHandle,
|
NtCreateKey(OUT PHANDLE KeyHandle,
|
||||||
|
@ -32,7 +30,9 @@ NtCreateKey(OUT PHANDLE KeyHandle,
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
CM_PARSE_CONTEXT ParseContext = {0};
|
CM_PARSE_CONTEXT ParseContext = {0};
|
||||||
|
HANDLE Handle;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtCreateKey(OB 0x%wZ)\n", ObjectAttributes->ObjectName);
|
||||||
|
|
||||||
/* Setup the parse context */
|
/* Setup the parse context */
|
||||||
ParseContext.CreateOperation = TRUE;
|
ParseContext.CreateOperation = TRUE;
|
||||||
|
@ -46,13 +46,13 @@ NtCreateKey(OUT PHANDLE KeyHandle,
|
||||||
NULL,
|
NULL,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
&ParseContext,
|
&ParseContext,
|
||||||
KeyHandle);
|
&Handle);
|
||||||
|
if (NT_SUCCESS(Status)) *KeyHandle = Handle;
|
||||||
|
|
||||||
/* Return data to user */
|
/* Return data to user */
|
||||||
if (Disposition) *Disposition = ParseContext.Disposition;
|
if (Disposition) *Disposition = ParseContext.Disposition;
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -61,18 +61,26 @@ NtOpenKey(OUT PHANDLE KeyHandle,
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
IN POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
{
|
{
|
||||||
CM_PARSE_CONTEXT ParseContext = {0};
|
CM_PARSE_CONTEXT ParseContext = {0};
|
||||||
|
HANDLE Handle;
|
||||||
|
NTSTATUS Status;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
DPRINT("NtOpenKey(OB 0x%wZ)\n", ObjectAttributes->ObjectName);
|
||||||
|
|
||||||
/* Just let the object manager handle this */
|
/* Just let the object manager handle this */
|
||||||
return ObOpenObjectByName(ObjectAttributes,
|
Status = ObOpenObjectByName(ObjectAttributes,
|
||||||
CmpKeyObjectType,
|
CmpKeyObjectType,
|
||||||
ExGetPreviousMode(),
|
ExGetPreviousMode(),
|
||||||
NULL,
|
NULL,
|
||||||
DesiredAccess,
|
DesiredAccess,
|
||||||
&ParseContext,
|
&ParseContext,
|
||||||
KeyHandle);
|
&Handle);
|
||||||
|
if (NT_SUCCESS(Status)) *KeyHandle = Handle;
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NtDeleteKey(IN HANDLE KeyHandle)
|
NtDeleteKey(IN HANDLE KeyHandle)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,7 +12,6 @@
|
||||||
#include <ntoskrnl.h>
|
#include <ntoskrnl.h>
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include "ntoskrnl/cm/cm.h"
|
|
||||||
#include "ntstrsafe.h"
|
#include "ntstrsafe.h"
|
||||||
|
|
||||||
typedef struct _INIT_BUFFER
|
typedef struct _INIT_BUFFER
|
||||||
|
|
|
@ -1,248 +1,248 @@
|
||||||
/*
|
/*
|
||||||
* PROJECT: ReactOS Kernel
|
* PROJECT: ReactOS Kernel
|
||||||
* LICENSE: GPL - See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* FILE: ntoskrnl/cm/cm_x.h
|
* FILE: ntoskrnl/cm/cm_x.h
|
||||||
* PURPOSE: Inlined Functions for the Configuration Manager
|
* PURPOSE: Inlined Functions for the Configuration Manager
|
||||||
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns whether or not this is a small valued key
|
// Returns whether or not this is a small valued key
|
||||||
//
|
//
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
CmpIsKeyValueSmall(OUT PULONG RealLength,
|
CmpIsKeyValueSmall(OUT PULONG RealLength,
|
||||||
IN ULONG Length)
|
IN ULONG Length)
|
||||||
{
|
{
|
||||||
/* Check if the length has the special size value */
|
/* Check if the length has the special size value */
|
||||||
if (Length >= CM_KEY_VALUE_SPECIAL_SIZE)
|
if (Length >= CM_KEY_VALUE_SPECIAL_SIZE)
|
||||||
{
|
{
|
||||||
/* It does, so this is a small key: return the real length */
|
/* It does, so this is a small key: return the real length */
|
||||||
*RealLength = Length - CM_KEY_VALUE_SPECIAL_SIZE;
|
*RealLength = Length - CM_KEY_VALUE_SPECIAL_SIZE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is not a small key, return the length we read */
|
/* This is not a small key, return the length we read */
|
||||||
*RealLength = Length;
|
*RealLength = Length;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns whether or not this is a big valued key
|
// Returns whether or not this is a big valued key
|
||||||
//
|
//
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
CmpIsKeyValueBig(IN PHHIVE Hive,
|
CmpIsKeyValueBig(IN PHHIVE Hive,
|
||||||
IN ULONG Length)
|
IN ULONG Length)
|
||||||
{
|
{
|
||||||
/* Check if the hive is XP Beta 1 or newer */
|
/* Check if the hive is XP Beta 1 or newer */
|
||||||
if (Hive->Version >= HSYS_WHISTLER_BETA1)
|
if (Hive->Version >= HSYS_WHISTLER_BETA1)
|
||||||
{
|
{
|
||||||
/* Check if the key length is valid for a big value key */
|
/* Check if the key length is valid for a big value key */
|
||||||
if ((Length < CM_KEY_VALUE_SPECIAL_SIZE) && (Length > CM_KEY_VALUE_BIG))
|
if ((Length < CM_KEY_VALUE_SPECIAL_SIZE) && (Length > CM_KEY_VALUE_BIG))
|
||||||
{
|
{
|
||||||
/* Yes, this value is big */
|
/* Yes, this value is big */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not a big value key */
|
/* Not a big value key */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns the hashkey corresponding to a convkey
|
// Returns the hashkey corresponding to a convkey
|
||||||
//
|
//
|
||||||
#define GET_HASH_KEY(ConvKey) \
|
#define GET_HASH_KEY(ConvKey) \
|
||||||
((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
|
((CMP_HASH_IRRATIONAL * (ConvKey)) % CMP_HASH_PRIME)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns the index into the hash table, or the entry itself
|
// Returns the index into the hash table, or the entry itself
|
||||||
//
|
//
|
||||||
#define GET_HASH_INDEX(ConvKey) \
|
#define GET_HASH_INDEX(ConvKey) \
|
||||||
GET_HASH_KEY(ConvKey) % CmpHashTableSize
|
GET_HASH_KEY(ConvKey) % CmpHashTableSize
|
||||||
#define GET_HASH_ENTRY(Table, ConvKey) \
|
#define GET_HASH_ENTRY(Table, ConvKey) \
|
||||||
(Table[GET_HASH_INDEX(ConvKey)])
|
(Table[GET_HASH_INDEX(ConvKey)])
|
||||||
|
|
||||||
//
|
//
|
||||||
// Returns whether or not the cell is cached
|
// Returns whether or not the cell is cached
|
||||||
//
|
//
|
||||||
#define CMP_IS_CELL_CACHED(c) \
|
#define CMP_IS_CELL_CACHED(c) \
|
||||||
(((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
|
(((c) & HCELL_CACHED) && ((c) != HCELL_NIL))
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return data from a cached cell
|
// Return data from a cached cell
|
||||||
//
|
//
|
||||||
#define CMP_GET_CACHED_CELL(c) \
|
#define CMP_GET_CACHED_CELL(c) \
|
||||||
(ULONG_PTR)((c) & ~HCELL_CACHED)
|
(ULONG_PTR)((c) & ~HCELL_CACHED)
|
||||||
#define CMP_GET_CACHED_DATA(c) \
|
#define CMP_GET_CACHED_DATA(c) \
|
||||||
(&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData))
|
(&(((PCM_CACHED_VALUE_INDEX)(CMP_GET_CACHED_CELL(c)))->Data.CellData))
|
||||||
#define CMP_GET_CACHED_INDEX(c) \
|
#define CMP_GET_CACHED_INDEX(c) \
|
||||||
(&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex))
|
(&(((PCM_CACHED_ENTRY)(CMP_GET_CACHED_CELL(c)))->CellIndex))
|
||||||
#define CMP_GET_CACHED_VALUE(c) \
|
#define CMP_GET_CACHED_VALUE(c) \
|
||||||
(&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
|
(&(((PCM_CACHED_VALUE)(CMP_GET_CACHED_CELL(c)))->KeyValue))
|
||||||
|
|
||||||
//
|
//
|
||||||
// Makes sure that the registry is locked
|
// Makes sure that the registry is locked
|
||||||
//
|
//
|
||||||
#define CMP_ASSERT_REGISTRY_LOCK() \
|
#define CMP_ASSERT_REGISTRY_LOCK() \
|
||||||
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
||||||
(CmpTestRegistryLock() == TRUE))
|
(CmpTestRegistryLock() == TRUE))
|
||||||
|
|
||||||
//
|
//
|
||||||
// Makes sure that the registry is exclusively locked
|
// Makes sure that the registry is exclusively locked
|
||||||
//
|
//
|
||||||
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
|
#define CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() \
|
||||||
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
ASSERT((CmpSpecialBootCondition == TRUE) || \
|
||||||
(CmpTestRegistryLockExclusive() == TRUE))
|
(CmpTestRegistryLockExclusive() == TRUE))
|
||||||
|
|
||||||
//
|
//
|
||||||
// Checks if a KCB is exclusively locked
|
// Checks if a KCB is exclusively locked
|
||||||
//
|
//
|
||||||
#define CmpIsKcbLockedExclusive(k) \
|
#define CmpIsKcbLockedExclusive(k) \
|
||||||
(GET_HASH_ENTRY(CmpCacheTable, \
|
(GET_HASH_ENTRY(CmpCacheTable, \
|
||||||
(k)->ConvKey).Owner == KeGetCurrentThread())
|
(k)->ConvKey).Owner == KeGetCurrentThread())
|
||||||
|
|
||||||
//
|
//
|
||||||
// Exclusively acquires a KCB
|
// Exclusively acquires a KCB
|
||||||
//
|
//
|
||||||
#define CmpAcquireKcbLockExclusive(k) \
|
#define CmpAcquireKcbLockExclusive(k) \
|
||||||
{ \
|
{ \
|
||||||
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
|
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
|
||||||
(k)->ConvKey).Lock); \
|
(k)->ConvKey).Lock); \
|
||||||
GET_HASH_ENTRY(CmpCacheTable, \
|
GET_HASH_ENTRY(CmpCacheTable, \
|
||||||
(k)->ConvKey).Owner = KeGetCurrentThread(); \
|
(k)->ConvKey).Owner = KeGetCurrentThread(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Exclusively acquires a KCB by index
|
// Exclusively acquires a KCB by index
|
||||||
//
|
//
|
||||||
#define CmpAcquireKcbLockExclusiveByIndex(i) \
|
#define CmpAcquireKcbLockExclusiveByIndex(i) \
|
||||||
{ \
|
{ \
|
||||||
ExAcquirePushLockExclusive(&CmpCacheTable[(i)].Lock); \
|
ExAcquirePushLockExclusive(&CmpCacheTable[(i)].Lock); \
|
||||||
CmpCacheTable[(i)].Owner = KeGetCurrentThread(); \
|
CmpCacheTable[(i)].Owner = KeGetCurrentThread(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Exclusively acquires a KCB by key
|
// Exclusively acquires a KCB by key
|
||||||
//
|
//
|
||||||
#define CmpAcquireKcbLockExclusiveByKey(k) \
|
#define CmpAcquireKcbLockExclusiveByKey(k) \
|
||||||
{ \
|
{ \
|
||||||
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
|
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpCacheTable, \
|
||||||
(k)).Lock); \
|
(k)).Lock); \
|
||||||
GET_HASH_ENTRY(CmpCacheTable, \
|
GET_HASH_ENTRY(CmpCacheTable, \
|
||||||
(k)).Owner = KeGetCurrentThread(); \
|
(k)).Owner = KeGetCurrentThread(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Shared acquires a KCB
|
// Shared acquires a KCB
|
||||||
//
|
//
|
||||||
#define CmpAcquireKcbLockShared(k) \
|
#define CmpAcquireKcbLockShared(k) \
|
||||||
{ \
|
{ \
|
||||||
ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \
|
ExAcquirePushLockShared(&GET_HASH_ENTRY(CmpCacheTable, \
|
||||||
(k)->ConvKey).Lock); \
|
(k)->ConvKey).Lock); \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Shared acquires a KCB by index
|
// Shared acquires a KCB by index
|
||||||
//
|
//
|
||||||
#define CmpAcquireKcbLockSharedByIndex(i) \
|
#define CmpAcquireKcbLockSharedByIndex(i) \
|
||||||
{ \
|
{ \
|
||||||
ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \
|
ExAcquirePushLockShared(&CmpCacheTable[(i)].Lock); \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Tries to convert a KCB lock
|
// Tries to convert a KCB lock
|
||||||
//
|
//
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
|
CmpTryToConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
|
||||||
{
|
{
|
||||||
ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
|
ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
|
||||||
if (ExConvertPushLockSharedToExclusive(
|
if (ExConvertPushLockSharedToExclusive(
|
||||||
&GET_HASH_ENTRY(CmpCacheTable, k->ConvKey).Lock))
|
&GET_HASH_ENTRY(CmpCacheTable, k->ConvKey).Lock))
|
||||||
{
|
{
|
||||||
GET_HASH_ENTRY(CmpCacheTable,
|
GET_HASH_ENTRY(CmpCacheTable,
|
||||||
k->ConvKey).Owner = KeGetCurrentThread();
|
k->ConvKey).Owner = KeGetCurrentThread();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Releases an exlusively or shared acquired KCB
|
// Releases an exlusively or shared acquired KCB
|
||||||
//
|
//
|
||||||
#define CmpReleaseKcbLock(k) \
|
#define CmpReleaseKcbLock(k) \
|
||||||
{ \
|
{ \
|
||||||
GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
|
GET_HASH_ENTRY(CmpCacheTable, (k)->ConvKey).Owner = NULL; \
|
||||||
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
|
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
|
||||||
(k)->ConvKey).Lock); \
|
(k)->ConvKey).Lock); \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Releases an exlusively or shared acquired KCB by index
|
// Releases an exlusively or shared acquired KCB by index
|
||||||
//
|
//
|
||||||
#define CmpReleaseKcbLockByIndex(i) \
|
#define CmpReleaseKcbLockByIndex(i) \
|
||||||
{ \
|
{ \
|
||||||
CmpCacheTable[(i)].Owner = NULL; \
|
CmpCacheTable[(i)].Owner = NULL; \
|
||||||
ExReleasePushLock(&CmpCacheTable[(i)].Lock); \
|
ExReleasePushLock(&CmpCacheTable[(i)].Lock); \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Releases an exlusively or shared acquired KCB by key
|
// Releases an exlusively or shared acquired KCB by key
|
||||||
//
|
//
|
||||||
#define CmpReleaseKcbLockByKey(k) \
|
#define CmpReleaseKcbLockByKey(k) \
|
||||||
{ \
|
{ \
|
||||||
GET_HASH_ENTRY(CmpCacheTable, (k)).Owner = NULL; \
|
GET_HASH_ENTRY(CmpCacheTable, (k)).Owner = NULL; \
|
||||||
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
|
ExReleasePushLock(&GET_HASH_ENTRY(CmpCacheTable, \
|
||||||
(k)).Lock); \
|
(k)).Lock); \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Converts a KCB lock
|
// Converts a KCB lock
|
||||||
//
|
//
|
||||||
FORCEINLINE
|
FORCEINLINE
|
||||||
VOID
|
VOID
|
||||||
CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
|
CmpConvertKcbSharedToExclusive(IN PCM_KEY_CONTROL_BLOCK k)
|
||||||
{
|
{
|
||||||
ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
|
ASSERT(CmpIsKcbLockedExclusive(k) == FALSE);
|
||||||
CmpReleaseKcbLock(k);
|
CmpReleaseKcbLock(k);
|
||||||
CmpAcquireKcbLockExclusive(k);
|
CmpAcquireKcbLockExclusive(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Exclusively acquires an NCB
|
// Exclusively acquires an NCB
|
||||||
//
|
//
|
||||||
#define CmpAcquireNcbLockExclusive(n) \
|
#define CmpAcquireNcbLockExclusive(n) \
|
||||||
{ \
|
{ \
|
||||||
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
||||||
(n)->ConvKey).Lock); \
|
(n)->ConvKey).Lock); \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Exclusively acquires an NCB by key
|
// Exclusively acquires an NCB by key
|
||||||
//
|
//
|
||||||
#define CmpAcquireNcbLockExclusiveByKey(k) \
|
#define CmpAcquireNcbLockExclusiveByKey(k) \
|
||||||
{ \
|
{ \
|
||||||
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
ExAcquirePushLockExclusive(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
||||||
(k)).Lock); \
|
(k)).Lock); \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Releases an exlusively or shared acquired NCB
|
// Releases an exlusively or shared acquired NCB
|
||||||
//
|
//
|
||||||
#define CmpReleaseNcbLock(k) \
|
#define CmpReleaseNcbLock(k) \
|
||||||
{ \
|
{ \
|
||||||
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
||||||
(k)->ConvKey).Lock); \
|
(k)->ConvKey).Lock); \
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Releases an exlusively or shared acquired NCB by key
|
// Releases an exlusively or shared acquired NCB by key
|
||||||
//
|
//
|
||||||
#define CmpReleaseNcbLockByKey(k) \
|
#define CmpReleaseNcbLockByKey(k) \
|
||||||
{ \
|
{ \
|
||||||
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
ExReleasePushLock(&GET_HASH_ENTRY(CmpNameCacheTable, \
|
||||||
(k)).Lock); \
|
(k)).Lock); \
|
||||||
}
|
}
|
|
@ -30,6 +30,7 @@
|
||||||
#include "ob.h"
|
#include "ob.h"
|
||||||
#include "mm.h"
|
#include "mm.h"
|
||||||
#include "ex.h"
|
#include "ex.h"
|
||||||
|
#include "cm.h"
|
||||||
#include "ps.h"
|
#include "ps.h"
|
||||||
#include "cc.h"
|
#include "cc.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
|
|
@ -142,12 +142,6 @@
|
||||||
<file>cmwraprs.c</file>
|
<file>cmwraprs.c</file>
|
||||||
<file>ntapi.c</file>
|
<file>ntapi.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="cm">
|
|
||||||
<file>ntfunc.c</file>
|
|
||||||
<file>regfile.c</file>
|
|
||||||
<file>registry.c</file>
|
|
||||||
<file>regobj.c</file>
|
|
||||||
</directory>
|
|
||||||
<directory name="dbgk">
|
<directory name="dbgk">
|
||||||
<file>dbgkutil.c</file>
|
<file>dbgkutil.c</file>
|
||||||
<file>dbgkobj.c</file>
|
<file>dbgkobj.c</file>
|
||||||
|
|
|
@ -138,9 +138,6 @@
|
||||||
<file>cmwraprs.c</file>
|
<file>cmwraprs.c</file>
|
||||||
<file>ntapi.c</file>
|
<file>ntapi.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="cm">
|
|
||||||
<file>regobj.c</file>
|
|
||||||
</directory>
|
|
||||||
<directory name="dbgk">
|
<directory name="dbgk">
|
||||||
<file>dbgkutil.c</file>
|
<file>dbgkutil.c</file>
|
||||||
<file>dbgkobj.c</file>
|
<file>dbgkobj.c</file>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue