376 lines
8.4 KiB
C
376 lines
8.4 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
cmhvlist.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Code to maintain registry node that lists where the roots of
|
|||
|
hives are and what files they map to.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Bryan M. Willman (bryanwi) 14-May-1992
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "cmp.h"
|
|||
|
|
|||
|
#define HIVE_LIST L"\\registry\\machine\\system\\currentcontrolset\\control\\hivelist"
|
|||
|
|
|||
|
extern PCMHIVE CmpMasterHive;
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CmpGetHiveName(
|
|||
|
PCMHIVE CmHive,
|
|||
|
PUNICODE_STRING HiveName
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE,CmpAddToHiveFileList)
|
|||
|
#pragma alloc_text(PAGE,CmpRemoveFromHiveFileList)
|
|||
|
#pragma alloc_text(PAGE,CmpGetHiveName)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
CmpAddToHiveFileList(
|
|||
|
PCMHIVE CmHive
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Add Hive to list of hives and their files in
|
|||
|
\registry\machine\system\currentcontrolset\control\hivelist
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
HivePath - path to root of hive (e.g. \registry\machine\system)
|
|||
|
|
|||
|
CmHive - pointer to CM_HIVE structure for hive.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ntstatus
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// PERFNOTE - allocate small instead of large buffers after
|
|||
|
// NtQueryObject is fixec - bryanwi 15may92
|
|||
|
//
|
|||
|
#define NAME_BUFFER_SIZE 512
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
HANDLE KeyHandle;
|
|||
|
NTSTATUS Status;
|
|||
|
PUCHAR Buffer;
|
|||
|
ULONG Length;
|
|||
|
PWSTR FilePath;
|
|||
|
WCHAR UnicodeNull=UNICODE_NULL;
|
|||
|
UNICODE_STRING TempName;
|
|||
|
UNICODE_STRING HivePath;
|
|||
|
|
|||
|
//
|
|||
|
// create/open the hive list key
|
|||
|
//
|
|||
|
RtlInitUnicodeString(
|
|||
|
&TempName,
|
|||
|
HIVE_LIST
|
|||
|
);
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&ObjectAttributes,
|
|||
|
&TempName,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
(HANDLE)NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
Status = ZwCreateKey(
|
|||
|
&KeyHandle,
|
|||
|
KEY_READ | KEY_WRITE,
|
|||
|
&ObjectAttributes,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
REG_OPTION_VOLATILE,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpAddToHiveFileList: "));
|
|||
|
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"Create/Open of Hive list failed status = %08lx\n", Status));
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// allocate work buffers
|
|||
|
//
|
|||
|
Buffer = ExAllocatePool(PagedPool, NAME_BUFFER_SIZE);
|
|||
|
if (Buffer == NULL) {
|
|||
|
NtClose(KeyHandle);
|
|||
|
return STATUS_NO_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// compute name of hive
|
|||
|
//
|
|||
|
if (! CmpGetHiveName(CmHive, &HivePath)) {
|
|||
|
NtClose(KeyHandle);
|
|||
|
ExFreePool(Buffer);
|
|||
|
return STATUS_NO_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// get name of file
|
|||
|
//
|
|||
|
if (!(CmHive->Hive.HiveFlags & HIVE_VOLATILE)) {
|
|||
|
Status = ZwQueryObject(
|
|||
|
CmHive->FileHandles[HFILE_TYPE_PRIMARY],
|
|||
|
ObjectNameInformation,
|
|||
|
(PVOID)Buffer,
|
|||
|
NAME_BUFFER_SIZE,
|
|||
|
&Length
|
|||
|
);
|
|||
|
Length -= sizeof(UNICODE_STRING);
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpAddToHiveFileList: "));
|
|||
|
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"Query of name2 failed status = %08lx\n", Status));
|
|||
|
NtClose(KeyHandle);
|
|||
|
ExFreePool(HivePath.Buffer);
|
|||
|
ExFreePool(Buffer);
|
|||
|
return Status;
|
|||
|
}
|
|||
|
FilePath = ((POBJECT_NAME_INFORMATION)Buffer)->Name.Buffer;
|
|||
|
FilePath[Length/sizeof(WCHAR)] = UNICODE_NULL;
|
|||
|
Length+=sizeof(WCHAR);
|
|||
|
} else {
|
|||
|
FilePath = &UnicodeNull;
|
|||
|
Length = sizeof(UnicodeNull);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// set entry in list
|
|||
|
//
|
|||
|
Status = ZwSetValueKey(
|
|||
|
KeyHandle,
|
|||
|
&HivePath,
|
|||
|
0,
|
|||
|
REG_SZ,
|
|||
|
FilePath,
|
|||
|
Length
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpAddToHiveFileList: "));
|
|||
|
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"Set of entry in Hive list failed status = %08lx\n", Status));
|
|||
|
}
|
|||
|
|
|||
|
NtClose(KeyHandle);
|
|||
|
ExFreePool(HivePath.Buffer);
|
|||
|
ExFreePool(Buffer);
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
CmpRemoveFromHiveFileList(
|
|||
|
PCMHIVE CmHive
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Remove hive name from hive file list key
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CmHive - pointer to CM_HIVE structure for hive.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ntstatus
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
UNICODE_STRING EntryName;
|
|||
|
UNICODE_STRING TempName;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
HANDLE KeyHandle;
|
|||
|
|
|||
|
//
|
|||
|
// open the hive list key
|
|||
|
//
|
|||
|
RtlInitUnicodeString(
|
|||
|
&TempName,
|
|||
|
HIVE_LIST
|
|||
|
);
|
|||
|
|
|||
|
InitializeObjectAttributes(
|
|||
|
&ObjectAttributes,
|
|||
|
&TempName,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
(HANDLE)NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
Status = ZwOpenKey(
|
|||
|
&KeyHandle,
|
|||
|
KEY_READ | KEY_WRITE,
|
|||
|
&ObjectAttributes
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if( CmpGetHiveName(CmHive, &EntryName) ) {
|
|||
|
ZwDeleteValueKey(KeyHandle, &EntryName);
|
|||
|
ExFreePool(EntryName.Buffer);
|
|||
|
}
|
|||
|
|
|||
|
NtClose(KeyHandle);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CmpGetHiveName(
|
|||
|
PCMHIVE CmHive,
|
|||
|
PUNICODE_STRING HiveName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compute full path to a hive.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CmHive - pointer to CmHive structure
|
|||
|
|
|||
|
HiveName - supplies pointer to unicode string structure that
|
|||
|
will be filled in with pointer to name.
|
|||
|
|
|||
|
CALL IS EXPECTED TO FREE BUFFER
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE = it worked, FALSE = it failed (memory)
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HCELL_INDEX RootCell;
|
|||
|
HCELL_INDEX LinkCell;
|
|||
|
PCM_KEY_NODE LinkKey;
|
|||
|
PCM_KEY_NODE LinkParent;
|
|||
|
ULONG size;
|
|||
|
ULONG rsize;
|
|||
|
ULONG KeySize;
|
|||
|
ULONG ParentSize;
|
|||
|
PWCHAR p;
|
|||
|
PCM_KEY_NODE EntryKey;
|
|||
|
|
|||
|
//
|
|||
|
// First find the link cell.
|
|||
|
//
|
|||
|
RootCell = CmHive->Hive.BaseBlock->RootCell;
|
|||
|
EntryKey = (PCM_KEY_NODE)HvGetCell((PHHIVE)CmHive, RootCell);
|
|||
|
if( EntryKey == NULL ) {
|
|||
|
//
|
|||
|
// we couldn't map a view for the bin containing this cell
|
|||
|
//
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
LinkCell = EntryKey->Parent;
|
|||
|
HvReleaseCell((PHHIVE)CmHive, RootCell);
|
|||
|
|
|||
|
// for master we don't need to count cell usage
|
|||
|
ASSERT( ((PHHIVE)CmpMasterHive)->ReleaseCellRoutine == NULL );
|
|||
|
//
|
|||
|
// Compute the value entry name, which is of the form:
|
|||
|
// \registry\<parent of link node name>\<link node name>
|
|||
|
//
|
|||
|
LinkKey = (PCM_KEY_NODE)HvGetCell((PHHIVE)CmpMasterHive, LinkCell);
|
|||
|
if( LinkKey == NULL ) {
|
|||
|
//
|
|||
|
// we couldn't map a view for the bin containing this cell
|
|||
|
//
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
LinkParent = (PCM_KEY_NODE)HvGetCell(
|
|||
|
(PHHIVE)CmpMasterHive,
|
|||
|
LinkKey->Parent
|
|||
|
);
|
|||
|
if( LinkParent == NULL ) {
|
|||
|
//
|
|||
|
// we couldn't map a view for the bin containing this cell
|
|||
|
//
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
rsize = wcslen(L"\\REGISTRY\\");
|
|||
|
|
|||
|
KeySize = CmpHKeyNameLen(LinkKey);
|
|||
|
ParentSize = CmpHKeyNameLen(LinkParent);
|
|||
|
size = KeySize + ParentSize +
|
|||
|
(rsize * sizeof(WCHAR)) + sizeof(WCHAR);
|
|||
|
|
|||
|
HiveName->Buffer = ExAllocatePool(PagedPool, size);
|
|||
|
if (HiveName->Buffer == NULL) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
HiveName->Length = (USHORT)size;
|
|||
|
HiveName->MaximumLength = (USHORT)size;
|
|||
|
p = HiveName->Buffer;
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
(PVOID)p,
|
|||
|
(PVOID)L"\\REGISTRY\\",
|
|||
|
rsize * sizeof(WCHAR)
|
|||
|
);
|
|||
|
p += rsize;
|
|||
|
|
|||
|
if (LinkParent->Flags & KEY_COMP_NAME) {
|
|||
|
CmpCopyCompressedName(p,
|
|||
|
ParentSize,
|
|||
|
LinkParent->Name,
|
|||
|
LinkParent->NameLength);
|
|||
|
} else {
|
|||
|
RtlCopyMemory(
|
|||
|
(PVOID)p,
|
|||
|
(PVOID)&(LinkParent->Name[0]),
|
|||
|
ParentSize
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
p += ParentSize / sizeof(WCHAR);
|
|||
|
|
|||
|
*p = OBJ_NAME_PATH_SEPARATOR;
|
|||
|
p++;
|
|||
|
|
|||
|
if (LinkKey->Flags & KEY_COMP_NAME) {
|
|||
|
CmpCopyCompressedName(p,
|
|||
|
KeySize,
|
|||
|
LinkKey->Name,
|
|||
|
LinkKey->NameLength);
|
|||
|
|
|||
|
} else {
|
|||
|
RtlCopyMemory(
|
|||
|
(PVOID)p,
|
|||
|
(PVOID)&(LinkKey->Name[0]),
|
|||
|
KeySize
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|