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