- Implement NtDeleteValueKey as a simple wrapper around CmDeleteValueKey so that handles, callbacks and SEH is abstracted away.

- Implement CmpRemoveValueFromList.
- Implement CmDeleteValueKey based on the old code, make it use CmpRemoveValueFromList.
- Remove CmiDeleteValueFromKey, CmiDestroyValueCell.

svn path=/trunk/; revision=26768
This commit is contained in:
Alex Ionescu 2007-05-14 00:44:26 +00:00
parent e834db9305
commit 4752c4b4c7
6 changed files with 218 additions and 184 deletions

View file

@ -261,10 +261,9 @@ CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive,
OUT PCM_KEY_VALUE *ValueCell);
NTSTATUS
CmiDeleteValueFromKey(IN PEREGISTRY_HIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN HCELL_INDEX KeyCellOffset,
IN PUNICODE_STRING ValueName);
NTAPI
CmDeleteValueKey(IN PKEY_OBJECT KeyControlBlock,
IN UNICODE_STRING ValueName);
NTSTATUS
CmiAllocateHashTableCell(IN PEREGISTRY_HIVE RegistryHive,
@ -308,10 +307,6 @@ NTSTATUS
CmiConnectHive(POBJECT_ATTRIBUTES KeyObjectAttributes,
PEREGISTRY_HIVE RegistryHive);
NTSTATUS
CmiDisconnectHive (POBJECT_ATTRIBUTES KeyObjectAttributes,
PEREGISTRY_HIVE *RegistryHive);
NTSTATUS
CmiInitHives(BOOLEAN SetupBoot);

View file

@ -1854,88 +1854,48 @@ NtSetValueKey(IN HANDLE KeyHandle,
return Status;
}
NTSTATUS STDCALL
NtDeleteValueKey (IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName)
NTSTATUS
NTAPI
NtDeleteValueKey(IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName)
{
PKEY_OBJECT KeyObject;
NTSTATUS Status;
REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo;
KPROCESSOR_MODE PreviousMode;
UNICODE_STRING CapturedValueName;
PKEY_OBJECT KeyObject;
NTSTATUS Status;
REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo;
REG_POST_OPERATION_INFORMATION PostOperationInfo;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PAGED_CODE();
PAGED_CODE();
PreviousMode = ExGetPreviousMode();
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_SET_VALUE,
CmpKeyObjectType,
PreviousMode,
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_SET_VALUE,
CmpKeyObjectType,
PreviousMode,
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
/* Do the callback */
DeleteValueKeyInfo.Object = (PVOID)KeyObject;
DeleteValueKeyInfo.ValueName = ValueName;
Status = CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey,
&DeleteValueKeyInfo);
if (NT_SUCCESS(Status))
{
return Status;
/* Call the internal API */
Status = CmDeleteValueKey(KeyObject, *ValueName);
/* Do the post callback */
PostOperationInfo.Object = (PVOID)KeyObject;
PostOperationInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey,
&PostOperationInfo);
}
Status = ProbeAndCaptureUnicodeString(&CapturedValueName,
PreviousMode,
ValueName);
if (!NT_SUCCESS(Status))
{
goto Fail;
}
DeleteValueKeyInfo.Object = (PVOID)KeyObject;
DeleteValueKeyInfo.ValueName = &CapturedValueName;
/* FIXME - check if value exists before calling the callbacks? */
Status = CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey, &DeleteValueKeyInfo);
if (!NT_SUCCESS(Status))
{
PostOperationInfo.Object = (PVOID)KeyObject;
PostOperationInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey, &PostOperationInfo);
ReleaseCapturedUnicodeString(&CapturedValueName,
PreviousMode);
Fail:
ObDereferenceObject(KeyObject);
return Status;
}
/* Acquire hive lock */
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
Status = CmiDeleteValueFromKey(KeyObject->RegistryHive,
KeyObject->KeyCell,
KeyObject->KeyCellOffset,
ValueName);
KeQuerySystemTime (&KeyObject->KeyCell->LastWriteTime);
HvMarkCellDirty (&KeyObject->RegistryHive->Hive, KeyObject->KeyCellOffset);
/* Release hive lock */
ExReleaseResourceLite(&CmpRegistryLock);
KeLeaveCriticalRegion();
ReleaseCapturedUnicodeString(&CapturedValueName,
PreviousMode);
PostOperationInfo.Object = (PVOID)KeyObject;
PostOperationInfo.Status = Status;
CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey, &PostOperationInfo);
ObDereferenceObject (KeyObject);
CmiSyncHives ();
return Status;
/* Dereference the key body and synchronize the hives */
ObDereferenceObject(KeyObject);
CmiSyncHives();
return Status;
}
/*

View file

@ -664,79 +664,6 @@ CmiGetValueFromKeyByIndex(IN PEREGISTRY_HIVE RegistryHive,
return STATUS_SUCCESS;
}
NTSTATUS
CmiDeleteValueFromKey(IN PEREGISTRY_HIVE RegistryHive,
IN PCM_KEY_NODE KeyCell,
IN HCELL_INDEX KeyCellOffset,
IN PUNICODE_STRING ValueName)
{
PVALUE_LIST_CELL ValueListCell;
PCM_KEY_VALUE CurValueCell;
ULONG i;
NTSTATUS Status;
if (KeyCell->ValueList.List == -1)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
ValueListCell = HvGetCell (&RegistryHive->Hive, KeyCell->ValueList.List);
VERIFY_VALUE_LIST_CELL(ValueListCell);
for (i = 0; i < KeyCell->ValueList.Count; i++)
{
CurValueCell = HvGetCell (&RegistryHive->Hive, ValueListCell->ValueOffset[i]);
if (CmiComparePackedNames(ValueName,
CurValueCell->Name,
CurValueCell->NameSize,
(BOOLEAN)((CurValueCell->Flags & REG_VALUE_NAME_PACKED) ? TRUE : FALSE)))
{
Status = CmiDestroyValueCell(RegistryHive,
CurValueCell,
ValueListCell->ValueOffset[i]);
if (CurValueCell == NULL)
{
DPRINT1("CmiDestroyValueCell() failed\n");
return Status;
}
if (i < (KeyCell->ValueList.Count - 1))
{
RtlMoveMemory(&ValueListCell->ValueOffset[i],
&ValueListCell->ValueOffset[i + 1],
sizeof(HCELL_INDEX) * (KeyCell->ValueList.Count - 1 - i));
}
ValueListCell->ValueOffset[KeyCell->ValueList.Count - 1] = 0;
KeyCell->ValueList.Count--;
if (KeyCell->ValueList.Count == 0)
{
HvFreeCell(&RegistryHive->Hive, KeyCell->ValueList.List);
KeyCell->ValueList.List = -1;
}
else
{
HvMarkCellDirty(&RegistryHive->Hive,
KeyCell->ValueList.List);
}
HvMarkCellDirty(&RegistryHive->Hive,
KeyCellOffset);
return STATUS_SUCCESS;
}
}
DPRINT("Couldn't find the desired value\n");
return STATUS_OBJECT_NAME_NOT_FOUND;
}
NTSTATUS
CmiAllocateHashTableCell (IN PEREGISTRY_HIVE RegistryHive,
OUT PHASH_TABLE_CELL *HashBlock,
@ -831,31 +758,6 @@ CmiRemoveKeyFromHashTable(PEREGISTRY_HIVE RegistryHive,
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
CmiDestroyValueCell(PEREGISTRY_HIVE RegistryHive,
PCM_KEY_VALUE ValueCell,
HCELL_INDEX ValueCellOffset)
{
DPRINT("CmiDestroyValueCell(Cell %p Offset %lx)\n",
ValueCell, ValueCellOffset);
VERIFY_VALUE_CELL(ValueCell);
/* Destroy the data cell */
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET)
&& ValueCell->DataSize > sizeof(HCELL_INDEX)
&& ValueCell->DataOffset != HCELL_NULL)
{
HvFreeCell (&RegistryHive->Hive, ValueCell->DataOffset);
}
/* Destroy the value cell */
HvFreeCell (&RegistryHive->Hive, ValueCellOffset);
return STATUS_SUCCESS;
}
ULONG
CmiGetPackedNameLength(IN PUNICODE_STRING Name,
OUT PBOOLEAN Packable)

View file

@ -1064,6 +1064,14 @@ CmpFreeValueData(
IN ULONG DataLength
);
NTSTATUS
NTAPI
CmpRemoveValueFromList(
IN PHHIVE Hive,
IN ULONG Index,
IN OUT PCHILD_LIST ChildList
);
//
// Boot Routines
//

View file

@ -86,7 +86,7 @@ CmpSetValueKeyNew(IN PHHIVE Hive,
/* Otherwise, set the data length, and make sure the data is dirty */
CellData->u.KeyValue.DataLength = DataSize;
ASSERT(HvIsCellDirty(Hive,CellData->u.KeyValue.Data));
ASSERT(HvIsCellDirty(Hive, CellData->u.KeyValue.Data));
}
else
{
@ -105,7 +105,7 @@ CmpSetValueKeyNew(IN PHHIVE Hive,
/* If we failed, free the entire cell, including the data */
if (!NT_SUCCESS(Status)) CmpFreeValue(Hive, ValueCell);
/* Return status */
/* Return Status */
return Status;
}
@ -340,3 +340,117 @@ Quickie:
return Status;
}
NTSTATUS
NTAPI
CmDeleteValueKey(IN PKEY_OBJECT KeyObject,
IN UNICODE_STRING ValueName)
{
NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
PHHIVE Hive;
PCM_KEY_NODE Parent;
HCELL_INDEX ChildCell, Cell;
PCHILD_LIST ChildList;
PCM_KEY_VALUE Value = NULL;
ULONG ChildIndex;
BOOLEAN Result;
/* Acquire hive lock */
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
/* Get the hive and the cell index */
Hive = &KeyObject->RegistryHive->Hive;
Cell = KeyObject->KeyCellOffset;
/* Get the parent key node */
Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
if (!Parent)
{
/* Fail */
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quickie;
}
/* Get the value list and check if it has any entries */
ChildList = &Parent->ValueList;
if (ChildList->Count)
{
/* Try to find this value */
Result = CmpFindNameInList(Hive,
ChildList,
&ValueName,
&ChildIndex,
&ChildCell);
if (!Result)
{
/* Fail */
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quickie;
}
/* Value not found, return error */
if (ChildCell == HCELL_NIL) goto Quickie;
/* We found the value, mark all relevant cells dirty */
HvMarkCellDirty(Hive, Cell);
HvMarkCellDirty(Hive, Parent->ValueList.List);
HvMarkCellDirty(Hive, ChildCell);
/* Get the key value */
Value = (PCM_KEY_VALUE)HvGetCell(Hive,ChildCell);
if (!Value) ASSERT(FALSE);
/* Mark it and all related data as dirty */
CmpMarkValueDataDirty(Hive, Value);
/* Ssanity checks */
ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List));
ASSERT(HvIsCellDirty(Hive, ChildCell));
/* Remove the value from the child list */
Status = CmpRemoveValueFromList(Hive, ChildIndex, ChildList);
if(!NT_SUCCESS(Status)) goto Quickie;
/* Remove the value and its data itself */
if (!CmpFreeValue(Hive, ChildCell))
{
/* Failed to free the value, fail */
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quickie;
}
/* Set the last write time */
KeQuerySystemTime(&Parent->LastWriteTime);
/* Sanity check */
ASSERT(HvIsCellDirty(Hive, Cell));
/* Check if the value list is empty now */
if (!Parent->ValueList.Count)
{
/* Then clear key node data */
Parent->MaxValueNameLen = 0;
Parent->MaxValueDataLen = 0;
}
/* Change default status to success */
Status = STATUS_SUCCESS;
}
Quickie:
/* Release the parent cell, if any */
if (Parent) HvReleaseCell(Hive, Cell);
/* Check if we had a value */
if (Value)
{
/* Release the child cell */
ASSERT(ChildCell != HCELL_NIL);
HvReleaseCell(Hive, ChildCell);
}
/* Release hive lock */
ExReleaseResourceLite(&CmpRegistryLock);
KeLeaveCriticalRegion();
return Status;
}

View file

@ -307,3 +307,58 @@ CmpSetValueDataNew(IN PHHIVE Hive,
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
CmpRemoveValueFromList(IN PHHIVE Hive,
IN ULONG Index,
IN OUT PCHILD_LIST ChildList)
{
ULONG Count;
PCELL_DATA CellData;
HCELL_INDEX NewCell;
PAGED_CODE();
/* Sanity check */
ASSERT((((LONG)Index) >= 0) && (Index <= ChildList->Count));
/* Get the new count after removal */
Count = ChildList->Count - 1;
if (Count > 0)
{
/* Get the actual list array */
CellData = HvGetCell(Hive, ChildList->List);
if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
/* Make sure cells data have been made dirty */
ASSERT(HvIsCellDirty(Hive, ChildList->List));
ASSERT(HvIsCellDirty(Hive, CellData->u.KeyList[Index]));
/* Loop the list */
while (Index < Count)
{
/* Move everything up */
CellData->u.KeyList[Index] = CellData->u.KeyList[Index + 1];
Index++;
}
/* Re-allocate the cell for the list by decreasing the count */
NewCell = HvReallocateCell(Hive,
ChildList->List,
Count * sizeof(HCELL_INDEX));
ASSERT(NewCell != HCELL_NIL);
HvReleaseCell(Hive,ChildList->List);
/* Update the list cell */
ChildList->List = NewCell;
}
else
{
/* Otherwise, we were the last entry, so free the list entirely */
HvFreeCell(Hive, ChildList->List);
ChildList->List = HCELL_NIL;
}
/* Update the child list with the new count */
ChildList->Count = Count;
return STATUS_SUCCESS;
}