From 4752c4b4c78d8a28ea50834ee51855f0d926ffe2 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 14 May 2007 00:44:26 +0000 Subject: [PATCH] - 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 --- reactos/ntoskrnl/cm/cm.h | 11 +-- reactos/ntoskrnl/cm/ntfunc.c | 112 +++++++++------------------- reactos/ntoskrnl/cm/regfile.c | 98 ------------------------- reactos/ntoskrnl/config/cm.h | 8 ++ reactos/ntoskrnl/config/cmapi.c | 118 +++++++++++++++++++++++++++++- reactos/ntoskrnl/config/cmvalue.c | 55 ++++++++++++++ 6 files changed, 218 insertions(+), 184 deletions(-) diff --git a/reactos/ntoskrnl/cm/cm.h b/reactos/ntoskrnl/cm/cm.h index f39581586c4..b87a37c880f 100644 --- a/reactos/ntoskrnl/cm/cm.h +++ b/reactos/ntoskrnl/cm/cm.h @@ -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); diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c index d6ace2de218..de08756e043 100644 --- a/reactos/ntoskrnl/cm/ntfunc.c +++ b/reactos/ntoskrnl/cm/ntfunc.c @@ -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; } /* diff --git a/reactos/ntoskrnl/cm/regfile.c b/reactos/ntoskrnl/cm/regfile.c index e02878e5ddd..78f2d8d66b0 100644 --- a/reactos/ntoskrnl/cm/regfile.c +++ b/reactos/ntoskrnl/cm/regfile.c @@ -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) diff --git a/reactos/ntoskrnl/config/cm.h b/reactos/ntoskrnl/config/cm.h index a12ebbb681a..00c97690c9d 100644 --- a/reactos/ntoskrnl/config/cm.h +++ b/reactos/ntoskrnl/config/cm.h @@ -1064,6 +1064,14 @@ CmpFreeValueData( IN ULONG DataLength ); +NTSTATUS +NTAPI +CmpRemoveValueFromList( + IN PHHIVE Hive, + IN ULONG Index, + IN OUT PCHILD_LIST ChildList +); + // // Boot Routines // diff --git a/reactos/ntoskrnl/config/cmapi.c b/reactos/ntoskrnl/config/cmapi.c index c9cad213779..8369cf50a71 100644 --- a/reactos/ntoskrnl/config/cmapi.c +++ b/reactos/ntoskrnl/config/cmapi.c @@ -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; +} diff --git a/reactos/ntoskrnl/config/cmvalue.c b/reactos/ntoskrnl/config/cmvalue.c index 77b2099df76..79c07f2bf6c 100644 --- a/reactos/ntoskrnl/config/cmvalue.c +++ b/reactos/ntoskrnl/config/cmvalue.c @@ -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; +}