CcUnpinFileDataEx

VOID __stdcall CcUnpinFileDataEx(VOID *Bcb, UINT8 ReadOnly, UNMAP_ACTIONS UnmapAction){
  void *v3; 
  __int64 v6; 
  _KEVENT *v7; 
  _SHARED_CACHE_MAP *v8; 
  __int64 v9; 
  UINT8 CurrentIrql; 
  signed __int32 v11; 
  _MI_PARTITION *v12; 
  _FAST_MUTEX *v13; 
  _ETHREAD *CurrentThread; 
  __int64 v15; 
  char v16; 
  __int64 v17; 
  NTSTATUS SessionId; 
  bool v19; 
  unsigned __int8 v20; 
  int v21; 
  _SHARED_CACHE_MAP *v22; 
  int v23; 
  __int64 v24; 
  __int16 v25; 
  char *v26; 
  __int16 v27; 
  _ETHREAD *v28; 
  unsigned __int8 v29; 
  _ETHREAD *v30; 
  __int16 v31; 
  unsigned int SpareByte0; 
  _ETHREAD *v33; 
  INT64 v34; 
  unsigned int v35; 
  bool v36; 
  __int64 v37; 
  int v38; 
  int v39; 
  _KSPIN_LOCK_QUEUE *volatile Next; 
  char v41; 
  _ADJUST_REASON v42; 
  unsigned __int64 OldIrql_low; 
  unsigned __int32 v44; 
  _KEVENT *v45; 
  __int64 v46; 
  unsigned int v47; 
  unsigned int v48; 
  INT64 v49; 
  VOID **v50; 
  VOID **v51; 
  unsigned __int8 v52; 
  _ETHREAD *v53; 
  __int64 v54; 
  _KEVENT *v55; 
  unsigned __int64 v56; 
  char *v57; 
  __int64 v58; 
  unsigned int *v59; 
  unsigned __int64 v60; 
  __int64 AbOrphanedEntrySummary; 
  signed __int32 v62; 
  __int64 v63; 
  int v64; 
  __int64 v65; 
  _KWAIT_BLOCK **v66; 
  _KWAIT_BLOCK *v67; 
  _KWAIT_BLOCK *v68; 
  __int64 Flink; 
  _KWAIT_BLOCK **Blink; 
  unsigned __int8 WaitType; 
  _QWORD *v72; 
  _DWORD *v73; 
  char v74; 
  int v75; 
  INT64 *v76; 
  INT64 v77; 
  char v78; 
  INT64 v79; 
  _KLOCK_QUEUE_HANDLE LockQueue; 
  VOID *Object; 
  __int64 v82; 
  __int64 v83; 
  _KPRCB *Prcb; 
  int v85; 
  UINT64 a3; 
  __int64 v87; 
  INT64 Entry; 
  _QWORD *v89; 
  _KPRCB *CurrentPrcb; 
  _ETHREAD *v91; 
  _KWAIT_BLOCK *v92; 
  _KWAIT_BLOCK *v93; 
  volatile signed __int32 *v94; 
  __int64 v95; 
  __int64 v96; 
  _KLOCK_QUEUE_HANDLE LockHandle; 
  _SHARED_CACHE_MAP *SharedCacheMap; 
  UINT64 SpinCount; 

  v3 = (void *)(int)UnmapAction;
  memset(&LockHandle, 0, sizeof(LockHandle));
  if( *(_WORD *)Bcb != 765 )
  {
    v6 = *((_QWORD *)Bcb + 1);
    if( !(unsigned __int16)_InterlockedDecrement((volatile signed __int32 *)Bcb + 4) )
    {
      v7 = *(_KEVENT **)(v6 + 184);
      if( v7 )
        KeSetEvent(v7, 0, 0);
      _InterlockedDecrement((volatile signed __int32 *)(v6 + 544));
    }
    return;
  }
  v8 = (_SHARED_CACHE_MAP *)*((_QWORD *)Bcb + 22);
  v83 = *((_QWORD *)v8 + 66);
  SharedCacheMap = v8;
  if( *((_QWORD *)v8 + 21) )
  {
    v9 = *(_QWORD *)((*((_QWORD *)v8 + 12) & 0xFFFFFFFFFFFFFFF0ui64) + 0x28);
    CurrentIrql = KeGetCurrentIrql();
    __writecr8(2ui64);
    LODWORD(SpinCount) = 0;
    if( _interlockedbittestandset((volatile signed __int32 *)&SpinLock, 0x1Fu) )
      LODWORD(SpinCount) = ExpWaitForSpinLockExclusiveAndAcquire(&SpinLock, CurrentIrql);
    v11 = SpinLock;
    while( (v11 & 0xBFFFFFFF) != 0x80000000 )
    {
      if( (v11 & 0x40000000) == 0 )
      {
        v62 = _InterlockedCompareExchange((volatile signed __int32 *)&SpinLock, v11 | 0x40000000, v11);
        v19 = v11 == v62;
        v11 = v62;
        if( !v19 )
          continue;
      }
      KeYieldProcessorEx(&SpinCount);
      v11 = SpinLock;
    }
    if( *(_QWORD *)v9 )
      v12 = *(_MI_PARTITION **)(*(&stru_140C4DB30 + 267) + 8i64 * (*(_WORD *)(*(_QWORD *)v9 + 60i64) & 0x3FF));
    else
      v12 = &Irp;
    LODWORD(SpinLock) = 0;
    __writecr8(CurrentIrql);
    if( (void *)v83 != v12->Core.PartitionObject->CcPartition )
      KeBugCheckEx(0x34u, (PVOID)0x1313, (PVOID)0xFFFFFFFFC0000420i64, 0i64, 0i64);
    v8 = SharedCacheMap;
  }
  if( (*((_DWORD *)v8 + 38) & 0x200) == 0 || (_DWORD)v3 == 1 )
    ReadOnly = 1;
  LODWORD(a3) = 0;
  v13 = (_FAST_MUTEX *)((char *)v8 + 280);
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  --CurrentThread->Tcb.SpecialApcDisable;
  if( ++CurrentThread->Tcb.AbAllocationRegionCount != 1 )
    KeBugCheckEx(0x192u, CurrentThread, (char *)v8 + 280, (PVOID)KeGetCurrentIrql(), 0i64);
  LOBYTE(v15) = CurrentThread->Tcb.AbEntrySummary;
  v85 = 0;
  if( !(_BYTE)v15 )
  {
    if( !CurrentThread->Tcb.AbOrphanedEntrySummary )
    {
      v17 = 0i64;
      goto LABEL_119;
    }
    AbOrphanedEntrySummary = CurrentThread->Tcb.AbOrphanedEntrySummary;
    CurrentThread->Tcb.AbOrphanedEntrySummary = 0;
    LOBYTE(v15) = AbOrphanedEntrySummary | CurrentThread->Tcb.AbEntrySummary;
  }
  v16 = v15;
  _BitScanForward((unsigned int *)&v15, (unsigned __int8)v15);
  v85 = v15;
  CurrentThread->Tcb.AbEntrySummary = v16 & ~(1 << v15);
  v17 = (__int64)&CurrentThread->Tcb.LockEntries[v15];
  if( !v17 )
  {
LABEL_119:
    _interlockedbittestandset((volatile signed __int32 *)&CurrentThread->Tcb.116 + 1, 0x10u);
    goto LABEL_23;
  }
  if( (unsigned __int64)v13 >= 0xFFFF800000000000ui64
    && *((_BYTE *)&MiState[1537] + (((unsigned __int64)v13 >> 39) & 0x1FF)) == 1 )
  {
    SessionId = MmGetSessionIdEx(CurrentThread->Tcb.ApcState.Process);
  }
  else
  {
    SessionId = -1;
  }
  *(_DWORD *)(v17 + 40) = SessionId;
  *(_QWORD *)(v17 + 32) = (unsigned __int64)v13 & 0x7FFFFFFFFFFFFFFCi64;
LABEL_23:
  --CurrentThread->Tcb.AbAllocationRegionCount;
  KiAbThreadRemoveBoosts(&CurrentThread->Tcb, v13, &a3);
  v19 = CurrentThread->Tcb.SpecialApcDisable++ == -1;
  if( v19
    && ($F25F8C4BA33AF922A5F1AF68CD89DDDF *)CurrentThread->Tcb.ApcState.ApcListHead[0].Flink != &CurrentThread->Tcb.152 )
  {
    KiCheckForKernelApcDelivery();
  }
  v20 = KeGetCurrentIrql();
  __writecr8(1ui64);
  if( !_interlockedbittestandreset(&v13->Count, 0) )
    ExpAcquireFastMutexContended(v13, (VOID *)v17);
  if( v17 )
    *(_BYTE *)(v17 + 26) |= 1u;
  v13->Owner = KeGetCurrentThread();
  v13->OldIrql = v20;
  if( !(_DWORD)v3 || (_DWORD)v3 == 1 )
  {
    v21 = *((_DWORD *)Bcb + 16);
    if( !v21 )
      KeBugCheckEx(0x34u, (PVOID)0x443, (PVOID)0xFFFFFFFFC0000420i64, 0i64, 0i64);
    v22 = SharedCacheMap;
    v23 = v21 - 1;
    *((_DWORD *)Bcb + 16) = v23;
  }
  else
  {
    if( (_DWORD)v3 != 2 )
      KeBugCheckEx(0x34u, (PVOID)0x2047A, v3, 0i64, 0i64);
    if( *((_BYTE *)Bcb + 2) )
    {
      v46 = v83;
      v47 = *((_DWORD *)Bcb + 1) >> 12;
      *((_BYTE *)Bcb + 2) = 0;
      *((_QWORD *)Bcb + 5) = 0i64;
      *((_QWORD *)Bcb + 6) = 0i64;
      KeAcquireInStackQueuedSpinLock((PKSPIN_LOCK)(v46 + 128), &LockHandle);
      v22 = SharedCacheMap;
      CcDeductDirtyPages(SharedCacheMap, v47);
      v48 = 0;
      if( *(_DWORD *)(v46 + 496) > v47 )
        v48 = *(_DWORD *)(v46 + 496) - v47;
      *(_DWORD *)(v46 + 496) = v48;
      if( !*((_DWORD *)SharedCacheMap + 28) && *((_DWORD *)SharedCacheMap + 1) )
        CcInsertIntoCleanSharedCacheMapList(SharedCacheMap);
      KeReleaseInStackQueuedSpinLockFromDpcLevel(&LockHandle);
      __writecr8(LockHandle.OldIrql);
    }
    else
    {
      v22 = SharedCacheMap;
    }
    v23 = *((_DWORD *)Bcb + 16);
  }
  if( v23 )
  {
    if( !ReadOnly )
      ExReleaseResourceLite((PERESOURCE)((char *)Bcb + 72));
    KeReleaseGuardedMutex(v13);
  }
  else
  {
    if( *((_BYTE *)Bcb + 2) )
    {
      if( *((_QWORD *)Bcb + 23) )
      {
        v24 = *(_QWORD *)(*((_QWORD *)Bcb + 7) + 8i64);
        if( !(unsigned __int16)_InterlockedDecrement((volatile signed __int32 *)(*((_QWORD *)Bcb + 7) + 16i64)) )
        {
          v45 = *(_KEVENT **)(v24 + 184);
          if( v45 )
            KeSetEvent(v45, 0, 0);
          _InterlockedDecrement((volatile signed __int32 *)(v24 + 544));
        }
        *((_QWORD *)Bcb + 23) = 0i64;
        *((_QWORD *)Bcb + 7) = 0i64;
      }
      if( ReadOnly )
        goto LABEL_68;
      v25 = *((_WORD *)Bcb + 49);
      v26 = (char *)Bcb + 72;
      if( (v25 & 0x41) == 1 )
        KeBugCheckEx(0x1C6u, (PVOID)0xF, v26, 0i64, 0i64);
      v27 = v25 & 1;
      if( v27 )
      {
        v52 = KeGetCurrentIrql();
        v53 = (_ETHREAD *)KeGetCurrentThread();
        if( v52 > 2u )
          KeBugCheckEx(0x1C6u, 0i64, (PVOID)v52, (PVOID)2, 0i64);
        if( !v52 && (v53->Tcb._bf_0 & 0x400) == 0 && !v53->Tcb.WaitBlock[3].SpareLong )
          KeBugCheckEx(0x1C6u, (PVOID)7, 0i64, 0i64, 0i64);
      }
      if( v27 )
      {
        ExpFastResourceLegacyRelease(v26);
        goto LABEL_68;
      }
      v28 = (_ETHREAD *)KeGetCurrentThread();
      LockQueue.LockQueue.Lock = (unsigned __int64 *volatile)(v26 + 96);
      LockQueue.LockQueue.Next = 0i64;
      v29 = KeGetCurrentIrql();
      __writecr8(2ui64);
      *(_QWORD *)&LockQueue.OldIrql = v29;
      if( _InterlockedExchange64((volatile __int64 *)v26 + 12, (__int64)&LockQueue) )
        KxWaitForLockOwnerShip((INT64)&LockQueue);
      v30 = (_ETHREAD *)KeGetCurrentThread();
      v31 = *((_WORD *)v26 + 13);
      if( ((v31 & 1) != 0 || *(&WheapDeferredInternalLogsEventLock + 740))
        && ((unsigned __int8)v28 & 3) != 3
        && v28 != v30 )
      {
        KeBugCheckEx(0x16Eu, v26, v30, v28, 0i64);
      }
      if( (v31 & 0x80u) != 0 )
      {
        ExpReleaseResourceExclusiveForThreadLite(v26, v28);
        goto LABEL_68;
      }
      v82 = 0i64;
      if( ((unsigned __int8)v28 & 3) != 0 )
        SpareByte0 = 0;
      else
        SpareByte0 = v28->Tcb.SchedulerApc.SpareByte0;
      v33 = (_ETHREAD *)*((_QWORD *)v26 + 6);
      v34 = (INT64)(v26 + 48);
      if( v33 != v28 )
      {
        v56 = 0i64;
        v57 = 0i64;
        if( v33 )
          v56 = 1i64;
        else
          v57 = v26 + 48;
        if( !SpareByte0
          || (v58 = *((_QWORD *)v26 + 2)) == 0
          || SpareByte0 >= *(_DWORD *)(v58 + 8)
          || (v34 = v58 + 16i64 * SpareByte0, *(_ETHREAD **)v34 != v28) )
        {
          v59 = (unsigned int *)*((_QWORD *)v26 + 2);
          v60 = *((unsigned int *)v26 + 16) + (unsigned __int64)*((unsigned int *)v26 + 18);
          if( !v59 || (v34 = (INT64)(v59 + 4), v56 >= v60) )
LABEL_145:
            KeBugCheckEx(0xE3u, v26, v28, v59, (PVOID)2);
          while( *(_ETHREAD **)v34 != v28 )
          {
            if( *(_QWORD *)v34 )
            {
              if( ++v56 == v60 )
                goto LABEL_145;
            }
            else if( !v57 )
            {
              v57 = (char *)v34;
            }
            v34 += 16i64;
            if( (unsigned int *)v34 == &v59[4 * v59[2]] )
              goto LABEL_145;
          }
          KeGetCurrentThread()->SchedulerApc.SpareByte0 = (v34 - (__int64)v59) >> 4;
        }
      }
      v35 = *(_DWORD *)(v34 + 8) & 7 | (8 * (*(_DWORD *)(v34 + 8) >> 3) - 8);
      *(_DWORD *)(v34 + 8) = v35;
      if( v35 >= 8 )
      {
        KeReleaseInStackQueuedSpinLockFromDpcLevel(&LockQueue);
        __writecr8(LockQueue.OldIrql);
        goto LABEL_67;
      }
      ExpFreeOwnerEntry(v34);
      v36 = *((_DWORD *)v26 + 16) <= 1u;
      v37 = 0i64;
      v87 = 0i64;
      if( !v36 )
        goto LABEL_54;
      if( *((_DWORD *)v26 + 19) )
      {
        KeCaptureWaitChainHeadEx((_QWORD **)v26 + 5, &v82, &v87);
        --*((_DWORD *)v26 + 19);
        *((_WORD *)v26 + 13) |= 0x80u;
        v38 = 1;
        v37 = v87;
      }
      else
      {
        if( !*((_DWORD *)v26 + 18) )
        {
LABEL_54:
          v38 = 0;
          goto LABEL_55;
        }
        v63 = *((_QWORD *)v26 + 4);
        *((_QWORD *)v26 + 4) = 0i64;
        v82 = v63;
        v38 = *((_DWORD *)v26 + 18);
        *((_DWORD *)v26 + 18) = 0;
      }
LABEL_55:
      v39 = v38 - 1;
      v19 = v39 + *((_DWORD *)v26 + 16) == 0;
      *((_DWORD *)v26 + 16) += v39;
      if( v19 )
        *((_WORD *)v26 + 12) = 0;
      if( !*((_DWORD *)v26 + 19) && !*((_DWORD *)v26 + 18) )
        *((_WORD *)v26 + 13) &= 0xF9u;
      HIDWORD(a3) = (unsigned __int8)v26[27];
      if( v37 )
      {
        v64 = *((_DWORD *)v26 + 14) & 7;
        *((_QWORD *)v26 + 6) = v37;
        *((_DWORD *)v26 + 14) = v64 | 8;
      }
      _m_prefetchw(&LockQueue);
      Next = LockQueue.LockQueue.Next;
      if( !LockQueue.LockQueue.Next )
      {
        if( (_KLOCK_QUEUE_HANDLE *)_InterlockedCompareExchange64(
                                      (volatile signed __int64 *)LockQueue.LockQueue.Lock,
                                      0i64,
                                      (signed __int64)&LockQueue) == &LockQueue )
          goto LABEL_64;
        Next = KxWaitForLockChainValid(&LockQueue.LockQueue);
      }
      LockQueue.LockQueue.Next = 0i64;
      _InterlockedXor64((volatile signed __int64 *)&Next->Lock, 1ui64);
LABEL_64:
      __writecr8(LockQueue.OldIrql);
      v41 = 1;
      if( v87 )
        v41 = 3;
      v42 = AdjustUnwait;
      if( !v82 )
        goto LABEL_67;
      v96 = KeGetCurrentIrql();
      __writecr8(2ui64);
      v65 = v82;
      Prcb = KeGetCurrentPrcb();
      do
      {
        v83 = v65;
        v95 = *(_QWORD *)v65;
        v94 = (volatile signed __int32 *)(v65 + 24);
        KiAcquireKobjectLockSafe((VOID *)(v65 + 24));
        v66 = (_KWAIT_BLOCK **)(v83 + 32);
        v93 = (_KWAIT_BLOCK *)(v83 + 32);
        *(_DWORD *)(v83 + 28) = 1;
        v67 = *v66;
        if( *v66 != (_KWAIT_BLOCK *)v66 )
        {
          do
          {
            v68 = v67;
            Entry = (INT64)v67;
            Flink = (__int64)v67->WaitListEntry.Flink;
            v92 = (_KWAIT_BLOCK *)Flink;
            Blink = (_KWAIT_BLOCK **)v68->WaitListEntry.Blink;
            if( *(_KWAIT_BLOCK **)(Flink + 8) != v68 || *Blink != v68 )
              goto LABEL_182;
            *Blink = (_KWAIT_BLOCK *)Flink;
            *(_QWORD *)(Flink + 8) = Blink;
            WaitType = v68->WaitType;
            if( WaitType == 1 )
            {
              if( KiTryUnwaitThread(Prcb, v68, v68->WaitKey, 0i64) )
              {
                v19 = (*(_DWORD *)(v83 + 28))-- == 1;
                if( v19 )
                  break;
              }
            }
            else
            {
              if( WaitType == 2 )
              {
                v68->BlockState = 5;
                Object = v68->Thread;
                v89 = (char *)Object + 8;
                v68->WaitListEntry.Flink = 0i64;
                KeGetCurrentIrql();
                __writecr8(2ui64);
                CurrentPrcb = KeGetCurrentPrcb();
                v91 = CurrentPrcb->CurrentThread;
                KiAcquireKobjectLockSafe(Object);
                v72 = v89;
                v73 = Object;
                if( (_QWORD *)*v72 == v72
                  || *((_DWORD *)Object + 10) >= *((_DWORD *)Object + 11)
                  || v91->Tcb.Queue == Object && v91->Tcb.WaitReason == 15 )
                {
LABEL_166:
                  v75 = v73[1];
                  v73[1] = v75 + 1;
                  v76 = (INT64 *)*((_QWORD *)v73 + 4);
                  if( (_DWORD *)*v76 != v73 + 6 )
                    goto LABEL_182;
                  v77 = Entry;
                  *(_QWORD *)Entry = v73 + 6;
                  *(_QWORD *)(v77 + 8) = v76;
                  *v76 = v77;
                  *((_QWORD *)v73 + 4) = v77;
                  if( !v75 && (_QWORD *)*v72 != v72 )
                  {
                    KiWakeOtherQueueWaiters(CurrentPrcb, (_KQUEUE *)v73);
                    v73 = Object;
                  }
                }
                else
                {
                  KiWakeQueueWaiter(CurrentPrcb, (_KQUEUE *)Object, Entry);
                  v73 = Object;
                  if( !v74 )
                  {
                    v72 = v89;
                    goto LABEL_166;
                  }
                }
                _InterlockedAnd(v73, 0xFFFFFF7F);
                v19 = (*(_DWORD *)(v83 + 28))-- == 1;
                if( v19 )
                  break;
                goto LABEL_173;
              }
              KiTryUnwaitThread(Prcb, v68, 256i64, 0i64);
            }
LABEL_173:
            v67 = v92;
          }
          while( v92 != v93 );
        }
        _InterlockedAnd(v94, 0xFFFFFF7F);
        v65 = v95;
      }
      while( v95 != v82 );
      KiRemoveBoostThread(Prcb, Prcb->CurrentThread);
      v79 = HIDWORD(a3);
      if( HIDWORD(a3) )
      {
        v42 = AdjustBoost;
        if( v78 > SBYTE4(a3) )
          v79 = (unsigned int)v78;
      }
      if( (v41 & 2) != 0 && v42 == AdjustUnwait )
        v79 = 1i64;
      KiExitDispatcher(Prcb, 0i64, v42, v79, v96);
      v82 = 0i64;
LABEL_67:
      __incgsdword(0x8670u);
LABEL_68:
      OldIrql_low = LOBYTE(v13->OldIrql);
      v13->Owner = 0i64;
      v44 = _InterlockedCompareExchange(&v13->Count, 1, 0);
      if( v44 )
        ExpReleaseFastMutexContended(v13, v44);
      __writecr8(OldIrql_low);
      KeAbPostRelease(v13);
      return;
    }
    ExAcquirePushLockExclusiveEx((_EX_PUSH_LOCK *)v22 + 13, 0i64);
    v50 = (VOID **)*((_QWORD *)Bcb + 2);
    v51 = (VOID **)*((_QWORD *)Bcb + 3);
    if( v50[1] != (char *)Bcb + 16 || *v51 != (char *)Bcb + 16 )
LABEL_182:
      __fastfail(3u);
    *v51 = v50;
    v50[1] = v51;
    if( *((__int64 *)v22 + 4) > 0x2000000 && (*((_DWORD *)v22 + 38) & 0x200) != 0 )
      CcAdjustVacbLevelLockCount(v22, *((_QWORD *)Bcb + 1), 0xFFFFFFFFi64, v49);
    ExReleasePushLockEx((_DWORD)v22 + 104, 0);
    if( *((_QWORD *)Bcb + 23) )
    {
      v54 = *(_QWORD *)(*((_QWORD *)Bcb + 7) + 8i64);
      if( !(unsigned __int16)_InterlockedDecrement((volatile signed __int32 *)(*((_QWORD *)Bcb + 7) + 16i64)) )
      {
        v55 = *(_KEVENT **)(v54 + 184);
        if( v55 )
          KeSetEvent(v55, 0, 0);
        _InterlockedDecrement((volatile signed __int32 *)(v54 + 544));
      }
    }
    KeReleaseGuardedMutex(v13);
    CcDeallocateBcb((_BCB *)Bcb);
  }
}

Referenced by:

CcAcquireByteRangeForWrite
CcGetDirtyPagesHelper
CcPinFileData
CcReleaseByteRangeFromWrite
CcUnpinData
CcUnpinDataForThread
CcUnpinRepinnedBcb
CcZeroDataInCache