MiMoveDirtyBitsToPfns

VOID __fastcall MiMoveDirtyBitsToPfns(_MMPTE *PointerPte, _MMPTE *EndPte, INT64 WsIrql, _KTBFLUSH_TYPE a4){
  char v7; 
  UINT64 v8; 
  _MMPTE *PteBase; 
  unsigned __int64 v10; 
  unsigned __int64 v11; 
  _EPROCESS *Process; 
  _MMSUPPORT_INSTANCE *p_Instance; 
  __int64 *i; 
  volatile signed __int32 *v15; 
  unsigned __int8 v16; 
  volatile __int32 *v17; 
  UINT64 CurrentIrql; 
  struct _KPRCB *CurrentPrcb; 
  int v20; 
  __int64 v21; 
  __int64 v22; 
  int v23; 
  _MMPTE *v24; 
  unsigned __int64 v25; 
  unsigned __int64 v26; 
  _MMSUPPORT_FULL *AnyMultiplexedVm; 
  NTSTATUS v28; 
  unsigned int v29; 
  _MMPTE *v30; 
  UINT64 v31; 
  UINT64 v32; 
  unsigned __int64 v33; 
  _MMPTE *v34; 
  unsigned __int64 v35; 
  unsigned __int64 v36; 
  __int64 v37; 
  __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; 
  _MMSUPPORT_FLAGS Flags; 
  __int64 v59; 
  _MMPTE *v60; 
  unsigned int v61; 
  unsigned __int64 v62; 
  UINT64 v63; 
  int v64; 
  char v65; 
  __int64 v66; 
  unsigned int v67; 
  char v68; 
  __int64 v69; 
  unsigned __int64 v70; 
  UINT64 v71; 
  _MI_PARTITION *v72; 
  _MMPFN *v73; 
  unsigned __int8 v74; 
  union {unsigned __int64 Long;volatile unsigned __int64 VolatileLong;_MMPTE_HARDWARE Hard;_MMPTE_PROTOTYPE Proto;_MMPTE_SOFTWARE Soft;_MMPTE_TIMESTAMP TimeStamp;_MMPTE_TRANSITION Trans;_MMPTE_SUBSECTION Subsect;_MMPTE_LIST List;} v75; 
  __int64 v76; 
  __int64 v77; 
  unsigned __int64 v78; 
  unsigned __int64 v79; 
  int v80; 
  _MMPTE *PteLimit; 
  unsigned __int64 v82; 
  __int64 v83; 
  unsigned __int64 v84; 
  __int64 v85; 
  UINT64 v86; 
  INT64 v87; 
  _MMPTE *v88; 
  INT64 *v89; 
  UINT64 v90; 
  UINT64 v91; 
  UINT64 v92; 
  unsigned __int64 v93; 
  UINT64 SpinCount; 
  _MMSUPPORT_FULL *p_Vm; 
  __int64 v96; 
  INT64 v97; 
  UINT64 v98; 
  unsigned __int64 *v99; 
  __int64 v100; 
  __int128 v101; 
  _MMWSL_INSTANCE *VmWorkingSetList; 
  __int64 v103; 
  _QWORD v104[22]; 
  _MI_TB_FLUSH_LIST TbFlushList; 
  __int16 v106; 
  __int16 v107; 
  __int64 v108; 
  __int64 v109; 
  __int64 Base[21]; 

  v97 = WsIrql;
  LOBYTE(v89) = a4;
  v107 = 0;
  v100 = 0i64;
  v7 = a4;
  memset(&Base[1], 0i64, 0x98u);
  v90 = 0i64;
  v8 = 0i64;
  HIDWORD(v89) = 0;
  PteBase = MmGetPteBase();
  v10 = (unsigned __int64)PteBase + (((unsigned __int64)PointerPte >> 9) & 0x7FFFFFFFF8i64);
  v11 = (unsigned __int64)PteBase + (((unsigned __int64)EndPte >> 9) & 0x7FFFFFFFF8i64);
  v93 = v11;
  Process = KeGetCurrentThread()->ApcState.Process;
  p_Instance = &Process->Vm.Instance;
  VmWorkingSetList = Process->Vm.Instance.VmWorkingSetList;
  p_Vm = &Process->Vm;
  HIDWORD(SpinCount) = v7 & 1;
  if( (v7 & 1) != 0 )
  {
    for( i = *(__int64 **)(WsIrql + 56); i; i = (__int64 *)*i )
    {
      if( (i[8] & 4) != 0 )
        break;
    }
    v99 = (unsigned __int64 *)(i + 1);
  }
  else
  {
    v99 = 0i64;
  }
  v106 = 0;
  v109 = 0i64;
  Base[0] = 0i64;
  v15 = (volatile signed __int32 *)((char *)&stru_140C4DB30 + 6544);
  v108 = 20i64;
  TbFlushList = 1;
  v16 = p_Instance->Flags._bf_0 & 7;
  if( v16 >= 6u )
  {
    CurrentIrql = KeGetCurrentIrql();
    v91 = CurrentIrql;
    __writecr8(2ui64);
  }
  else
  {
    if( v16 == 2 )
      v17 = (volatile __int32 *)((char *)&stru_140C4DB30 + 6544);
    else
      v17 = (volatile __int32 *)&p_Instance[1];
    CurrentIrql = KeGetCurrentIrql();
    __writecr8(2ui64);
    CurrentPrcb = KeGetCurrentPrcb();
    if( CurrentPrcb->SchedulerAssist && CurrentPrcb->NestingLevel <= 1u && CurrentPrcb->NestingLevel == 1 )
      PteBase = MmGetPteBase();
    _m_prefetchw((const void *)v17);
    v20 = *v17 & 0x7FFFFFFF;
    if( v20 != _InterlockedCompareExchange(v17, v20 + 1, v20) )
    {
      ExpWaitForSpinLockSharedAndAcquire((INT64 *)v17, CurrentIrql);
      PteBase = MmGetPteBase();
    }
    v8 = 0i64;
    if( *((_DWORD *)v17 + 1) )
      _InterlockedExchange(v17 + 1, 0);
    v91 = CurrentIrql;
  }
  if( v10 > v11 )
    goto LABEL_68;
  v21 = (_QWORD)PteBase << 25;
  v96 = (_QWORD)PteBase << 25;
  v22 = (__int64)((v11 << 25) - ((_QWORD)PteBase << 25)) >> 16;
  v23 = (unsigned __int8)v89 & 2;
  v103 = v22;
  LODWORD(v89) = v23;
  while( 2 )
  {
    if( v8 )
    {
      MiFlushTbList(&TbFlushList);
      MiUnlockPageTableInternal((INT64)p_Instance, v8);
      v90 = 0i64;
      LOBYTE(v80) = MiWorkingSetIsContended((INT64)p_Instance);
      if( v80 || (unsigned int)KeShouldYieldProcessor() )
      {
        MiUnlockWorkingSetShared(p_Instance, (unsigned __int8)CurrentIrql);
        MiLockWorkingSetShared();
      }
      v23 = (int)v89;
    }
    if( v23 )
      _InterlockedIncrement64((volatile signed __int64 *)&VmWorkingSetList[15].NextPteToAccessClear);
    v101 = 0i64;
    memset((char *)v104 + 2, 0i64, 0xAEu);
    v24 = MmGetPteBase();
    LOWORD(v104[0]) = 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 );
      p_Instance = &p_Vm->Instance;
    }
    if( v26 < 0xFFFF800000000000ui64 || v26 >= *(&stru_140C4DB30 + 937) && v26 <= *(&stru_140C4DB30 + 175) )
      AnyMultiplexedVm = &KeGetCurrentThread()->ApcState.Process->Vm;
    else
      AnyMultiplexedVm = (_MMSUPPORT_FULL *)MiGetAnyMultiplexedVm(MiWorkingSetTypeSystemViews, v24);
    v28 = MiFastLockLeafPageTable((INT64)AnyMultiplexedVm, v25);
    if( v28 )
    {
      v29 = v28 - 1;
      LODWORD(v101) = v28 - 1;
      v30 = MmGetPteBase();
      v31 = (UINT64)v30 + ((v25 >> 9) & 0x7FFFFFFFF8i64);
      *((_QWORD *)&v101 + 1) = v31;
    }
    else
    {
      LOWORD(v104[0]) |= 4u;
      v104[21] = &v101;
      v104[2] = 0i64;
      v104[3] = AnyMultiplexedVm;
      BYTE2(v104[0]) = BYTE2(v104[0]) & 0xE3 | 4;
      v104[20] = MiGetNextPageTableTail;
      BYTE6(v104[0]) = v91;
      v104[4] = v25;
      v104[5] = v22;
      MiWalkPageTables((INT64)v104);
      v29 = v101;
      v31 = *((_QWORD *)&v101 + 1);
      v30 = MmGetPteBase();
    }
    v32 = v31;
    if( v31 )
    {
      v90 = (UINT64)v30 + ((v31 >> 9) & 0x7FFFFFFFF8i64);
      if( v29 )
      {
        v32 = (UINT64)v30 + ((v31 >> 9) & 0x7FFFFFFFF8i64);
        v82 = (unsigned __int64)v30 + ((v11 >> 9) & 0x7FFFFFFFF8i64);
        if( v29 > 1 )
        {
          v83 = v29 - 1;
          do
          {
            v32 = (UINT64)v30 + ((v32 >> 9) & 0x7FFFFFFFF8i64);
            v82 = (unsigned __int64)v30 + ((v82 >> 9) & 0x7FFFFFFFF8i64);
            --v83;
          }
          while( v83 );
        }
        v84 = v32 + 8;
        v90 = (UINT64)v30 + ((v32 >> 9) & 0x7FFFFFFFF8i64);
        if( ((v32 + 8) & 0xFFF) != 0 )
        {
          do
          {
            if( v84 > v82 )
              break;
            LODWORD(v85) = MI_READ_PTE_LOCK_FREE(v84);
            v100 = v85;
            if( (v85 & 1) == 0 )
              break;
            if( (v85 & 0x80u) == 0i64 )
              break;
            v84 += 8i64;
          }
          while( (v84 & 0xFFF) != 0 );
          v30 = MmGetPteBase();
        }
        v33 = v84 - 8;
      }
      else
      {
        v33 = (v31 & 0xFFFFFFFFFFFFF000ui64) + 4088;
        if( v33 > v11 )
          v33 = v11;
      }
    }
    else
    {
      v33 = v11;
    }
    if( !HIDWORD(SpinCount) )
      goto LABEL_52;
    HIDWORD(v89) = 1;
    if( v10 >= (unsigned __int64)v30 )
    {
      v34 = MmGetPteLimit();
      do
      {
        if( v10 > (unsigned __int64)v34 )
          break;
        v10 = (__int64)((v10 << 25) - v96) >> 16;
      }
      while( v10 >= (unsigned __int64)v30 );
      p_Instance = &p_Vm->Instance;
    }
    v35 = (v10 >> 12) - (*(unsigned int *)(v97 + 24) | ((unsigned __int64)*(unsigned __int8 *)(v97 + 32) << 32));
    LODWORD(v36) = MiGetVadMandatoryPageSize(v97);
    if( v36 != 1 )
      v35 /= v36;
    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 );
      p_Instance = &p_Vm->Instance;
    }
    if( v40 > (((*(unsigned int *)(v39 + 28) | ((unsigned __int64)*(unsigned __int8 *)(v39 + 33) << 32)) << 12) | 0xFFF) )
    {
      v43 = *v99;
    }
    else
    {
      v43 = (v40 >> 12) - v37;
      if( v36 != 1 )
        v43 /= v36;
    }
    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 = v93;
    if( !v44 )
      goto LABEL_52;
    v48 = v35;
    v49 = v35 & 7;
    v50 = (_BYTE *)(v99[1] + (v48 >> 3));
    if( v49 + v44 > 8 )
    {
      if( (_DWORD)v49 )
      {
        *v50++ &= byte_14001DA00[v49];
        v44 -= (unsigned int)(8 - v49);
      }
      if( v44 > 8 )
      {
        memset(v50, 0i64, v44 >> 3);
        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 = v93;
LABEL_52:
    if( !v31 )
      break;
    if( v32 > v33 )
      goto LABEL_59;
    v52 = HIDWORD(SpinCount);
    v53 = (int)v89;
    do
    {
      v54 = *(_QWORD *)v32;
      v100 = v54;
      if( (v54 & 1) == 0 || (v54 & 0x42) == 0 )
        goto LABEL_57;
      if( !v52 )
      {
        if( v53 && v54 < 0 )
          goto LABEL_57;
        LODWORD(v86) = MiGetLeafVa(v32);
        if( (MiGetWsleContents(v87, v86) & 0xF) == 9 )
          goto LABEL_57;
      }
      v59 = *(_QWORD *)v32;
      v60 = MmGetPteBase();
      v92 = *(_QWORD *)v32 & 0xFFFFFFFFFFFFFFBDui64;
      v61 = 0;
      v62 = (__int64)((v32 << 25) - v96) >> 16;
      if( v62 < (unsigned __int64)v60 )
        goto LABEL_82;
      v88 = MmGetPteLimit();
      do
      {
        if( v62 > (unsigned __int64)v88 )
          break;
        ++v61;
        v62 = (__int64)((v62 << 25) - v96) >> 16;
      }
      while( v62 >= (unsigned __int64)v60 );
      if( v61 )
      {
        MiRewritePteWithLockBit((INT64)&KeGetCurrentThread()->ApcState.Process->Vm, (INT64 *)v32, v92);
        MiInsertLargeTbFlushEntry(&TbFlushList, v61, v32);
      }
      else
      {
LABEL_82:
        v63 = v92 ^ (v59 ^ v92) & 0xF00000000000000i64 ^ (v59 ^ v92 ^ (v59 ^ v92) & 0xF00000000000000i64) & 0x7000000000000000i64;
        LOBYTE(v64) = MiPteInShadowRange(v32);
        if( v64 && (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0 && (v63 & 1) != 0 )
          v63 |= 0x8000000000000000ui64;
        *(_QWORD *)v32 = v63;
        v65 = v106;
        v66 = 1i64;
        if( TbFlushList != 1
          && (v106 & 8) == 0
          && v62 >= (unsigned __int64)v60
          && v62 <= (unsigned __int64)MmGetPteLimit() )
        {
          v65 = v106 | 8;
          LOBYTE(v106) = v106 | 8;
        }
        v67 = HIDWORD(v108);
        if( !HIDWORD(v108) )
        {
LABEL_99:
          if( HIDWORD(v108) >= (unsigned int)v108 )
          {
            HIBYTE(v106) = 1;
          }
          else
          {
            while( 1 )
            {
              v77 = (unsigned __int64)(v66 - 1) > 0x3FF ? 1024i64 : v66;
              v78 = v62 & 0xFFFFFFFFFFFFF000ui64 | ((_WORD)v77 - 1) & 0x3FF;
              v66 -= v77;
              v62 += v77 << 12;
              Base[v67] = v78;
              v109 += v77;
              v67 = HIDWORD(v108) + 1;
              HIDWORD(v108) = v67;
              if( v67 == (_DWORD)v108 && (v106 & 4) == 0 )
              {
                qsort((UINT64)Base, v67, 8ui64, (INT64)MiTbFlushSort, v89, v90, v91);
                MiCompressTbFlushList(&TbFlushList);
                v67 = HIDWORD(v108);
                if( HIDWORD(v108) == (_DWORD)v108 )
                  break;
              }
              if( !v66 )
                goto LABEL_91;
            }
            if( v66 )
            {
              HIBYTE(v106) = 1;
              v109 = HIDWORD(v108);
            }
          }
          goto LABEL_91;
        }
        v68 = v65 & 4;
        if( v68
          || (v69 = Base[HIDWORD(v108) - 1], (v69 & 0xC00) != 0)
          || (v70 = Base[HIDWORD(v108) - 1] & 0x3FF, (v69 & 0xFFFFFFFFFFFFF000ui64) + ((v70 + 1) << 12) != v62)
          || v70 + 1 <= v70
          || v70 + 1 > 0x3FF )
        {
          if( v68 )
            goto LABEL_99;
          v76 = Base[HIDWORD(v108) - 1];
          if( (v76 & 0xC00) != 0 )
            goto LABEL_99;
          if( (v76 & 0xFFFFFFFFFFFFF000ui64) != v62 + 4096 )
            goto LABEL_99;
          v79 = Base[HIDWORD(v108) - 1] & 0x3FF;
          if( v79 + 1 > 0x3FF || v79 + 1 <= v79 )
            goto LABEL_99;
          ++v109;
          Base[HIDWORD(v108) - 1] = ((unsigned __int16)(v76 - 4096) ^ (unsigned __int16)(v76 - 4096 + 1)) & 0x3FF ^ (unsigned __int64)(v76 - 4096);
        }
        else
        {
          ++v109;
          Base[HIDWORD(v108) - 1] = ((unsigned __int16)v69 ^ (unsigned __int16)(v69 + 1)) & 0x3FF ^ (unsigned __int64)v69;
        }
      }
LABEL_91:
      v71 = v92;
      MiPteInShadowRange((UINT64)&v92);
      v72 = 0i64;
      v73 = &MmGetPfnDb()[(v71 >> 12) & 0xFFFFFFFFFi64];
      LODWORD(v98) = 0;
      while( _interlockedbittestandset64((volatile signed __int32 *)&v73->u2, 0x3Fui64) )
      {
        do
          KeYieldProcessorEx(&v98);
        while( v73->u2._bf_0 < 0 );
      }
      v74 = *((_BYTE *)&v73->u3 + 2);
      v75.Long = 0i64;
      if( (v74 & 0x10) == 0 )
      {
        if( (!_bittest64(
                 &v73->OriginalPte.u.Hard.$976DF529DAC3D73085C9E386D94B91E6::$E228DCF3D8940E384DBC5EFCA756D8B6::_bf_0,
                 0xAu) & (unsigned __int8)~(v74 >> 3)) != 0 )
        {
          v75.Long = MiCapturePageFileInfoInline(&v73->OriginalPte, 1ui64, 0i64).u.Long;
          v74 = *((_BYTE *)&v73->u3 + 2);
        }
        *((_BYTE *)&v73->u3 + 2) = v74 | 0x10;
        if( v75.Long )
          v72 = *(_MI_PARTITION **)(*(&stru_140C4DB30 + 267) + 8 * (((unsigned __int64)v73->u4._bf_0 >> 39) & 0x3FF));
      }
      _InterlockedAnd64(&v73->u2.Lock, 0x7FFFFFFFFFFFFFFFui64);
      if( v75.Long )
        MiReleasePageFileInfo(v72, (_MMPTE)v75.Long, 1ui64);
LABEL_57:
      v32 += 8i64;
    }
    while( v32 <= v33 );
    p_Instance = &p_Vm->Instance;
    v11 = v93;
LABEL_59:
    if( HIDWORD(v89) )
    {
      _InterlockedAnd((volatile signed __int32 *)(v97 + 48), 0xFFFFFFFC);
      __writecr8(2ui64);
      HIDWORD(v89) = 0;
    }
    v55 = v32;
    v56 = MmGetPteBase();
    if( v32 >= (unsigned __int64)v56 )
    {
      v57 = MmGetPteLimit();
      do
      {
        if( v55 > (unsigned __int64)v57 )
          break;
        v55 = (__int64)((v55 << 25) - v96) >> 16;
      }
      while( v55 >= (unsigned __int64)v56 );
      p_Instance = &p_Vm->Instance;
      v11 = v93;
    }
    v21 = v96;
    v10 = (unsigned __int64)v56 + ((v55 >> 9) & 0x7FFFFFFFF8i64);
    v22 = v103;
    v23 = (int)v89;
    if( v10 <= v11 )
    {
      v8 = v90;
      LOBYTE(CurrentIrql) = v91;
      continue;
    }
    break;
  }
  v15 = (volatile signed __int32 *)((char *)&stru_140C4DB30 + 6544);
LABEL_68:
  MiFlushTbList(&TbFlushList);
  if( HIDWORD(v89) )
    MiUnlockVadCore(v97, 2u);
  if( v90 )
    MiUnlockPageTableInternal((INT64)p_Instance, v90);
  if( (p_Instance->Flags._bf_0 & 7u) < 6 )
  {
    Flags = p_Instance->Flags;
    if( (Flags.$2436257948A9E417F8C1432C685A007E::$56A022E0416FA8F0D143F219D5D8FA21::_bf_0 & 8) != 0
      || (Flags.$2436257948A9E417F8C1432C685A007E::$56A022E0416FA8F0D143F219D5D8FA21::_bf_0 & 4) != 0
      || (Flags.$2436257948A9E417F8C1432C685A007E::$56A022E0416FA8F0D143F219D5D8FA21::_bf_0 & 0x10) != 0 )
    {
      MiPreUnlockWorkingSetShared(p_Instance, v91);
      Flags.$9F51E323906620A7CE080F79FB124AD0::$3F85127412E45D453B47E0230FB8DC78::_bf_0 = p_Instance->Flags._bf_0;
    }
    if( (Flags.$9F51E323906620A7CE080F79FB124AD0::$3F85127412E45D453B47E0230FB8DC78::_bf_0 & 7) != 2 )
      v15 = (volatile signed __int32 *)&p_Instance[1];
    MiCheckProcessShadow();
    _InterlockedAnd(v15, 0xBFFFFFFF);
    _InterlockedDecrement(v15);
  }
  __writecr8((unsigned __int8)v91);
}

Referenced by:

MiBeginHoldingDirtyFaults
MiProcessVaRangesInfoClass
NtResetWriteWatch