MiSwapStackPage

NTSTATUS __stdcall MiSwapStackPage(
        _MMPFN *Pfn1,
        _MMPTE_COPY_LIST *PteCopyList,
        UINT64 ReplacementColor,
        UINT64 *ReplacementPage,
        UINT64 *FastPath){
  int v7; 
  _QWORD *Pool; 
  _QWORD *v9; 
  unsigned __int64 v10; 
  __int64 v11; 
  NTSTATUS SystemRegionType; 
  VOID *v13; 
  _MI_WORKING_SET_TYPE v14; 
  _MMSUPPORT_INSTANCE *AnyMultiplexedVm; 
  _MMSUPPORT_INSTANCE *v16; 
  unsigned int v17; 
  __int128 v18; 
  signed __int64 v19; 
  unsigned int v20; 
  __int64 v21; 
  int v22; 
  UINT64 v23; 
  _MMPFN *v24; 
  UINT64 v25; 
  char v26; 
  char v27; 
  NTSTATUS v28; 
  char *v29; 
  UINT64 v30; 
  UINT64 v31; 
  _ETHREAD *LeafPfnBuddy; 
  _MMPTE *PteFromCopyList; 
  char v34; 
  char v35; 
  _KPRCB *v36; 
  unsigned __int64 Long; 
  int v38; 
  UINT64 v39; 
  UINT64 v40; 
  unsigned __int64 v41; 
  int v42; 
  UINT64 v43; 
  _ETHREAD *v44; 
  INT64 v45; 
  NTSTATUS v46; 
  unsigned __int64 v47; 
  int v48; 
  _MMPFN *v49; 
  unsigned __int64 v50; 
  unsigned __int64 v51; 
  char WsIrql; 
  int WsIrql_4; 
  INT64 v55; 
  UINT64 DestinationPage; 
  VOID *Token; 
  _ETHREAD *CurrentThread; 
  __int64 v59; 
  UINT64 *v62; 
  _DWORD *v63; 

  Token = 0i64;
  v7 = (int)ReplacementPage;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  Pool = MiAllocatePool(64i64, 0x50ui64, 0x734B694Dui64);
  v9 = Pool;
  if( !Pool )
    return 0;
  Pool[4] = Pfn1;
  v10 = *((_QWORD *)PteCopyList + 1) | 0x8000000000000000ui64;
  v11 = (__int64)((v10 << 25) - ((_QWORD)MmGetPteBase() << 25)) >> 16;
  Pool[6] = v11;
  SystemRegionType = MiGetSystemRegionType(v11);
  LODWORD(v55) = SystemRegionType;
  if( SystemRegionType == 14 )
  {
    v14 = MiWorkingSetTypeKernelStacks;
  }
  else
  {
    if( SystemRegionType != 12 )
    {
LABEL_59:
      ExFreePoolWithTag(v9, 0);
      return 0;
    }
    v14 = MiWorkingSetTypeSystemViews;
  }
  AnyMultiplexedVm = MiGetAnyMultiplexedVm(v14, v13);
  v9[8] = AnyMultiplexedVm;
  v16 = AnyMultiplexedVm;
  if( !*(&stru_140C4DB30 + 4332) )
    goto LABEL_59;
  v17 = 512;
  v18 = ((char *)PteCopyList - (char *)MmGetPfnDb()) * (__int128)0x2AAAAAAAAAAAAAABi64;
  v19 = ((char *)PteCopyList - (char *)MmGetPfnDb()) / 48;
  v59 = v19;
  if( v7 == -1 )
  {
    LODWORD(v21) = MiSearchNumaNodeTable((PVOID)((*((_QWORD *)&v18 + 1) >> 63) + (*((__int64 *)&v18 + 1) >> 3)));
    v22 = *(_DWORD *)(v21 + 8);
    v20 = (MiGetPfnChannel((INT64)PteCopyList) << *(&stru_140C4DB30 + 157)) | *(&stru_140C4DB30 + 66) & v19 | (v22 << *(&stru_140C4DB30 + 156));
    if( ((unsigned int)FastPath & 0x3000000) != 0 )
      v17 = 66048;
  }
  else
  {
    v17 = 560;
    v20 = *(&stru_140C4DB30 + 66) & v19 | v7 & ~*(&stru_140C4DB30 + 66);
  }
  LODWORD(v23) = MiGetPage((ULONG_PTR *)Pfn1, v20, v17);
  DestinationPage = v23;
  if( v23 == -1i64 )
    goto LABEL_59;
  v24 = &MmGetPfnDb()[v23];
  MiSetPfnTbFlushStamp(v24, 0i64, 0i64);
  v9[7] = 0i64;
  MiLockWorkingSetShared();
  WsIrql_4 = 0;
  v27 = v26;
  WsIrql = v26;
  while( _interlockedbittestandset64(PteCopyList + 6, 0x3Fui64) )
  {
    do
      KeYieldProcessorEx((UINT64 *)&WsIrql_4);
    while( *((__int64 *)PteCopyList + 3) < 0 );
  }
  if( *(_MMPFN **)(*(&stru_140C4DB30 + 267) + 8 * ((*((_QWORD *)PteCopyList + 5) >> 39) & 0x3FFi64)) != Pfn1
    || v10 != (*((_QWORD *)PteCopyList + 1) | 0x8000000000000000ui64)
    || (v28 = MiGetSystemRegionType(v9[6]), (_DWORD)v55 != v28)
    || !MiCanStealKernelStack((_MMPFN *)PteCopyList, 1u)
    || (v29 = (char *)MmGetPteBase() + ((v10 >> 9) & 0x7FFFFFFFF8i64),
        !MiLockPageTableInternal((INT64)v16, (UINT64)v29, (UINT8 *)1)) )
  {
    _InterlockedAnd64((volatile signed __int64 *)PteCopyList + 3, 0x7FFFFFFFFFFFFFFFui64);
    goto LABEL_57;
  }
  if( (MiFlags & 0x800) != 0
    || MiSwapStackPageNoDpc((_MMPTE_COPY_LIST *)ReplacementColor, (_MMPFN *)PteCopyList, v24) != 1 )
  {
    LeafPfnBuddy = (_ETHREAD *)MiGetLeafPfnBuddy(PteCopyList);
    v55 = (INT64)LeafPfnBuddy;
    if( ((unsigned __int64)&LeafPfnBuddy->Tcb.QuantumTarget & 0xFFFFFFFFFFFFFFDFui64) != 0 )
    {
      PteFromCopyList = MiGetPteFromCopyList(
                          (_MMPTE_COPY_LIST *)ReplacementColor,
                          DestinationPage,
                          0xFFFFFFFFFFFFFFFFui64);
      if( LeafPfnBuddy != (_ETHREAD *)-16i64 && LeafPfnBuddy != CurrentThread )
      {
        KeTryToFreezeThreadStack(LeafPfnBuddy, &Token);
        if( v34 == 1 )
        {
          MiCopyKstack(v24, (_MMPFN *)PteCopyList, PteFromCopyList);
          MiLockNestedPageAtDpcInline(v24);
          MiSwitchKstackPages(v24, (_MMPFN *)PteCopyList);
          _InterlockedAnd64(&v24->u2.Lock, 0x7FFFFFFFFFFFFFFFui64);
          v35 = *((_BYTE *)PteCopyList + 34);
          *((_QWORD *)PteCopyList + 5) &= ~0x8000000000000000ui64;
          *((_BYTE *)PteCopyList + 34) = v35 & 0xC7;
          *((_BYTE *)PteCopyList + 35) &= ~0x20u;
          *((_QWORD *)PteCopyList + 3) &= 0xC000000000000000ui64;
          _InterlockedAnd64((volatile signed __int64 *)PteCopyList + 3, 0x7FFFFFFFFFFFFFFFui64);
          KeFlushSingleTb(v9[6], FlushKernel, 2i64);
          KiReleaseThreadStateLock(v36, (_KSHARED_READY_QUEUE *)Token);
          KiReleaseThreadLockSafe(v55);
          Long = ZeroPte.u.Long;
          LOBYTE(v38) = MiPteInShadowRange((UINT64)PteFromCopyList);
          if( v38 && (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0 && (ZeroPte.u.Long & 1) != 0 )
            Long = ZeroPte.u.Long | 0x8000000000000000ui64;
          PteFromCopyList->u.Long = Long;
          MiUnlockPageTableInternal((INT64)v16, (UINT64)v29);
          LOBYTE(v39) = WsIrql;
          MiUnlockWorkingSetShared(v16, v39);
          v31 = DestinationPage;
          *v63 = 1;
          goto LABEL_52;
        }
        goto LABEL_39;
      }
      if( MiAddLockedPageCharge((_MMPFN *)PteCopyList, 0i64) )
      {
        v9[7] = PteCopyList;
LABEL_39:
        _InterlockedAnd64((volatile signed __int64 *)PteCopyList + 3, 0x7FFFFFFFFFFFFFFFui64);
        MiUnlockPageTableInternal((INT64)v16, (UINT64)v29);
        LOBYTE(v43) = WsIrql;
        MiUnlockWorkingSetShared(v16, v43);
        v44 = CurrentThread;
        v31 = DestinationPage;
        *v9 = v59;
        v45 = v55;
        v9[3] = v44;
        v9[1] = v31;
        v9[2] = PteFromCopyList;
        *((_DWORD *)v9 + 10) = 0;
        if( v45 == -16 || (_ETHREAD *)v45 == v44 )
        {
          v46 = KeExpandKernelStackAndCalloutInternal(MiJumpStack, v9, 0x6000ui64, 1, 0i64);
          if( v46 < 0 )
            *((_DWORD *)v9 + 10) = v46;
        }
        else
        {
          KeGenericCallDpc((__int64)MiDoStackCopy, (__int64)v9);
        }
        if( *((int *)v9 + 10) >= 0 )
        {
          *v63 = 0;
          v51 = MiLockPageInline((_MMPFN *)PteCopyList);
          *((_QWORD *)PteCopyList + 3) &= 0xC000000000000000ui64;
          _InterlockedAnd64((volatile signed __int64 *)PteCopyList + 3, 0x7FFFFFFFFFFFFFFFui64);
          __writecr8(v51);
          goto LABEL_52;
        }
        v47 = ZeroPte.u.Long;
        LOBYTE(v48) = MiPteInShadowRange((UINT64)PteFromCopyList);
        if( v48 && (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0 && (ZeroPte.u.Long & 1) != 0 )
          v47 = ZeroPte.u.Long | 0x8000000000000000ui64;
        PteFromCopyList->u.Long = v47;
        MiReleaseFreshPage(v24);
        v49 = (_MMPFN *)v9[7];
        if( v49 )
        {
          v50 = MiLockPageInline(v49);
          MiRemoveLockedPageChargeAndDecRef((_MMPFN *)v9[7]);
          _InterlockedAnd64((volatile signed __int64 *)(v9[7] + 24i64), 0x7FFFFFFFFFFFFFFFui64);
          __writecr8(v50);
        }
        goto LABEL_59;
      }
      _InterlockedAnd64((volatile signed __int64 *)PteCopyList + 3, 0x7FFFFFFFFFFFFFFFui64);
      MiUnlockPageTableInternal((INT64)v16, (UINT64)v29);
      LOBYTE(v40) = WsIrql;
      MiUnlockWorkingSetShared(v16, v40);
      v41 = ZeroPte.u.Long;
      LOBYTE(v42) = MiPteInShadowRange((UINT64)PteFromCopyList);
      if( v42 && (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0 && (ZeroPte.u.Long & 1) != 0 )
        v41 = ZeroPte.u.Long | 0x8000000000000000ui64;
      PteFromCopyList->u.Long = v41;
      goto LABEL_58;
    }
    _InterlockedAnd64((volatile signed __int64 *)PteCopyList + 3, 0x7FFFFFFFFFFFFFFFui64);
    MiUnlockPageTableInternal((INT64)v16, (UINT64)v29);
LABEL_57:
    LOBYTE(v25) = v27;
    MiUnlockWorkingSetShared(v16, v25);
LABEL_58:
    MiReleaseFreshPage(v24);
    goto LABEL_59;
  }
  _InterlockedAnd64((volatile signed __int64 *)PteCopyList + 3, 0x7FFFFFFFFFFFFFFFui64);
  MiUnlockPageTableInternal((INT64)v16, (UINT64)v29);
  LOBYTE(v30) = v27;
  MiUnlockWorkingSetShared(v16, v30);
  v31 = DestinationPage;
  *v63 = 1;
LABEL_52:
  *((_WORD *)PteCopyList + 16) = 0;
  if( v62 )
    *v62 = v31;
  ExFreePoolWithTag(v9, 0);
  return 1;
}

Referenced by:

MiTradePage