mirror of
https://github.com/reactos/reactos.git
synced 2024-07-08 21:55:08 +00:00
- 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:
parent
e834db9305
commit
4752c4b4c7
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1064,6 +1064,14 @@ CmpFreeValueData(
|
|||
IN ULONG DataLength
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpRemoveValueFromList(
|
||||
IN PHHIVE Hive,
|
||||
IN ULONG Index,
|
||||
IN OUT PCHILD_LIST ChildList
|
||||
);
|
||||
|
||||
//
|
||||
// Boot Routines
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue