Fixed a potential cause of registry corruption in NtSetValueKey():

- Mark all modified cells dirty.
- Allocate value cell after value list cell has been created or resized.

svn path=/trunk/; revision=7643
This commit is contained in:
Eric Kohl 2004-01-15 09:26:56 +00:00
parent c6f4c292e9
commit 9dfb5ee1cc
3 changed files with 40 additions and 33 deletions

View file

@ -502,15 +502,16 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive,
OUT PVALUE_CELL *ValueCell); OUT PVALUE_CELL *ValueCell);
NTSTATUS NTSTATUS
CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell, IN PKEY_CELL KeyCell,
IN PUNICODE_STRING ValueName, IN BLOCK_OFFSET KeyCellOffset,
OUT PVALUE_CELL *pValueCell, IN PUNICODE_STRING ValueName,
OUT BLOCK_OFFSET *pVBOffset); OUT PVALUE_CELL *pValueCell,
OUT BLOCK_OFFSET *pValueCellOffset);
NTSTATUS NTSTATUS
CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive, CmiDeleteValueFromKey(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell, IN PKEY_CELL KeyCell,
IN BLOCK_OFFSET KeyCellOffset, IN BLOCK_OFFSET KeyCellOffset,
IN PUNICODE_STRING ValueName); IN PUNICODE_STRING ValueName);

View file

@ -1276,13 +1276,10 @@ NtSetValueKey(IN HANDLE KeyHandle,
DPRINT("Allocate new value cell\n"); DPRINT("Allocate new value cell\n");
Status = CmiAddValueToKey(RegistryHive, Status = CmiAddValueToKey(RegistryHive,
KeyCell, KeyCell,
KeyObject->KeyCellOffset,
ValueName, ValueName,
&ValueCell, &ValueCell,
&ValueCellOffset); &ValueCellOffset);
if (NT_SUCCESS(Status))
{
CmiMarkBlockDirty(RegistryHive, ValueCellOffset);
}
} }
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))

View file

@ -2818,31 +2818,23 @@ CmiGetValueFromKeyByIndex(IN PREGISTRY_HIVE RegistryHive,
NTSTATUS NTSTATUS
CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive, CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
IN PKEY_CELL KeyCell, IN PKEY_CELL KeyCell,
IN BLOCK_OFFSET KeyCellOffset,
IN PUNICODE_STRING ValueName, IN PUNICODE_STRING ValueName,
OUT PVALUE_CELL *pValueCell, OUT PVALUE_CELL *pValueCell,
OUT BLOCK_OFFSET *pVBOffset) OUT BLOCK_OFFSET *pValueCellOffset)
{ {
PVALUE_LIST_CELL NewValueListCell; PVALUE_LIST_CELL NewValueListCell;
PVALUE_LIST_CELL ValueListCell; PVALUE_LIST_CELL ValueListCell;
PVALUE_CELL NewValueCell; PVALUE_CELL NewValueCell;
BLOCK_OFFSET VLBOffset; BLOCK_OFFSET NewValueListCellOffset;
BLOCK_OFFSET VBOffset; BLOCK_OFFSET ValueListCellOffset;
BLOCK_OFFSET NewValueCellOffset;
ULONG CellSize; ULONG CellSize;
NTSTATUS Status; NTSTATUS Status;
Status = CmiAllocateValueCell(RegistryHive,
&NewValueCell,
&VBOffset,
ValueName);
if (!NT_SUCCESS(Status))
{
return Status;
}
DPRINT("KeyCell->ValuesOffset %lu\n", (ULONG)KeyCell->ValueListOffset); DPRINT("KeyCell->ValuesOffset %lu\n", (ULONG)KeyCell->ValueListOffset);
ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL); ValueListCell = CmiGetCell (RegistryHive, KeyCell->ValueListOffset, NULL);
if (ValueListCell == NULL) if (ValueListCell == NULL)
{ {
CellSize = sizeof(VALUE_LIST_CELL) + CellSize = sizeof(VALUE_LIST_CELL) +
@ -2850,14 +2842,15 @@ CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
Status = CmiAllocateCell (RegistryHive, Status = CmiAllocateCell (RegistryHive,
CellSize, CellSize,
(PVOID) &ValueListCell, (PVOID) &ValueListCell,
&VLBOffset); &ValueListCellOffset);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset);
return Status; return Status;
} }
KeyCell->ValueListOffset = VLBOffset;
KeyCell->ValueListOffset = ValueListCellOffset;
CmiMarkBlockDirty(RegistryHive, KeyCellOffset);
CmiMarkBlockDirty(RegistryHive, ValueListCellOffset);
} }
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)))
@ -2867,10 +2860,9 @@ CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
Status = CmiAllocateCell (RegistryHive, Status = CmiAllocateCell (RegistryHive,
CellSize, CellSize,
(PVOID) &NewValueListCell, (PVOID) &NewValueListCell,
&VLBOffset); &NewValueListCellOffset);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
CmiDestroyValueCell(RegistryHive, NewValueCell, VBOffset);
return Status; return Status;
} }
@ -2878,8 +2870,12 @@ CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
&ValueListCell->ValueOffset[0], &ValueListCell->ValueOffset[0],
sizeof(BLOCK_OFFSET) * KeyCell->NumberOfValues); sizeof(BLOCK_OFFSET) * KeyCell->NumberOfValues);
CmiDestroyCell (RegistryHive, ValueListCell, KeyCell->ValueListOffset); CmiDestroyCell (RegistryHive, ValueListCell, KeyCell->ValueListOffset);
KeyCell->ValueListOffset = VLBOffset; CmiMarkBlockDirty (RegistryHive, KeyCell->ValueListOffset);
KeyCell->ValueListOffset = NewValueListCellOffset;
ValueListCell = NewValueListCell; ValueListCell = NewValueListCell;
CmiMarkBlockDirty (RegistryHive, KeyCellOffset);
CmiMarkBlockDirty (RegistryHive, NewValueListCellOffset);
} }
DPRINT("KeyCell->NumberOfValues %lu, ValueListCell->CellSize %lu (%lu %lx)\n", DPRINT("KeyCell->NumberOfValues %lu, ValueListCell->CellSize %lu (%lu %lx)\n",
@ -2888,11 +2884,24 @@ CmiAddValueToKey(IN PREGISTRY_HIVE RegistryHive,
((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET), ((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET),
((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET)); ((ULONG)ABS_VALUE(ValueListCell->CellSize) - sizeof(VALUE_LIST_CELL)) / sizeof(BLOCK_OFFSET));
ValueListCell->ValueOffset[KeyCell->NumberOfValues] = VBOffset; Status = CmiAllocateValueCell(RegistryHive,
&NewValueCell,
&NewValueCellOffset,
ValueName);
if (!NT_SUCCESS(Status))
{
return Status;
}
ValueListCell->ValueOffset[KeyCell->NumberOfValues] = NewValueCellOffset;
KeyCell->NumberOfValues++; KeyCell->NumberOfValues++;
CmiMarkBlockDirty(RegistryHive, KeyCellOffset);
CmiMarkBlockDirty(RegistryHive, KeyCell->ValueListOffset);
CmiMarkBlockDirty(RegistryHive, NewValueCellOffset);
*pValueCell = NewValueCell; *pValueCell = NewValueCell;
*pVBOffset = VBOffset; *pValueCellOffset = NewValueCellOffset;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }