553 lines
11 KiB
C
553 lines
11 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
cmwraper.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Provides wrapper routines to support ntos\config routines called from
|
|||
|
user-mode.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Vert (jvert) 26-Mar-1992
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
#include "edithive.h"
|
|||
|
#include "nturtl.h"
|
|||
|
#include "stdlib.h"
|
|||
|
#include "stdio.h"
|
|||
|
|
|||
|
extern ULONG UsedStorage;
|
|||
|
|
|||
|
CCHAR KiFindFirstSetRight[256] = {
|
|||
|
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
|
|||
|
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
|
|||
|
|
|||
|
|
|||
|
ULONG MmSizeOfPagedPoolInBytes = 0xffffffff; // stub out
|
|||
|
|
|||
|
ULONG
|
|||
|
DbgPrint (
|
|||
|
IN PCH Format,
|
|||
|
...
|
|||
|
)
|
|||
|
{
|
|||
|
va_list arglist;
|
|||
|
UCHAR Buffer[512];
|
|||
|
STRING Output;
|
|||
|
|
|||
|
//
|
|||
|
// Format the output into a buffer and then print it.
|
|||
|
//
|
|||
|
|
|||
|
va_start(arglist, Format);
|
|||
|
Output.Length = _vsnprintf(Buffer, sizeof(Buffer), Format, arglist);
|
|||
|
Output.Buffer = Buffer;
|
|||
|
printf("%s", Buffer);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Structure that describes the mapping of generic access rights to object
|
|||
|
// specific access rights for registry key and keyroot objects.
|
|||
|
//
|
|||
|
|
|||
|
GENERIC_MAPPING CmpKeyMapping = {
|
|||
|
KEY_READ,
|
|||
|
KEY_WRITE,
|
|||
|
KEY_EXECUTE,
|
|||
|
KEY_ALL_ACCESS
|
|||
|
};
|
|||
|
BOOLEAN CmpNoWrite = FALSE;
|
|||
|
ULONG CmLogLevel=0;
|
|||
|
ULONG CmLogSelect=0;
|
|||
|
PCMHIVE CmpMasterHive = NULL;
|
|||
|
LIST_ENTRY CmpHiveListHead; // List of CMHIVEs
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MyCmpInitHiveFromFile(
|
|||
|
IN PUNICODE_STRING FileName,
|
|||
|
OUT PCMHIVE *CmHive,
|
|||
|
OUT PBOOLEAN Allocate
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
CmpLazyFlush(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
CmpFreeSecurityDescriptor(
|
|||
|
IN PHHIVE Hive,
|
|||
|
IN HCELL_INDEX Cell
|
|||
|
)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
CmpReportNotify(
|
|||
|
UNICODE_STRING Name,
|
|||
|
PHHIVE Hive,
|
|||
|
HCELL_INDEX Cell,
|
|||
|
ULONG Filter
|
|||
|
)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
CmpLockRegistry(VOID)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CmpTryLockRegistryExclusive(
|
|||
|
IN BOOLEAN CanWait
|
|||
|
)
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
CmpUnlockRegistry(
|
|||
|
)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CmpTestRegistryLock()
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CmpTestRegistryLockExclusive()
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
LONG
|
|||
|
KeReleaseMutex (
|
|||
|
IN PKMUTEX Mutex,
|
|||
|
IN BOOLEAN Wait
|
|||
|
)
|
|||
|
{
|
|||
|
return(0);
|
|||
|
}
|
|||
|
NTSTATUS
|
|||
|
KeWaitForSingleObject (
|
|||
|
IN PVOID Object,
|
|||
|
IN KWAIT_REASON WaitReason,
|
|||
|
IN KPROCESSOR_MODE WaitMode,
|
|||
|
IN BOOLEAN Alertable,
|
|||
|
IN PLARGE_INTEGER Timeout OPTIONAL
|
|||
|
)
|
|||
|
{
|
|||
|
return(STATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CmpValidateHiveSecurityDescriptors(
|
|||
|
IN PHHIVE Hive
|
|||
|
)
|
|||
|
{
|
|||
|
PCM_KEY_NODE RootNode;
|
|||
|
PCM_KEY_SECURITY SecurityCell;
|
|||
|
HCELL_INDEX ListAnchor;
|
|||
|
HCELL_INDEX NextCell;
|
|||
|
HCELL_INDEX LastCell;
|
|||
|
BOOLEAN ValidHive = TRUE;
|
|||
|
|
|||
|
CMLOG(CML_FLOW, CMS_SEC) {
|
|||
|
KdPrint(("CmpValidateHiveSecurityDescriptor: Hive = %lx\n",(ULONG)Hive));
|
|||
|
}
|
|||
|
RootNode = (PCM_KEY_NODE) HvGetCell(Hive, Hive->BaseBlock->RootCell);
|
|||
|
ListAnchor = NextCell = RootNode->u1.s1.Security;
|
|||
|
|
|||
|
do {
|
|||
|
SecurityCell = (PCM_KEY_SECURITY) HvGetCell(Hive, NextCell);
|
|||
|
if (NextCell != ListAnchor) {
|
|||
|
//
|
|||
|
// Check to make sure that our Blink points to where we just
|
|||
|
// came from.
|
|||
|
//
|
|||
|
if (SecurityCell->Blink != LastCell) {
|
|||
|
CMLOG(CML_MAJOR, CMS_SEC) {
|
|||
|
KdPrint((" Invalid Blink (%ld) on security cell %ld\n",SecurityCell->Blink, NextCell));
|
|||
|
KdPrint((" should point to %ld\n", LastCell));
|
|||
|
}
|
|||
|
ValidHive = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
CMLOG(CML_MINOR, CMS_SEC) {
|
|||
|
KdPrint(("CmpValidSD: SD shared by %d nodes\n",SecurityCell->ReferenceCount));
|
|||
|
}
|
|||
|
// SetUsed(Hive, NextCell);
|
|||
|
LastCell = NextCell;
|
|||
|
NextCell = SecurityCell->Flink;
|
|||
|
} while ( NextCell != ListAnchor );
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KeBugCheck(
|
|||
|
IN ULONG BugCheckCode
|
|||
|
)
|
|||
|
{
|
|||
|
printf("BugCheck: code = %08lx\n", BugCheckCode);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KeBugCheckEx(
|
|||
|
IN ULONG BugCheckCode,
|
|||
|
IN ULONG Arg1,
|
|||
|
IN ULONG Arg2,
|
|||
|
IN ULONG Arg3,
|
|||
|
IN ULONG Arg4
|
|||
|
)
|
|||
|
{
|
|||
|
printf("BugCheck: code = %08lx\n", BugCheckCode);
|
|||
|
printf("Args =%08lx %08lx %08lx %08lx\n", Arg1, Arg2, Arg3, Arg4);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
KeQuerySystemTime(
|
|||
|
OUT PLARGE_INTEGER SystemTime
|
|||
|
)
|
|||
|
{
|
|||
|
NtQuerySystemTime(SystemTime);
|
|||
|
}
|
|||
|
|
|||
|
#ifdef POOL_TAGGING
|
|||
|
PVOID
|
|||
|
ExAllocatePoolWithTag(
|
|||
|
IN POOL_TYPE PoolType,
|
|||
|
IN ULONG NumberOfBytes,
|
|||
|
IN ULONG Tag
|
|||
|
)
|
|||
|
{
|
|||
|
PVOID Address = NULL;
|
|||
|
ULONG Size;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
Size = ROUND_UP(NumberOfBytes, HBLOCK_SIZE);
|
|||
|
status = NtAllocateVirtualMemory(
|
|||
|
NtCurrentProcess(),
|
|||
|
&Address,
|
|||
|
0,
|
|||
|
&Size,
|
|||
|
MEM_COMMIT,
|
|||
|
PAGE_READWRITE
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
return Address;
|
|||
|
}
|
|||
|
#else
|
|||
|
|
|||
|
PVOID
|
|||
|
ExAllocatePool(
|
|||
|
IN POOL_TYPE PoolType,
|
|||
|
IN ULONG NumberOfBytes
|
|||
|
)
|
|||
|
{
|
|||
|
PVOID Address = NULL;
|
|||
|
ULONG Size;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
Size = ROUND_UP(NumberOfBytes, HBLOCK_SIZE);
|
|||
|
status = NtAllocateVirtualMemory(
|
|||
|
NtCurrentProcess(),
|
|||
|
&Address,
|
|||
|
0,
|
|||
|
&Size,
|
|||
|
MEM_COMMIT,
|
|||
|
PAGE_READWRITE
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
return Address;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
VOID
|
|||
|
ExFreePool(
|
|||
|
IN PVOID P
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG size;
|
|||
|
size = HBLOCK_SIZE;
|
|||
|
|
|||
|
// if it was really more than 1 page, well, too bad
|
|||
|
NtFreeVirtualMemory(
|
|||
|
NtCurrentProcess(),
|
|||
|
&P,
|
|||
|
&size,
|
|||
|
MEM_DECOMMIT
|
|||
|
);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
CmpWorkerCommand(
|
|||
|
IN OUT PREGISTRY_COMMAND Command
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine just encapsulates all the necessary synchronization for
|
|||
|
sending a command to the worker thread.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Command - Supplies a pointer to an initialized REGISTRY_COMMAND structure
|
|||
|
which will be copied into the global communication structure.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS = Command.Status
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PCMHIVE CmHive;
|
|||
|
PUNICODE_STRING FileName;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
switch (Command->Command) {
|
|||
|
|
|||
|
case REG_CMD_FLUSH_KEY:
|
|||
|
return CmFlushKey(Command->Hive, Command->Cell);
|
|||
|
break;
|
|||
|
|
|||
|
case REG_CMD_FILE_SET_SIZE:
|
|||
|
return CmpDoFileSetSize(
|
|||
|
Command->Hive,
|
|||
|
Command->FileType,
|
|||
|
Command->FileSize
|
|||
|
);
|
|||
|
break;
|
|||
|
|
|||
|
case REG_CMD_HIVE_OPEN:
|
|||
|
|
|||
|
//
|
|||
|
// Open the file.
|
|||
|
//
|
|||
|
FileName = Command->FileAttributes->ObjectName;
|
|||
|
|
|||
|
return MyCmpInitHiveFromFile(FileName,
|
|||
|
&Command->CmHive,
|
|||
|
&Command->Allocate);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case REG_CMD_HIVE_CLOSE:
|
|||
|
|
|||
|
//
|
|||
|
// Close the files associated with this hive.
|
|||
|
//
|
|||
|
CmHive = Command->CmHive;
|
|||
|
|
|||
|
for (i=0; i<HFILE_TYPE_MAX; i++) {
|
|||
|
if (CmHive->FileHandles[i] != NULL) {
|
|||
|
NtClose(CmHive->FileHandles[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
return STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
|
|||
|
case REG_CMD_SHUTDOWN:
|
|||
|
|
|||
|
//
|
|||
|
// shut down the registry
|
|||
|
//
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
return STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MyCmpInitHiveFromFile(
|
|||
|
IN PUNICODE_STRING FileName,
|
|||
|
OUT PCMHIVE *CmHive,
|
|||
|
OUT PBOOLEAN Allocate
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine opens a file and log, allocates a CMHIVE, and initializes
|
|||
|
it.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileName - Supplies name of file to be loaded.
|
|||
|
|
|||
|
CmHive - Returns pointer to initialized hive (if successful)
|
|||
|
|
|||
|
Allocate - Returns whether the hive was allocated or existing.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PCMHIVE NewHive;
|
|||
|
ULONG Disposition;
|
|||
|
ULONG SecondaryDisposition;
|
|||
|
HANDLE PrimaryHandle;
|
|||
|
HANDLE LogHandle;
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG FileType;
|
|||
|
ULONG Operation;
|
|||
|
|
|||
|
BOOLEAN Success;
|
|||
|
|
|||
|
*CmHive = NULL;
|
|||
|
|
|||
|
Status = CmpOpenHiveFiles(FileName,
|
|||
|
L".log",
|
|||
|
&PrimaryHandle,
|
|||
|
&LogHandle,
|
|||
|
&Disposition,
|
|||
|
&SecondaryDisposition,
|
|||
|
TRUE,
|
|||
|
NULL
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
if (LogHandle == NULL) {
|
|||
|
FileType = HFILE_TYPE_PRIMARY;
|
|||
|
} else {
|
|||
|
FileType = HFILE_TYPE_LOG;
|
|||
|
}
|
|||
|
|
|||
|
if (Disposition == FILE_CREATED) {
|
|||
|
Operation = HINIT_CREATE;
|
|||
|
*Allocate = TRUE;
|
|||
|
} else {
|
|||
|
Operation = HINIT_FILE;
|
|||
|
*Allocate = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
Success = CmpInitializeHive(&NewHive,
|
|||
|
Operation,
|
|||
|
FALSE,
|
|||
|
FileType,
|
|||
|
NULL,
|
|||
|
PrimaryHandle,
|
|||
|
NULL,
|
|||
|
LogHandle,
|
|||
|
NULL,
|
|||
|
NULL);
|
|||
|
if (!Success) {
|
|||
|
NtClose(PrimaryHandle);
|
|||
|
if (LogHandle != NULL) {
|
|||
|
NtClose(LogHandle);
|
|||
|
}
|
|||
|
return(STATUS_REGISTRY_CORRUPT);
|
|||
|
} else {
|
|||
|
*CmHive = NewHive;
|
|||
|
return(STATUS_SUCCESS);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
CmpLinkHiveToMaster(
|
|||
|
PUNICODE_STRING LinkName,
|
|||
|
HANDLE RootDirectory,
|
|||
|
PCMHIVE CmHive,
|
|||
|
BOOLEAN Allocate,
|
|||
|
PSECURITY_DESCRIPTOR SecurityDescriptor
|
|||
|
)
|
|||
|
{
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CmpFileSetSize(
|
|||
|
PHHIVE Hive,
|
|||
|
ULONG FileType,
|
|||
|
ULONG FileSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine sets the size of a file. It must not return until
|
|||
|
the size is guaranteed, therefore, it does a flush.
|
|||
|
|
|||
|
It is environment specific.
|
|||
|
|
|||
|
This routine will force execution to the correct thread context.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Hive - Hive we are doing I/O for
|
|||
|
|
|||
|
FileType - which supporting file to use
|
|||
|
|
|||
|
FileSize - 32 bit value to set the file's size to
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
FALSE if failure
|
|||
|
TRUE if success
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
status = CmpDoFileSetSize(Hive, FileType, FileSize);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
CMLOG(CML_MAJOR, CMS_IO_ERROR) {
|
|||
|
KdPrint(("CmpFileSetSize:\n\t"));
|
|||
|
KdPrint(("Failure: status = %08lx ", status));
|
|||
|
}
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|