MiCopyOnWrite
NTSTATUS __stdcall MiCopyOnWrite(UINT64 rcx0, INT64 *a2, UINT64 Page, INT64 a4){
unsigned __int64 v4;
int v6;
_MMPFN *v7;
unsigned int v8;
__int64 Blink;
_BOOL4 v10;
NTSTATUS SystemRegionType;
VOID *v12;
VOID *v13;
int v14;
unsigned int v15;
int v16;
int v17;
unsigned int v19;
unsigned int v20;
unsigned __int64 v21;
UINT8 v22;
int v23;
char v24;
NTSTATUS WsleProtection;
UINT64 v26;
unsigned __int64 v27;
int v28;
signed __int32 v29;
UINT64 v30;
_MI_PARTITION *v31;
_MMPFN *PfnDb;
_MMVAD *Address;
unsigned int v34;
_MMPFN *v35;
volatile __int64 *v36;
_MMPTE *v37;
_MMPTE *v38;
unsigned __int64 *v39;
unsigned __int64 v40;
_ETHREAD *CurrentThread;
unsigned int PagePriorityThread;
int v43;
unsigned __int64 v44;
unsigned int v45;
UINT64 v46;
bool v47;
_MMSUPPORT_INSTANCE *v48;
UINT64 v49;
UINT64 v50;
_MMPTE *PxeUserLimit;
_EPROCESS *v52;
char v53;
_MI_PAGE_DELETE_RESULT v54;
_MMCLONE_DESCRIPTOR *CloneAddress;
ULONG_PTR v56;
_MMVAD **BugCheckParameter4;
int v58;
int v59;
_MMSUPPORT_INSTANCE *SessionVm;
UINT64 v62;
int v63;
int v64;
int v65;
UINT64 SpinCount;
char ControlArea[140];
_MMSUPPORT_INSTANCE Vm;
__int128 v69;
__int128 v70;
__int128 v71;
__int128 v72;
__int128 v73;
__int128 v74;
__int128 v75;
__int128 v76;
__int128 v77;
__int64 v78;
v4 = *a2;
HIWORD(Vm.PeakWorkingSetSize) = 0;
*(_OWORD *)&ControlArea[52] = 0i64;
v78 = 0i64;
v69 = 0i64;
v63 = a4;
v70 = 0i64;
*(_QWORD *)&ControlArea[20] = a2;
v71 = 0i64;
v72 = 0i64;
v73 = 0i64;
v74 = 0i64;
v75 = 0i64;
v76 = 0i64;
v77 = 0i64;
memset(&ControlArea[108], 0, 32);
LOBYTE(v6) = MiPteInShadowRange((UINT64)a2);
v65 = v6;
v62 = v4;
MiPteInShadowRange((UINT64)&v62);
*(_QWORD *)&ControlArea[100] = (v4 >> 12) & 0xFFFFFFFFFi64;
v7 = &MmGetPfnDb()[*(_QWORD *)&ControlArea[100]];
*(_QWORD *)&ControlArea[4] = 0i64;
v8 = 0;
Blink = (__int64)v7->ListEntry.Blink;
v10 = (v4 & 0x200) == 0;
*(_QWORD *)&ControlArea[36] = Blink | 0x8000000000000000ui64;
*(_QWORD *)&ControlArea[12] = KeGetCurrentThread()->ApcState.Process;
SystemRegionType = MiGetSystemRegionType(rcx0);
if( SystemRegionType == 1 )
{
SessionVm = MiGetSessionVm(1i64, (INT64)v12, 2);
v15 = (v4 & 0x200) == 0;
if( (v7->u4._bf_0 & 0x1000000000i64) == 0 && Blink > 0 )
v15 = v14 | v10;
v58 = v14;
}
else if( SystemRegionType == 12 )
{
v58 = 0;
SessionVm = MiGetAnyMultiplexedVm(MiWorkingSetTypeSystemViews, v12);
v15 = (v4 & 0x200) == 0;
if( (v7->u4._bf_0 & 0x1000000000i64) == 0 && Blink > 0 )
v15 = v16 | v10;
}
else
{
if( SystemRegionType == 9 || SystemRegionType == 14 )
KeBugCheckEx(0x1Au, (PVOID)0x3300, (PVOID)rcx0, (PVOID)v4, (PVOID)2);
if( SystemRegionType == 6 )
{
v58 = 0;
SessionVm = MiGetAnyMultiplexedVm(MiWorkingSetTypePagedPool, v12);
v15 = v17 | v10;
if( (v7->u4._bf_0 & 0x1000000000i64) != 0 || Blink <= 0 )
KeBugCheckEx(0x1Au, (PVOID)0x3300, (PVOID)rcx0, (PVOID)v4, 0i64);
}
else
{
if( SystemRegionType == 5 )
KeBugCheckEx(0x1Au, (PVOID)0x3300, (PVOID)rcx0, (PVOID)v4, (PVOID)1);
if( *(_QWORD *)(*(_QWORD *)&ControlArea[12] + 1248i64) )
return -1073740748;
v58 = 1;
v15 = (v4 & 0x200) == 0;
SessionVm = (_MMSUPPORT_INSTANCE *)(*(_QWORD *)&ControlArea[12] + 1664i64);
if( (v7->u4._bf_0 & 0x1000000000i64) == 0 && Blink > 0 )
v15 = v10 | 2;
Vm.AgeDistribution[2] = *(_QWORD *)&ControlArea[12] + 1664i64;
memset(&Vm.TrimmedPageCount, 0, 48);
*(_QWORD *)&Vm.NextPageColor = rcx0;
memset(&Vm.AgeDistribution[3], 0, 72);
MiComputeFaultNode(&Vm, 0i64, (_CONTROL_AREA *)&ControlArea[4], v13, BugCheckParameter4);
v8 = v19;
}
}
v20 = 0;
*(_QWORD *)&ControlArea[44] = *(_QWORD *)(*(&stru_140C4DB30 + 267) + 8i64 * SessionVm->PartitionId);
HIDWORD(SpinCount) = (__int64)v7->ListEntry.Flink & 1;
*(_QWORD *)&ControlArea[92] = (char *)MmGetPteBase() + ((rcx0 >> 9) & 0x7FFFFFFFF8i64);
v21 = **(_QWORD **)&ControlArea[92];
MiPteInShadowRange(*(UINT64 *)&ControlArea[92]);
v22 = HIBYTE(v21) & 0xF | (16 * ((v21 >> 60) & 7));
v64 = v63 & 1;
if( (v63 & 1) != 0 || (HIBYTE(v21) & 0xF) == 10 )
{
v23 = v58;
}
else
{
v23 = v58;
if( (HIBYTE(v21) & 0xF) == 9 )
{
v22 = (16 * ((v21 >> 60) & 7)) | 0xA;
}
else if( v58 != 1 && (*((_BYTE *)&v7->u3 + 3) & 8) != 0 )
{
v22 = (16 * ((v21 >> 60) & 7)) | 0xA;
}
}
v24 = v22 & 0xF;
if( (v22 & 0xF) == 10 )
goto LABEL_37;
if( v24 == 8 && v23 != 2 )
{
v20 = 1;
if( (*(_DWORD *)(&v7->3 + 1) & 0x400i64) != 0 )
v20 = 2;
}
WsleProtection = MiGetWsleProtection(rcx0, v22);
if( !WsleProtection )
{
LABEL_37:
LODWORD(v27) = MI_READ_PTE_LOCK_FREE((INT64)&v7->OriginalPte.u.Hard);
WsleProtection = (v27 >> 5) & 0x1F;
}
v28 = MmMakeProtectNotWriteCopy[WsleProtection];
v59 = v28;
if( Page == -1i64 )
{
MiInitializePageColorBase(SessionVm, v8, (_MI_COLOR_BASE *)&ControlArea[52]);
v29 = _InterlockedExchangeAdd(*(volatile signed __int32 **)&ControlArea[52], 1u);
LODWORD(v30) = MiGetPage(
*(ULONG_PTR **)&ControlArea[44],
*(_DWORD *)&ControlArea[60] & (unsigned int)v29 | *(_DWORD *)&ControlArea[64],
0i64);
Page = v30;
if( v30 == -1i64 )
return -1073741801;
}
if( v20 )
{
if( v20 >= 2 )
{
v31 = *(_MI_PARTITION **)(*(&stru_140C4DB30 + 267) + 8 * (((unsigned __int64)v7->u4._bf_0 >> 39) & 0x3FF));
MiReturnCommit(v31, 1ui64);
if( v58 == 1 )
_InterlockedDecrement64((volatile signed __int64 *)&v31->Vp.ProcessLockedFilePages);
v28 = v59;
}
PfnDb = MmGetPfnDb();
MiUnlockPageTableCharges((_DWORD)PfnDb + 48 * LODWORD(v7->u4._bf_0), 1u, v26);
}
else
{
PfnDb = MmGetPfnDb();
}
if( v28 == 24 )
{
Address = *(_MMVAD **)&ControlArea[4];
LOBYTE(v28) = 1;
LOBYTE(v59) = 1;
if( *(_QWORD *)&ControlArea[4]
|| (Address = MiLocateAddress((VOID *)rcx0), (*(_QWORD *)&ControlArea[4] = Address) != 0i64) )
{
v34 = (Address->Core.u.LongFlags >> 7) & 0x1F;
if( v34 >> 3 == 3 && (v34 & 7) != 0 )
{
LOBYTE(v28) = 25;
}
else if( v34 >> 3 == 1 )
{
LOBYTE(v28) = 9;
}
LOBYTE(v59) = v28;
}
}
v35 = &PfnDb[Page];
v35->OriginalPte.u.Long = MiSwizzleInvalidPte(32i64 * (v28 & 0x1F));
if( v24 == 10 )
{
v38 = *(_MMPTE **)&ControlArea[20];
}
else
{
v36 = (volatile __int64 *)((char *)&stru_140C4DB30 + 6608);
*(_QWORD *)&ControlArea[84] = 0i64;
if( (SessionVm->Flags._bf_0 & 7) != 2 )
v36 = (volatile __int64 *)&SessionVm[1].AgeDistribution[3];
*(_QWORD *)&ControlArea[76] = v36;
*(_QWORD *)&ControlArea[68] = 0i64;
if( _InterlockedExchange64(v36, (__int64)&ControlArea[68]) )
KxWaitForLockOwnerShip((INT64)&ControlArea[68]);
++SessionVm->WorkingSetPrivateSize;
if( rcx0 < (unsigned __int64)MmGetPteBase() || rcx0 > (unsigned __int64)MmGetPteLimit() )
++SessionVm->WorkingSetLeafPrivateSize;
KeReleaseInStackQueuedSpinLockFromDpcLevel((PKLOCK_QUEUE_HANDLE)&ControlArea[68]);
v37 = *(_MMPTE **)&ControlArea[92];
MiPteInShadowRange(*(UINT64 *)&ControlArea[92]);
MiWriteValidPteVolatile(v37, 0x80000000ui64);
v38 = *(_MMPTE **)&ControlArea[20];
v62 = **(_QWORD **)&ControlArea[20];
}
v35->u3.ReferenceCount = 1;
v39 = (unsigned __int64 *)((char *)&MmGetPteBase()->u.Long + (((unsigned __int64)v38 >> 9) & 0x7FFFFFFFF8i64));
v40 = *v39;
MiPteInShadowRange((UINT64)v39);
*(_QWORD *)&ControlArea[28] = v40;
MiPteInShadowRange((UINT64)&ControlArea[28]);
v35->u4._bf_0 ^= (v35->u4._bf_0 ^ (v40 >> 12)) & 0xFFFFFFFFFi64;
CurrentThread = (_ETHREAD *)KeGetCurrentThread();
if( (CurrentThread->SameThreadApcFlags & 0x100) != 0 )
PagePriorityThread = (CurrentThread->SameThreadApcFlags & 0xE00) >> 9;
else
PagePriorityThread = PsGetPagePriorityThread(CurrentThread);
LODWORD(SpinCount) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)&v35->u2, 0x3Fui64) )
{
do
KeYieldProcessorEx(&SpinCount);
while( v35->u2._bf_0 < 0 );
}
if( HIDWORD(SpinCount) )
v35->u1.$976DF529DAC3D73085C9E386D94B91E6::$E228DCF3D8940E384DBC5EFCA756D8B6::_bf_0 |= 1ui64;
*((_BYTE *)&v35->u3 + 2) |= 0x10u;
if( v58 || (*((_BYTE *)&v7->u3 + 3) & 8) == 0 || v64 )
*((_BYTE *)&v35->u3 + 3) &= ~8u;
else
*((_BYTE *)&v35->u3 + 3) |= 8u;
v43 = *((unsigned __int8 *)&v7->u3 + 2) >> 6;
if( *((unsigned __int8 *)&v35->u3 + 2) >> 6 != v43 )
MiChangePageAttribute(v35, (_MI_PFN_CACHE_ATTRIBUTE)v43, 1ui64);
MiSetPfnTbFlushStamp(v35, 0i64, 1ui64);
v44 = v35->u2._bf_0 & 0xC000000000000001ui64;
v35->PteLong = (unsigned __int64)v38;
v35->u2._bf_0 = v44 | 1;
*((_BYTE *)&v35->u3 + 3) ^= (*((_BYTE *)&v35->u3 + 3) ^ PagePriorityThread) & 7;
*((_BYTE *)&v35->u3 + 2) = *(_BYTE *)(&v35->u3 + 1) & 0xF8 | 6;
if( v15 >= 4 )
MiIdentifyPfn(v35, (_MMPFN_IDENTITY *)&ControlArea[108]);
_InterlockedAnd64(&v35->u2.Lock, 0x7FFFFFFFFFFFFFFFui64);
if( v15 >= 4 )
{
*(_QWORD *)&ControlArea[132] |= 8ui64;
Vm.WorkingSetPrivateSize = (unsigned __int64)&ControlArea[108];
Vm.MaximumWorkingSetSize = 32i64;
EtwTraceKernelEvent((__int64)&Vm.WorkingSetPrivateSize, 1u, 0x28000001u, 0x282u, 0x11401B02u);
}
__incgsdword(0x2E94u);
v45 = 1;
if( (v59 & 2) == 0 )
{
v45 = 9;
LABEL_88:
v46 = rcx0;
goto LABEL_89;
}
if( (MiFlags & 0x40000) != 0 )
goto LABEL_88;
v46 = rcx0;
if( (MiFlags & 0x10000) == 0 )
{
LABEL_89:
if( v46 >= 0xFFFF800000000000ui64 )
goto LABEL_92;
goto LABEL_90;
}
if( rcx0 >= 0xFFFF800000000000ui64 )
{
v45 = 17;
if( (v63 & 2) != 0 )
v45 = 49;
goto LABEL_89;
}
LABEL_90:
if( (*(_BYTE *)&KeGetCurrentThread()->ApcState.Process->Pcb.SecureState & 1) != 0 )
v45 |= 0x10u;
LABEL_92:
MiCopyPage(Page, *(UINT64 *)&ControlArea[100], 0i64, v45);
if( *(&stru_140C4DB30 + 654) )
{
v47 = PagePriorityThread < *(&stru_140C4DB30 + 655);
v48 = SessionVm;
if( !v47 )
MiLogPageAccess(SessionVm, v38);
}
else
{
v48 = SessionVm;
}
v49 = v62;
if( (v15 & 1) == 0 )
{
if( (v62 & 0x8000000000000000ui64) != 0i64 || v58 != 1 )
v49 = v62 | 0x42;
v49 = v49 & 0xFFFFFFFFFFFFF5DFui64 | 0x820;
}
*(_QWORD *)&Vm.HardFaultCount = 20i64;
v50 = v49 ^ (v49 ^ (Page << 12)) & 0xFFFFFFFFF000i64;
WORD2(Vm.PeakWorkingSetSize) = 0;
Vm.SelfmapLock = 0i64;
*(_QWORD *)&Vm.Flags._bf_0 = 0i64;
v62 = v50;
LODWORD(Vm.PeakWorkingSetSize) = v58;
MiInsertTbFlushEntry(
(_MI_TB_FLUSH_LIST *)&Vm.PeakWorkingSetSize,
(VOID *)(rcx0 & 0xFFFFFFFFFFFFF000ui64),
1ui64,
0i64);
if( (v45 & 0x20) != 0 || (v50 & 0x42) == 0 )
{
MI_INTERLOCKED_EXCHANGE_PTE((INT64 *)v38, v50);
MiFlushTbList((_MI_TB_FLUSH_LIST *)&Vm.PeakWorkingSetSize);
}
else
{
PxeUserLimit = MmGetPxeUserLimit();
v38->u.Long = v50 & 0xFFFFFFFFFFFFFBFEui64 | 0x400;
MiFlushTbList((_MI_TB_FLUSH_LIST *)&Vm.PeakWorkingSetSize);
if( v38 >= MmGetPml4eBase()
&& v38 <= PxeUserLimit
&& (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0
&& (v50 & 1) != 0 )
{
v50 |= 0x8000000000000000ui64;
}
v38->u.Long = v50;
}
v52 = *(_EPROCESS **)&ControlArea[12];
if( v58 == 1 )
_InterlockedExchangeAdd64((volatile signed __int64 *)(*(_QWORD *)&ControlArea[12] + 1272i64), 1ui64);
*(_DWORD *)ControlArea = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)&v7->u2, 0x3Fui64) )
{
do
KeYieldProcessorEx((UINT64 *)ControlArea);
while( v7->u2._bf_0 < 0 );
}
if( !v58 && !v64 )
{
v53 = *((_BYTE *)&v7->u3 + 3);
if( (v53 & 8) != 0 )
*((_BYTE *)&v7->u3 + 3) = v53 & 0xF7;
}
MiDecrementShareCount(v7);
_InterlockedAnd64(&v7->u2.Lock, 0x7FFFFFFFFFFFFFFFui64);
if( (v15 & 2) != 0 )
{
v54 = MiDecrementCombinedPte((_MMPTE *)v48);
}
else
{
if( (v48->Flags._bf_0 & 7) != 0 )
return 0;
CloneAddress = MiLocateCloneAddress(v52, *(VOID **)&ControlArea[36]);
if( !CloneAddress )
return 0;
v54 = MiDecrementCloneBlockReference((ULONG_PTR)CloneAddress, v56, (ULONG_PTR)v52);
}
if( v54 == PageStillReferenced )
MiChargeCommit(*(_MI_PARTITION **)&ControlArea[44], 1ui64, 4ui64);
return 0;
}Referenced by:
MiCompleteProtoPteFault
MiCopyToUserVa
MiFaultInPagedPool
MiLockCode
MiLockDriverPageRange
MiLockPagedAddress
MiMakeDriverPagesPrivate
MiMakeProtoPrivate
MiPrepareImagePagesForHotPatch
MiProbeLeafPteAccess
MiSetProtectionOnSection
MiSplitPrivatePage
MiSplitReducedCommitClonePage
MiSystemFault
MiValidFault
MiValidVirtualizationFault
MiWalkVaRange
MmProtectPool
MmReplaceImportEntry