windows-nt/Source/XPSP1/NT/base/ntos/config/cmhvlist.c
2020-09-26 16:20:57 +08:00

376 lines
8.4 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
}