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