mirror of
https://github.com/reactos/reactos.git
synced 2024-11-27 05:23:33 +08:00
[CMLIB] Fix the bin during hive initialization from memory if it's corrupt
As we iterate over the chunk hive data pointer for hive bins that we are going to enlist, we might encounter one or several bins that would get corrupted during a premature abortion of a registry writing operation such as due to a power outage of the system, hardware malfunction, etc. Corruption at the level of hive bins is nasty because they contain actual cell data of registry information such as keys, values etc. Assuming a bin is corrupt in part we can fix it by recovering some of the bin properties that, theoretically, could be fixed -- namely the signature, size and offset. For size and offset we are more or less safe because a bin typically has a size of a block, and the offset is the coordinate index of where a hive bin should lay at.
This commit is contained in:
parent
27917c14ed
commit
279f8f8864
@ -368,13 +368,31 @@ HvpInitializeMemoryHive(
|
||||
{
|
||||
Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HBLOCK_SIZE);
|
||||
if (Bin->Signature != HV_HBIN_SIGNATURE ||
|
||||
(Bin->Size % HBLOCK_SIZE) != 0)
|
||||
(Bin->Size % HBLOCK_SIZE) != 0 ||
|
||||
(Bin->FileOffset / HBLOCK_SIZE) != BlockIndex)
|
||||
{
|
||||
DPRINT1("Invalid bin at BlockIndex %lu, Signature 0x%x, Size 0x%x\n",
|
||||
/*
|
||||
* Bin is toast but luckily either the signature, size or offset
|
||||
* is out of order. For the signature it is obvious what we are going
|
||||
* to do, for the offset we are re-positioning the bin back to where it
|
||||
* was and for the size we will set it up to a block size, since technically
|
||||
* a hive bin is large as a block itself to accommodate cells.
|
||||
*/
|
||||
if (!CmIsSelfHealEnabled(FALSE))
|
||||
{
|
||||
DPRINT1("Invalid bin at BlockIndex %lu, Signature 0x%x, Size 0x%x. Self-heal not possible!\n",
|
||||
(unsigned long)BlockIndex, (unsigned)Bin->Signature, (unsigned)Bin->Size);
|
||||
Hive->Free(Hive->Storage[Stable].BlockList, 0);
|
||||
Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
|
||||
return STATUS_REGISTRY_CORRUPT;
|
||||
Hive->Free(Hive->Storage[Stable].BlockList, 0);
|
||||
Hive->Free(Hive->BaseBlock, Hive->BaseBlockAlloc);
|
||||
return STATUS_REGISTRY_CORRUPT;
|
||||
}
|
||||
|
||||
/* Fix this bin */
|
||||
Bin->Signature = HV_HBIN_SIGNATURE;
|
||||
Bin->Size = HBLOCK_SIZE;
|
||||
Bin->FileOffset = BlockIndex * HBLOCK_SIZE;
|
||||
ChunkBase->BootType |= HBOOT_TYPE_SELF_HEAL;
|
||||
DPRINT1("Bin at index %lu is corrupt and it has been repaired!\n", (unsigned long)BlockIndex);
|
||||
}
|
||||
|
||||
NewBin = Hive->Allocate(Bin->Size, TRUE, TAG_CM);
|
||||
|
Loading…
Reference in New Issue
Block a user