MiPrepareImagePagesForHotPatch

NTSTATUS __stdcall MiPrepareImagePagesForHotPatch(INT64 *a1, UINT64 a2, INT64 a3){
  _EPROCESS *Process; 
  _MMSUPPORT_INSTANCE *p_Instance; 
  _MMVAD *v6; 
  unsigned __int64 v7; 
  __int64 v8; 
  UINT64 v9; 
  UINT64 v10; 
  NTSTATUS result; 
  char *v12; 
  int v13; 
  UINT8 v14; 
  INT64 v15; 
  __int16 v16; 
  UINT64 v17; 
  unsigned __int64 v18; 
  _MMPFN *v19; 
  _UNICODE_STRING *v20; 
  UINT8 v21; 
  PWCHAR v22; 
  int v23; 
  __int64 v24; 
  NTSTATUS v25; 
  UINT64 v26; 
  UINT64 v27; 
  INT64 v28; 
  _MDL *v29; 
  INT64 v30; 
  NTSTATUS v31; 
  _EPROCESS *v32; 
  __int64 v33; 
  _MMPTE *v34; 
  _MMPTE *v35; 
  unsigned __int8 CurrentIrql; 
  __int64 v37; 
  _MMPFN *v38; 
  unsigned int v39; 
  union {_MI_SECTION_IMAGE_INFORMATION *ImageInformation;void *FirstMappedVa;} v40; 
  INT64 v41; 
  unsigned __int64 v42; 
  UINT64 v43; 
  UINT64 v44; 
  int v45; 
  UINT64 rcx0a; 
  UINT64 SpinCount; 
  _MMVAD *v48; 
  __int64 v49; 
  PMDL Mdl; 
  _MMPTE *v51; 
  INT64 v52; 
  _EPROCESS *v53; 
  _EPROCESS *TargetProcess; 
  UINT64 v55; 
  __int64 v56; 
  UINT8 WsIrql; 
  _MMPTE *WsIrqla; 

  v52 = 0i64;
  v56 = 0i64;
  Process = KeGetCurrentThread()->ApcState.Process;
  v53 = Process;
  TargetProcess = Process;
  p_Instance = &Process->Vm.Instance;
  v6 = (_MMVAD *)*a1;
  v48 = v6;
  Mdl = 0i64;
  v7 = (unsigned __int64)MmGetPteBase() + ((a2 >> 9) & 0x7FFFFFFFF8i64);
  v51 = (_MMPTE *)(v7 + 8 * (a3 - 1));
  v8 = 0i64;
  v49 = 0i64;
  LODWORD(v9) = MiCountSharedPages(v6, (_MMPTE *)v7, v51);
  v10 = v9;
  v55 = v9;
  if( v9 )
  {
    result = MiChargeFullProcessCommitment((ULONG_PTR)Process, v9);
    if( result < 0 )
      return result;
  }
  rcx0a = a2;
  v12 = 0i64;
  v13 = 1;
  v45 = 1;
  MiLockWorkingSetShared();
  WsIrql = v14;
  while( v7 <= (unsigned __int64)v51 )
  {
    if( v13 || (v7 & 0xFFF) == 0 )
    {
      if( v12 )
        MiUnlockPageTableInternal((INT64)p_Instance, (UINT64)v12);
      v12 = (char *)MmGetPteBase() + ((v7 >> 9) & 0x7FFFFFFFF8i64);
      LODWORD(v44) = 0;
      MiMakeSystemAddressValid((VOID *)v7, 0i64, (v6->Core.u.LongFlags >> 12) & 0x3F, WsIrql, v44);
      v45 = 0;
    }
    LODWORD(v15) = MI_READ_PTE_LOCK_FREE(v7);
    v16 = v15;
    v52 = v15;
    if( (*(_BYTE *)v7 & 1) != 0 )
    {
      LODWORD(v18) = MI_READ_PTE_LOCK_FREE((INT64)&v52);
      v19 = &MmGetPfnDb()[(v18 >> 12) & 0xFFFFFFFFFi64];
      LOBYTE(v23) = MI_PFN_IS_PROTO((_UNICODE_STRING *)v19, v20, v21, v22);
      if( v23
        && ((v19->u4._bf_0 & 0x1000000000i64) != 0 || (__int64)v19->ListEntry.Blink <= 0)
        && (MiGetProtoPteAddress(), (v19->PteLong | 0x8000000000000000ui64) == v24) )
      {
        v25 = MiCopyOnWrite(rcx0a, (INT64 *)v7, 0xFFFFFFFFFFFFFFFFui64, 0i64);
        if( v25 >= 0 )
        {
          if( (v16 & 0x200) == 0 )
            v49 = ++v8;
          goto LABEL_20;
        }
        MiUnlockPageTableInternal((INT64)p_Instance, (UINT64)v12);
        LOBYTE(v26) = WsIrql;
        MiUnlockWorkingSetShared(p_Instance, v26);
        v12 = 0i64;
        MiCopyOnWriteCheckConditions((INT64)p_Instance, (unsigned int)v25);
        v13 = 1;
        v45 = 1;
        MiLockWorkingSetShared();
        v6 = v48;
      }
      else
      {
LABEL_20:
        v7 += 8i64;
        rcx0a += 4096i64;
        v6 = v48;
        v13 = v45;
      }
    }
    else
    {
      MiUnlockPageTableInternal((INT64)p_Instance, (UINT64)v12);
      LOBYTE(v17) = WsIrql;
      MiUnlockWorkingSetShared(p_Instance, v17);
      v12 = 0i64;
      v13 = 1;
      v45 = 1;
      MiLockWorkingSetShared();
    }
  }
  MiUnlockPageTableInternal((INT64)p_Instance, (UINT64)v12);
  LOBYTE(v27) = WsIrql;
  MiUnlockWorkingSetShared(p_Instance, v27);
  v28 = a3;
  v29 = IoAllocateMdl((VOID *)a2, (unsigned int)((_DWORD)a3 << 12), 0, 0, 0i64);
  v30 = (INT64)v29;
  Mdl = v29;
  if( v29 )
  {
    MiProbeAndLockPages((INT64)v29, 0, 0i64);
    *(_WORD *)(v30 + 10) |= 0x80u;
    v33 = 0i64;
    v34 = (_MMPTE *)(v30 + 48);
    WsIrqla = (_MMPTE *)(v30 + 48);
    v35 = (_MMPTE *)(v30 + 8 * (a3 + 6));
    v51 = v35;
    CurrentIrql = KeGetCurrentIrql();
    __writecr8(2ui64);
    if( v30 + 48 < (unsigned __int64)v35 )
    {
      do
      {
        v37 = v33;
        v38 = &MmGetPfnDb()[v34->u.Long];
        LODWORD(SpinCount) = 0;
        if( _interlockedbittestandset64((volatile signed __int32 *)&v38->u2, 0x3Fui64) )
        {
          do
          {
            do
              KeYieldProcessorEx(&SpinCount);
            while( v38->u2._bf_0 < 0 );
          }
          while( _interlockedbittestandset64((volatile signed __int32 *)&v38->u2, 0x3Fui64) );
          v34 = WsIrqla;
          v35 = v51;
          v37 = v33;
        }
        v39 = ((v38->u2._bf_0 & 0x3FFFFFFFFFFFFFFFi64) != 0) + 2;
        if( (*(_BYTE *)(&v38->u3 + 1) & 8) == 0 )
          v39 = ((v38->u2._bf_0 & 0x3FFFFFFFFFFFFFFFi64) != 0) + 1;
        v33 = v37 + 1;
        if( v38->u3.ReferenceCount <= v39 )
          v33 = v37;
        _InterlockedAnd64(&v38->u2.Lock, 0x7FFFFFFFFFFFFFFFui64);
        WsIrqla = ++v34;
      }
      while( v34 < v35 );
      v28 = a3;
    }
    __writecr8(CurrentIrql);
    if( v33 )
    {
      v40.ImageInformation = (_MI_SECTION_IMAGE_INFORMATION *)v6->Subsection->ControlArea->Segment->u2;
      MiLogHotPatchPagesLocked(
        a2,
        (v28 << 12) + a2 - 1,
        v40.ImageInformation->ExportedImageInformation.CheckSum,
        v40.ImageInformation->InternalImageInformation.TimeDateStamp,
        v33);
    }
    v41 = a1[7];
    if( v41 )
      *(_QWORD *)v30 = v41;
    a1[7] = v30;
    v31 = 0;
  }
  else
  {
    v31 = -1073741670;
  }
  v32 = v53;
  if( v8 )
  {
    v42 = v8 + (v6->Core.u1.LongFlags1 & 0x7FFFFFFF | ((unsigned __int64)v6->Core.CommitChargeHigh << 31));
    v6->Core.u1.LongFlags1 ^= (v6->Core.u1.LongFlags1 ^ (v8
                                                       + (v6->Core.u1.LongFlags1 & 0x7FFFFFFF | (v6->Core.CommitChargeHigh << 31)))) & 0x7FFFFFFF;
    v6->Core.CommitChargeHigh = v42 >> 31;
  }
  v43 = v10 - v8;
  if( v43 )
    MiReturnFullProcessCommitment(v32, v43);
  return v31;
}

Referenced by:

MiPrepareToHotPatchImage