VOID NTAPI CmpCleanUpKcbCacheWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb, IN BOOLEAN LockHeldExclusively) { PCM_KEY_CONTROL_BLOCK Parent; PAGED_CODE(); /* Sanity checks */ ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) || (CmpTestRegistryLockExclusive() == TRUE)); ASSERT(Kcb->RefCount == 0); /* Cleanup the value cache */ CmpCleanUpKcbValueCache(Kcb); /* Dereference the NCB */ CmpDereferenceNameControlBlockWithLock(Kcb->NameBlock); /* Check if we have an index hint block and free it */ if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) CmpFree(Kcb->IndexHint, 0); /* Check if we were already deleted */ Parent = Kcb->ParentKcb; if (!Kcb->Delete) CmpRemoveKeyControlBlock(Kcb); /* Set invalid KCB signature */ Kcb->Signature = CM_KCB_INVALID_SIGNATURE; /* Free the KCB as well */ CmpFreeKeyControlBlock(Kcb); /* Check if we have a parent */ if (Parent) { /* Dereference the parent */ LockHeldExclusively ? CmpDereferenceKeyControlBlockWithLock(Parent,LockHeldExclusively) : CmpDelayDerefKeyControlBlock(Parent); } }
VOID CmpCleanUpKcbCacheWithLock( PCM_KEY_CONTROL_BLOCK KeyControlBlock ) /*++ Routine Description: Clean up all cached allocations that are associated to this key. If the parent is still open just because of this one, Remove the parent as well. Arguments: KeyControlBlock - pointer to a key control block. Return Value: NONE. --*/ { PCM_KEY_CONTROL_BLOCK Kcb; PCM_KEY_CONTROL_BLOCK ParentKcb; Kcb = KeyControlBlock; ASSERT(KeyControlBlock->RefCount == 0); while (Kcb->RefCount == 0) { // // First, free allocations for Value/data. // CmpCleanUpKcbValueCache(Kcb); // // Free the kcb and dereference parentkcb and nameblock. // CmpDereferenceNameControlBlockWithLock(Kcb->NameBlock); if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) { // // Now free the HintIndex allocation // ExFreePoolWithTag(Kcb->IndexHint, CM_CACHE_INDEX_TAG | PROTECTED_POOL); } // // Save the ParentKcb before we free the Kcb // ParentKcb = Kcb->ParentKcb; // // We cannot call CmpDereferenceKeyControlBlockWithLock so we can avoid recurrsion. // if (!Kcb->Delete) { CmpRemoveKeyControlBlock(Kcb); } SET_KCB_SIGNATURE(Kcb, '4FmC'); ASSERT_KEYBODY_LIST_EMPTY(Kcb); ExFreePoolWithTag(Kcb, CM_KCB_TAG | PROTECTED_POOL); Kcb = ParentKcb; Kcb->RefCount--; } }
VALUE_SEARCH_RETURN_TYPE NTAPI CmpCompareNewValueDataAgainstKCBCache(IN PCM_KEY_CONTROL_BLOCK Kcb, IN PUNICODE_STRING ValueName, IN ULONG Type, IN PVOID Data, IN ULONG DataSize) { VALUE_SEARCH_RETURN_TYPE SearchResult; PCM_KEY_NODE KeyNode; PCM_CACHED_VALUE *CachedValue; ULONG Index; PCM_KEY_VALUE Value; BOOLEAN ValueCached, BufferAllocated = FALSE; PVOID Buffer; HCELL_INDEX ValueCellToRelease = HCELL_NIL, CellToRelease = HCELL_NIL; BOOLEAN IsSmall; ULONG CompareResult; PAGED_CODE(); /* Check if this is a symlink */ if (Kcb->Flags & KEY_SYM_LINK) { /* We need the exclusive lock */ if (!(CmpIsKcbLockedExclusive(Kcb)) && !(CmpTryToConvertKcbSharedToExclusive(Kcb))) { /* We need the exclusive lock */ return SearchNeedExclusiveLock; } /* Otherwise, get the key node */ KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell); if (!KeyNode) return SearchFail; /* Cleanup the KCB cache */ CmpCleanUpKcbValueCache(Kcb); /* Sanity checks */ ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))); ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)); /* Set the value cache */ Kcb->ValueCache.Count = KeyNode->ValueList.Count; Kcb->ValueCache.ValueList = KeyNode->ValueList.List; /* Release the cell */ HvReleaseCell(Kcb->KeyHive, Kcb->KeyCell); } /* Do the search */ SearchResult = CmpFindValueByNameFromCache(Kcb, ValueName, &CachedValue, &Index, &Value, &ValueCached, &ValueCellToRelease); if (SearchResult == SearchNeedExclusiveLock) { /* We need the exclusive lock */ ASSERT(!CmpIsKcbLockedExclusive(Kcb)); ASSERT(ValueCellToRelease == HCELL_NIL); ASSERT(Value == NULL); goto Quickie; } else if (SearchResult == SearchSuccess) { /* Sanity check */ ASSERT(Value); /* First of all, check if the key size and type matches */ if ((Type == Value->Type) && (DataSize == (Value->DataLength & ~CM_KEY_VALUE_SPECIAL_SIZE))) { /* Check if this is a small key */ IsSmall = (DataSize <= CM_KEY_VALUE_SMALL) ? TRUE: FALSE; if (IsSmall) { /* Compare against the data directly */ Buffer = &Value->Data; } else { /* Do a search */ SearchResult = CmpGetValueDataFromCache(Kcb, CachedValue, (PCELL_DATA)Value, ValueCached, &Buffer, &BufferAllocated, &CellToRelease); if (SearchResult != SearchSuccess) { /* Sanity checks */ ASSERT(Buffer == NULL); ASSERT(BufferAllocated == FALSE); goto Quickie; } } /* Now check the data size */ if (DataSize) { /* Do the compare */ CompareResult = RtlCompareMemory(Buffer, Data, DataSize & ~CM_KEY_VALUE_SPECIAL_SIZE); } else { /* It's equal */ CompareResult = 0; } /* Now check if the compare wasn't equal */ if (CompareResult != DataSize) SearchResult = SearchFail; } else { /* The length or type isn't equal */ SearchResult = SearchFail; } } Quickie: /* Release the value cell */ if (ValueCellToRelease) HvReleaseCell(Kcb->KeyHive, ValueCellToRelease); /* Free the buffer */ if (BufferAllocated) CmpFree(Buffer, 0); /* Free the cell */ if (CellToRelease) HvReleaseCell(Kcb->KeyHive, CellToRelease); /* Return the search result */ return SearchResult; }