Author: hbelusca
Date: Wed Jan 13 01:40:58 2016
New Revision: 70582
URL:
http://svn.reactos.org/svn/reactos?rev=70582&view=rev
Log:
[CMLIB]
- Fix HBLOCK_SIZE vs. HSECTOR_SIZE mix-ups in HvpGetHiveHeader.
- Add a function to create cluster-aligned hive base blocks (HBASE_BLOCK) based on the
existing code of HvpGetHiveHeader, and use it everytime we need to allocate HBASE_BLOCKs.
- Keep the actual base block size in the BaseBlockAlloc member, and use this value for the
"quota" parameter when we free the blocks.
- Introduce & use a function to initialize the hive file name array (mainly used for
debugging purposes).
- "HvpInitializeMemoryInplaceHive" should read "HvpInitializeFlatHive"
instead since this function is used to initialize a flat hive. Memory-in-place hives are a
different thing.
- Fix some memory leaks in the error paths of HvLoadHive.
- Initialize some additional hive members in HvInitialize(Hive).
Modified:
trunk/reactos/lib/cmlib/hiveinit.c
Modified: trunk/reactos/lib/cmlib/hiveinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/hiveinit.c?rev=7…
==============================================================================
--- trunk/reactos/lib/cmlib/hiveinit.c [iso-8859-1] (original)
+++ trunk/reactos/lib/cmlib/hiveinit.c [iso-8859-1] Wed Jan 13 01:40:58 2016
@@ -14,10 +14,9 @@
*
* Internal function to verify that a hive header has valid format.
*/
-
BOOLEAN CMAPI
HvpVerifyHiveHeader(
- PHBASE_BLOCK BaseBlock)
+ IN PHBASE_BLOCK BaseBlock)
{
if (BaseBlock->Signature != HV_SIGNATURE ||
BaseBlock->Major != HSYS_MAJOR ||
@@ -28,10 +27,10 @@
BaseBlock->Sequence1 != BaseBlock->Sequence2 ||
HvpHiveHeaderChecksum(BaseBlock) != BaseBlock->CheckSum)
{
- DPRINT1("Verify Hive Header failed: \n");
+ DPRINT1("Verify Hive Header failed:\n");
DPRINT1(" Signature: 0x%x, expected 0x%x; Major: 0x%x, expected
0x%x\n",
BaseBlock->Signature, HV_SIGNATURE, BaseBlock->Major, HSYS_MAJOR);
- DPRINT1(" Minor: 0x%x is not >= 0x%x; Type: 0x%x, expected
0x%x\n",
+ DPRINT1(" Minor: 0x%x expected to be >= 0x%x; Type: 0x%x, expected
0x%x\n",
BaseBlock->Minor, HSYS_MINOR, BaseBlock->Type,
HFILE_TYPE_PRIMARY);
DPRINT1(" Format: 0x%x, expected 0x%x; Cluster: 0x%x, expected
1\n",
BaseBlock->Format, HBASE_FORMAT_MEMORY, BaseBlock->Cluster);
@@ -48,10 +47,8 @@
/**
* @name HvpFreeHiveBins
*
- * Internal function to free all bin storage associated with hive
- * descriptor.
- */
-
+ * Internal function to free all bin storage associated with a hive descriptor.
+ */
VOID CMAPI
HvpFreeHiveBins(
PHHIVE Hive)
@@ -82,27 +79,98 @@
}
/**
+ * @name HvpAllocBaseBlockAligned
+ *
+ * Internal helper function to allocate cluster-aligned hive base blocks.
+ */
+static __inline PHBASE_BLOCK
+HvpAllocBaseBlockAligned(
+ IN PHHIVE Hive,
+ IN BOOLEAN Paged,
+ IN ULONG Tag)
+{
+ PHBASE_BLOCK BaseBlock;
+ ULONG Alignment;
+
+ ASSERT(sizeof(HBASE_BLOCK) >= (HSECTOR_SIZE * Hive->Cluster));
+
+ /* Allocate the buffer */
+ BaseBlock = Hive->Allocate(Hive->BaseBlockAlloc, Paged, Tag);
+ if (!BaseBlock) return NULL;
+
+ /* Check for, and enforce, alignment */
+ Alignment = Hive->Cluster * HSECTOR_SIZE -1;
+ if ((ULONG_PTR)BaseBlock & Alignment)
+ {
+ /* Free the old header and reallocate a new one, always paged */
+ Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
+ BaseBlock = Hive->Allocate(PAGE_SIZE, TRUE, Tag);
+ if (!BaseBlock) return NULL;
+
+ Hive->BaseBlockAlloc = PAGE_SIZE;
+ }
+
+ return BaseBlock;
+}
+
+/**
+ * @name HvpInitFileName
+ *
+ * Internal function to initialize the UNICODE NULL-terminated hive file name
+ * member of a hive header by copying the last 31 characters of the file name.
+ * Mainly used for debugging purposes.
+ */
+static VOID
+HvpInitFileName(
+ IN OUT PHBASE_BLOCK BaseBlock,
+ IN PCUNICODE_STRING FileName OPTIONAL)
+{
+ ULONG_PTR Offset;
+ SIZE_T Length;
+
+ /* Always NULL-initialize */
+ RtlZeroMemory(BaseBlock->FileName, (HIVE_FILENAME_MAXLEN + 1) * sizeof(WCHAR));
+
+ /* Copy the 31 last characters of the hive file name if any */
+ if (!FileName) return;
+
+ if (FileName->Length / sizeof(WCHAR) <= HIVE_FILENAME_MAXLEN)
+ {
+ Offset = 0;
+ Length = FileName->Length;
+ }
+ else
+ {
+ Offset = FileName->Length / sizeof(WCHAR) - HIVE_FILENAME_MAXLEN;
+ Length = HIVE_FILENAME_MAXLEN * sizeof(WCHAR);
+ }
+
+ RtlCopyMemory(BaseBlock->FileName, FileName->Buffer + Offset, Length);
+}
+
+/**
* @name HvpCreateHive
*
- * Internal helper function to initialize hive descriptor structure for
- * newly created hive.
+ * Internal helper function to initialize a hive descriptor structure
+ * for a newly created hive in memory.
*
* @see HvInitialize
*/
-
NTSTATUS CMAPI
HvpCreateHive(
- PHHIVE RegistryHive,
- PCUNICODE_STRING FileName OPTIONAL)
+ IN OUT PHHIVE RegistryHive,
+ IN PCUNICODE_STRING FileName OPTIONAL)
{
PHBASE_BLOCK BaseBlock;
ULONG Index;
- BaseBlock = RegistryHive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM);
+ /* Allocate the base block */
+ BaseBlock = HvpAllocBaseBlockAligned(RegistryHive, FALSE, TAG_CM);
if (BaseBlock == NULL)
return STATUS_NO_MEMORY;
- RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK));
+ /* Clear it */
+ RtlZeroMemory(BaseBlock, RegistryHive->BaseBlockAlloc);
BaseBlock->Signature = HV_SIGNATURE;
BaseBlock->Major = HSYS_MAJOR;
@@ -114,37 +182,29 @@
BaseBlock->Length = 0;
BaseBlock->Sequence1 = 1;
BaseBlock->Sequence2 = 1;
-
- /* Copy the 31 last characters of the hive file name if any */
- if (FileName)
- {
- if (FileName->Length / sizeof(WCHAR) <= HIVE_FILENAME_MAXLEN)
- {
- RtlCopyMemory(BaseBlock->FileName,
- FileName->Buffer,
- FileName->Length);
- }
- else
- {
- RtlCopyMemory(BaseBlock->FileName,
- FileName->Buffer +
- FileName->Length / sizeof(WCHAR) - HIVE_FILENAME_MAXLEN,
- HIVE_FILENAME_MAXLEN * sizeof(WCHAR));
- }
-
- /* NULL-terminate */
- BaseBlock->FileName[HIVE_FILENAME_MAXLEN] = L'\0';
- }
-
- BaseBlock->CheckSum = HvpHiveHeaderChecksum(BaseBlock);
-
+ BaseBlock->TimeStamp.QuadPart = 0ULL;
+
+ /*
+ * No need to compute the checksum since
+ * the hive resides only in memory so far.
+ */
+ BaseBlock->CheckSum = 0;
+
+ /* Set default boot type */
+ BaseBlock->BootType = 0;
+
+ /* Setup hive data */
RegistryHive->BaseBlock = BaseBlock;
+ RegistryHive->Version = BaseBlock->Minor; // == HSYS_MINOR
+
for (Index = 0; Index < 24; Index++)
{
RegistryHive->Storage[Stable].FreeDisplay[Index] = HCELL_NIL;
RegistryHive->Storage[Volatile].FreeDisplay[Index] = HCELL_NIL;
}
+ HvpInitFileName(BaseBlock, FileName);
+
return STATUS_SUCCESS;
}
@@ -152,16 +212,16 @@
* @name HvpInitializeMemoryHive
*
* Internal helper function to initialize hive descriptor structure for
- * a hive stored in memory. The data of the hive are copied and it is
- * prepared for read/write access.
+ * an existing hive stored in memory. The data of the hive is copied
+ * and it is prepared for read/write access.
*
* @see HvInitialize
*/
-
NTSTATUS CMAPI
HvpInitializeMemoryHive(
PHHIVE Hive,
- PVOID ChunkBase)
+ PHBASE_BLOCK ChunkBase,
+ IN PCUNICODE_STRING FileName OPTIONAL)
{
SIZE_T BlockIndex;
PHBIN Bin, NewBin;
@@ -170,23 +230,26 @@
PULONG BitmapBuffer;
SIZE_T ChunkSize;
- ChunkSize = ((PHBASE_BLOCK)ChunkBase)->Length;
+ ChunkSize = ChunkBase->Length;
DPRINT("ChunkSize: %lx\n", ChunkSize);
if (ChunkSize < sizeof(HBASE_BLOCK) ||
- !HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
+ !HvpVerifyHiveHeader(ChunkBase))
{
DPRINT1("Registry is corrupt: ChunkSize %lu < sizeof(HBASE_BLOCK) %lu,
"
- "or HvpVerifyHiveHeader() failed\n", ChunkSize,
(SIZE_T)sizeof(HBASE_BLOCK));
+ "or HvpVerifyHiveHeader() failed\n", ChunkSize,
sizeof(HBASE_BLOCK));
return STATUS_REGISTRY_CORRUPT;
}
- Hive->BaseBlock = Hive->Allocate(sizeof(HBASE_BLOCK), FALSE, TAG_CM);
+ /* Allocate the base block */
+ Hive->BaseBlock = HvpAllocBaseBlockAligned(Hive, FALSE, TAG_CM);
if (Hive->BaseBlock == NULL)
- {
return STATUS_NO_MEMORY;
- }
+
RtlCopyMemory(Hive->BaseBlock, ChunkBase, sizeof(HBASE_BLOCK));
+
+ /* Setup hive data */
+ Hive->Version = ChunkBase->Minor;
/*
* Build a block list from the in-memory chunk and copy the data as
@@ -200,7 +263,7 @@
if (Hive->Storage[Stable].BlockList == NULL)
{
DPRINT1("Allocating block list failed\n");
- Hive->Free(Hive->BaseBlock, 0);
+ Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
return STATUS_NO_MEMORY;
}
@@ -212,16 +275,16 @@
{
DPRINT1("Invalid bin at BlockIndex %lu, Signature 0x%x, Size
0x%x\n",
(unsigned long)BlockIndex, (unsigned)Bin->Signature,
(unsigned)Bin->Size);
- Hive->Free(Hive->BaseBlock, 0);
Hive->Free(Hive->Storage[Stable].BlockList, 0);
+ Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
return STATUS_REGISTRY_CORRUPT;
}
NewBin = Hive->Allocate(Bin->Size, TRUE, TAG_CM);
if (NewBin == NULL)
{
- Hive->Free(Hive->BaseBlock, 0);
Hive->Free(Hive->Storage[Stable].BlockList, 0);
+ Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
return STATUS_NO_MEMORY;
}
@@ -246,7 +309,7 @@
if (HvpCreateHiveFreeCellList(Hive))
{
HvpFreeHiveBins(Hive);
- Hive->Free(Hive->BaseBlock, 0);
+ Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
return STATUS_NO_MEMORY;
}
@@ -256,18 +319,20 @@
if (BitmapBuffer == NULL)
{
HvpFreeHiveBins(Hive);
- Hive->Free(Hive->BaseBlock, 0);
+ Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
return STATUS_NO_MEMORY;
}
RtlInitializeBitMap(&Hive->DirtyVector, BitmapBuffer, BitmapSize * 8);
RtlClearAllBits(&Hive->DirtyVector);
+ HvpInitFileName(Hive->BaseBlock, FileName);
+
return STATUS_SUCCESS;
}
/**
- * @name HvpInitializeMemoryInplaceHive
+ * @name HvpInitializeFlatHive
*
* Internal helper function to initialize hive descriptor structure for
* a hive stored in memory. The in-memory data of the hive are directly
@@ -275,20 +340,22 @@
*
* @see HvInitialize
*/
-
NTSTATUS CMAPI
-HvpInitializeMemoryInplaceHive(
+HvpInitializeFlatHive(
PHHIVE Hive,
- PVOID ChunkBase)
-{
- if (!HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
- {
+ PHBASE_BLOCK ChunkBase)
+{
+ if (!HvpVerifyHiveHeader(ChunkBase))
return STATUS_REGISTRY_CORRUPT;
- }
-
- Hive->BaseBlock = (PHBASE_BLOCK)ChunkBase;
+
+ /* Setup hive data */
+ Hive->BaseBlock = ChunkBase;
+ Hive->Version = ChunkBase->Minor;
+ Hive->Flat = TRUE;
Hive->ReadOnly = TRUE;
- Hive->Flat = TRUE;
+
+ /* Set default boot type */
+ ChunkBase->BootType = 0;
return STATUS_SUCCESS;
}
@@ -310,25 +377,15 @@
IN PLARGE_INTEGER TimeStamp)
{
PHBASE_BLOCK BaseBlock;
- ULONG Alignment;
ULONG Result;
ULONG Offset = 0;
- ASSERT(sizeof(HBASE_BLOCK) >= (HBLOCK_SIZE * Hive->Cluster));
-
- /* Assume failure and allocate the buffer */
- *HiveBaseBlock = 0;
- BaseBlock = Hive->Allocate(sizeof(HBASE_BLOCK), TRUE, TAG_CM);
+
+ ASSERT(sizeof(HBASE_BLOCK) >= (HSECTOR_SIZE * Hive->Cluster));
+
+ /* Assume failure and allocate the base block */
+ *HiveBaseBlock = NULL;
+ BaseBlock = HvpAllocBaseBlockAligned(Hive, TRUE, TAG_CM);
if (!BaseBlock) return NoMemory;
-
- /* Check for, and enforce, alignment */
- Alignment = Hive->Cluster * HBLOCK_SIZE -1;
- if ((ULONG_PTR)BaseBlock & Alignment)
- {
- /* Free the old header */
- Hive->Free(BaseBlock, 0);
- BaseBlock = Hive->Allocate(PAGE_SIZE, TRUE, TAG_CM);
- if (!BaseBlock) return NoMemory;
- }
/* Clear it */
RtlZeroMemory(BaseBlock, sizeof(HBASE_BLOCK));
@@ -338,7 +395,7 @@
HFILE_TYPE_PRIMARY,
&Offset,
BaseBlock,
- Hive->Cluster * HBLOCK_SIZE);
+ Hive->Cluster * HSECTOR_SIZE);
/* Couldn't read: assume it's not a hive */
if (!Result) return NotHive;
@@ -353,8 +410,10 @@
}
NTSTATUS CMAPI
-HvLoadHive(IN PHHIVE Hive)
-{
+HvLoadHive(IN PHHIVE Hive,
+ IN PCUNICODE_STRING FileName OPTIONAL)
+{
+ NTSTATUS Status;
PHBASE_BLOCK BaseBlock = NULL;
ULONG Result;
LARGE_INTEGER TimeStamp;
@@ -391,12 +450,16 @@
/* Setup hive data */
Hive->BaseBlock = BaseBlock;
- Hive->Version = Hive->BaseBlock->Minor;
+ Hive->Version = BaseBlock->Minor;
/* Allocate a buffer large enough to hold the hive */
- FileSize = HBLOCK_SIZE + BaseBlock->Length;
+ FileSize = HBLOCK_SIZE + BaseBlock->Length; // == sizeof(HBASE_BLOCK) +
BaseBlock->Length;
HiveData = Hive->Allocate(FileSize, TRUE, TAG_CM);
- if (!HiveData) return STATUS_INSUFFICIENT_RESOURCES;
+ if (!HiveData)
+ {
+ Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
/* Now read the whole hive */
Result = Hive->FileRead(Hive,
@@ -404,14 +467,23 @@
&Offset,
HiveData,
FileSize);
- if (!Result) return STATUS_NOT_REGISTRY_FILE;
+ if (!Result)
+ {
+ Hive->Free(HiveData, FileSize);
+ Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
+ return STATUS_NOT_REGISTRY_FILE;
+ }
// This is a HACK!
/* Free our base block... it's usless in this implementation */
- Hive->Free(BaseBlock, 0);
+ Hive->Free(BaseBlock, Hive->BaseBlockAlloc);
/* Initialize the hive directly from memory */
- return HvpInitializeMemoryHive(Hive, HiveData);
+ Status = HvpInitializeMemoryHive(Hive, HiveData, FileName);
+ if (!NT_SUCCESS(Status))
+ Hive->Free(HiveData, FileSize);
+
+ return Status;
}
/**
@@ -444,7 +516,6 @@
*
* @see HvFree
*/
-
NTSTATUS CMAPI
HvInitialize(
PHHIVE RegistryHive,
@@ -464,8 +535,6 @@
NTSTATUS Status;
PHHIVE Hive = RegistryHive;
- UNREFERENCED_PARAMETER(FileType);
-
/*
* Create a new hive structure that will hold all the maintenance data.
*/
@@ -474,13 +543,18 @@
Hive->Allocate = Allocate;
Hive->Free = Free;
+ Hive->FileSetSize = FileSetSize;
+ Hive->FileWrite = FileWrite;
Hive->FileRead = FileRead;
- Hive->FileWrite = FileWrite;
- Hive->FileSetSize = FileSetSize;
Hive->FileFlush = FileFlush;
+
+ Hive->RefreshCount = 0;
Hive->StorageTypeCount = HTYPE_COUNT;
- Hive->Cluster = 1;
+ Hive->Cluster = Cluster;
+ Hive->BaseBlockAlloc = sizeof(HBASE_BLOCK); // == HBLOCK_SIZE
+
Hive->Version = HSYS_MINOR;
+ Hive->Log = (FileType == HFILE_TYPE_LOG);
Hive->HiveFlags = HiveFlags & ~HIVE_NOLAZYFLUSH;
switch (OperationType)
@@ -490,16 +564,16 @@
break;
case HINIT_MEMORY:
- Status = HvpInitializeMemoryHive(Hive, HiveData);
+ Status = HvpInitializeMemoryHive(Hive, HiveData, FileName);
break;
case HINIT_FLAT:
- Status = HvpInitializeMemoryInplaceHive(Hive, HiveData);
+ Status = HvpInitializeFlatHive(Hive, HiveData);
break;
case HINIT_FILE:
{
- Status = HvLoadHive(Hive);
+ Status = HvLoadHive(Hive, FileName);
if ((Status != STATUS_SUCCESS) &&
(Status != STATUS_REGISTRY_RECOVERED))
{
@@ -512,6 +586,12 @@
break;
}
+ case HINIT_MEMORY_INPLACE:
+ // Status = HvpInitializeMemoryInplaceHive(Hive, HiveData);
+ // break;
+
+ case HINIT_MAPFILE:
+
default:
/* FIXME: A better return status value is needed */
Status = STATUS_NOT_IMPLEMENTED;
@@ -520,6 +600,9 @@
if (!NT_SUCCESS(Status)) return Status;
+ /* HACK: ROS: Init root key cell and prepare the hive */
+ // r31253
+ // if (OperationType == HINIT_CREATE) CmCreateRootNode(Hive, L"");
if (OperationType != HINIT_CREATE) CmPrepareHive(Hive);
return Status;
@@ -531,7 +614,6 @@
* Free all stroage and handles associated with hive descriptor.
* But do not free the hive descriptor itself.
*/
-
VOID CMAPI
HvFree(
PHHIVE RegistryHive)
@@ -549,7 +631,7 @@
/* Free the BaseBlock */
if (RegistryHive->BaseBlock)
{
- RegistryHive->Free(RegistryHive->BaseBlock, 0);
+ RegistryHive->Free(RegistryHive->BaseBlock,
RegistryHive->BaseBlockAlloc);
RegistryHive->BaseBlock = NULL;
}
}