MiMoveDirtyBitsToPfns

INT64 __fastcall MiMoveDirtyBitsToPfns(UINT64 a1, UINT64 a2, INT64 a3, CHAR a4){
  UINT64 v8; 
  _MMPTE *PteBase; 
  unsigned __int64 v10; 
  unsigned __int64 v11; 
  __int64 v12; 
  INT64 v13; 
  __int64 *i; 
  volatile signed __int32 *v15; 
  unsigned __int8 v16; 
  LONG *v17; 
  INT64 CurrentIrql; 
  struct _KPRCB *CurrentPrcb; 
  int v20; 
  INT64 v21; 
  __int64 v22; 
  int v23; 
  _MMPTE *v24; 
  unsigned __int64 v25; 
  unsigned __int64 v26; 
  CHAR *AnyMultiplexedVm; 
  int v28; 
  unsigned int v29; 
  _MMPTE *v30; 
  UINT64 v31; 
  UINT64 v32; 
  unsigned __int64 v33; 
  _MMPTE *v34; 
  unsigned __int64 v35; 
  __int64 v36; 
  unsigned __int64 VadMandatoryPageSize; 
  __int64 v38; 
  __int64 v39; 
  unsigned __int64 v40; 
  _MMPTE *v41; 
  _MMPTE *v42; 
  unsigned __int64 v43; 
  unsigned __int64 v44; 
  signed __int32 v45; 
  __int64 v46; 
  signed __int32 v47; 
  unsigned __int64 v48; 
  unsigned __int64 v49; 
  _BYTE *v50; 
  char v51; 
  int v52; 
  int v53; 
  __int64 v54; 
  unsigned __int64 v55; 
  _MMPTE *v56; 
  _MMPTE *v57; 
  int v58; 
  INT64 v59; 
  __int64 v60; 
  _MMPTE *v61; 
  unsigned int v62; 
  unsigned __int64 v63; 
  char v64; 
  __int64 v65; 
  unsigned int v66; 
  char v67; 
  unsigned __int64 v68; 
  unsigned __int64 v69; 
  UINT64 v70; 
  INT64 v71; 
  INT64 v72; 
  char *v73; 
  unsigned __int8 v74; 
  UINT64 v75; 
  INT64 v76; 
  __int64 v77; 
  unsigned __int64 v78; 
  unsigned __int64 v79; 
  _MMPTE *PteLimit; 
  unsigned __int64 v81; 
  __int64 v82; 
  unsigned __int64 v83; 
  INT64 v84; 
  UINT64 LeafVa; 
  INT64 v86; 
  _MMPTE *v87; 
  INT64 a5; 
  UINT64 v89; 
  INT64 a7; 
  UINT64 v91; 
  INT64 a9; 
  UINT64 SpinCount; 
  INT64 a11; 
  INT64 a12; 
  INT64 v96; 
  UINT64 v97; 
  unsigned __int64 *v98; 
  INT64 v99; 
  __int128 v100; 
  __int64 v101; 
  __int64 v102; 
  __int16 v103; 
  _BYTE v104[14]; 
  __int64 v105; 
  CHAR *v106; 
  unsigned __int64 v107; 
  __int64 v108; 
  INT64(__fastcall *v109)(INT64); 
  __int128 *v110; 
  int v111; 
  __int16 v112; 
  __int16 v113; 
  __int64 v114; 
  __int64 v115; 
  __int64 Base; 
  INT64 result[20]; 
  v96 = a3;
  LOBYTE(a5) = a4;
  v113 = 0;
  v99 = 0i64;
  memset((INT64)result, 0i64);
  v89 = 0i64;
  v8 = 0i64;
  HIDWORD(a5) = 0;
  PteBase = MmGetPteBase();
  v10 = (unsigned __int64)PteBase + ((a1 >> 9) & 0x7FFFFFFFF8i64);
  v11 = (unsigned __int64)PteBase + ((a2 >> 9) & 0x7FFFFFFFF8i64);
  a9 = v11;
  v12 = *((_QWORD *)KeGetCurrentThread() + 23);
  v13 = v12 + 1664;
  v101 = *(_QWORD *)(v12 + 1680);
  a11 = v12 + 1664;
  HIDWORD(SpinCount) = a4 & 1;
  if( (a4 & 1) != 0 )
  {
    for( i = *(__int64 **)(a3 + 56); i; i = (__int64 *)*i )
    {
      if( (i[8] & 4) != 0 )
        break;
    }
    v98 = (unsigned __int64 *)(i + 1);
  }
  else
  {
    v98 = 0i64;
  }
  v112 = 0;
  v115 = 0i64;
  Base = 0i64;
  v15 = &dword_140C4F4C0;
  v114 = 20i64;
  v111 = 1;
  v16 = *(_BYTE *)(v13 + 184) & 7;
  if( v16 >= 6u )
  {
    CurrentIrql = KeGetCurrentIrql();
    a7 = CurrentIrql;
    __writecr8(2ui64);
  }
  else
  {
    if( v16 == 2 )
      v17 = &dword_140C4F4C0;
    else
      v17 = (LONG *)(v13 + 192);
    CurrentIrql = KeGetCurrentIrql();
    __writecr8(2ui64);
    CurrentPrcb = KeGetCurrentPrcb();
    if( *((_QWORD *)CurrentPrcb + 4247) && *((_BYTE *)CurrentPrcb + 32) <= 1u && *((_BYTE *)CurrentPrcb + 32) == 1 )
      PteBase = MmGetPteBase();
    _m_prefetchw(v17);
    v20 = *v17 & 0x7FFFFFFF;
    if( v20 != _InterlockedCompareExchange(v17, v20 + 1, v20) )
    {
      ExpWaitForSpinLockSharedAndAcquire((INT64 *)v17, CurrentIrql);
      PteBase = MmGetPteBase();
    }
    v8 = 0i64;
    if( v17[1] )
      _InterlockedExchange(v17 + 1, 0);
    a7 = CurrentIrql;
  }
  if( v10 > v11 )
    goto LABEL_68;
  v21 = (_QWORD)PteBase << 25;
  a12 = (_QWORD)PteBase << 25;
  v22 = (__int64)((v11 << 25) - ((_QWORD)PteBase << 25)) >> 16;
  v23 = a5 & 2;
  v102 = v22;
  LODWORD(a5) = v23;
  while( 2 )
  {
    if( v8 )
    {
      MiFlushTbList((__int64)&v111);
      MiUnlockPageTableInternal(v13, v8);
      v89 = 0i64;
      if( MiWorkingSetIsContended(v13) || KeShouldYieldProcessor() )
      {
        MiUnlockWorkingSetShared(v13, CurrentIrql);
        MiLockWorkingSetShared(v13);
      }
      v23 = a5;
    }
    if( v23 )
      _InterlockedIncrement64((volatile signed __int64 *)(v101 + 616));
    v100 = 0i64;
    memset((INT64)v104, 0i64);
    v24 = MmGetPteBase();
    v103 = 2273;
    v25 = (__int64)((v10 << 25) - v21) >> 16;
    v26 = v25;
    if( v25 >= (unsigned __int64)v24 )
    {
      PteLimit = MmGetPteLimit();
      do
      {
        if( v26 > (unsigned __int64)PteLimit )
          break;
        v26 = (__int64)((v26 << 25) - v21) >> 16;
      }
      while( v26 >= (unsigned __int64)v24 );
      v13 = a11;
    }
    if( v26 < 0xFFFF800000000000ui64 || v26 >= qword_140C4F878 && v26 <= qword_140C4E0A8 )
      AnyMultiplexedVm = (CHAR *)(*((_QWORD *)KeGetCurrentThread() + 23) + 1664i64);
    else
      AnyMultiplexedVm = MiGetAnyMultiplexedVm(1i64);
    v28 = MiFastLockLeafPageTable((INT64)AnyMultiplexedVm, v25);
    if( v28 )
    {
      v29 = v28 - 1;
      LODWORD(v100) = v28 - 1;
      v30 = MmGetPteBase();
      v31 = (UINT64)v30 + ((v25 >> 9) & 0x7FFFFFFFF8i64);
      *((_QWORD *)&v100 + 1) = v31;
    }
    else
    {
      v103 |= 4u;
      v110 = &v100;
      v105 = 0i64;
      v106 = AnyMultiplexedVm;
      v104[0] = v104[0] & 0xE3 | 4;
      v109 = MiGetNextPageTableTail;
      v104[4] = a7;
      v107 = v25;
      v108 = v22;
      MiWalkPageTables((INT64)&v103);
      v29 = v100;
      v31 = *((_QWORD *)&v100 + 1);
      v30 = MmGetPteBase();
    }
    v32 = v31;
    if( v31 )
    {
      v89 = (UINT64)v30 + ((v31 >> 9) & 0x7FFFFFFFF8i64);
      if( v29 )
      {
        v32 = (UINT64)v30 + ((v31 >> 9) & 0x7FFFFFFFF8i64);
        v81 = (unsigned __int64)v30 + ((v11 >> 9) & 0x7FFFFFFFF8i64);
        if( v29 > 1 )
        {
          v82 = v29 - 1;
          do
          {
            v32 = (UINT64)v30 + ((v32 >> 9) & 0x7FFFFFFFF8i64);
            v81 = (unsigned __int64)v30 + ((v81 >> 9) & 0x7FFFFFFFF8i64);
            --v82;
          }
          while( v82 );
        }
        v83 = v32 + 8;
        v89 = (UINT64)v30 + ((v32 >> 9) & 0x7FFFFFFFF8i64);
        if( ((v32 + 8) & 0xFFF) != 0 )
        {
          do
          {
            if( v83 > v81 )
              break;
            v84 = MI_READ_PTE_LOCK_FREE(v83);
            v99 = v84;
            if( (v84 & 1) == 0 )
              break;
            if( (v84 & 0x80u) == 0i64 )
              break;
            v83 += 8i64;
          }
          while( (v83 & 0xFFF) != 0 );
          v30 = MmGetPteBase();
        }
        v33 = v83 - 8;
      }
      else
      {
        v33 = (v31 & 0xFFFFFFFFFFFFF000ui64) + 4088;
        if( v33 > v11 )
          v33 = v11;
      }
    }
    else
    {
      v33 = v11;
    }
    if( !HIDWORD(SpinCount) )
      goto LABEL_52;
    HIDWORD(a5) = 1;
    if( v10 >= (unsigned __int64)v30 )
    {
      v34 = MmGetPteLimit();
      do
      {
        if( v10 > (unsigned __int64)v34 )
          break;
        v10 = (__int64)((v10 << 25) - a12) >> 16;
      }
      while( v10 >= (unsigned __int64)v30 );
      v13 = a11;
    }
    v35 = (v10 >> 12) - (*(unsigned int *)(v96 + 24) | ((unsigned __int64)*(unsigned __int8 *)(v96 + 32) << 32));
    VadMandatoryPageSize = MiGetVadMandatoryPageSize(v96);
    if( VadMandatoryPageSize != 1 )
      v35 /= VadMandatoryPageSize;
    v40 = v33 + 8;
    v41 = MmGetPteBase();
    if( v33 + 8 >= (unsigned __int64)v41 )
    {
      v42 = MmGetPteLimit();
      do
      {
        if( v40 > (unsigned __int64)v42 )
          break;
        v40 = (__int64)((v40 << 25) - v38) >> 16;
      }
      while( v40 >= (unsigned __int64)v41 );
      v13 = a11;
    }
    if( v40 > (((*(unsigned int *)(v39 + 28) | ((unsigned __int64)*(unsigned __int8 *)(v39 + 33) << 32)) << 12) | 0xFFF) )
    {
      v43 = *v98;
    }
    else
    {
      v43 = (v40 >> 12) - v36;
      if( VadMandatoryPageSize != 1 )
        v43 /= VadMandatoryPageSize;
    }
    v44 = v43 - v35;
    LODWORD(SpinCount) = 0;
    KeGetCurrentIrql();
    __writecr8(2ui64);
    v45 = *(_DWORD *)(v39 + 48);
    v46 = v39;
    do
    {
      while( (v45 & 1) != 0 )
      {
        if( (v45 & 2) != 0 )
        {
          LODWORD(SpinCount) = 0;
          do
          {
            KeYieldProcessorEx(&SpinCount);
            v45 = *(_DWORD *)(v46 + 48);
          }
          while( (v45 & 1) != 0 );
        }
        else
        {
          v45 = _InterlockedCompareExchange((volatile signed __int32 *)(v46 + 48), v45 | 2, v45);
        }
      }
      v47 = v45;
      v45 = _InterlockedCompareExchange((volatile signed __int32 *)(v46 + 48), v45 & 0xFFFFFFFC | 1, v45);
    }
    while( v47 != v45 );
    v11 = a9;
    if( !v44 )
      goto LABEL_52;
    v48 = v35;
    v49 = v35 & 7;
    v50 = (_BYTE *)(v98[1] + (v48 >> 3));
    if( v49 + v44 > 8 )
    {
      if( (_DWORD)v49 )
      {
        *v50++ &= byte_14001DA00[v49];
        v44 -= (unsigned int)(8 - v49);
      }
      if( v44 > 8 )
      {
        memset((INT64)v50, 0i64);
        v50 += v44 >> 3;
        v44 &= 7u;
      }
      if( !v44 )
        goto LABEL_51;
      v51 = byte_14001A768[v44];
    }
    else
    {
      v51 = ~(byte_14001DA00[v44] << v49);
    }
    *v50 &= v51;
LABEL_51:
    v11 = a9;
LABEL_52:
    if( !v31 )
      break;
    if( v32 > v33 )
      goto LABEL_59;
    v52 = HIDWORD(SpinCount);
    v53 = a5;
    do
    {
      v54 = *(_QWORD *)v32;
      v99 = v54;
      if( (v54 & 1) == 0 || (v54 & 0x42) == 0 )
        goto LABEL_57;
      if( !v52 )
      {
        if( v53 && v54 < 0 )
          goto LABEL_57;
        LeafVa = MiGetLeafVa(v32);
        if( (MiGetWsleContents(v86, LeafVa) & 0xF) == 9 )
          goto LABEL_57;
      }
      v60 = *(_QWORD *)v32;
      v61 = MmGetPteBase();
      v91 = *(_QWORD *)v32 & 0xFFFFFFFFFFFFFFBDui64;
      v62 = 0;
      v63 = (__int64)((v32 << 25) - a12) >> 16;
      if( v63 < (unsigned __int64)v61 )
        goto LABEL_82;
      v87 = MmGetPteLimit();
      do
      {
        if( v63 > (unsigned __int64)v87 )
          break;
        ++v62;
        v63 = (__int64)((v63 << 25) - a12) >> 16;
      }
      while( v63 >= (unsigned __int64)v61 );
      if( v62 )
      {
        MiRewritePteWithLockBit(*((_QWORD *)KeGetCurrentThread() + 23) + 1664i64, (volatile INT64 *)v32, v91);
        MiInsertLargeTbFlushEntry((INT64)&v111, v62, v32);
      }
      else
      {
LABEL_82:
        *(_QWORD *)v32 = v91 ^ (v60 ^ v91) & 0xF00000000000000i64 ^ (v60 ^ v91 ^ (v60 ^ v91) & 0xF00000000000000i64) & 0x7000000000000000i64;
        v64 = v112;
        v65 = 1i64;
        if( v111 != 1 && (v112 & 8) == 0 && v63 >= (unsigned __int64)v61 && v63 <= (unsigned __int64)MmGetPteLimit() )
        {
          v64 = v112 | 8;
          LOBYTE(v112) = v112 | 8;
        }
        v66 = HIDWORD(v114);
        if( !HIDWORD(v114) )
        {
LABEL_98:
          if( HIDWORD(v114) >= (unsigned int)v114 )
          {
            HIBYTE(v112) = 1;
          }
          else
          {
            while( 1 )
            {
              v77 = (unsigned __int64)(v65 - 1) > 0x3FF ? 1024i64 : v65;
              v78 = v63 & 0xFFFFFFFFFFFFF000ui64 | ((_WORD)v77 - 1) & 0x3FF;
              v65 -= v77;
              v63 += v77 << 12;
              result[v66 - 1] = v78;
              v115 += v77;
              v66 = HIDWORD(v114) + 1;
              HIDWORD(v114) = v66;
              if( v66 == (_DWORD)v114 && (v112 & 4) == 0 )
              {
                qsort((WCHAR *)&Base, v66, (const WCHAR *)8, MiTbFlushSort);
                MiCompressTbFlushList((INT64)&v111);
                v66 = HIDWORD(v114);
                if( HIDWORD(v114) == (_DWORD)v114 )
                  break;
              }
              if( !v65 )
                goto LABEL_90;
            }
            if( v65 )
            {
              HIBYTE(v112) = 1;
              v115 = HIDWORD(v114);
            }
          }
          goto LABEL_90;
        }
        v67 = v64 & 4;
        if( v67
          || (v68 = result[(unsigned int)(HIDWORD(v114) - 1) - 1], (v68 & 0xC00) != 0)
          || (v69 = result[(unsigned int)(HIDWORD(v114) - 1) - 1] & 0x3FF,
              (v68 & 0xFFFFFFFFFFFFF000ui64) + ((v69 + 1) << 12) != v63)
          || v69 + 1 <= v69
          || v69 + 1 > 0x3FF )
        {
          if( v67 )
            goto LABEL_98;
          v76 = result[(unsigned int)(HIDWORD(v114) - 1) - 1];
          if( (v76 & 0xC00) != 0 )
            goto LABEL_98;
          if( (v76 & 0xFFFFFFFFFFFFF000ui64) != v63 + 4096 )
            goto LABEL_98;
          v79 = result[(unsigned int)(HIDWORD(v114) - 1) - 1] & 0x3FF;
          if( v79 + 1 > 0x3FF || v79 + 1 <= v79 )
            goto LABEL_98;
          ++v115;
          result[(unsigned int)(HIDWORD(v114) - 1) - 1] = ((unsigned __int16)(v76 - 4096) ^ (unsigned __int16)(v76 - 4096 + 1)) & 0x3FF ^ (unsigned __int64)(v76 - 4096);
        }
        else
        {
          ++v115;
          result[(unsigned int)(HIDWORD(v114) - 1) - 1] = ((unsigned __int16)v68 ^ (unsigned __int16)(v68 + 1)) & 0x3FF ^ v68;
        }
      }
LABEL_90:
      v70 = v91;
      MiPteInShadowRange((UINT64)&v91);
      v72 = 0i64;
      v73 = (char *)MmGetPfnDb() + 48 * ((v70 >> 12) & 0xFFFFFFFFFi64);
      LODWORD(v97) = 0;
      while( _interlockedbittestandset64((volatile signed __int32 *)v73 + 6, 0x3Fui64) )
      {
        do
          KeYieldProcessorEx(&v97);
        while( *((__int64 *)v73 + 3) < 0 );
      }
      v74 = v73[34];
      v75 = 0i64;
      if( (v74 & 0x10) == 0 )
      {
        if( (!_bittest64((const signed __int64 *)v73 + 2, 0xAu) & (unsigned __int8)~(v74 >> 3)) != 0 )
        {
          v75 = MiCapturePageFileInfoInline((UINT64 *)v73 + 2, 1i64, 0i64);
          v74 = v73[34];
        }
        v73[34] = v74 | 0x10;
        if( v75 )
          v72 = *(_QWORD *)(qword_140C4E388 + 8 * ((*((_QWORD *)v73 + 5) >> 39) & 0x3FFi64));
      }
      _InterlockedAnd64((volatile signed __int64 *)v73 + 3, 0x7FFFFFFFFFFFFFFFui64);
      if( v75 )
        MiReleasePageFileInfo(v72, v75, 1, v71, a5, v89, a7, v91, a9, SpinCount, a11, a12);
LABEL_57:
      v32 += 8i64;
    }
    while( v32 <= v33 );
    v13 = a11;
    v11 = a9;
LABEL_59:
    if( HIDWORD(a5) )
    {
      _InterlockedAnd((volatile signed __int32 *)(v96 + 48), 0xFFFFFFFC);
      __writecr8(2ui64);
      HIDWORD(a5) = 0;
    }
    v55 = v32;
    v56 = MmGetPteBase();
    if( v32 >= (unsigned __int64)v56 )
    {
      v57 = MmGetPteLimit();
      do
      {
        if( v55 > (unsigned __int64)v57 )
          break;
        v55 = (__int64)((v55 << 25) - a12) >> 16;
      }
      while( v55 >= (unsigned __int64)v56 );
      v13 = a11;
      v11 = a9;
    }
    v21 = a12;
    v10 = (unsigned __int64)v56 + ((v55 >> 9) & 0x7FFFFFFFF8i64);
    v22 = v102;
    v23 = a5;
    if( v10 <= v11 )
    {
      v8 = v89;
      LOBYTE(CurrentIrql) = a7;
      continue;
    }
    break;
  }
  v15 = &dword_140C4F4C0;
LABEL_68:
  MiFlushTbList((__int64)&v111);
  if( HIDWORD(a5) )
    MiUnlockVadCore(v96, 2u);
  if( v89 )
    MiUnlockPageTableInternal(v13, v89);
  if( (*(_BYTE *)(v13 + 184) & 7u) < 6 )
  {
    v58 = *(_DWORD *)(v13 + 184);
    if( (v58 & 0x8000000) != 0 || (v58 & 0x4000000) != 0 || (v58 & 0x10000000) != 0 )
    {
      MiPreUnlockWorkingSetShared(v13, a7);
      LOBYTE(v58) = *(_BYTE *)(v13 + 184);
    }
    if( (v58 & 7) != 2 )
      v15 = (volatile signed __int32 *)(v13 + 192);
    MiCheckProcessShadow();
    _InterlockedAnd(v15, 0xBFFFFFFF);
    _InterlockedDecrement(v15);
  }
  v59 = (unsigned __int8)a7;
  __writecr8((unsigned __int8)a7);
  return v59;
}

Referenced by:

MiBeginHoldingDirtyFaults
MiProcessVaRangesInfoClass
NtResetWriteWatch