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