CmpDereferenceKeyControlBlock
VOID __fastcall CmpDereferenceKeyControlBlock(UINT64 P4){
unsigned __int64 v2;
_CMHIVE *v3;
unsigned __int64 v4;
bool v5;
__int64 v6;
unsigned int v7;
_EX_PUSH_LOCK *v8;
signed __int32 v9;
signed __int32 v10;
__int64 v11;
_CMHIVE *v12;
signed __int64 v13;
bool v14;
int v15;
_BYTE *v16;
_BYTE *v17;
unsigned __int8 CurrentIrql;
__int64 v19;
_QWORD *v20;
int v21;
bool v22;
unsigned __int64 v23;
unsigned __int32 v24;
int v25;
unsigned __int64 v26;
__int64 v27;
__int64 v28;
_ETHREAD *CurrentThread;
INT64 RegLockHeldEx[2];
_CM_KEY_CONTROL_BLOCK *BugCheckParameter2;
*(_OWORD *)RegLockHeldEx = 0i64;
CmpInitializeDelayDerefContext(RegLockHeldEx);
v2 = *(_QWORD *)P4;
v3 = *(_CMHIVE **)(P4 + 32);
if( *(_QWORD *)P4 <= 1ui64 )
{
LABEL_8:
v6 = *(_QWORD *)(P4 + 32);
v7 = *(_DWORD *)(P4 + 16);
v8 = (_EX_PUSH_LOCK *)(*(_QWORD *)(v6 + 1640)
+ 24
* ((unsigned int)(*(_DWORD *)(v6 + 1648) - 1) & ((101027 * (v7 ^ (v7 >> 9))) ^ ((unsigned __int64)(101027 * (v7 ^ (v7 >> 9))) >> 9))));
ExAcquirePushLockExclusiveEx(v8, 0i64);
v8[1]._bf_0 = (__int64)KeGetCurrentThread();
_m_prefetchw((const void *)(v6 + 4272));
v9 = *(_DWORD *)(v6 + 4272);
if( !v9 )
LABEL_63:
KeBugCheckEx(0x51u, (PVOID)0x17, (PVOID)v6, (PVOID)8, (PVOID)P4);
while( 1 )
{
v10 = v9;
v9 = _InterlockedCompareExchange((volatile signed __int32 *)(v6 + 4272), v9 + 1, v9);
if( v10 == v9 )
break;
if( !v9 )
goto LABEL_63;
}
ExAcquirePushLockExclusiveEx((_EX_PUSH_LOCK *)(P4 + 48), 0i64);
*(_QWORD *)(P4 + 56) = KeGetCurrentThread();
v11 = *(_QWORD *)(P4 + 192);
BugCheckParameter2 = 0i64;
if( v11 )
{
v27 = *(_QWORD *)(v11 + 24);
if( v27 )
{
BugCheckParameter2 = *(_CM_KEY_CONTROL_BLOCK **)(v27 + 16);
CmpUnlockKcb((_CM_KEY_CONTROL_BLOCK *)P4);
CmpLockKcbExclusive((INT64)BugCheckParameter2);
CmpLockKcbExclusive(P4);
}
}
v12 = *(_CMHIVE **)(P4 + 32);
v13 = _InterlockedDecrement64((volatile signed __int64 *)P4);
if( v13 == 2 )
{
if( (*(_DWORD *)(P4 + 184) & 0x40000) != 0 && v12->Frozen == 1 )
CmpDoQueueLateUnloadWorker(v12);
}
else if( !v13 )
{
if( (*(_DWORD *)(P4 + 184) & 0x40000) != 0 )
{
v28 = *(_QWORD *)(P4 + 32);
CmpCleanUpKcbCacheWithLock((_CM_KEY_CONTROL_BLOCK *)P4, (INT64)RegLockHeldEx);
CurrentThread = (_ETHREAD *)KeGetCurrentThread();
*(_DWORD *)(v28 + 160) |= 0x80u;
*(_QWORD *)(v28 + 4216) = CurrentThread;
*(_DWORD *)(v28 + 4i64 * (_InterlockedExchangeAdd((volatile signed __int32 *)(v28 + 4276), 1u) & 0x7F) + 4280) = 31;
if( (*(_DWORD *)(v28 + 160) & 0x20) == 0
&& _InterlockedExchangeAdd((volatile signed __int32 *)(v28 + 4272), 0xFFFFFFFF) == 1 )
{
CmpDeleteHive((PVOID)v28);
}
}
else
{
v14 = 0;
v15 = *(_DWORD *)(P4 + 8);
if( (v15 & 0x20) == 0 )
v14 = (v15 & 0x20000) == 0;
if( (_DWORD)CmpHoldLazyFlush && (*(_WORD *)(P4 + 186) & 0x10) == 0 && (*(_BYTE *)(P4 + 8) & 8) == 0 || !v14 )
{
CmpCleanUpKcbCacheWithLock((_CM_KEY_CONTROL_BLOCK *)P4, (INT64)RegLockHeldEx);
if( *(struct _KTHREAD **)(P4 + 56) != KeGetCurrentThread() && (*(_DWORD *)(P4 + 8) & 0x80000) != 0 )
CmpFreeKeyControlBlock(P4);
}
else
{
v16 = KeAbPreAcquire((char *)&CmpDummyThreadEvent + 640, 0i64, 0i64);
v17 = v16;
CurrentIrql = KeGetCurrentIrql();
__writecr8(1ui64);
if( !_interlockedbittestandreset((_DWORD *)&CmpDummyThreadEvent + 160, 0) )
ExpAcquireFastMutexContended((_FAST_MUTEX *)((char *)&CmpDummyThreadEvent + 640), v16);
if( v17 )
v17[26] |= 1u;
v19 = *(&CmpDummyThreadEvent + 88);
*(&CmpDummyThreadEvent + 81) = KeGetCurrentThread();
*(&CmpDummyThreadEvent + 172) = CurrentIrql;
v20 = (_QWORD *)(P4 + 224);
if( *(_UNKNOWN **)(*(&CmpDummyThreadEvent + 88) + 8i64) != (_UNKNOWN *)((char *)&CmpDummyThreadEvent + 704) )
__fastfail(3u);
*v20 = *(&CmpDummyThreadEvent + 88);
*(_QWORD *)(P4 + 232) = (char *)&CmpDummyThreadEvent + 704;
*(_QWORD *)(v19 + 8) = v20;
*(&CmpDummyThreadEvent + 88) = P4 + 224;
v21 = CmpDelayedCloseElements;
*(_BYTE *)(P4 + 64) |= 2u;
++qword_140D2DF88;
CmpDelayedCloseElements = v21 + 1;
v22 = v21 + 1 > (unsigned int)CmpDelayedCloseSize;
v23 = *(&CmpDummyThreadEvent + 688);
*(&CmpDummyThreadEvent + 81) = 0i64;
v24 = _InterlockedCompareExchange((_DWORD *)&CmpDummyThreadEvent + 160, 1, 0);
if( v24 )
ExpReleaseFastMutexContended((_FAST_MUTEX *)((char *)&CmpDummyThreadEvent + 640), v24);
__writecr8(v23);
KeAbPostRelease((char *)&CmpDummyThreadEvent + 640);
if( v22 )
CmpArmDelayedCloseTimer();
}
}
}
v25 = *(_DWORD *)(P4 + 8) & 0x80000;
if( *(struct _KTHREAD **)(P4 + 56) == KeGetCurrentThread() )
*(_QWORD *)(P4 + 56) = 0i64;
else
_InterlockedDecrement((volatile signed __int32 *)(P4 + 56));
ExReleasePushLockEx(P4 + 48, 0);
if( v25 && (*(_DWORD *)(P4 + 8) & 0x80000) != 0 )
CmpFreeKeyControlBlock(P4);
if( BugCheckParameter2 )
CmpUnlockKcb(BugCheckParameter2);
v26 = *(_QWORD *)(v6 + 1640)
+ 24
* ((unsigned int)(*(_DWORD *)(v6 + 1648) - 1) & ((101027 * (v7 ^ (v7 >> 9))) ^ ((unsigned __int64)(101027 * (v7 ^ (v7 >> 9))) >> 9)));
*(_QWORD *)(v26 + 8) = 0i64;
ExReleasePushLockEx(v26, 0);
if( _InterlockedExchangeAdd((volatile signed __int32 *)(v6 + 4272), 0xFFFFFFFF) == 1 )
CmpDeleteHive((PVOID)v6);
CmpDrainDelayDerefContext((UINT64 **)RegLockHeldEx);
}
else
{
while( 1 )
{
v4 = v2 - 1;
v5 = v2 == 3 && (*(_DWORD *)(P4 + 184) & 0x40000) != 0 && v3->Frozen == 1;
v2 = _InterlockedCompareExchange64((volatile signed __int64 *)P4, v4, v2);
if( v2 == v4 + 1 )
break;
if( v2 <= 1 )
goto LABEL_8;
}
if( v2 < v4 )
KeBugCheckEx(0x51u, (PVOID)0x25, (PVOID)P4, 0i64, 0i64);
if( v5 )
CmpDoQueueLateUnloadWorker(v3);
}
}Referenced by:
CmEnumerateKey
CmLoadDifferencingKey
CmReleaseLoadKeyContext
CmpCleanupParseContext
CmpDeleteKeyObject
CmpDestroyVirtualStack
CmpDoBuildVirtualStack
CmpDoParseKey
CmpFreeSiloKeyLockEntry
CmpGetSymbolicLinkTarget
CmpGlobalUnlockKeyForWrite
CmpKeyEnumStackFreeResumeContext
CmpLateUnloadHiveWorker
CmpPerformCompleteKcbCacheLookup
CmpTransMgrFreeVolatileData
CmpWalkOneLevel