MmOutSwapWorkingSet

NTSTATUS __stdcall MmOutSwapWorkingSet(_EPROCESS *Process, UINT64 IncludeSharedPages){
  _MMSUPPORT_FULL *p_Vm; 
  int v3; 
  unsigned int v5; 
  _MI_PARTITION *v6; 
  unsigned int SessionId; 
  unsigned int BestOutswapPagefile; 
  VOID *Pool; 
  INT64 *p_WorkingSetInswapLock; 
  unsigned __int64 v11; 
  VOID *WorkingSetSwapSupport; 
  _MMSUPPORT_INSTANCE *v13; 
  UINT64 v14; 
  unsigned int v15; 
  UINT64 PagesToOutSwap; 
  _MI_WS_SWAP_SUPPORT *v17; 
  UINT64 WorkingSetSize; 
  _EPROCESS *v19; 
  bool v20; 
  _ETHREAD *v21; 
  _MMVAD *Root; 
  _MMVAD *v23; 
  _MMVAD *ExtraCreateInfo; 
  INT64 v25; 
  int v26; 
  _MMVAD *v27; 
  _MI_WS_SWAP_SUPPORT *v28; 
  __int64 v29; 
  int v30; 
  INT64 *v31; 
  unsigned __int64 v32; 
  _MMSUPPORT_INSTANCE *v33; 
  _MMSUPPORT_SHARED *SharedVm; 
  UINT64 v35; 
  _EX_PUSH_LOCK *p_WorkingSetSwapLock; 
  UINT64 v37; 
  _ETHREAD *CurrentThread; 
  unsigned __int8 v39; 
  int v40; 
  __int64 v41; 
  _KLOCK_ENTRY *v42; 
  __int64 v43; 
  PVOID v44; 
  _MI_WS_SWAP_SUPPORT *v46; 
  NTSTATUS v47; 
  int v48; 
  _MI_WS_SWAP_SUPPORT *v49; 
  INT64 a5; 
  int v51; 
  UINT64 ExtendPages; 
  UINT64 SwapFileNumber; 
  UINT64 a3; 
  _MI_PARTITION *Partition; 
  _ETHREAD *Thread; 
  INT64 *SpinLock; 
  PVOID P; 
  _EPROCESS *Processa; 
  INT64 v60[20]; 
  __int128 EventParameters; 
  __int128 v62; 
  __int64 v63; 

  LODWORD(SwapFileNumber) = 0;
  p_Vm = &Process->Vm;
  Processa = Process;
  v63 = 0i64;
  EventParameters = 0i64;
  v3 = IncludeSharedPages;
  v62 = 0i64;
  Thread = (_ETHREAD *)KeGetCurrentThread();
  ExtendPages = 0i64;
  v5 = 0;
  P = 0i64;
  memset(v60, 0i64, 0x98u);
  Partition = *(_MI_PARTITION **)(*(&stru_140C4DB30 + 267) + 8i64 * p_Vm->Instance.PartitionId);
  v6 = Partition;
  LODWORD(EventParameters) = v3 != 0;
  v60[3] = (INT64)Partition;
  SessionId = -1;
  v51 = -1;
  if( (unsigned int)SmStoreExistsForProcess(Process) )
  {
    LODWORD(EventParameters) = EventParameters | 4;
    v5 = 2;
    LODWORD(v60[4]) = -1;
  }
  EtwTraceWorkingSetSwap(Process, 2ui64, &EventParameters);
  BestOutswapPagefile = MiFindBestOutswapPagefile(Partition, &SwapFileNumber);
  if( BestOutswapPagefile == 16 )
  {
    v30 = -1073741497;
  }
  else
  {
    Pool = MiAllocatePool(64i64, 0x50ui64, 0x43536D4Dui64);
    if( Pool )
    {
      v5 |= 1u;
      --Thread->Tcb.SpecialApcDisable;
      ExAcquirePushLockExclusiveEx(&v6->Modwriter.WorkingSetSwapLock, 0i64);
      p_WorkingSetInswapLock = (INT64 *)&v6->Modwriter.WorkingSetInswapLock;
      SpinLock = (INT64 *)&v6->Modwriter.WorkingSetInswapLock;
      v11 = (unsigned __int8)ExAcquireSpinLockExclusive((INT64 *)&v6->Modwriter.WorkingSetInswapLock);
      WorkingSetSwapSupport = MiGetWorkingSetSwapSupport(&p_Vm->Instance);
      if( WorkingSetSwapSupport )
      {
        if( WorkingSetSwapSupport == (VOID *)1 )
        {
          v30 = -1073740682;
        }
        else
        {
          v30 = -1073741791;
          if( WorkingSetSwapSupport == (VOID *)2 )
            v30 = -1073741558;
        }
        ExReleaseSpinLockExclusiveFromDpcLevel(SpinLock);
        __writecr8(v11);
        v6 = Partition;
      }
      else
      {
        MiGetSharedVm(v13)->WsSwapSupport = (void *)1;
        ExReleaseSpinLockExclusiveFromDpcLevel(p_WorkingSetInswapLock);
        __writecr8(v11);
        v15 = SwapFileNumber;
        while( 1 )
        {
          PagesToOutSwap = p_Vm->Instance.WorkingSetLeafPrivateSize;
          ExtendPages = PagesToOutSwap;
          if( !PagesToOutSwap )
          {
            v30 = -1073741779;
            goto LABEL_35;
          }
          if( LODWORD(v60[4]) == -1 )
            break;
          LODWORD(a5) = v15;
          v30 = MiReserveWorkingSetSwapSpace(Partition, &v60[5], v14, BestOutswapPagefile, a5, PagesToOutSwap);
          if( v30 >= 0 )
          {
            PagesToOutSwap = ExtendPages;
            break;
          }
          if( v15 < 0x10 )
          {
            BestOutswapPagefile = v15;
            v30 = MiExtendWorkingSetSwapPagefile(Partition, ExtendPages, v15);
            if( v30 >= 0 )
              continue;
          }
          goto LABEL_35;
        }
        v17 = MiAllocateWorkingSetSwapSupport(PagesToOutSwap);
        *(_QWORD *)Pool = v17;
        if( !v17 )
          goto LABEL_83;
        if( LODWORD(v60[4]) != -1 )
          v17[8] |= 1u;
        WorkingSetSize = 0i64;
        if( !v3 )
          goto LABEL_13;
        WorkingSetSize = p_Vm->Instance.WorkingSetSize;
        if( WorkingSetSize - p_Vm->Instance.WorkingSetPrivateSize <= WorkingSetSize )
          WorkingSetSize = p_Vm->Instance.WorkingSetSize - p_Vm->Instance.WorkingSetPrivateSize;
        if( WorkingSetSize
          && (v46 = MiAllocateWorkingSetSwapSupport(WorkingSetSize), (*((_QWORD *)Pool + 1) = v46) == 0i64) )
        {
LABEL_83:
          v30 = -1073741670;
        }
        else
        {
LABEL_13:
          v19 = Processa;
          v60[0] = *(_QWORD *)Pool;
          v60[1] = *((_QWORD *)Pool + 1);
          v20 = Processa->VmContext == 0i64;
          v60[2] = (INT64)p_Vm;
          if( !v20 )
          {
            v47 = VmCheckLargePageInswap((INT64)Processa);
            v48 = v60[18];
            if( v47 )
              v48 = 1;
            LODWORD(v60[18]) = v48;
          }
          v21 = Thread;
          --Thread->Tcb.SpecialApcDisable;
          ExAcquirePushLockSharedEx(&v19->AddressCreationLock, 0i64);
          v21->$84F33738BEE95ACDF5C5BF1C8FDC7C8C::_bf_0 |= 2u;
          if( (v19->Flags & 0x20) != 0 )
          {
            UNLOCK_ADDRESS_SPACE_SHARED(v21, v19);
            v30 = -1073741558;
          }
          else
          {
            Root = (_MMVAD *)v19->VadRoot.Root;
            v23 = 0i64;
            while( Root )
            {
              v23 = Root;
              Root = (_MMVAD *)Root->Core.NextVad;
            }
            while( v23 )
            {
              if( !MiVadMapsLargeImage(v23) )
              {
                LOBYTE(v26) = MiVadSupportsPrivateCommit(v25);
                if( v26 )
                  MiOutSwapWorkingSet(
                    &p_Vm->Instance,
                    (INT64)v23,
                    (v23->Core.StartingVpn | ((unsigned __int64)v23->Core.StartingVpnHigh << 32)) << 12,
                    ((v23->Core.EndingVpn | ((unsigned __int64)v23->Core.EndingVpnHigh << 32)) << 12) | 0xFFF,
                    (INT64)v60);
              }
              ExtraCreateInfo = (_MMVAD *)v23->Core.ExtraCreateInfo;
              v27 = v23;
              if( ExtraCreateInfo )
              {
                do
                {
                  v23 = ExtraCreateInfo;
                  ExtraCreateInfo = (_MMVAD *)ExtraCreateInfo->Core.NextVad;
                }
                while( ExtraCreateInfo );
              }
              else
              {
                while( 1 )
                {
                  v23 = (_MMVAD *)(v23->Core.VadNode.ParentValue & 0xFFFFFFFFFFFFFFFCui64);
                  if( !v23 || (_MMVAD *)v23->Core.NextVad == v27 )
                    break;
                  v27 = v23;
                }
              }
            }
            UNLOCK_ADDRESS_SPACE_SHARED(v21, v19);
            if( *(_QWORD *)(*(_QWORD *)Pool + 16i64) < ExtendPages )
            {
              v28 = MiReAllocateWorkingSetSwapSupport(*(_MI_WS_SWAP_SUPPORT **)Pool);
              if( v28 )
              {
                ExFreePoolWithTag(*(PVOID *)Pool, 0);
                *(_QWORD *)Pool = v28;
              }
            }
            v29 = *((_QWORD *)Pool + 1);
            if( v29 )
            {
              if( *(_QWORD *)(v29 + 16) < WorkingSetSize )
              {
                v49 = MiReAllocateWorkingSetSwapSupport((_MI_WS_SWAP_SUPPORT *)v29);
                if( v49 )
                {
                  ExFreePoolWithTag(*((PVOID *)Pool + 1), 0);
                  *((_QWORD *)Pool + 1) = v49;
                }
              }
            }
            ExtendPages = *(_QWORD *)(*(_QWORD *)Pool + 24i64);
            MiGetKernelStackSwapSupport((__int64)Pool, (__int64)v19);
            if( v5 >= 2 )
              P = MiReAllocateWorkingSetSwapSupport(*(_MI_WS_SWAP_SUPPORT **)Pool);
            v5 |= 4u;
            v30 = 0;
          }
        }
LABEL_35:
        v31 = SpinLock;
        v32 = (unsigned __int8)ExAcquireSpinLockExclusive(SpinLock);
        if( MiGetWorkingSetSwapSupport(&p_Vm->Instance) == (VOID *)1 )
        {
          SharedVm = MiGetSharedVm(v33);
          if( v5 < 4 )
          {
            SharedVm->WsSwapSupport = 0i64;
          }
          else
          {
            SharedVm->WsSwapSupport = Pool;
            Pool = 0i64;
            v30 = 0;
          }
        }
        else
        {
          v30 = -1073741558;
        }
        ExReleaseSpinLockExclusiveFromDpcLevel(v31);
        __writecr8(v32);
        v6 = Partition;
        MiFreeReservationRuns(Partition, (_MI_WS_SWAP_RESERVATION_RUN *)&v60[5], v35);
      }
      if( Pool )
        MiFreeWorkingSetSwapContext(v6, Pool);
    }
    else
    {
      v30 = -1073741670;
    }
    SessionId = -1;
  }
  if( (v5 & 1) != 0 )
  {
    p_WorkingSetSwapLock = &v6->Modwriter.WorkingSetSwapLock;
    if( (_InterlockedExchangeAdd64(&v6->Modwriter.WorkingSetSwapLock._bf_0, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
      ExfTryToWakePushLock(&v6->Modwriter.WorkingSetSwapLock);
    LODWORD(a3) = 0;
    v37 = (UINT64)&v6->Modwriter.WorkingSetSwapLock;
    CurrentThread = (_ETHREAD *)KeGetCurrentThread();
    if( MiGetSystemRegionType(v37) == 1 )
    {
      SessionId = MmGetSessionIdEx(CurrentThread->Tcb.ApcState.Process);
      v51 = SessionId;
    }
    --CurrentThread->Tcb.SpecialApcDisable;
    v39 = ++CurrentThread->Tcb.AbAllocationRegionCount;
    v40 = ((char)CurrentThread->Tcb.AbEntrySummary | (char)CurrentThread->Tcb.AbOrphanedEntrySummary) ^ 0x3F;
    v20 = !_BitScanReverse((unsigned int *)&v41, v40);
    HIDWORD(SwapFileNumber) = v41;
    if( v20 )
    {
LABEL_69:
      if( (*(&CurrentThread->Tcb.MiscFlags + 1) & 0x10000) == 0 )
        KeBugCheckEx(0x162u, CurrentThread, p_WorkingSetSwapLock, (PVOID)SessionId, 0i64);
    }
    else
    {
      while( 1 )
      {
        v42 = &CurrentThread->Tcb.LockEntries[v41];
        v40 &= ~(1 << v41);
        if( (v42->AcquiredByte & 1) != 0
          && (v42->LockState.$E8276A2CF8B819ED32D1B6FEB35D730A::_bf_0 & 1) == 0
          && (v42->LockState.$E8276A2CF8B819ED32D1B6FEB35D730A::_bf_0 & 0x7FFFFFFFFFFFFFFCi64) == ((unsigned __int64)p_WorkingSetSwapLock & 0x7FFFFFFFFFFFFFFCi64)
          && v42->LockState.SessionId == v51 )
        {
          v42->AcquiredByte &= ~1u;
          if( v42->LockState.$E8276A2CF8B819ED32D1B6FEB35D730A::_bf_0 )
            break;
        }
        v20 = !_BitScanReverse((unsigned int *)&v41, v40);
        HIDWORD(SwapFileNumber) = v41;
        if( v20 )
          goto LABEL_68;
      }
      if( !v42 )
      {
LABEL_68:
        SessionId = v51;
        goto LABEL_69;
      }
      v42->CrossThreadReleasableAndBusyByte |= 2u;
      if( v42->LockState.$E8276A2CF8B819ED32D1B6FEB35D730A::_bf_0 < 0 )
        KiAbEntryRemoveFromTree(v42);
      LODWORD(a3) = v42->BoostBitmap.AllFields & 0x1FFFF;
      v42->BoostBitmap.AllFields &= 0xFFFE0000;
      v42->ThreadLocalFlags &= ~1u;
      v42->LockState.$E8276A2CF8B819ED32D1B6FEB35D730A::_bf_0 = 0i64;
      v43 = v42 - CurrentThread->Tcb.LockEntries;
      if( v39 == 1 )
        CurrentThread->Tcb.AbEntrySummary |= 1 << v43;
      else
        _InterlockedOr8((volatile signed __int8 *)&CurrentThread->Tcb.AbOrphanedEntrySummary, 1 << v43);
    }
    --CurrentThread->Tcb.AbAllocationRegionCount;
    KiAbThreadRemoveBoosts(&CurrentThread->Tcb, p_WorkingSetSwapLock, &a3);
    v20 = CurrentThread->Tcb.SpecialApcDisable++ == -1;
    if( v20
      && ($F25F8C4BA33AF922A5F1AF68CD89DDDF *)CurrentThread->Tcb.ApcState.ApcListHead[0].Flink != &CurrentThread->Tcb.152 )
    {
      KiCheckForKernelApcDelivery();
    }
    KiLeaveGuardedRegionUnsafe((__int64)Thread);
  }
  v44 = P;
  if( P )
  {
    if( v5 >= 4 )
      SmStoreSetProcessVaRanges(*(VOID **)P, *((_QWORD *)P + 2));
    ExFreePoolWithTag(v44, 0);
  }
  *(_QWORD *)&EventParameters = ExtendPages;
  *((_QWORD *)&EventParameters + 1) = v60[15];
  v62 = *(_OWORD *)&v60[16];
  LODWORD(v63) = v30;
  EtwTraceWorkingSetSwap(Processa, 0i64, &EventParameters);
  return v30;
}

Referenced by:

PspChangeProcessExecutionState