MiPrepareImagePagesForHotPatch

INT64 __fastcall MiPrepareImagePagesForHotPatch(INT64 *a1, UINT64 a2, INT64 a3){
  ULONG_PTR v4; 
  INT64 v5; 
  INT64 v6; 
  UINT64 v7; 
  __int64 v8; 
  unsigned __int64 v9; 
  unsigned __int64 v10; 
  INT64 result; 
  char *v12; 
  int v13; 
  INT64 v14; 
  __int16 v15; 
  UNICODE_STRING *v16; 
  UNICODE_STRING *v17; 
  UINT8 v18; 
  PWCHAR v19; 
  int v20; 
  int v21; 
  INT64 v22; 
  struct _MDL *v23; 
  INT64 v24; 
  unsigned int v25; 
  ULONG_PTR v26; 
  __int64 v27; 
  _QWORD *v28; 
  unsigned __int64 v29; 
  unsigned __int8 CurrentIrql; 
  __int64 v31; 
  char *v32; 
  unsigned int v33; 
  __int64 v34; 
  INT64 v35; 
  unsigned __int64 v36; 
  unsigned __int64 v37; 
  INT64 a5; 
  int v39; 
  UINT64 v40; 
  UINT64 SpinCount; 
  _MMVAD *Vad; 
  __int64 v43; 
  PMDL Mdl; 
  UINT64 v45; 
  INT64 v46; 
  ULONG_PTR v47; 
  ULONG_PTR v48; 
  unsigned __int64 v49; 
  void *ContainingSubsection[9]; 
  UINT8 v54; 
  _QWORD *v55; 
  v46 = 0i64;
  ContainingSubsection[0] = 0i64;
  v4 = *((_QWORD *)KeGetCurrentThread() + 23);
  v47 = v4;
  v48 = v4;
  v5 = v4 + 1664;
  v6 = *a1;
  Vad = (_MMVAD *)v6;
  Mdl = 0i64;
  v7 = (UINT64)MmGetPteBase() + ((a2 >> 9) & 0x7FFFFFFFF8i64);
  v45 = v7 + 8 * (a3 - 1);
  v8 = 0i64;
  v43 = 0i64;
  v9 = MiCountSharedPages(v6, v7, v45);
  v10 = v9;
  v49 = v9;
  if( v9 )
  {
    result = MiChargeFullProcessCommitment(v4, v9);
    if( (int)result < 0 )
      return result;
  }
  v40 = a2;
  v12 = 0i64;
  v13 = 1;
  v39 = 1;
  v54 = MiLockWorkingSetShared(v5);
  while( v7 <= v45 )
  {
    if( v13 || (v7 & 0xFFF) == 0 )
    {
      if( v12 )
        MiUnlockPageTableInternal(v5, (UINT64)v12);
      v12 = (char *)MmGetPteBase() + ((v7 >> 9) & 0x7FFFFFFFF8i64);
      MiMakeSystemAddressValid(v7, 0i64, (*(_DWORD *)(v6 + 48) >> 12) & 0x3F, v54, 0);
      v39 = 0;
    }
    v14 = MI_READ_PTE_LOCK_FREE(v7);
    v15 = v14;
    v46 = v14;
    if( (*(_BYTE *)v7 & 1) != 0 )
    {
      v16 = (UNICODE_STRING *)((char *)MmGetPfnDb()
                             + 48 * (((unsigned __int64)MI_READ_PTE_LOCK_FREE((INT64)&v46) >> 12) & 0xFFFFFFFFFi64));
      LOBYTE(v20) = MI_PFN_IS_PROTO(v16, v17, v18, v19);
      if( v20
        && (((__int64)v16[2].Buffer & 0x1000000000i64) != 0 || (__int64)v16->Buffer <= 0)
        && (_MMPTE *)((unsigned __int64)v16->Buffer | 0x8000000000000000ui64) == MiGetProtoPteAddress(
                                                                                   Vad,
                                                                                   v40 >> 12,
                                                                                   0i64,
                                                                                   (_SUBSECTION **)ContainingSubsection) )
      {
        v21 = MiCopyOnWrite(v40, (UINT64 *)v7, -1i64, 0i64);
        if( v21 >= 0 )
        {
          if( (v15 & 0x200) == 0 )
            v43 = ++v8;
          goto LABEL_20;
        }
        MiUnlockPageTableInternal(v5, (UINT64)v12);
        MiUnlockWorkingSetShared(v5, v54);
        v12 = 0i64;
        MiCopyOnWriteCheckConditions(v5, (unsigned int)v21);
        v13 = 1;
        v39 = 1;
        MiLockWorkingSetShared(v5);
        v6 = (INT64)Vad;
      }
      else
      {
LABEL_20:
        v7 += 8i64;
        v40 += 4096i64;
        v6 = (INT64)Vad;
        v13 = v39;
      }
    }
    else
    {
      MiUnlockPageTableInternal(v5, (UINT64)v12);
      MiUnlockWorkingSetShared(v5, v54);
      v12 = 0i64;
      v13 = 1;
      v39 = 1;
      MiLockWorkingSetShared(v5);
    }
  }
  MiUnlockPageTableInternal(v5, (UINT64)v12);
  MiUnlockWorkingSetShared(v5, v54);
  v22 = a3;
  v23 = IoAllocateMdl((PVOID)a2, (_DWORD)a3 << 12, 0, 0, 0i64);
  v24 = (INT64)v23;
  Mdl = v23;
  if( v23 )
  {
    MiProbeAndLockPages((INT64)v23, 0, 0i64);
    *(_WORD *)(v24 + 10) |= 0x80u;
    v27 = 0i64;
    v28 = (_QWORD *)(v24 + 48);
    v55 = (_QWORD *)(v24 + 48);
    v29 = v24 + 8 * (a3 + 6);
    v45 = v29;
    CurrentIrql = KeGetCurrentIrql();
    __writecr8(2ui64);
    if( v24 + 48 < v29 )
    {
      do
      {
        v31 = v27;
        v32 = (char *)MmGetPfnDb() + 48 * *v28;
        LODWORD(SpinCount) = 0;
        if( _interlockedbittestandset64((volatile signed __int32 *)v32 + 6, 0x3Fui64) )
        {
          do
          {
            do
              KeYieldProcessorEx(&SpinCount);
            while( *((__int64 *)v32 + 3) < 0 );
          }
          while( _interlockedbittestandset64((volatile signed __int32 *)v32 + 6, 0x3Fui64) );
          v28 = v55;
          v29 = v45;
          v31 = v27;
        }
        v33 = ((*((_QWORD *)v32 + 3) & 0x3FFFFFFFFFFFFFFFi64) != 0) + 2;
        if( (v32[34] & 8) == 0 )
          v33 = ((*((_QWORD *)v32 + 3) & 0x3FFFFFFFFFFFFFFFi64) != 0) + 1;
        v27 = v31 + 1;
        if( *((unsigned __int16 *)v32 + 16) <= v33 )
          v27 = v31;
        _InterlockedAnd64((volatile signed __int64 *)v32 + 3, 0x7FFFFFFFFFFFFFFFui64);
        v55 = ++v28;
      }
      while( (unsigned __int64)v28 < v29 );
      v22 = a3;
    }
    __writecr8(CurrentIrql);
    if( v27 )
    {
      v34 = *(_QWORD *)(***(_QWORD ***)(v6 + 72) + 56i64);
      LODWORD(a5) = v27;
      MiLogHotPatchPagesLocked(a2, (v22 << 12) + a2 - 1, *(unsigned int *)(v34 + 60), *(unsigned int *)(v34 + 72), a5);
    }
    v35 = a1[7];
    if( v35 )
      *(_QWORD *)v24 = v35;
    a1[7] = v24;
    v25 = 0;
  }
  else
  {
    v25 = -1073741670;
  }
  v26 = v47;
  if( v8 )
  {
    v36 = v8 + (*(_DWORD *)(v6 + 52) & 0x7FFFFFFF | ((unsigned __int64)*(unsigned __int8 *)(v6 + 34) << 31));
    *(_DWORD *)(v6 + 52) ^= (*(_DWORD *)(v6 + 52) ^ (v8
                                                   + (*(_DWORD *)(v6 + 52) & 0x7FFFFFFF | (*(unsigned __int8 *)(v6 + 34) << 31)))) & 0x7FFFFFFF;
    *(_BYTE *)(v6 + 34) = v36 >> 31;
  }
  v37 = v10 - v8;
  if( v37 )
    MiReturnFullProcessCommitment(v26, v37);
  return v25;
}

Referenced by:

MiPrepareToHotPatchImage