MiCopyOnWrite
INT64 __fastcall MiCopyOnWrite(UINT64 a1, UINT64 *rdx0, INT64 Page, INT64 a4){
UINT64 v4;
char *v6;
unsigned int v7;
__int64 v8;
BOOL v9;
int SystemRegionType;
void *v11;
int v12;
unsigned int v13;
int v14;
int v15;
unsigned int v17;
unsigned int v18;
unsigned __int64 v19;
UINT8 v20;
int v21;
char v22;
int WsleProtection;
UINT64 v24;
int v25;
signed __int32 v26;
__int64 v27;
_MMPFN *PfnDb;
RTL_BALANCED_NODE *Address;
unsigned int v30;
INT64 v31;
unsigned __int64 *v32;
KSPIN_LOCK_QUEUE *v33;
unsigned __int64 v34;
_ETHREAD *CurrentThread;
unsigned int PagePriorityThread;
INT64 v37;
unsigned __int64 v38;
int v39;
UINT64 v40;
bool v41;
INT64 v42;
UINT64 v43;
INT64 v44;
_MMPTE *PxeUserLimit;
UINT64 v46;
char v47;
int v48;
_QWORD *CloneAddress;
volatile INT64 *v50;
_MMVAD **BugCheckParameter4;
int v52;
int v53;
UINT64 SessionVm;
UINT64 v56;
int v57;
int v58;
BOOL v59;
UINT64 SpinCount;
char v61[12];
UINT64 v62;
UINT64 v63;
UINT64 v64;
_MMPTE *v65;
_MI_PARTITION *Partition;
INT64 v67[2];
struct _KLOCK_QUEUE_HANDLE LockHandle;
UINT64 v69;
__int64 v70;
UINT64 a2[2];
__int128 v72;
_MMSUPPORT_INSTANCE Vm;
__int128 v74;
__int128 v75;
__int128 v76;
__int128 v77;
__int128 v78;
__int128 v79;
__int128 v80;
__int128 v81;
__int128 v82;
__int64 v83;
v4 = *rdx0;
HIWORD(Vm.PeakWorkingSetSize) = 0;
*(_OWORD *)v67 = 0i64;
v83 = 0i64;
v74 = 0i64;
v57 = a4;
v75 = 0i64;
v63 = (UINT64)rdx0;
v76 = 0i64;
v77 = 0i64;
v78 = 0i64;
v79 = 0i64;
v80 = 0i64;
v81 = 0i64;
v82 = 0i64;
*(_OWORD *)a2 = 0i64;
v72 = 0i64;
v59 = MiPteInShadowRange((UINT64)rdx0);
v56 = v4;
v70 = (v4 >> 12) & 0xFFFFFFFFFi64;
v6 = (char *)MmGetPfnDb() + 48 * v70;
*(_QWORD *)&v61[4] = 0i64;
v7 = 0;
v8 = *((_QWORD *)v6 + 1);
v9 = (v4 & 0x200) == 0;
v65 = (_MMPTE *)(v8 | 0x8000000000000000ui64);
v62 = *((_QWORD *)KeGetCurrentThread() + 23);
SystemRegionType = MiGetSystemRegionType(a1);
if( SystemRegionType == 1 )
{
SessionVm = MiGetSessionVm();
v13 = (v4 & 0x200) == 0;
if( (*((_QWORD *)v6 + 5) & 0x1000000000i64) == 0 && v8 > 0 )
v13 = v12 | v9;
v52 = v12;
}
else if( SystemRegionType == 12 )
{
v52 = 0;
SessionVm = (UINT64)MiGetAnyMultiplexedVm(1i64);
v13 = (v4 & 0x200) == 0;
if( (*((_QWORD *)v6 + 5) & 0x1000000000i64) == 0 && v8 > 0 )
v13 = v14 | v9;
}
else
{
if( SystemRegionType == 9 || SystemRegionType == 14 )
KeBugCheckEx(0x1Au, 0x3300ui64, a1, v4, 2ui64);
if( SystemRegionType == 6 )
{
v52 = 0;
SessionVm = (UINT64)MiGetAnyMultiplexedVm(2i64);
v13 = v15 | v9;
if( (*((_QWORD *)v6 + 5) & 0x1000000000i64) != 0 || v8 <= 0 )
KeBugCheckEx(0x1Au, 0x3300ui64, a1, v4, 0i64);
}
else
{
if( SystemRegionType == 5 )
KeBugCheckEx(0x1Au, 0x3300ui64, a1, v4, 1ui64);
if( *(_QWORD *)(v62 + 1248) )
return 3221226548i64;
v52 = 1;
v13 = (v4 & 0x200) == 0;
SessionVm = v62 + 1664;
if( (*((_QWORD *)v6 + 5) & 0x1000000000i64) == 0 && v8 > 0 )
v13 = v9 | 2;
Vm.AgeDistribution[2] = v62 + 1664;
memset(&Vm.TrimmedPageCount, 0, 48);
*(_QWORD *)&Vm.NextPageColor = a1;
memset(&Vm.AgeDistribution[3], 0, 72);
MiComputeFaultNode(&Vm, 0i64, (_CONTROL_AREA *)&v61[4], v11, BugCheckParameter4);
v7 = v17;
}
}
v18 = 0;
Partition = *(_MI_PARTITION **)(qword_140C4E388 + 8i64 * *(unsigned __int16 *)(SessionVm + 174));
HIDWORD(SpinCount) = *(_DWORD *)v6 & 1;
v69 = (UINT64)MmGetPteBase() + ((a1 >> 9) & 0x7FFFFFFFF8i64);
v19 = *(_QWORD *)v69;
v20 = HIBYTE(v19) & 0xF | (16 * ((v19 >> 60) & 7));
v58 = v57 & 1;
if( (v57 & 1) != 0 || (HIBYTE(v19) & 0xF) == 10 )
{
v21 = v52;
}
else
{
v21 = v52;
if( (HIBYTE(v19) & 0xF) == 9 )
{
v20 = (16 * ((v19 >> 60) & 7)) | 0xA;
}
else if( v52 != 1 && (v6[35] & 8) != 0 )
{
v20 = (16 * ((v19 >> 60) & 7)) | 0xA;
}
}
v22 = v20 & 0xF;
if( (v20 & 0xF) == 10 )
goto LABEL_37;
if( v22 == 8 && v21 != 2 )
{
v18 = 1;
if( (*((_DWORD *)v6 + 4) & 0x400i64) != 0 )
v18 = 2;
}
WsleProtection = MiGetWsleProtection(a1, v20);
if( !WsleProtection )
LABEL_37:
WsleProtection = ((unsigned __int64)MI_READ_PTE_LOCK_FREE((INT64)(v6 + 16)) >> 5) & 0x1F;
v25 = MmMakeProtectNotWriteCopy[WsleProtection];
v53 = v25;
if( Page == -1 )
{
MiInitializePageColorBase(SessionVm, v7, (INT64)v67);
v26 = _InterlockedExchangeAdd((volatile signed __int32 *)v67[0], 1u);
Page = MiGetPage(Partition, v67[1] & v26 | HIDWORD(v67[1]), 0i64);
if( Page == -1 )
return 3221225495i64;
}
if( v18 )
{
if( v18 >= 2 )
{
v27 = *(_QWORD *)(qword_140C4E388 + 8 * ((*((_QWORD *)v6 + 5) >> 39) & 0x3FFi64));
MiReturnCommit((_MI_PARTITION *)v27, 1ui64);
if( v52 == 1 )
_InterlockedDecrement64((volatile signed __int64 *)(v27 + 7616));
v25 = v53;
}
PfnDb = MmGetPfnDb();
MiUnlockPageTableCharges((_MMPFN *)((char *)PfnDb + 48 * (*((_QWORD *)v6 + 5) & 0xFFFFFFFFFi64)), 1u, v24);
}
else
{
PfnDb = MmGetPfnDb();
}
if( v25 == 24 )
{
Address = *(RTL_BALANCED_NODE **)&v61[4];
LOBYTE(v25) = 1;
LOBYTE(v53) = 1;
if( *(_QWORD *)&v61[4] || (Address = MiLocateAddress(a1), (*(_QWORD *)&v61[4] = Address) != 0i64) )
{
v30 = (LODWORD(Address[2].Children[0]) >> 7) & 0x1F;
if( v30 >> 3 == 3 && (v30 & 7) != 0 )
{
LOBYTE(v25) = 25;
}
else if( v30 >> 3 == 1 )
{
LOBYTE(v25) = 9;
}
LOBYTE(v53) = v25;
}
}
v31 = (INT64)PfnDb + 48 * Page;
*(_QWORD *)(v31 + 16) = MiSwizzleInvalidPte(32i64 * (v25 & 0x1F));
if( v22 == 10 )
{
v34 = v63;
}
else
{
v32 = &qword_140C4F500;
*(_QWORD *)&LockHandle.OldIrql = 0i64;
if( (*(_BYTE *)(SessionVm + 184) & 7) != 2 )
v32 = (unsigned __int64 *)(SessionVm + 256);
LockHandle.LockQueue.Lock = v32;
LockHandle.LockQueue.Next = 0i64;
v33 = (KSPIN_LOCK_QUEUE *)_InterlockedExchange64((volatile __int64 *)v32, (__int64)&LockHandle);
if( v33 )
KxWaitForLockOwnerShip(&LockHandle.LockQueue, v33);
++*(_QWORD *)(SessionVm + 144);
if( a1 < (unsigned __int64)MmGetPteBase() || a1 > (unsigned __int64)MmGetPteLimit() )
++*(_QWORD *)(SessionVm + 128);
KeReleaseInStackQueuedSpinLockFromDpcLevel(&LockHandle);
MiWriteValidPteVolatile((MMPTE *)v69, 0x80000000ui64);
v34 = v63;
v56 = *(_QWORD *)v63;
}
*(_WORD *)(v31 + 32) = 1;
v64 = *(_QWORD *)((char *)MmGetPteBase() + ((v34 >> 9) & 0x7FFFFFFFF8i64));
*(_QWORD *)(v31 + 40) ^= (*(_QWORD *)(v31 + 40) ^ (v64 >> 12)) & 0xFFFFFFFFFi64;
CurrentThread = (_ETHREAD *)KeGetCurrentThread();
if( (*((_DWORD *)CurrentThread + 326) & 0x100) != 0 )
PagePriorityThread = (*((_DWORD *)CurrentThread + 326) & 0xE00u) >> 9;
else
PagePriorityThread = PsGetPagePriorityThread((__int64)CurrentThread);
LODWORD(SpinCount) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)(v31 + 24), 0x3Fui64) )
{
do
KeYieldProcessorEx(&SpinCount);
while( *(__int64 *)(v31 + 24) < 0 );
}
if( HIDWORD(SpinCount) )
*(_QWORD *)v31 |= 1ui64;
*(_BYTE *)(v31 + 34) |= 0x10u;
if( v52 || (v6[35] & 8) == 0 || v58 )
*(_BYTE *)(v31 + 35) &= ~8u;
else
*(_BYTE *)(v31 + 35) |= 8u;
v37 = (unsigned __int8)v6[34] >> 6;
if( *(unsigned __int8 *)(v31 + 34) >> 6 != (_DWORD)v37 )
MiChangePageAttribute(v31, v37, 1);
MiSetPfnTbFlushStamp((_MMPFN *)v31, 0i64, 1ui64);
v38 = *(_QWORD *)(v31 + 24) & 0xC000000000000001ui64;
*(_QWORD *)(v31 + 8) = v34;
*(_QWORD *)(v31 + 24) = v38 | 1;
*(_BYTE *)(v31 + 35) ^= (*(_BYTE *)(v31 + 35) ^ PagePriorityThread) & 7;
*(_BYTE *)(v31 + 34) = *(_BYTE *)(v31 + 34) & 0xF8 | 6;
if( v13 >= 4 )
MiIdentifyPfn((_MMPFN *)v31, a2);
_InterlockedAnd64((volatile signed __int64 *)(v31 + 24), 0x7FFFFFFFFFFFFFFFui64);
if( v13 >= 4 )
{
*((_QWORD *)&v72 + 1) |= 8ui64;
Vm.WorkingSetPrivateSize = (unsigned __int64)a2;
Vm.MaximumWorkingSetSize = 32i64;
LODWORD(BugCheckParameter4) = 289413890;
EtwTraceKernelEvent(
(EVENT_DATA_DESCRIPTOR *)&Vm.WorkingSetPrivateSize,
1ui64,
0x28000001ui64,
0x282u,
(UINT64)BugCheckParameter4);
}
__incgsdword(0x2E94u);
v39 = 1;
if( (v53 & 2) == 0 )
{
v39 = 9;
LABEL_88:
v40 = a1;
goto LABEL_89;
}
if( (MiFlags & 0x40000) != 0 )
goto LABEL_88;
v40 = a1;
if( (MiFlags & 0x10000) == 0 )
{
LABEL_89:
if( v40 >= 0xFFFF800000000000ui64 )
goto LABEL_92;
goto LABEL_90;
}
if( a1 >= 0xFFFF800000000000ui64 )
{
v39 = 17;
if( (v57 & 2) != 0 )
v39 = 49;
goto LABEL_89;
}
LABEL_90:
if( (*(_BYTE *)(*((_QWORD *)KeGetCurrentThread() + 23) + 992i64) & 1) != 0 )
v39 |= 0x10u;
LABEL_92:
MiCopyPage(Page, v70, 0i64, v39);
if( (_DWORD)dword_140C4E568 )
{
v41 = PagePriorityThread < dword_140C4E56C;
v42 = SessionVm;
if( !v41 )
MiLogPageAccess(SessionVm, v34);
}
else
{
v42 = SessionVm;
}
v43 = v56;
if( (v13 & 1) == 0 )
{
if( (v56 & 0x8000000000000000ui64) != 0i64 || v52 != 1 )
v43 = v56 | 0x42;
v43 = v43 & 0xFFFFFFFFFFFFF5DFui64 | 0x820;
}
*(_QWORD *)&Vm.HardFaultCount = 20i64;
v44 = v43 ^ (v43 ^ (Page << 12)) & 0xFFFFFFFFF000i64;
WORD2(Vm.PeakWorkingSetSize) = 0;
Vm.SelfmapLock = 0i64;
*(_QWORD *)&Vm.Flags.0 = 0i64;
v56 = v44;
LODWORD(Vm.PeakWorkingSetSize) = v52;
MiInsertTbFlushEntry((INT64)&Vm.PeakWorkingSetSize, a1 & 0xFFFFFFFFFFFFF000ui64, 1i64, 0i64);
if( (v39 & 0x20) != 0 || (v44 & 0x42) == 0 )
{
MI_INTERLOCKED_EXCHANGE_PTE((volatile INT64 *)v34, v44);
MiFlushTbList((__int64)&Vm.PeakWorkingSetSize);
}
else
{
PxeUserLimit = MmGetPxeUserLimit();
*(_QWORD *)v34 = v44 & 0xFFFFFFFFFFFFFBFEui64 | 0x400;
MiFlushTbList((__int64)&Vm.PeakWorkingSetSize);
if( v34 >= (unsigned __int64)MmGetPml4eBase()
&& v34 <= (unsigned __int64)PxeUserLimit
&& (*(_DWORD *)(*((_QWORD *)KeGetCurrentThread() + 23) + 2172i64) & 0x1000) != 0
&& (v44 & 1) != 0 )
{
v44 |= 0x8000000000000000ui64;
}
*(_QWORD *)v34 = v44;
}
v46 = v62;
if( v52 == 1 )
_InterlockedExchangeAdd64((volatile signed __int64 *)(v62 + 1272), 1ui64);
*(_DWORD *)v61 = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)v6 + 6, 0x3Fui64) )
{
do
KeYieldProcessorEx((UINT64 *)v61);
while( *((__int64 *)v6 + 3) < 0 );
}
if( !v52 && !v58 )
{
v47 = v6[35];
if( (v47 & 8) != 0 )
v6[35] = v47 & 0xF7;
}
MiDecrementShareCount((UINT64)v6);
_InterlockedAnd64((volatile signed __int64 *)v6 + 3, 0x7FFFFFFFFFFFFFFFui64);
if( (v13 & 2) != 0 )
{
v48 = MiDecrementCombinedPte(v42, v65);
}
else
{
if( (*(_BYTE *)(v42 + 184) & 7) != 0 )
return 0i64;
CloneAddress = MiLocateCloneAddress(v46, (unsigned __int64)v65);
if( !CloneAddress )
return 0i64;
v48 = MiDecrementCloneBlockReference((UINT64)CloneAddress, v50, v46);
}
if( v48 == 3 )
MiChargeCommit(Partition, 1ui64, 4ui64);
return 0i64;
}Referenced by:
MiCompleteProtoPteFault
MiCopyToUserVa
MiFaultInPagedPool
MiLockCode
MiLockDriverPageRange
MiLockPagedAddress
MiMakeDriverPagesPrivate
MiMakeProtoPrivate
MiPrepareImagePagesForHotPatch
MiProbeLeafPteAccess
MiSetProtectionOnSection
MiSplitPrivatePage
MiSplitReducedCommitClonePage
MiSystemFault
MiValidFault
MiValidVirtualizationFault
MiWalkVaRange
MmProtectPool
MmReplaceImportEntry