- CmiAddValueToKey(): Double the size of the value list cell when it is completely filled. This prevents fragmentation if a key got lots of values.

- CmiDeleteValueFromKey(): Fix corruption of the value list cell when a value is removed from the list.
- Rename the variable VBOffset to ValueCellOffset.

svn path=/trunk/; revision=11047
This commit is contained in:
Eric Kohl 2004-09-25 15:25:28 +00:00
parent 1f82196fd5
commit 23a709ca5f

View file

@ -2611,43 +2611,43 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
if (ValueList != NULL) /* Enumerate all values */
for (i = 0; i < SubKey->KeyCell->NumberOfValues; i++)
{ {
/* Enumerate all values */ /* Get pointer to value cell */
for (i = 0; i < SubKey->KeyCell->NumberOfValues; i++) ValueCell = CmiGetCell(RegistryHive,
ValueList->ValueOffset[i],
NULL);
if (ValueCell == NULL)
{ {
/* Get pointer to value cell */ DPRINT("CmiGetCell() failed\n");
ValueCell = CmiGetCell (RegistryHive, return STATUS_UNSUCCESSFUL;
ValueList->ValueOffset[i], }
NULL);
if (ValueCell != NULL) if (ValueCell->DataSize > sizeof(BLOCK_OFFSET))
{
DataCell = CmiGetCell (RegistryHive,
ValueCell->DataOffset,
NULL);
if (DataCell == NULL)
{ {
if (ValueCell->DataSize > sizeof(BLOCK_OFFSET)) DPRINT("CmiGetCell() failed\n");
{ return STATUS_UNSUCCESSFUL;
DataCell = CmiGetCell (RegistryHive, }
ValueCell->DataOffset,
NULL);
if (DataCell == NULL)
{
DPRINT("CmiGetCell() failed\n");
return STATUS_UNSUCCESSFUL;
}
if (DataCell != NULL) if (DataCell != NULL)
{ {
/* Destroy data cell */ /* Destroy data cell */
CmiDestroyCell (RegistryHive,
DataCell,
ValueCell->DataOffset);
}
}
/* Destroy value cell */
CmiDestroyCell (RegistryHive, CmiDestroyCell (RegistryHive,
ValueCell, DataCell,
ValueList->ValueOffset[i]); ValueCell->DataOffset);
} }
} }
/* Destroy value cell */
CmiDestroyCell (RegistryHive,
ValueCell,
ValueList->ValueOffset[i]);
} }
/* Destroy value list cell */ /* Destroy value list cell */
@ -2657,6 +2657,9 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
SubKey->KeyCell->NumberOfValues = 0; SubKey->KeyCell->NumberOfValues = 0;
SubKey->KeyCell->ValueListOffset = (BLOCK_OFFSET)-1; SubKey->KeyCell->ValueListOffset = (BLOCK_OFFSET)-1;
CmiMarkBlockDirty(RegistryHive,
SubKey->KeyCellOffset);
} }
/* Remove the key from the parent key's hash block */ /* Remove the key from the parent key's hash block */
@ -2744,7 +2747,9 @@ CmiRemoveSubKey(PREGISTRY_HIVE RegistryHive,
SubKey->KeyCell = NULL; SubKey->KeyCell = NULL;
SubKey->KeyCellOffset = (BLOCK_OFFSET)-1; SubKey->KeyCellOffset = (BLOCK_OFFSET)-1;
return(STATUS_SUCCESS); DPRINT("CmiRemoveSubKey() done\n");
return STATUS_SUCCESS;
} }
@ -2894,8 +2899,11 @@ CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
else if (KeyCell->NumberOfValues >= else if (KeyCell->NumberOfValues >=
(((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET))) (((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET)))
{ {
#if 0
CellSize = sizeof(VALUE_LIST_CELL) + CellSize = sizeof(VALUE_LIST_CELL) +
((KeyCell->NumberOfValues + REG_VALUE_LIST_CELL_MULTIPLE) * sizeof(BLOCK_OFFSET)); ((KeyCell->NumberOfValues + REG_VALUE_LIST_CELL_MULTIPLE) * sizeof(BLOCK_OFFSET));
#endif
CellSize = 2 * (ULONG)ABS_VALUE(ValueListCell->CellSize);
Status = CmiAllocateCell (RegistryHive, Status = CmiAllocateCell (RegistryHive,
CellSize, CellSize,
(PVOID) &NewValueListCell, (PVOID) &NewValueListCell,
@ -2954,13 +2962,13 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
{ {
PVALUE_LIST_CELL ValueListCell; PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL CurValueCell; PVALUE_CELL CurValueCell;
ULONG i; ULONG i;
NTSTATUS Status;
ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL); ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL);
if (ValueListCell == NULL) if (ValueListCell == NULL)
{ {
DPRINT("CmiGetBlock() failed\n"); DPRINT1("CmiGetBlock() failed\n");
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2971,50 +2979,58 @@ CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
CurValueCell = CmiGetCell (RegistryHive, ValueListCell->ValueOffset[i], NULL); CurValueCell = CmiGetCell (RegistryHive, ValueListCell->ValueOffset[i], NULL);
if (CurValueCell == NULL) if (CurValueCell == NULL)
{ {
DPRINT("CmiGetBlock() failed\n"); DPRINT1("CmiGetBlock() failed\n");
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
if ((CurValueCell != NULL) && if (CmiComparePackedNames(ValueName,
CmiComparePackedNames(ValueName,
CurValueCell->Name, CurValueCell->Name,
CurValueCell->NameSize, CurValueCell->NameSize,
(BOOLEAN)((CurValueCell->Flags & REG_VALUE_NAME_PACKED) ? TRUE : FALSE))) (BOOLEAN)((CurValueCell->Flags & REG_VALUE_NAME_PACKED) ? TRUE : FALSE)))
{ {
CmiDestroyValueCell(RegistryHive, CurValueCell, ValueListCell->ValueOffset[i]); Status = CmiDestroyValueCell(RegistryHive,
CurValueCell,
if ((KeyCell->NumberOfValues - 1) < i) ValueListCell->ValueOffset[i]);
if (CurValueCell == NULL)
{ {
RtlCopyMemory(&ValueListCell->ValueOffset[i], DPRINT1("CmiDestroyValueCell() failed\n");
return Status;
}
if (i < (KeyCell->NumberOfValues - 1))
{
RtlMoveMemory(&ValueListCell->ValueOffset[i],
&ValueListCell->ValueOffset[i + 1], &ValueListCell->ValueOffset[i + 1],
sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues - 1 - i)); sizeof(BLOCK_OFFSET) * (KeyCell->NumberOfValues - 1 - i));
} }
ValueListCell->ValueOffset[KeyCell->NumberOfValues - 1] = 0;
KeyCell->NumberOfValues--;
if (KeyCell->NumberOfValues == 0)
{
CmiDestroyCell(RegistryHive,
ValueListCell,
KeyCell->ValueListOffset);
KeyCell->ValueListOffset = -1;
}
else else
{ {
RtlZeroMemory(&ValueListCell->ValueOffset[i], sizeof(BLOCK_OFFSET)); CmiMarkBlockDirty(RegistryHive,
KeyCell->ValueListOffset);
} }
KeyCell->NumberOfValues -= 1; CmiMarkBlockDirty(RegistryHive,
break; KeyCellOffset);
return STATUS_SUCCESS;
} }
} }
if (KeyCell->NumberOfValues == 0) DPRINT("Couldn't find the desired value\n");
{
CmiDestroyCell (RegistryHive,
ValueListCell,
KeyCell->ValueListOffset);
}
else
{
CmiMarkBlockDirty(RegistryHive,
KeyCell->ValueListOffset);
}
CmiMarkBlockDirty(RegistryHive, return STATUS_OBJECT_NAME_NOT_FOUND;
KeyCellOffset);
return STATUS_SUCCESS;
} }
@ -3189,44 +3205,45 @@ CmiAllocateValueCell(PREGISTRY_HIVE RegistryHive,
NTSTATUS NTSTATUS
CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive, CmiDestroyValueCell(PREGISTRY_HIVE RegistryHive,
PVALUE_CELL ValueCell, PVALUE_CELL ValueCell,
BLOCK_OFFSET VBOffset) BLOCK_OFFSET ValueCellOffset)
{ {
NTSTATUS Status; NTSTATUS Status;
PVOID pBlock; PVOID DataCell;
PHBIN pBin; PHBIN Bin;
DPRINT("CmiDestroyValueCell(Cell %p Offset %lx)\n", ValueCell, VBOffset); DPRINT("CmiDestroyValueCell(Cell %p Offset %lx)\n",
ValueCell, ValueCellOffset);
VERIFY_VALUE_CELL(ValueCell); VERIFY_VALUE_CELL(ValueCell);
/* Destroy the data cell */ /* Destroy the data cell */
if (ValueCell->DataSize > sizeof(BLOCK_OFFSET)) if (ValueCell->DataSize > sizeof(BLOCK_OFFSET))
{ {
pBlock = CmiGetCell (RegistryHive, ValueCell->DataOffset, &pBin); DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, &Bin);
if (pBlock == NULL) if (DataCell == NULL)
{ {
DPRINT("CmiGetBlock() failed\n"); DPRINT("CmiGetCell() failed\n");
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
Status = CmiDestroyCell (RegistryHive, pBlock, ValueCell->DataOffset); Status = CmiDestroyCell (RegistryHive, DataCell, ValueCell->DataOffset);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return Status; return Status;
} }
/* Update time of heap */ /* Update time of heap */
if (!IsNoFileHive(RegistryHive)) if (!IsNoFileHive(RegistryHive))
NtQuerySystemTime(&pBin->DateModified); NtQuerySystemTime(&Bin->DateModified);
} }
/* Destroy the value cell */ /* Destroy the value cell */
Status = CmiDestroyCell (RegistryHive, ValueCell, VBOffset); Status = CmiDestroyCell (RegistryHive, ValueCell, ValueCellOffset);
/* Update time of heap */ /* Update time of heap */
if (!IsNoFileHive(RegistryHive) && CmiGetCell (RegistryHive, VBOffset, &pBin)) if (!IsNoFileHive(RegistryHive) && CmiGetCell (RegistryHive, ValueCellOffset, &Bin))
{ {
NtQuerySystemTime(&pBin->DateModified); NtQuerySystemTime(&Bin->DateModified);
} }
return Status; return Status;