Windows2000/private/ntos/config/cmhvlist.c
2020-09-30 17:12:32 +02:00

216 lines
6.6 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
--*/
#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)) {
CMLOG(CML_MAJOR, CMS_INIT_ERROR) {
KdPrint(("CmpAddToHiveFileList: "));
KdPrint(("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)) {
CMLOG(CML_MAJOR, CMS_INIT_ERROR) {
KdPrint(("CmpAddToHiveFileList: "));
KdPrint(("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)) {
CMLOG(CML_MAJOR, CMS_INIT_ERROR) {
KdPrint(("CmpAddToHiveFileList: "));
KdPrint(("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;
}
CmpGetHiveName(CmHive, &EntryName);
ZwDeleteValueKey(KeyHandle, &EntryName);
NtClose(KeyHandle);
ExFreePool(EntryName.Buffer);
}
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);
LinkCell = EntryKey->Parent;
// 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);
LinkParent = (PCM_KEY_NODE)HvGetCell((PHHIVE)CmpMasterHive, LinkKey->Parent);
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 {
RtlMoveMemory( (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 {
RtlMoveMemory((PVOID)p, (PVOID)&(LinkKey->Name[0]), KeySize);
}
return TRUE;
}