mirror of
https://github.com/reactos/reactos.git
synced 2025-07-27 07:41:51 +00:00
- Fix prototype of NtLoadKeyEx.
- Refactor CmiLoadHives using new config routines instead of deprecated cm routines. - Stop using deprecated CmiScanKeyForValue (delete regfile.c as a result). - Add code for parallel hive loading to speed up boot process, but don't yet fully use it due to changes required in linking hives. - Add code for new hive linking process (CmpCreateLinkNode/CmpDoOpen). Not yet used to avoid too many changes in one patch. - Add new code in CmiLoadHives to deal with updated linking process when it becomes used. - Implement NtLoadKey2 to cal NtLoadKeyEx. - Implement NtLoadKeyEx as a new config routine, using CmLoadKey, move out of Cm. - Add some more code in CmpInitializeSystemHive to deal with SYSTEM hive creation during setup, once hive linking is refactored. - Implement a new command except for flushing -- open: CmpCmdHiveOpen. Used by CmLoadKey. - Add support for impersonating the SYSTEM account if the hive can't be open in the current client security context. - Fill out CmpMachineHiveList, to be used in parallel hive loading. svn path=/trunk/; revision=30680
This commit is contained in:
parent
76f076659d
commit
95e31f7de7
14 changed files with 1039 additions and 279 deletions
|
@ -139,10 +139,7 @@ NtLoadKeyEx(
|
||||||
IN POBJECT_ATTRIBUTES TargetKey,
|
IN POBJECT_ATTRIBUTES TargetKey,
|
||||||
IN POBJECT_ATTRIBUTES SourceFile,
|
IN POBJECT_ATTRIBUTES SourceFile,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
IN HANDLE TrustClassKey,
|
IN HANDLE TrustClassKey
|
||||||
IN HANDLE Event,
|
|
||||||
IN ACCESS_MASK DesiredAccess,
|
|
||||||
OUT PHANDLE RootHandle
|
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -578,65 +578,25 @@ openkey_cleanup:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE:
|
|
||||||
* KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
|
|
||||||
* KeyObjectAttributes->Name specifies the name of the key to load.
|
|
||||||
* Flags can be 0 or REG_NO_LAZY_FLUSH.
|
|
||||||
*/
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
|
||||||
IN POBJECT_ATTRIBUTES FileObjectAttributes,
|
|
||||||
IN ULONG Flags)
|
|
||||||
{
|
|
||||||
NTSTATUS Status;
|
|
||||||
PAGED_CODE();
|
|
||||||
DPRINT ("NtLoadKey2() called\n");
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (!SeSinglePrivilegeCheck (SeRestorePrivilege, ExGetPreviousMode ()))
|
|
||||||
return STATUS_PRIVILEGE_NOT_HELD;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Acquire hive lock */
|
|
||||||
KeEnterCriticalRegion();
|
|
||||||
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
|
|
||||||
|
|
||||||
Status = CmiLoadHive (KeyObjectAttributes,
|
|
||||||
FileObjectAttributes->ObjectName,
|
|
||||||
Flags);
|
|
||||||
if (!NT_SUCCESS (Status))
|
|
||||||
{
|
|
||||||
DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release hive lock */
|
|
||||||
ExReleaseResourceLite(&CmpRegistryLock);
|
|
||||||
KeLeaveCriticalRegion();
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NtInitializeRegistry (IN USHORT Flag)
|
NtInitializeRegistry (IN USHORT Flag)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
if (CmiRegistryInitialized == TRUE)
|
if (CmiRegistryInitialized == TRUE)
|
||||||
return STATUS_ACCESS_DENIED;
|
return STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
/* Save boot log file */
|
/* Save boot log file */
|
||||||
IopSaveBootLogToFile();
|
IopSaveBootLogToFile();
|
||||||
|
|
||||||
Status = CmiInitHives (Flag);
|
Status = CmiInitHives (Flag);
|
||||||
|
|
||||||
CmpCmdInit(Flag);
|
CmpCmdInit(Flag);
|
||||||
CmiRegistryInitialized = TRUE;
|
CmiRegistryInitialized = TRUE;
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
* PROJECT: ReactOS Kernel
|
|
||||||
* COPYRIGHT: GPL - See COPYING in the top level directory
|
|
||||||
* FILE: ntoskrnl/cm/regfile.c
|
|
||||||
* PURPOSE: Registry file manipulation routines
|
|
||||||
*
|
|
||||||
* PROGRAMMERS: Casper Hornstrup
|
|
||||||
* Eric Kohl
|
|
||||||
* Filip Navara
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
|
||||||
#define NDEBUG
|
|
||||||
#include <internal/debug.h>
|
|
||||||
#include "cm.h"
|
|
||||||
|
|
||||||
/* LOCAL MACROS *************************************************************/
|
|
||||||
|
|
||||||
#define ABS_VALUE(V) (((V) < 0) ? -(V) : (V))
|
|
||||||
#define REG_DATA_SIZE_MASK 0x7FFFFFFF
|
|
||||||
#define REG_DATA_IN_OFFSET 0x80000000
|
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiLoadHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
|
||||||
IN PCUNICODE_STRING FileName,
|
|
||||||
IN ULONG Flags)
|
|
||||||
{
|
|
||||||
PCMHIVE Hive = NULL;
|
|
||||||
NTSTATUS Status;
|
|
||||||
BOOLEAN Allocate = TRUE;
|
|
||||||
|
|
||||||
DPRINT ("CmiLoadHive(Filename %wZ)\n", FileName);
|
|
||||||
|
|
||||||
if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
Status = CmpInitHiveFromFile(FileName,
|
|
||||||
(Flags & REG_NO_LAZY_FLUSH) ? HIVE_NOLAZYFLUSH : 0,
|
|
||||||
&Hive,
|
|
||||||
&Allocate,
|
|
||||||
0);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("CmpInitHiveFromFile() failed (Status %lx)\n", Status);
|
|
||||||
if (Hive) ExFreePool(Hive);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = CmiConnectHive(KeyObjectAttributes, Hive);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status);
|
|
||||||
// CmiRemoveRegistryHive (Hive);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT ("CmiLoadHive() done\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiScanKeyForValue(IN PCMHIVE RegistryHive,
|
|
||||||
IN PCM_KEY_NODE KeyCell,
|
|
||||||
IN PUNICODE_STRING ValueName,
|
|
||||||
OUT PCM_KEY_VALUE *ValueCell,
|
|
||||||
OUT HCELL_INDEX *ValueCellOffset)
|
|
||||||
{
|
|
||||||
HCELL_INDEX CellIndex;
|
|
||||||
|
|
||||||
/* Assume failure */
|
|
||||||
*ValueCell = NULL;
|
|
||||||
if (ValueCellOffset) *ValueCellOffset = HCELL_NIL;
|
|
||||||
|
|
||||||
/* Call newer Cm API */
|
|
||||||
CellIndex = CmpFindValueByName(&RegistryHive->Hive, KeyCell, ValueName);
|
|
||||||
if (CellIndex == HCELL_NIL) return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
|
|
||||||
/* Otherwise, get the cell data back too */
|
|
||||||
if (ValueCellOffset) *ValueCellOffset = CellIndex;
|
|
||||||
*ValueCell = (PCM_KEY_VALUE)HvGetCell(&RegistryHive->Hive, CellIndex);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -328,6 +328,8 @@ CmiInitHives(BOOLEAN SetupBoot)
|
||||||
ULONG BufferSize;
|
ULONG BufferSize;
|
||||||
ULONG ResultSize;
|
ULONG ResultSize;
|
||||||
PWSTR EndPtr;
|
PWSTR EndPtr;
|
||||||
|
PCMHIVE CmHive;
|
||||||
|
BOOLEAN Allocate = TRUE;
|
||||||
|
|
||||||
DPRINT("CmiInitHives() called\n");
|
DPRINT("CmiInitHives() called\n");
|
||||||
|
|
||||||
|
@ -379,138 +381,172 @@ CmiInitHives(BOOLEAN SetupBoot)
|
||||||
wcscpy(ConfigPath, L"\\SystemRoot");
|
wcscpy(ConfigPath, L"\\SystemRoot");
|
||||||
}
|
}
|
||||||
wcscat(ConfigPath, L"\\system32\\config");
|
wcscat(ConfigPath, L"\\system32\\config");
|
||||||
|
|
||||||
DPRINT("ConfigPath: %S\n", ConfigPath);
|
DPRINT("ConfigPath: %S\n", ConfigPath);
|
||||||
|
|
||||||
EndPtr = ConfigPath + wcslen(ConfigPath);
|
EndPtr = ConfigPath + wcslen(ConfigPath);
|
||||||
|
|
||||||
/* FIXME: Save boot log */
|
/* Setup the file name for the SECURITY hive */
|
||||||
|
wcscpy(EndPtr, REG_SEC_FILE_NAME);
|
||||||
|
RtlInitUnicodeString(&FileName, ConfigPath);
|
||||||
|
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
||||||
|
|
||||||
|
/* Load the hive */
|
||||||
|
Status = CmpInitHiveFromFile(&FileName,
|
||||||
|
0,
|
||||||
|
&CmHive,
|
||||||
|
&Allocate,
|
||||||
|
0);
|
||||||
|
|
||||||
|
/* Setup the key name for the SECURITY hive */
|
||||||
|
RtlInitUnicodeString(&KeyName, REG_SEC_KEY_NAME);
|
||||||
|
|
||||||
|
Status = CmpLinkHiveToMaster(&KeyName,
|
||||||
|
NULL,
|
||||||
|
CmHive,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Connect the SOFTWARE hive */
|
||||||
|
wcscpy(EndPtr, REG_SOFTWARE_FILE_NAME);
|
||||||
|
RtlInitUnicodeString(&FileName, ConfigPath);
|
||||||
|
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
||||||
|
|
||||||
|
/* Load the hive */
|
||||||
|
Status = CmpInitHiveFromFile(&FileName,
|
||||||
|
0,
|
||||||
|
&CmHive,
|
||||||
|
&Allocate,
|
||||||
|
0);
|
||||||
|
|
||||||
|
/* Setup the key name for the SECURITY hive */
|
||||||
|
RtlInitUnicodeString (&KeyName, REG_SOFTWARE_KEY_NAME);
|
||||||
|
|
||||||
|
Status = CmpLinkHiveToMaster(&KeyName,
|
||||||
|
NULL,
|
||||||
|
CmHive,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/* Connect the SYSTEM hive only if it has been created */
|
/* Connect the SYSTEM hive only if it has been created */
|
||||||
if (SetupBoot == TRUE)
|
if (SetupBoot == TRUE)
|
||||||
{
|
{
|
||||||
wcscpy(EndPtr, REG_SYSTEM_FILE_NAME);
|
wcscpy(EndPtr, REG_SYSTEM_FILE_NAME);
|
||||||
|
RtlInitUnicodeString(&FileName, ConfigPath);
|
||||||
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
||||||
|
#if 0
|
||||||
RtlInitUnicodeString (&KeyName,
|
HANDLE PrimaryHandle, LogHandle;
|
||||||
REG_SYSTEM_KEY_NAME);
|
ULONG PrimaryDisposition, SecondaryDisposition;
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
ULONG ClusterSize, Length;
|
||||||
&KeyName,
|
|
||||||
OBJ_CASE_INSENSITIVE,
|
/* Build the file name */
|
||||||
NULL,
|
wcscpy(EndPtr, REG_SYSTEM_FILE_NAME);
|
||||||
NULL);
|
RtlInitUnicodeString(&FileName, ConfigPath);
|
||||||
|
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
||||||
RtlInitUnicodeString (&FileName,
|
|
||||||
ConfigPath);
|
/* Hive already exists */
|
||||||
Status = CmiLoadHive (&ObjectAttributes,
|
CmHive = CmpMachineHiveList[3].CmHive;
|
||||||
&FileName,
|
|
||||||
0);
|
/* Open the hive file and log */
|
||||||
if (!NT_SUCCESS(Status))
|
Status = CmpOpenHiveFiles(&FileName,
|
||||||
|
L".LOG",
|
||||||
|
&PrimaryHandle,
|
||||||
|
&LogHandle,
|
||||||
|
&PrimaryDisposition,
|
||||||
|
&SecondaryDisposition,
|
||||||
|
TRUE,
|
||||||
|
TRUE,
|
||||||
|
FALSE,
|
||||||
|
&ClusterSize);
|
||||||
|
if (!(NT_SUCCESS(Status)) || !(LogHandle))
|
||||||
{
|
{
|
||||||
DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status);
|
/* Bugcheck */
|
||||||
return Status;
|
KeBugCheck(BAD_SYSTEM_CONFIG_INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save the file handles */
|
||||||
|
CmHive->FileHandles[HFILE_TYPE_LOG] = LogHandle;
|
||||||
|
CmHive->FileHandles[HFILE_TYPE_PRIMARY] = PrimaryHandle;
|
||||||
|
|
||||||
|
/* Allow lazy flushing since the handles are there */
|
||||||
|
ASSERT(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH);
|
||||||
|
CmHive->Hive.HiveFlags &= ~HIVE_NOLAZYFLUSH;
|
||||||
|
|
||||||
|
/* Get the real size of the hive */
|
||||||
|
Length = CmHive->Hive.Storage[Stable].Length + HBLOCK_SIZE;
|
||||||
|
|
||||||
|
/* Check if the cluster size doesn't match */
|
||||||
|
if (CmHive->Hive.Cluster != ClusterSize) ASSERT(FALSE);
|
||||||
|
|
||||||
|
/* Set the file size */
|
||||||
|
if (!CmpFileSetSize((PHHIVE)CmHive, HFILE_TYPE_PRIMARY, Length, Length))
|
||||||
|
{
|
||||||
|
/* This shouldn't fail */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup the key name for the SECURITY hive */
|
||||||
|
RtlInitUnicodeString (&KeyName, REG_SYSTEM_KEY_NAME);
|
||||||
|
#else
|
||||||
|
/* Load the hive */
|
||||||
|
Status = CmpInitHiveFromFile(&FileName,
|
||||||
|
0,
|
||||||
|
&CmHive,
|
||||||
|
&Allocate,
|
||||||
|
0);
|
||||||
|
|
||||||
|
/* Setup the key name for the SECURITY hive */
|
||||||
|
RtlInitUnicodeString (&KeyName, REG_SYSTEM_KEY_NAME);
|
||||||
|
|
||||||
|
Status = CmpLinkHiveToMaster(&KeyName,
|
||||||
|
NULL,
|
||||||
|
CmHive,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
Status = CmiInitControlSetLink ();
|
Status = CmiInitControlSetLink ();
|
||||||
if (!NT_SUCCESS(Status))
|
#endif
|
||||||
{
|
|
||||||
DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Connect the SOFTWARE hive */
|
|
||||||
wcscpy(EndPtr, REG_SOFTWARE_FILE_NAME);
|
|
||||||
RtlInitUnicodeString (&FileName,
|
|
||||||
ConfigPath);
|
|
||||||
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
|
||||||
|
|
||||||
RtlInitUnicodeString (&KeyName,
|
|
||||||
REG_SOFTWARE_KEY_NAME);
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
&KeyName,
|
|
||||||
OBJ_CASE_INSENSITIVE,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
Status = CmiLoadHive (&ObjectAttributes,
|
|
||||||
&FileName,
|
|
||||||
0);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Connect the SAM hive */
|
|
||||||
wcscpy(EndPtr, REG_SAM_FILE_NAME);
|
|
||||||
RtlInitUnicodeString (&FileName,
|
|
||||||
ConfigPath);
|
|
||||||
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
|
||||||
|
|
||||||
RtlInitUnicodeString (&KeyName,
|
|
||||||
REG_SAM_KEY_NAME);
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
&KeyName,
|
|
||||||
OBJ_CASE_INSENSITIVE,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
Status = CmiLoadHive (&ObjectAttributes,
|
|
||||||
&FileName,
|
|
||||||
0);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Connect the SECURITY hive */
|
|
||||||
wcscpy(EndPtr, REG_SEC_FILE_NAME);
|
|
||||||
RtlInitUnicodeString (&FileName,
|
|
||||||
ConfigPath);
|
|
||||||
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
|
||||||
|
|
||||||
RtlInitUnicodeString (&KeyName,
|
|
||||||
REG_SEC_KEY_NAME);
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
&KeyName,
|
|
||||||
OBJ_CASE_INSENSITIVE,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
Status = CmiLoadHive (&ObjectAttributes,
|
|
||||||
&FileName,
|
|
||||||
0);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
|
|
||||||
return(Status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connect the DEFAULT hive */
|
/* Connect the DEFAULT hive */
|
||||||
wcscpy(EndPtr, REG_DEFAULT_USER_FILE_NAME);
|
wcscpy(EndPtr, REG_DEFAULT_USER_FILE_NAME);
|
||||||
RtlInitUnicodeString (&FileName,
|
RtlInitUnicodeString(&FileName, ConfigPath);
|
||||||
ConfigPath);
|
|
||||||
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
||||||
|
|
||||||
RtlInitUnicodeString (&KeyName,
|
/* Load the hive */
|
||||||
REG_DEFAULT_USER_KEY_NAME);
|
Status = CmpInitHiveFromFile(&FileName,
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
0,
|
||||||
&KeyName,
|
&CmHive,
|
||||||
OBJ_CASE_INSENSITIVE,
|
&Allocate,
|
||||||
NULL,
|
0);
|
||||||
NULL);
|
|
||||||
Status = CmiLoadHive (&ObjectAttributes,
|
|
||||||
&FileName,
|
|
||||||
0);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("CmiInitHives() done\n");
|
/* Setup the key name for the SECURITY hive */
|
||||||
|
RtlInitUnicodeString (&KeyName, REG_DEFAULT_USER_KEY_NAME);
|
||||||
|
|
||||||
|
Status = CmpLinkHiveToMaster(&KeyName,
|
||||||
|
NULL,
|
||||||
|
CmHive,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
/* Connect the SAM hive */
|
||||||
|
wcscpy(EndPtr, REG_SAM_FILE_NAME);
|
||||||
|
RtlInitUnicodeString(&FileName, ConfigPath);
|
||||||
|
DPRINT ("ConfigPath: %S\n", ConfigPath);
|
||||||
|
|
||||||
|
/* Load the hive */
|
||||||
|
Status = CmpInitHiveFromFile(&FileName,
|
||||||
|
0,
|
||||||
|
&CmHive,
|
||||||
|
&Allocate,
|
||||||
|
0);
|
||||||
|
|
||||||
|
/* Setup the key name for the SECURITY hive */
|
||||||
|
RtlInitUnicodeString(&KeyName, REG_SAM_KEY_NAME);
|
||||||
|
Status = CmpLinkHiveToMaster(&KeyName,
|
||||||
|
NULL,
|
||||||
|
CmHive,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -838,22 +838,20 @@ CmiGetLinkTarget(PCMHIVE RegistryHive,
|
||||||
UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
|
UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
|
||||||
PCM_KEY_VALUE ValueCell;
|
PCM_KEY_VALUE ValueCell;
|
||||||
PVOID DataCell;
|
PVOID DataCell;
|
||||||
NTSTATUS Status;
|
HCELL_INDEX Cell;
|
||||||
|
|
||||||
DPRINT("CmiGetLinkTarget() called\n");
|
DPRINT("CmiGetLinkTarget() called\n");
|
||||||
|
|
||||||
/* Get Value block of interest */
|
/* Find the cell */
|
||||||
Status = CmiScanKeyForValue(RegistryHive,
|
Cell = CmpFindValueByName(&RegistryHive->Hive, KeyCell, &LinkName);
|
||||||
KeyCell,
|
if (Cell == HCELL_NIL)
|
||||||
&LinkName,
|
|
||||||
&ValueCell,
|
|
||||||
NULL);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
DPRINT1("CmiScanKeyForValue() failed (Status %lx)\n", Status);
|
DPRINT1("CmiScanKeyForValue() failed\n");
|
||||||
return(Status);
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the cell data */
|
||||||
|
ValueCell = (PCM_KEY_VALUE)HvGetCell(&RegistryHive->Hive, Cell);
|
||||||
if (ValueCell->Type != REG_LINK)
|
if (ValueCell->Type != REG_LINK)
|
||||||
{
|
{
|
||||||
DPRINT1("Type != REG_LINK\n!");
|
DPRINT1("Type != REG_LINK\n!");
|
||||||
|
|
|
@ -85,12 +85,17 @@
|
||||||
//
|
//
|
||||||
#define MAXIMUM_CACHED_DATA 2 * PAGE_SIZE
|
#define MAXIMUM_CACHED_DATA 2 * PAGE_SIZE
|
||||||
|
|
||||||
|
//
|
||||||
|
// Hives to load on startup
|
||||||
|
//
|
||||||
|
#define CM_NUMBER_OF_MACHINE_HIVES 6
|
||||||
|
|
||||||
//
|
//
|
||||||
// Number of items that can fit inside an Allocation Page
|
// Number of items that can fit inside an Allocation Page
|
||||||
//
|
//
|
||||||
#define CM_KCBS_PER_PAGE \
|
#define CM_KCBS_PER_PAGE \
|
||||||
PAGE_SIZE / sizeof(CM_KEY_CONTROL_BLOCK)
|
PAGE_SIZE / sizeof(CM_KEY_CONTROL_BLOCK)
|
||||||
#define CM_DELAYS_PER_PAGE \
|
#define CM_DELAYS_PER_PAGE \
|
||||||
PAGE_SIZE / sizeof(CM_DELAYED_CLOSE_ENTRY)
|
PAGE_SIZE / sizeof(CM_DELAYED_CLOSE_ENTRY)
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -429,9 +434,8 @@ typedef struct _CM_CACHED_VALUE
|
||||||
//
|
//
|
||||||
typedef struct _HIVE_LIST_ENTRY
|
typedef struct _HIVE_LIST_ENTRY
|
||||||
{
|
{
|
||||||
PWCHAR FileName;
|
PWSTR Name;
|
||||||
PWCHAR BaseName;
|
PWSTR BaseName;
|
||||||
PWCHAR RegRootName;
|
|
||||||
PCMHIVE CmHive;
|
PCMHIVE CmHive;
|
||||||
ULONG HHiveFlags;
|
ULONG HHiveFlags;
|
||||||
ULONG CmHiveFlags;
|
ULONG CmHiveFlags;
|
||||||
|
@ -439,7 +443,6 @@ typedef struct _HIVE_LIST_ENTRY
|
||||||
BOOLEAN ThreadFinished;
|
BOOLEAN ThreadFinished;
|
||||||
BOOLEAN ThreadStarted;
|
BOOLEAN ThreadStarted;
|
||||||
BOOLEAN Allocate;
|
BOOLEAN Allocate;
|
||||||
BOOLEAN WinPERequired;
|
|
||||||
} HIVE_LIST_ENTRY, *PHIVE_LIST_ENTRY;
|
} HIVE_LIST_ENTRY, *PHIVE_LIST_ENTRY;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -759,6 +762,12 @@ CmpInitHiveFromFile(
|
||||||
IN ULONG CheckFlags
|
IN ULONG CheckFlags
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CmpInitializeHiveList(
|
||||||
|
IN USHORT Flag
|
||||||
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Registry Utility Functions
|
// Registry Utility Functions
|
||||||
//
|
//
|
||||||
|
@ -956,7 +965,7 @@ CmpGetNextName(
|
||||||
);
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Flush Routines
|
// Command Routines (Flush, Open, Close, Init);
|
||||||
//
|
//
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -976,6 +985,16 @@ CmpCmdInit(
|
||||||
IN BOOLEAN SetupBoot
|
IN BOOLEAN SetupBoot
|
||||||
);
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmpCmdHiveOpen(
|
||||||
|
IN POBJECT_ATTRIBUTES FileAttributes,
|
||||||
|
IN PSECURITY_CLIENT_CONTEXT ImpersonationContext,
|
||||||
|
IN OUT PBOOLEAN Allocate,
|
||||||
|
OUT PCMHIVE *NewHive,
|
||||||
|
IN ULONG CheckFlags
|
||||||
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
CmpLazyFlush(
|
CmpLazyFlush(
|
||||||
|
@ -1351,7 +1370,7 @@ extern CM_SYSTEM_CONTROL_VECTOR CmControlVector[];
|
||||||
extern ULONG CmpConfigurationAreaSize;
|
extern ULONG CmpConfigurationAreaSize;
|
||||||
extern PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData;
|
extern PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData;
|
||||||
extern UNICODE_STRING CmTypeName[];
|
extern UNICODE_STRING CmTypeName[];
|
||||||
extern HIVE_LIST_ENTRY CmpMachineHiveList[5];
|
extern HIVE_LIST_ENTRY CmpMachineHiveList[];
|
||||||
extern UNICODE_STRING CmSymbolicLinkValueName;
|
extern UNICODE_STRING CmSymbolicLinkValueName;
|
||||||
extern UNICODE_STRING CmpSystemStartOptions;
|
extern UNICODE_STRING CmpSystemStartOptions;
|
||||||
extern UNICODE_STRING CmpLoadOptions;
|
extern UNICODE_STRING CmpLoadOptions;
|
||||||
|
|
|
@ -13,9 +13,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
CmiFlushRegistryHive(PCMHIVE RegistryHive);
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
@ -892,7 +889,7 @@ CmpQueryKeyData(IN PHHIVE Hive,
|
||||||
Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen;
|
Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen;
|
||||||
Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen;
|
Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen;
|
||||||
Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen;
|
Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen;
|
||||||
Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
|
Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
|
||||||
|
|
||||||
/* Check if we have a class */
|
/* Check if we have a class */
|
||||||
if (Node->ClassLength > 0)
|
if (Node->ClassLength > 0)
|
||||||
|
@ -1202,3 +1199,121 @@ CmFlushKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||||
/* Return the status */
|
/* Return the status */
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey,
|
||||||
|
IN POBJECT_ATTRIBUTES SourceFile,
|
||||||
|
IN ULONG Flags,
|
||||||
|
IN PKEY_OBJECT KeyBody)
|
||||||
|
{
|
||||||
|
SECURITY_QUALITY_OF_SERVICE ServiceQos;
|
||||||
|
SECURITY_CLIENT_CONTEXT ClientSecurityContext;
|
||||||
|
HANDLE KeyHandle;
|
||||||
|
BOOLEAN Allocate = TRUE;
|
||||||
|
PCMHIVE CmHive;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Check if we have a trust key */
|
||||||
|
if (KeyBody)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
DPRINT1("Trusted classes not yet supported\n");
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a service QoS for a security context */
|
||||||
|
ServiceQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
||||||
|
ServiceQos.ImpersonationLevel = SecurityImpersonation;
|
||||||
|
ServiceQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
||||||
|
ServiceQos.EffectiveOnly = TRUE;
|
||||||
|
Status = SeCreateClientSecurity(PsGetCurrentThread(),
|
||||||
|
&ServiceQos,
|
||||||
|
FALSE,
|
||||||
|
&ClientSecurityContext);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
DPRINT1("Security context failed\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the target key */
|
||||||
|
Status = ZwOpenKey(&KeyHandle, KEY_READ, TargetKey);
|
||||||
|
if (!NT_SUCCESS(Status)) KeyHandle = NULL;
|
||||||
|
|
||||||
|
/* Open the hive */
|
||||||
|
Status = CmpCmdHiveOpen(SourceFile,
|
||||||
|
&ClientSecurityContext,
|
||||||
|
&Allocate,
|
||||||
|
&CmHive,
|
||||||
|
0);
|
||||||
|
|
||||||
|
/* Get rid of the security context */
|
||||||
|
SeDeleteClientSecurity(&ClientSecurityContext);
|
||||||
|
|
||||||
|
/* See if we failed */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* See if the target already existed */
|
||||||
|
if (KeyHandle)
|
||||||
|
{
|
||||||
|
/* Lock the registry */
|
||||||
|
CmpLockRegistryExclusive();
|
||||||
|
|
||||||
|
/* FIXME: Check if we are already loaded */
|
||||||
|
|
||||||
|
/* Release the registry */
|
||||||
|
CmpUnlockRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the key handle if we had one */
|
||||||
|
if (KeyHandle) ZwClose(KeyHandle);
|
||||||
|
DPRINT1("Failed: %lx\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock the registry shared */
|
||||||
|
//CmpLockRegistry();
|
||||||
|
|
||||||
|
/* Lock the hive to this thread */
|
||||||
|
CmHive->Hive.HiveFlags |= HIVE_IS_UNLOADING;
|
||||||
|
CmHive->CreatorOwner = KeGetCurrentThread();
|
||||||
|
|
||||||
|
/* Set flag */
|
||||||
|
if (Flags & REG_NO_LAZY_FLUSH) CmHive->Hive.HiveFlags |= HIVE_NOLAZYFLUSH;
|
||||||
|
|
||||||
|
/* Link the hive */
|
||||||
|
Status = CmpLinkHiveToMaster(TargetKey->ObjectName,
|
||||||
|
TargetKey->RootDirectory,
|
||||||
|
CmHive,
|
||||||
|
FALSE,
|
||||||
|
TargetKey->SecurityDescriptor);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* FIXME: Add to HiveList key */
|
||||||
|
|
||||||
|
/* Sync the hive if necessary */
|
||||||
|
if (Allocate)
|
||||||
|
{
|
||||||
|
/* Sync it */
|
||||||
|
HvSyncHive(&CmHive->Hive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the hive */
|
||||||
|
CmHive->Hive.HiveFlags &= ~HIVE_IS_UNLOADING;
|
||||||
|
CmHive->CreatorOwner = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FIXME: TODO */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock the registry */
|
||||||
|
//CmpUnlockRegistry();
|
||||||
|
|
||||||
|
/* Close handle and return */
|
||||||
|
if (KeyHandle) ZwClose(KeyHandle);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,16 @@ PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData;
|
||||||
|
|
||||||
EX_PUSH_LOCK CmpHiveListHeadLock, CmpLoadHiveLock;
|
EX_PUSH_LOCK CmpHiveListHeadLock, CmpLoadHiveLock;
|
||||||
|
|
||||||
HIVE_LIST_ENTRY CmpMachineHiveList[5];
|
HIVE_LIST_ENTRY CmpMachineHiveList[] =
|
||||||
|
{
|
||||||
|
{ L"HARDWARE", L"MACHINE\\", NULL, HIVE_VOLATILE , 0 , NULL, FALSE, FALSE, FALSE},
|
||||||
|
{ L"SECURITY", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},
|
||||||
|
{ L"SOFTWARE", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},
|
||||||
|
{ L"SYSTEM", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},
|
||||||
|
{ L"DEFAULT", L"USER\\.DEFAULT", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},
|
||||||
|
{ L"SAM", L"MACHINE\\", NULL, HIVE_NOLAZYFLUSH , 0 , NULL, FALSE, FALSE, FALSE},
|
||||||
|
{ NULL, NULL, 0, 0 , 0 , NULL, FALSE, FALSE, FALSE}
|
||||||
|
};
|
||||||
|
|
||||||
UNICODE_STRING CmSymbolicLinkValueName =
|
UNICODE_STRING CmSymbolicLinkValueName =
|
||||||
RTL_CONSTANT_STRING(L"SymbolicLinkValue");
|
RTL_CONSTANT_STRING(L"SymbolicLinkValue");
|
||||||
|
|
|
@ -238,6 +238,56 @@ CmpCmdInit(IN BOOLEAN SetupBoot)
|
||||||
|
|
||||||
/* Testing: Force Lazy Flushing */
|
/* Testing: Force Lazy Flushing */
|
||||||
CmpHoldLazyFlush = FALSE;
|
CmpHoldLazyFlush = FALSE;
|
||||||
|
|
||||||
|
/* Setup the hive list */
|
||||||
|
CmpInitializeHiveList(SetupBoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmpCmdHiveOpen(IN POBJECT_ATTRIBUTES FileAttributes,
|
||||||
|
IN PSECURITY_CLIENT_CONTEXT ImpersonationContext,
|
||||||
|
IN OUT PBOOLEAN Allocate,
|
||||||
|
OUT PCMHIVE *NewHive,
|
||||||
|
IN ULONG CheckFlags)
|
||||||
|
{
|
||||||
|
PUNICODE_STRING FileName;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Open the file in the current security context */
|
||||||
|
FileName = FileAttributes->ObjectName;
|
||||||
|
Status = CmpInitHiveFromFile(FileName,
|
||||||
|
0,
|
||||||
|
NewHive,
|
||||||
|
Allocate,
|
||||||
|
CheckFlags);
|
||||||
|
if (((Status == STATUS_ACCESS_DENIED) ||
|
||||||
|
(Status == STATUS_NO_SUCH_USER) ||
|
||||||
|
(Status == STATUS_WRONG_PASSWORD) ||
|
||||||
|
(Status == STATUS_ACCOUNT_EXPIRED) ||
|
||||||
|
(Status == STATUS_ACCOUNT_DISABLED) ||
|
||||||
|
(Status == STATUS_ACCOUNT_RESTRICTION)) &&
|
||||||
|
(ImpersonationContext))
|
||||||
|
{
|
||||||
|
/* We failed due to an account/security error, impersonate SYSTEM */
|
||||||
|
Status = SeImpersonateClientEx(ImpersonationContext, NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Now try again */
|
||||||
|
Status = CmpInitHiveFromFile(FileName,
|
||||||
|
0,
|
||||||
|
NewHive,
|
||||||
|
Allocate,
|
||||||
|
CheckFlags);
|
||||||
|
|
||||||
|
/* Restore impersonation token */
|
||||||
|
PsRevertToSelf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return status of open attempt */
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -416,3 +416,299 @@ Exit:
|
||||||
ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);
|
ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmpDoOpen(IN PHHIVE Hive,
|
||||||
|
IN HCELL_INDEX Cell,
|
||||||
|
IN PCM_KEY_NODE Node,
|
||||||
|
IN PACCESS_STATE AccessState,
|
||||||
|
IN KPROCESSOR_MODE AccessMode,
|
||||||
|
IN ULONG Attributes,
|
||||||
|
IN PCM_PARSE_CONTEXT Context OPTIONAL,
|
||||||
|
IN ULONG ControlFlags,
|
||||||
|
IN OUT PCM_KEY_CONTROL_BLOCK *CachedKcb,
|
||||||
|
IN PUNICODE_STRING KeyName,
|
||||||
|
OUT PVOID *Object)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PKEY_OBJECT KeyBody = NULL;
|
||||||
|
PCM_KEY_CONTROL_BLOCK Kcb = NULL;
|
||||||
|
|
||||||
|
/* Make sure the hive isn't locked */
|
||||||
|
if ((Hive->HiveFlags & HIVE_IS_UNLOADING) &&
|
||||||
|
(((PCMHIVE)Hive)->CreatorOwner != KeGetCurrentThread()))
|
||||||
|
{
|
||||||
|
/* It is, don't touch it */
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have a KCB, make sure it's locked */
|
||||||
|
ASSERT(CmpIsKcbLockedExclusive(*CachedKcb));
|
||||||
|
|
||||||
|
/* Create the KCB */
|
||||||
|
Kcb = CmpCreateKeyControlBlock(Hive, Cell, Node, *CachedKcb, 0, KeyName);
|
||||||
|
if (!Kcb) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
/* Make sure it's also locked, and set the pointer */
|
||||||
|
ASSERT(CmpIsKcbLockedExclusive(Kcb));
|
||||||
|
*CachedKcb = Kcb;
|
||||||
|
|
||||||
|
/* Allocate the key object */
|
||||||
|
Status = ObCreateObject(AccessMode,
|
||||||
|
CmpKeyObjectType,
|
||||||
|
NULL,
|
||||||
|
AccessMode,
|
||||||
|
NULL,
|
||||||
|
sizeof(KEY_OBJECT),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
Object);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Get the key body and fill it out */
|
||||||
|
KeyBody = (PKEY_OBJECT)(*Object);
|
||||||
|
KeyBody->KeyControlBlock = Kcb;
|
||||||
|
KeyBody->SubKeyCounts = 0;
|
||||||
|
KeyBody->SubKeys = NULL;
|
||||||
|
KeyBody->SizeOfSubKeys = 0;
|
||||||
|
InsertTailList(&CmiKeyObjectListHead, &KeyBody->KeyBodyList);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Failed, dereference the KCB */
|
||||||
|
CmpDereferenceKeyControlBlockWithLock(Kcb, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove calls to CmCreateRootNode once this is used! */
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmpCreateLinkNode(IN PHHIVE Hive,
|
||||||
|
IN HCELL_INDEX Cell,
|
||||||
|
IN PACCESS_STATE AccessState,
|
||||||
|
IN UNICODE_STRING Name,
|
||||||
|
IN KPROCESSOR_MODE AccessMode,
|
||||||
|
IN ULONG CreateOptions,
|
||||||
|
IN PCM_PARSE_CONTEXT Context,
|
||||||
|
IN PCM_KEY_CONTROL_BLOCK ParentKcb,
|
||||||
|
OUT PVOID *Object)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
HCELL_INDEX KeyCell, LinkCell, ChildCell;
|
||||||
|
PKEY_OBJECT KeyBody;
|
||||||
|
LARGE_INTEGER TimeStamp;
|
||||||
|
PCM_KEY_NODE KeyNode;
|
||||||
|
PCM_KEY_CONTROL_BLOCK Kcb = ParentKcb;
|
||||||
|
|
||||||
|
/* Link nodes only allowed on the master */
|
||||||
|
if (Hive != &CmiVolatileHive->Hive)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
DPRINT1("Invalid link node attempt\n");
|
||||||
|
return STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Acquire the flusher locks */
|
||||||
|
ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock);
|
||||||
|
ExAcquirePushLockShared((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock);
|
||||||
|
|
||||||
|
/* Check if the parent is being deleted */
|
||||||
|
if (ParentKcb->Delete)
|
||||||
|
{
|
||||||
|
/* It is, quit */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a link node */
|
||||||
|
LinkCell = HvAllocateCell(Hive,
|
||||||
|
FIELD_OFFSET(CM_KEY_NODE, Name) +
|
||||||
|
CmpNameSize(Hive, &Name),
|
||||||
|
Stable,
|
||||||
|
HCELL_NIL);
|
||||||
|
if (LinkCell == HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the key cell */
|
||||||
|
KeyCell = Context->ChildHive.KeyCell;
|
||||||
|
if (KeyCell != HCELL_NIL)
|
||||||
|
{
|
||||||
|
/* Hive exists! */
|
||||||
|
ChildCell = KeyCell;
|
||||||
|
|
||||||
|
/* Get the node data */
|
||||||
|
KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, ChildCell);
|
||||||
|
if (!KeyNode)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill out the data */
|
||||||
|
KeyNode->Parent = LinkCell;
|
||||||
|
KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
|
||||||
|
HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
|
||||||
|
|
||||||
|
/* Now open the key cell */
|
||||||
|
KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, KeyCell);
|
||||||
|
if (!KeyNode)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the parent */
|
||||||
|
Status = CmpDoOpen(Context->ChildHive.KeyHive,
|
||||||
|
KeyCell,
|
||||||
|
KeyNode,
|
||||||
|
AccessState,
|
||||||
|
AccessMode,
|
||||||
|
CreateOptions,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&Kcb,
|
||||||
|
&Name,
|
||||||
|
Object);
|
||||||
|
HvReleaseCell(Context->ChildHive.KeyHive, KeyCell);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Do the actual create operation */
|
||||||
|
Status = CmpDoCreateChild(Context->ChildHive.KeyHive,
|
||||||
|
Cell,
|
||||||
|
NULL,
|
||||||
|
AccessState,
|
||||||
|
&Name,
|
||||||
|
AccessMode,
|
||||||
|
&Context->Class,
|
||||||
|
ParentKcb,
|
||||||
|
KEY_HIVE_ENTRY | KEY_NO_DELETE,
|
||||||
|
&ChildCell,
|
||||||
|
Object);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Setup root pointer */
|
||||||
|
Context->ChildHive.KeyHive->BaseBlock->RootCell = ChildCell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if open or create suceeded */
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Mark the cell dirty */
|
||||||
|
HvMarkCellDirty(Context->ChildHive.KeyHive, ChildCell, FALSE);
|
||||||
|
|
||||||
|
/* Get the key node */
|
||||||
|
KeyNode = HvGetCell(Context->ChildHive.KeyHive, ChildCell);
|
||||||
|
if (!KeyNode)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release it */
|
||||||
|
HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
|
||||||
|
|
||||||
|
/* Set the parent adn flags */
|
||||||
|
KeyNode->Parent = LinkCell;
|
||||||
|
KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
|
||||||
|
|
||||||
|
/* Get the link node */
|
||||||
|
KeyNode = HvGetCell(Hive, LinkCell);
|
||||||
|
if (!KeyNode)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set it up */
|
||||||
|
KeyNode->Signature = CM_LINK_NODE_SIGNATURE;
|
||||||
|
KeyNode->Flags = KEY_HIVE_EXIT | KEY_NO_DELETE;
|
||||||
|
KeyNode->Parent = Cell;
|
||||||
|
KeyNode->NameLength = CmpCopyName(Hive, KeyNode->Name, &Name);
|
||||||
|
if (KeyNode->NameLength < Name.Length) KeyNode->Flags |= KEY_COMP_NAME;
|
||||||
|
KeQuerySystemTime(&TimeStamp);
|
||||||
|
KeyNode->LastWriteTime = TimeStamp;
|
||||||
|
|
||||||
|
/* Clear out the rest */
|
||||||
|
KeyNode->SubKeyCounts[Stable] = 0;
|
||||||
|
KeyNode->SubKeyCounts[Volatile] = 0;
|
||||||
|
KeyNode->SubKeyLists[Stable] = HCELL_NIL;
|
||||||
|
KeyNode->SubKeyLists[Volatile] = HCELL_NIL;
|
||||||
|
KeyNode->ValueList.Count = 0;
|
||||||
|
KeyNode->ValueList.List = HCELL_NIL;
|
||||||
|
KeyNode->ClassLength = 0;
|
||||||
|
|
||||||
|
/* Reference the root node */
|
||||||
|
//KeyNode->ChildHiveReference.KeyHive = Context->ChildHive.KeyHive;
|
||||||
|
//KeyNode->ChildHiveReference.KeyCell = ChildCell;
|
||||||
|
HvReleaseCell(Hive, LinkCell);
|
||||||
|
|
||||||
|
/* Get the parent node */
|
||||||
|
KeyNode = HvGetCell(Hive, Cell);
|
||||||
|
if (!KeyNode)
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now add the subkey */
|
||||||
|
if (!CmpAddSubKey(Hive, Cell, LinkCell))
|
||||||
|
{
|
||||||
|
/* Failure! We don't handle this yet! */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the key body */
|
||||||
|
KeyBody = (PKEY_OBJECT)*Object;
|
||||||
|
|
||||||
|
/* Sanity checks */
|
||||||
|
ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell);
|
||||||
|
ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive);
|
||||||
|
//ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);
|
||||||
|
|
||||||
|
/* Update the timestamp */
|
||||||
|
KeQuerySystemTime(&TimeStamp);
|
||||||
|
KeyNode->LastWriteTime = TimeStamp;
|
||||||
|
|
||||||
|
/* Check if we need to update name maximum */
|
||||||
|
if (KeyNode->MaxNameLen < Name.Length)
|
||||||
|
{
|
||||||
|
/* Do it */
|
||||||
|
KeyNode->MaxNameLen = Name.Length;
|
||||||
|
KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we need toupdate class length maximum */
|
||||||
|
if (KeyNode->MaxClassLen < Context->Class.Length)
|
||||||
|
{
|
||||||
|
/* Update it */
|
||||||
|
KeyNode->MaxClassLen = Context->Class.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Exit:
|
||||||
|
/* Release the flusher locks and return status */
|
||||||
|
ExReleasePushLock((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock);
|
||||||
|
ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
KGUARDED_MUTEX CmpSelfHealQueueLock;
|
KGUARDED_MUTEX CmpSelfHealQueueLock;
|
||||||
LIST_ENTRY CmpSelfHealQueueListHead;
|
LIST_ENTRY CmpSelfHealQueueListHead;
|
||||||
|
KEVENT CmpLoadWorkerEvent;
|
||||||
|
LONG CmpLoadWorkerIncrement;
|
||||||
PEPROCESS CmpSystemProcess;
|
PEPROCESS CmpSystemProcess;
|
||||||
BOOLEAN HvShutdownComplete;
|
BOOLEAN HvShutdownComplete;
|
||||||
PVOID CmpRegistryLockCallerCaller, CmpRegistryLockCaller;
|
PVOID CmpRegistryLockCallerCaller, CmpRegistryLockCaller;
|
||||||
|
@ -496,11 +498,11 @@ CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
/* Create it */
|
/* Create it */
|
||||||
Status = CmpInitializeHive((PCMHIVE*)&SystemHive,
|
#if 0
|
||||||
|
Status = CmpInitializeHive(&SystemHive,
|
||||||
HINIT_CREATE,
|
HINIT_CREATE,
|
||||||
HIVE_NOLAZYFLUSH,
|
0, //HIVE_NOLAZYFLUSH,
|
||||||
HFILE_TYPE_LOG,
|
HFILE_TYPE_LOG,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -509,8 +511,10 @@ CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
&HiveName,
|
&HiveName,
|
||||||
0);
|
0);
|
||||||
if (!NT_SUCCESS(Status)) return FALSE;
|
if (!NT_SUCCESS(Status)) return FALSE;
|
||||||
|
|
||||||
|
/* Set the hive filename */
|
||||||
|
RtlCreateUnicodeString(&SystemHive->FileFullPath, SYSTEM_REG_FILE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Tell CmpLinkHiveToMaster to allocate a hive */
|
/* Tell CmpLinkHiveToMaster to allocate a hive */
|
||||||
Allocate = TRUE;
|
Allocate = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -746,6 +750,314 @@ CmpCreateRegistryRoot(VOID)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CmpLoadHiveThread(IN PVOID StartContext)
|
||||||
|
{
|
||||||
|
WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH];
|
||||||
|
UNICODE_STRING TempName, FileName, RegName;
|
||||||
|
ULONG FileStart, RegStart, i, ErrorResponse, ClusterSize, WorkerCount;
|
||||||
|
ULONG PrimaryDisposition, SecondaryDisposition, Length;
|
||||||
|
PCMHIVE CmHive;
|
||||||
|
HANDLE PrimaryHandle, LogHandle;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PVOID ErrorParameters;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Get the hive index, make sure it makes sense */
|
||||||
|
i = (ULONG)StartContext;
|
||||||
|
ASSERT(CmpMachineHiveList[i].Name != NULL);
|
||||||
|
DPRINT1("[HiveLoad] Parallel Thread: %d\n", i);
|
||||||
|
|
||||||
|
/* We were started */
|
||||||
|
CmpMachineHiveList[i].ThreadStarted = TRUE;
|
||||||
|
|
||||||
|
/* Build the file name and registry name strings */
|
||||||
|
RtlInitEmptyUnicodeString(&FileName, FileBuffer, MAX_PATH);
|
||||||
|
RtlInitEmptyUnicodeString(&RegName, RegBuffer, MAX_PATH);
|
||||||
|
|
||||||
|
/* Now build the system root path */
|
||||||
|
RtlInitUnicodeString(&TempName, L"\\SystemRoot\\System32\\Config\\");
|
||||||
|
RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName);
|
||||||
|
FileStart = FileName.Length;
|
||||||
|
|
||||||
|
/* And build the registry root path */
|
||||||
|
RtlInitUnicodeString(&TempName, L"\\REGISTRY\\");
|
||||||
|
RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
|
||||||
|
RegStart = RegName.Length;
|
||||||
|
|
||||||
|
/* Build the base name */
|
||||||
|
RegName.Length = RegStart;
|
||||||
|
RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName);
|
||||||
|
RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
|
||||||
|
|
||||||
|
/* Check if this is a child of the root */
|
||||||
|
if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == '\\')
|
||||||
|
{
|
||||||
|
/* Then setup the whole name */
|
||||||
|
RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);
|
||||||
|
RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now Add tge rest if the file name */
|
||||||
|
RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);
|
||||||
|
FileName.Length = FileStart;
|
||||||
|
RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName);
|
||||||
|
if (!CmpMachineHiveList[i].CmHive)
|
||||||
|
{
|
||||||
|
/* We need to allocate a ne whive structure */
|
||||||
|
CmpMachineHiveList[i].Allocate = TRUE;
|
||||||
|
|
||||||
|
/* Load the hive file */
|
||||||
|
DPRINT1("[HiveLoad]: Load from file %wZ\n", &FileName);
|
||||||
|
CmpMachineHiveList[i].CmHive2 = (PVOID)0xBAADBEEF;
|
||||||
|
goto Later;
|
||||||
|
Status = CmpInitHiveFromFile(&FileName,
|
||||||
|
CmpMachineHiveList[i].HHiveFlags,
|
||||||
|
&CmHive,
|
||||||
|
&CmpMachineHiveList[i].Allocate,
|
||||||
|
0);
|
||||||
|
if (!(NT_SUCCESS(Status)) || !(CmHive->FileHandles[HFILE_TYPE_LOG]))
|
||||||
|
{
|
||||||
|
/* We failed or couldn't get a log file, raise a hard error */
|
||||||
|
ErrorParameters = &FileName;
|
||||||
|
NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
(PULONG_PTR)&ErrorParameters,
|
||||||
|
OptionOk,
|
||||||
|
&ErrorResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the hive flags and newly allocated hive pointer */
|
||||||
|
CmHive->Flags = CmpMachineHiveList[i].CmHiveFlags;
|
||||||
|
CmpMachineHiveList[i].CmHive2 = CmHive;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We already have a hive, is it volatile? */
|
||||||
|
CmHive = CmpMachineHiveList[i].CmHive;
|
||||||
|
if (!(CmHive->Hive.HiveFlags & HIVE_VOLATILE))
|
||||||
|
{
|
||||||
|
DPRINT1("[HiveLoad]: Open from file %wZ\n", &FileName);
|
||||||
|
CmpMachineHiveList[i].CmHive2 = CmHive;
|
||||||
|
goto Later;
|
||||||
|
|
||||||
|
/* It's now, open the hive file and log */
|
||||||
|
Status = CmpOpenHiveFiles(&FileName,
|
||||||
|
L".LOG",
|
||||||
|
&PrimaryHandle,
|
||||||
|
&LogHandle,
|
||||||
|
&PrimaryDisposition,
|
||||||
|
&SecondaryDisposition,
|
||||||
|
TRUE,
|
||||||
|
TRUE,
|
||||||
|
FALSE,
|
||||||
|
&ClusterSize);
|
||||||
|
if (!(NT_SUCCESS(Status)) || !(LogHandle))
|
||||||
|
{
|
||||||
|
/* Couldn't open the hive or its log file, raise a hard error */
|
||||||
|
ErrorParameters = &FileName;
|
||||||
|
NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
(PULONG_PTR)&ErrorParameters,
|
||||||
|
OptionOk,
|
||||||
|
&ErrorResponse);
|
||||||
|
|
||||||
|
/* And bugcheck for posterity's sake */
|
||||||
|
KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 9, 0, i, Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the file handles. This should remove our sync hacks */
|
||||||
|
CmHive->FileHandles[HFILE_TYPE_LOG] = LogHandle;
|
||||||
|
CmHive->FileHandles[HFILE_TYPE_PRIMARY] = PrimaryHandle;
|
||||||
|
|
||||||
|
/* Allow lazy flushing since the handles are there -- remove sync hacks */
|
||||||
|
ASSERT(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH);
|
||||||
|
CmHive->Hive.HiveFlags &= ~HIVE_NOLAZYFLUSH;
|
||||||
|
|
||||||
|
/* Get the real size of the hive */
|
||||||
|
Length = CmHive->Hive.Storage[Stable].Length + HBLOCK_SIZE;
|
||||||
|
|
||||||
|
/* Check if the cluster size doesn't match */
|
||||||
|
if (CmHive->Hive.Cluster != ClusterSize) ASSERT(FALSE);
|
||||||
|
|
||||||
|
/* Set the file size */
|
||||||
|
if (!CmpFileSetSize((PHHIVE)CmHive, HFILE_TYPE_PRIMARY, Length, Length))
|
||||||
|
{
|
||||||
|
/* This shouldn't fail */
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Another thing we don't support is NTLDR-recovery */
|
||||||
|
if (CmHive->Hive.BaseBlock->BootRecover) ASSERT(FALSE);
|
||||||
|
|
||||||
|
/* Finally, set our allocated hive to the same hive we've had */
|
||||||
|
CmpMachineHiveList[i].CmHive2 = CmHive;
|
||||||
|
ASSERT(CmpMachineHiveList[i].CmHive == CmpMachineHiveList[i].CmHive2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We're done */
|
||||||
|
Later:
|
||||||
|
CmpMachineHiveList[i].ThreadFinished = TRUE;
|
||||||
|
|
||||||
|
/* Check if we're the last worker */
|
||||||
|
WorkerCount = InterlockedIncrement(&CmpLoadWorkerIncrement);
|
||||||
|
if (WorkerCount == CM_NUMBER_OF_MACHINE_HIVES)
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Signal the event */
|
||||||
|
KeSetEvent(&CmpLoadWorkerEvent, 0, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Kill the thread */
|
||||||
|
PsTerminateSystemThread(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CmpInitializeHiveList(IN USHORT Flag)
|
||||||
|
{
|
||||||
|
WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH];
|
||||||
|
UNICODE_STRING TempName, FileName, RegName;
|
||||||
|
HANDLE Thread;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG FileStart, RegStart, i;
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Allow writing for now */
|
||||||
|
CmpNoWrite = FALSE;
|
||||||
|
|
||||||
|
/* Build the file name and registry name strings */
|
||||||
|
RtlInitEmptyUnicodeString(&FileName, FileBuffer, MAX_PATH);
|
||||||
|
RtlInitEmptyUnicodeString(&RegName, RegBuffer, MAX_PATH);
|
||||||
|
|
||||||
|
/* Now build the system root path */
|
||||||
|
RtlInitUnicodeString(&TempName, L"\\SystemRoot\\System32\\Config\\");
|
||||||
|
RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName);
|
||||||
|
FileStart = FileName.Length;
|
||||||
|
|
||||||
|
/* And build the registry root path */
|
||||||
|
RtlInitUnicodeString(&TempName, L"\\REGISTRY\\");
|
||||||
|
RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
|
||||||
|
RegStart = RegName.Length;
|
||||||
|
|
||||||
|
/* Setup the event to synchronize workers */
|
||||||
|
KeInitializeEvent(&CmpLoadWorkerEvent, SynchronizationEvent, FALSE);
|
||||||
|
|
||||||
|
/* Enter special boot condition */
|
||||||
|
CmpSpecialBootCondition = TRUE;
|
||||||
|
|
||||||
|
/* Create the SD for the root hives */
|
||||||
|
SecurityDescriptor = CmpHiveRootSecurityDescriptor();
|
||||||
|
|
||||||
|
/* Loop every hive we care about */
|
||||||
|
for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++)
|
||||||
|
{
|
||||||
|
/* Make sure the list is setup */
|
||||||
|
ASSERT(CmpMachineHiveList[i].Name != NULL);
|
||||||
|
|
||||||
|
/* Create a thread to handle this hive */
|
||||||
|
Status = PsCreateSystemThread(&Thread,
|
||||||
|
THREAD_ALL_ACCESS,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
CmpLoadHiveThread,
|
||||||
|
(PVOID)i);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* We don't care about the handle -- the thread self-terminates */
|
||||||
|
ZwClose(Thread);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Can't imagine this happening */
|
||||||
|
KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 9, 3, i, Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we've reached the end of the list */
|
||||||
|
ASSERT(CmpMachineHiveList[i].Name == NULL);
|
||||||
|
|
||||||
|
/* Wait for hive loading to finish */
|
||||||
|
KeWaitForSingleObject(&CmpLoadWorkerEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Exit the special boot condition and make sure all workers completed */
|
||||||
|
CmpSpecialBootCondition = FALSE;
|
||||||
|
ASSERT(CmpLoadWorkerIncrement == CM_NUMBER_OF_MACHINE_HIVES);
|
||||||
|
|
||||||
|
/* Loop hives again */
|
||||||
|
for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++)
|
||||||
|
{
|
||||||
|
/* Make sure the thread ran and finished */
|
||||||
|
ASSERT(CmpMachineHiveList[i].ThreadFinished == TRUE);
|
||||||
|
ASSERT(CmpMachineHiveList[i].ThreadStarted == TRUE);
|
||||||
|
|
||||||
|
/* Check if this was a new hive */
|
||||||
|
if (!CmpMachineHiveList[i].CmHive)
|
||||||
|
{
|
||||||
|
/* Make sure we allocated something */
|
||||||
|
ASSERT(CmpMachineHiveList[i].CmHive2 != NULL);
|
||||||
|
|
||||||
|
/* Build the base name */
|
||||||
|
RegName.Length = RegStart;
|
||||||
|
RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName);
|
||||||
|
RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
|
||||||
|
|
||||||
|
/* Check if this is a child of the root */
|
||||||
|
if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == '\\')
|
||||||
|
{
|
||||||
|
/* Then setup the whole name */
|
||||||
|
RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name);
|
||||||
|
RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now link the hive to its master */
|
||||||
|
DPRINT1("[HiveLoad]: Link %wZ\n", &RegName);
|
||||||
|
#if 0
|
||||||
|
Status = CmpLinkHiveToMaster(&RegName,
|
||||||
|
NULL,
|
||||||
|
CmpMachineHiveList[i].CmHive2,
|
||||||
|
CmpMachineHiveList[i].Allocate,
|
||||||
|
SecurityDescriptor);
|
||||||
|
if (Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Linking needs to work */
|
||||||
|
KeBugCheckEx(CONFIG_LIST_FAILED, 11, Status, i, (ULONG_PTR)&RegName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we had to allocate a new hive */
|
||||||
|
if (CmpMachineHiveList[i].Allocate)
|
||||||
|
{
|
||||||
|
/* Sync the new hive */
|
||||||
|
HvSyncHive((PHHIVE)(CmpMachineHiveList[i].CmHive2));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we created a new hive */
|
||||||
|
if (CmpMachineHiveList[i].CmHive2)
|
||||||
|
{
|
||||||
|
/* TODO: Add to HiveList key */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get rid of the SD */
|
||||||
|
ExFreePool(SecurityDescriptor);
|
||||||
|
|
||||||
|
/* FIXME: Link SECURITY to SAM */
|
||||||
|
|
||||||
|
/* FIXME: Link S-1-5-18 to .Default */
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
CmInitSystem1(VOID)
|
CmInitSystem1(VOID)
|
||||||
|
|
|
@ -492,18 +492,71 @@ NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
||||||
return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0);
|
return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NtLoadKey2(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
||||||
|
IN POBJECT_ATTRIBUTES FileObjectAttributes,
|
||||||
|
IN ULONG Flags)
|
||||||
|
{
|
||||||
|
return NtLoadKeyEx(KeyObjectAttributes, FileObjectAttributes, Flags, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey,
|
||||||
|
IN POBJECT_ATTRIBUTES SourceFile,
|
||||||
|
IN ULONG Flags,
|
||||||
|
IN PKEY_OBJECT KeyBody);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey,
|
NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey,
|
||||||
IN POBJECT_ATTRIBUTES SourceFile,
|
IN POBJECT_ATTRIBUTES SourceFile,
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
IN HANDLE TrustClassKey,
|
IN HANDLE TrustClassKey)
|
||||||
IN HANDLE Event,
|
|
||||||
IN ACCESS_MASK DesiredAccess,
|
|
||||||
OUT PHANDLE RootHandle)
|
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
NTSTATUS Status;
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
|
PKEY_OBJECT KeyBody = NULL;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Validate flags */
|
||||||
|
if (Flags & ~REG_NO_LAZY_FLUSH) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
/* Validate privilege */
|
||||||
|
if (!SeSinglePrivilegeCheck(SeRestorePrivilege, PreviousMode))
|
||||||
|
{
|
||||||
|
/* Fail */
|
||||||
|
DPRINT1("Restore Privilege missing!\n");
|
||||||
|
//return STATUS_PRIVILEGE_NOT_HELD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Block APCs */
|
||||||
|
KeEnterCriticalRegion();
|
||||||
|
|
||||||
|
/* Check if we have a trust class */
|
||||||
|
if (TrustClassKey)
|
||||||
|
{
|
||||||
|
/* Reference it */
|
||||||
|
Status = ObReferenceObjectByHandle(TrustClassKey,
|
||||||
|
0,
|
||||||
|
CmpKeyObjectType,
|
||||||
|
PreviousMode,
|
||||||
|
(PVOID *)&KeyBody,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the internal API */
|
||||||
|
Status = CmLoadKey(TargetKey, SourceFile, Flags, KeyBody);
|
||||||
|
|
||||||
|
/* Dereference the trust key, if any */
|
||||||
|
if (KeyBody) ObDereferenceObject(KeyBody);
|
||||||
|
|
||||||
|
/* Bring back APCs */
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
|
||||||
|
/* Return status */
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -140,7 +140,6 @@
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="cm">
|
<directory name="cm">
|
||||||
<file>ntfunc.c</file>
|
<file>ntfunc.c</file>
|
||||||
<file>regfile.c</file>
|
|
||||||
<file>registry.c</file>
|
<file>registry.c</file>
|
||||||
<file>regobj.c</file>
|
<file>regobj.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
|
|
|
@ -101,7 +101,7 @@ NtListenPort 2
|
||||||
NtLoadDriver 1
|
NtLoadDriver 1
|
||||||
NtLoadKey 2
|
NtLoadKey 2
|
||||||
NtLoadKey2 3
|
NtLoadKey2 3
|
||||||
NtLoadKeyEx 7
|
NtLoadKeyEx 4
|
||||||
NtLockFile 10
|
NtLockFile 10
|
||||||
NtLockProductActivationKeys 2
|
NtLockProductActivationKeys 2
|
||||||
NtLockRegistryKey 1
|
NtLockRegistryKey 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue