VOID CmpCleanUpKcbValueCache( PCM_KEY_CONTROL_BLOCK KeyControlBlock ) /*++ Routine Description: Clean up cached value/data that are associated to this key. Arguments: KeyControlBlock - pointer to a key control block. Return Value: NONE. --*/ { ULONG i; PULONG_PTR CachedList; PCELL_DATA pcell; ULONG realsize; BOOLEAN small; if (CMP_IS_CELL_CACHED(KeyControlBlock->ValueCache.ValueList)) { CachedList = (PULONG_PTR) CMP_GET_CACHED_CELLDATA(KeyControlBlock->ValueCache.ValueList); for (i = 0; i < KeyControlBlock->ValueCache.Count; i++) { if (CMP_IS_CELL_CACHED(CachedList[i])) { // Trying to catch the BAD guy who writes over our pool. CmpMakeSpecialPoolReadWrite( CMP_GET_CACHED_ADDRESS(CachedList[i]) ); ExFreePool((PVOID) CMP_GET_CACHED_ADDRESS(CachedList[i])); } } // Trying to catch the BAD guy who writes over our pool. CmpMakeSpecialPoolReadWrite( CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList) ); ExFreePool((PVOID) CMP_GET_CACHED_ADDRESS(KeyControlBlock->ValueCache.ValueList)); // Mark the ValueList as NULL KeyControlBlock->ValueCache.ValueList = HCELL_NIL; } else if (KeyControlBlock->ExtFlags & CM_KCB_SYM_LINK_FOUND) { // // This is a symbolic link key with symbolic name resolved. // Dereference to its real kcb and clear the bit. // if ((KeyControlBlock->ValueCache.RealKcb->RefCount == 1) && !(KeyControlBlock->ValueCache.RealKcb->Delete)) { KeyControlBlock->ValueCache.RealKcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE; } CmpDereferenceKeyControlBlockWithLock(KeyControlBlock->ValueCache.RealKcb); KeyControlBlock->ExtFlags &= ~CM_KCB_SYM_LINK_FOUND; } }
VALUE_SEARCH_RETURN_TYPE CmpGetValueKeyFromCache( IN PCM_KEY_CONTROL_BLOCK KeyControlBlock, IN PCELL_DATA List, IN ULONG Index, OUT PPCM_CACHED_VALUE *ContainingList, OUT PCM_KEY_VALUE *Value, IN BOOLEAN IndexCached, OUT BOOLEAN *ValueCached, OUT PHCELL_INDEX CellToRelease ) /*++ Routine Description: Get the Valve Node. Check if it is already cached, if not but the index is cached, cache and return the value node. Arguments: Hive - pointer to hive control structure for hive of interest. List - pointer to the Value Index Array (of ULONG_PTR if cached and ULONG if non-cached) Index - Index in the Value index array ContainlingList - The address of the entry that will receive the found cached value. IndexCached - Indicate if the index list is cached. If not, everything is from the original registry data. ValueCached - Indicating whether Value is cached or not. Return Value: Pointer to the Value Node. NULL when we couldn't map a view --*/ { PULONG_PTR CachedList; ULONG AllocSize; ULONG CopySize; PCM_CACHED_VALUE CachedValue; PHHIVE Hive; *CellToRelease = HCELL_NIL; Hive = KeyControlBlock->KeyHive; *Value = NULL; if (IndexCached) { // // The index array is cached, so List is pointing to an array of ULONG_PTR. // Use CachedList. // CachedList = (PULONG_PTR) List; *ValueCached = TRUE; if (CMP_IS_CELL_CACHED(CachedList[Index])) { *Value = CMP_GET_CACHED_KEYVALUE(CachedList[Index]); *ContainingList = &((PCM_CACHED_VALUE) CachedList[Index]); } else { // // ensure exclusive lock. // if( (CmpIsKCBLockedExclusive(KeyControlBlock) == FALSE) && (CmpTryConvertKCBLockSharedToExclusive(KeyControlBlock) == FALSE) ) { // // need to upgrade lock to exclusive // return SearchNeedExclusiveLock; } *Value = (PCM_KEY_VALUE) HvGetCell(Hive, List->u.KeyList[Index]); if( *Value == NULL ) { // // we couldn't map a view for this cell // just return NULL; the caller must handle it gracefully // return SearchFail; } *CellToRelease = List->u.KeyList[Index]; // // Allocate a PagedPool to cache the value node. // CopySize = (ULONG) HvGetCellSize(Hive, *Value); AllocSize = CopySize + FIELD_OFFSET(CM_CACHED_VALUE, KeyValue); CachedValue = (PCM_CACHED_VALUE) ExAllocatePoolWithTag(PagedPool, AllocSize, CM_CACHE_VALUE_TAG); if (CachedValue) { // // Set the information for later use if we need to cache data as well. // if ((*Value)->Flags & VALUE_COMP_NAME) { CachedValue->HashKey = CmpComputeHashKeyForCompressedName(0,(*Value)->Name,(*Value)->NameLength); } else { UNICODE_STRING TmpStr; TmpStr.Length = (*Value)->NameLength; TmpStr.Buffer = (*Value)->Name; CachedValue->HashKey = CmpComputeHashKey(0,&TmpStr #if DBG , TRUE #endif ); } CachedValue->DataCacheType = CM_CACHE_DATA_NOT_CACHED; CachedValue->ValueKeySize = (USHORT) CopySize; RtlCopyMemory((PVOID)&(CachedValue->KeyValue), *Value, CopySize); // Trying to catch the BAD guy who writes over our pool. CmpMakeSpecialPoolReadWrite( CMP_GET_CACHED_ADDRESS(CachedList) ); CachedList[Index] = CMP_MARK_CELL_CACHED(CachedValue); // Trying to catch the BAD guy who writes over our pool. CmpMakeSpecialPoolReadOnly( CMP_GET_CACHED_ADDRESS(CachedList) ); // Trying to catch the BAD guy who writes over our pool. CmpMakeSpecialPoolReadOnly(CachedValue); *ContainingList = &((PCM_CACHED_VALUE) CachedList[Index]); // // Now we have the stuff cached, use the cache data. // (*Value) = CMP_GET_CACHED_KEYVALUE(CachedValue); } else { // // If the allocation fails, just do not cache it. continue. // *ValueCached = FALSE; } } } else { // // The Valve Index Array is from the registry hive, just get the cell and move on. // (*Value) = (PCM_KEY_VALUE) HvGetCell(Hive, List->u.KeyList[Index]); *ValueCached = FALSE; if( *Value == NULL ) { // // we couldn't map a view for this cell // just return NULL; the caller must handle it gracefully // OBS: we may remove this as we return pchild anyway; just for clarity // return SearchFail; } *CellToRelease = List->u.KeyList[Index]; } return SearchSuccess; }