mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
- 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:
parent
1f82196fd5
commit
23a709ca5f
1 changed files with 89 additions and 72 deletions
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue