From f09f448d95f3d6ca18faf4d1a68ae60a5043b0ac Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 10 Sep 2012 15:25:26 +0000 Subject: [PATCH] [NTOSKRNL]: CORE-6491 #resolve #comment Implement hive list support by hbelusca, with some minor cleanups by me. Loaded hives are now in the hivelist key. svn path=/trunk/; revision=57263 --- reactos/ntoskrnl/config/cmhvlist.c | 248 ++++++++++++++++++++++++- reactos/ntoskrnl/config/cmsysini.c | 6 +- reactos/ntoskrnl/include/internal/cm.h | 13 ++ 3 files changed, 258 insertions(+), 9 deletions(-) diff --git a/reactos/ntoskrnl/config/cmhvlist.c b/reactos/ntoskrnl/config/cmhvlist.c index 8fb2636f3dc..63d72baaa7d 100644 --- a/reactos/ntoskrnl/config/cmhvlist.c +++ b/reactos/ntoskrnl/config/cmhvlist.c @@ -1,24 +1,258 @@ /* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/config/cmwraprs.c - * PURPOSE: Configuration Manager - Wrappers for Hive Operations - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * FILE: ntoskrnl/config/cmhvlist.c + * PURPOSE: Configuration Manager - Hives file list management + * PROGRAMMERS: Hermes BELUSCA - MAITO */ -/* INCLUDES ******************************************************************/ +/* INCLUDES *******************************************************************/ #include "ntoskrnl.h" #define NDEBUG #include "debug.h" -/* FUNCTIONS *****************************************************************/ +/* GLOBALS ********************************************************************/ + +UNICODE_STRING HiveListValueName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\hivelist"); + +/* FUNCTIONS ******************************************************************/ + +/* Note: the caller is expected to free the HiveName string buffer */ +BOOLEAN +NTAPI +CmpGetHiveName(IN PCMHIVE Hive, + OUT PUNICODE_STRING HiveName) +{ + HCELL_INDEX RootCell, LinkCell; + PCELL_DATA RootData, LinkData, ParentData; + ULONG ParentNameSize, LinkNameSize; + SIZE_T NameSize; + PWCHAR p; + UNICODE_STRING RegistryName = RTL_CONSTANT_STRING(L"\\REGISTRY\\"); + + /* Get the root cell of this hive */ + RootCell = Hive->Hive.BaseBlock->RootCell; + RootData = HvGetCell(&Hive->Hive, RootCell); + if (!RootData) return FALSE; + + /* Get the cell index at which this hive is linked to, and its parent */ + LinkCell = RootData->u.KeyNode.Parent; + HvReleaseCell(&Hive->Hive, RootCell); + + /* Sanity check */ + ASSERT((&CmiVolatileHive->Hive)->ReleaseCellRoutine == NULL); + + /* Get the cell data for link and parent */ + LinkData = HvGetCell(&CmiVolatileHive->Hive, LinkCell); + if (!LinkData) return FALSE; + ParentData = HvGetCell(&CmiVolatileHive->Hive, LinkData->u.KeyNode.Parent); + if (!ParentData) return FALSE; + + /* Get the size of the parent name */ + if (ParentData->u.KeyNode.Flags & KEY_COMP_NAME) + { + ParentNameSize = CmpCompressedNameSize(ParentData->u.KeyNode.Name, + ParentData->u.KeyNode.NameLength); + } + else + { + ParentNameSize = ParentData->u.KeyNode.NameLength; + } + + /* Get the size of the link name */ + if (LinkData->u.KeyNode.Flags & KEY_COMP_NAME) + { + LinkNameSize = CmpCompressedNameSize(LinkData->u.KeyNode.Name, + LinkData->u.KeyNode.NameLength); + } + else + { + LinkNameSize = LinkData->u.KeyNode.NameLength; + } + + /* No need to account for terminal NULL character since we deal with counted UNICODE strings */ + NameSize = RegistryName.Length + ParentNameSize + sizeof(WCHAR) + LinkNameSize; + + /* Allocate the memory */ + HiveName->Buffer = ExAllocatePoolWithTag(PagedPool, NameSize, TAG_CM); + if (!HiveName->Buffer) + { + /* Fail */ + DPRINT1("CmpGetHiveName: Unable to allocate memory\n"); + return FALSE; + } + + /* Build the string for it */ + HiveName->Length = HiveName->MaximumLength = (USHORT)NameSize; + p = HiveName->Buffer; + + /* Copy the parent name */ + RtlCopyMemory(p, RegistryName.Buffer, RegistryName.Length); + p += RegistryName.Length / sizeof(WCHAR); + if (ParentData->u.KeyNode.Flags & KEY_COMP_NAME) + { + CmpCopyCompressedName(p, + ParentNameSize, + ParentData->u.KeyNode.Name, + ParentData->u.KeyNode.NameLength); + } + else + { + RtlCopyMemory(p, ParentData->u.KeyNode.Name, ParentNameSize); + } + + /* Add a path separator between parent and link */ + p += ParentNameSize / sizeof(WCHAR); + *p = OBJ_NAME_PATH_SEPARATOR; + ++p; + + /* Now copy the link name */ + if (LinkData->u.KeyNode.Flags & KEY_COMP_NAME) + { + CmpCopyCompressedName(p, + LinkNameSize, + LinkData->u.KeyNode.Name, + LinkData->u.KeyNode.NameLength); + + } + else + { + RtlCopyMemory(p, LinkData->u.KeyNode.Name, LinkNameSize); + } + + /* All done */ + return TRUE; +} NTSTATUS NTAPI CmpAddToHiveFileList(IN PCMHIVE Hive) { - return STATUS_SUCCESS; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + UNICODE_STRING HivePath; + PWCHAR FilePath; + CHAR Buffer[sizeof(OBJECT_NAME_INFORMATION) + 512 * sizeof(WCHAR)]; + ULONG Length = sizeof(Buffer); + POBJECT_NAME_INFORMATION LocalNameInfo = (POBJECT_NAME_INFORMATION)&Buffer; + HivePath.Buffer = NULL; + + /* Create or open the hive list key */ + InitializeObjectAttributes(&ObjectAttributes, + &HiveListValueName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL); + Status = ZwCreateKey(&KeyHandle, + KEY_READ | KEY_WRITE, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + NULL); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + DPRINT1("CmpAddToHiveFileList: Creation or opening of the hive list failed, status = %08lx\n", Status); + return Status; + } + + /* Retrieve the name of the hive */ + if (!CmpGetHiveName(Hive, &HivePath)) + { + /* Fail */ + DPRINT1("CmpAddToHiveFileList: Unable to retrieve the hive name\n"); + Status = STATUS_NO_MEMORY; + goto Quickie; + } + + /* Get the name of the corresponding file */ + if (!(Hive->Hive.HiveFlags & HIVE_VOLATILE)) + { + /* Try to get the value */ + Status = ZwQueryObject(Hive->FileHandles[HFILE_TYPE_PRIMARY], + ObjectNameInformation, + LocalNameInfo, + Length, + &Length); + if (NT_SUCCESS(Status)) + { + /* Null-terminate and add the length of the terminator */ + Length -= sizeof(OBJECT_NAME_INFORMATION); + FilePath = LocalNameInfo->Name.Buffer; + FilePath[Length / sizeof(WCHAR)] = UNICODE_NULL; + Length += sizeof(UNICODE_NULL); + } + else + { + /* Fail */ + DPRINT1("CmpAddToHiveFileList: Hive file name query failed, status = %08lx\n", Status); + goto Quickie; + } + } + else + { + /* No name */ + FilePath = L""; + Length = sizeof(UNICODE_NULL); + } + + /* Set the entry in the hive list */ + Status = ZwSetValueKey(KeyHandle, + &HivePath, + 0, + REG_SZ, + FilePath, + Length); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + DPRINT1("CmpAddToHiveFileList: Setting of entry in the hive list failed, status = %08lx\n", Status); + } + +Quickie: + /* Cleanup and return status */ + if (HivePath.Buffer) ExFreePoolWithTag(HivePath.Buffer, TAG_CM); + ObCloseHandle(KeyHandle, KernelMode); + return Status; } -/* EOF */ \ No newline at end of file +VOID +NTAPI +CmpRemoveFromHiveFileList(IN PCMHIVE Hive) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + UNICODE_STRING HivePath; + + /* Open the hive list key */ + InitializeObjectAttributes(&ObjectAttributes, + &HiveListValueName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL); + Status = ZwOpenKey(&KeyHandle, + KEY_READ | KEY_WRITE, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + DPRINT1("CmpRemoveFromHiveFileList: Opening of the hive list failed, status = %08lx\n", Status); + return; + } + + /* Get the hive path name */ + CmpGetHiveName(Hive, &HivePath); + + /* Delete the hive path name from the list */ + ZwDeleteValueKey(KeyHandle, &HivePath); + + /* Cleanup allocation and handle */ + ExFreePoolWithTag(HivePath.Buffer, TAG_CM); + ObCloseHandle(KeyHandle, KernelMode); +} + +/* EOF */ diff --git a/reactos/ntoskrnl/config/cmsysini.c b/reactos/ntoskrnl/config/cmsysini.c index 6d7e32a57f2..4cd9165df2a 100644 --- a/reactos/ntoskrnl/config/cmsysini.c +++ b/reactos/ntoskrnl/config/cmsysini.c @@ -1381,7 +1381,8 @@ CmpInitializeHiveList(IN USHORT Flag) /* Check if we created a new hive */ if (CmpMachineHiveList[i].CmHive2) { - /* TODO: Add to HiveList key */ + /* Add to HiveList key */ + CmpAddToHiveFileList(CmpMachineHiveList[i].CmHive2); } } @@ -1569,7 +1570,8 @@ CmInitSystem1(VOID) KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 12, Status, 0); } - /* FIXME: Add to HiveList key */ + /* Add to HiveList key */ + CmpAddToHiveFileList(HardwareHive); /* Free the security descriptor */ ExFreePoolWithTag(SecurityDescriptor, TAG_CM); diff --git a/reactos/ntoskrnl/include/internal/cm.h b/reactos/ntoskrnl/include/internal/cm.h index 619455b6fac..bc4ca1775ba 100644 --- a/reactos/ntoskrnl/include/internal/cm.h +++ b/reactos/ntoskrnl/include/internal/cm.h @@ -624,12 +624,25 @@ CmCheckRegistry( // // Hive List Routines // +BOOLEAN +NTAPI +CmpGetHiveName( + IN PCMHIVE Hive, + OUT PUNICODE_STRING HiveName +); + NTSTATUS NTAPI CmpAddToHiveFileList( IN PCMHIVE Hive ); +VOID +NTAPI +CmpRemoveFromHiveFileList( + IN PCMHIVE Hive +); + // // Quota Routines //