MiResolveTransitionFault
NTSTATUS __stdcall MiResolveTransitionFault(
VOID *FaultingAddress,
_MMPTE *PointerPte,
PVOID ProtoPfn,
_MMSUPPORT_INSTANCE *Vm,
VOID *TrapInformation,
UINT64 VmIrql,
UINT8 PreviousMode,
INT8 ReadBlock,
_MMINPAGE_SUPPORT **a9){
VOID *a5;
_MMSUPPORT_INSTANCE *v10;
UINT64 v12;
_MMPFN *v14;
unsigned __int64 v15;
unsigned __int64 v16;
union {$8D9ED47C9F2F2CD645B633E301950288 __s0;unsigned __int64 EntireField;} *p_u4;
_MMPFN *PfnDb;
unsigned __int64 v19;
_MMPFN *v20;
void *v21;
unsigned __int64 v22;
NTSTATUS result;
union {unsigned __int64 Long;volatile unsigned __int64 VolatileLong;_MMPTE_HARDWARE Hard;_MMPTE_PROTOTYPE Proto;_MMPTE_SOFTWARE Soft;_MMPTE_TIMESTAMP TimeStamp;_MMPTE_TRANSITION Trans;_MMPTE_SUBSECTION Subsect;_MMPTE_LIST List;} v24;
_MMPTE *Pml4eBase;
_MMPTE *PxeUserLimit;
union {unsigned __int64 Long;volatile unsigned __int64 VolatileLong;_MMPTE_HARDWARE Hard;_MMPTE_PROTOTYPE Proto;_MMPTE_SOFTWARE Soft;_MMPTE_TIMESTAMP TimeStamp;_MMPTE_TRANSITION Trans;_MMPTE_SUBSECTION Subsect;_MMPTE_LIST List;} v27;
NTSTATUS v28;
char v29;
unsigned __int64 v30;
_QWORD *v31;
wchar_t *v32;
_MMSUPPORT_INSTANCE *v33;
__int64 v34;
union {unsigned __int64 Long;volatile unsigned __int64 VolatileLong;_MMPTE_HARDWARE Hard;_MMPTE_PROTOTYPE Proto;_MMPTE_SOFTWARE Soft;_MMPTE_TIMESTAMP TimeStamp;_MMPTE_TRANSITION Trans;_MMPTE_SUBSECTION Subsect;_MMPTE_LIST List;} v35;
union {unsigned __int64 Long;volatile unsigned __int64 VolatileLong;_MMPTE_HARDWARE Hard;_MMPTE_PROTOTYPE Proto;_MMPTE_SOFTWARE Soft;_MMPTE_TIMESTAMP TimeStamp;_MMPTE_TRANSITION Trans;_MMPTE_SUBSECTION Subsect;_MMPTE_LIST List;} v36;
unsigned __int64 v37;
__int64 v38;
__int64 v39;
union {unsigned __int64 Long;volatile unsigned __int64 VolatileLong;_MMPTE_HARDWARE Hard;_MMPTE_PROTOTYPE Proto;_MMPTE_SOFTWARE Soft;_MMPTE_TIMESTAMP TimeStamp;_MMPTE_TRANSITION Trans;_MMPTE_SUBSECTION Subsect;_MMPTE_LIST List;} v40;
unsigned __int64 v41;
_MI_PARTITION *v42;
union {unsigned __int64 Long;volatile unsigned __int64 VolatileLong;_MMPTE_HARDWARE Hard;_MMPTE_PROTOTYPE Proto;_MMPTE_SOFTWARE Soft;_MMPTE_TIMESTAMP TimeStamp;_MMPTE_TRANSITION Trans;_MMPTE_SUBSECTION Subsect;_MMPTE_LIST List;} v43;
union {unsigned __int64 Long;volatile unsigned __int64 VolatileLong;_MMPTE_HARDWARE Hard;_MMPTE_PROTOTYPE Proto;_MMPTE_SOFTWARE Soft;_MMPTE_TIMESTAMP TimeStamp;_MMPTE_TRANSITION Trans;_MMPTE_SUBSECTION Subsect;_MMPTE_LIST List;} v44;
union {unsigned __int64 Long;volatile unsigned __int64 VolatileLong;_MMPTE_HARDWARE Hard;_MMPTE_PROTOTYPE Proto;_MMPTE_SOFTWARE Soft;_MMPTE_TIMESTAMP TimeStamp;_MMPTE_TRANSITION Trans;_MMPTE_SUBSECTION Subsect;_MMPTE_LIST List;} v45;
int v46;
int v47;
union {unsigned __int64 Long;volatile unsigned __int64 VolatileLong;_MMPTE_HARDWARE Hard;_MMPTE_PROTOTYPE Proto;_MMPTE_SOFTWARE Soft;_MMPTE_TIMESTAMP TimeStamp;_MMPTE_TRANSITION Trans;_MMPTE_SUBSECTION Subsect;_MMPTE_LIST List;} v48;
int v49;
unsigned __int64 v50;
unsigned __int64 v51;
__int64 CurrentPrcb;
_MMPFN *v53;
int v54;
int v55;
bool v56;
int v57;
__int64 v58;
_MMPTE *PteBase;
char v60;
int v61;
unsigned __int64 v62;
unsigned __int64 v63;
unsigned __int64 v64;
__int64 v65;
_MI_PARTITION *v66;
signed __int32 v67;
_MMINPAGE_SUPPORT *v68;
int v69;
wchar_t *v70;
_BYTE *v71;
int v72;
__int64 v73;
char v74;
int v75;
__int16 v76;
_UNICODE_STRING *v77;
int v78;
char v79;
_MI_FAULT_VA_LIST *a6;
_MMINPAGE_SUPPORT **p_Support;
UINT64 v82;
UINT64 SpinCount;
UINT64 StoreInstruction;
_MMPFN *v85;
_MMINPAGE_SUPPORT *Support;
_MI_PARTITION *Partition;
UINT64 v88;
_MMSUPPORT_INSTANCE *Vma;
a5 = TrapInformation;
v10 = (_MMSUPPORT_INSTANCE *)*((_QWORD *)FaultingAddress + 7);
v12 = *((_QWORD *)FaultingAddress + 2);
LODWORD(v82) = 0;
v14 = (_MMPFN *)FaultingAddress;
*(_QWORD *)TrapInformation = 0i64;
Vma = v10;
StoreInstruction = v12;
Support = 0i64;
if( !ProtoPfn )
{
LODWORD(v15) = MI_READ_PTE_LOCK_FREE((INT64)PointerPte);
v16 = v15;
if( (v15 & 0x800) != 0 )
{
p_u4 = &MmGetPfnDb()->u4;
do
{
PfnDb = MmGetPfnDb();
if( (v16 & 1) == 0 && (!v16 || !*(&stru_140C4DB30 + 42) || (*(&stru_140C4DB30 + 42) & v16) != 0) )
{
v19 = v16;
if( *(&stru_140C4DB30 + 42) && (v16 & 0x10) == 0 )
v19 = v16 & ~*(&stru_140C4DB30 + 42);
if( (p_u4[6 * ((v19 >> 12) & 0xFFFFFFFFFi64)]._bf_0 & 0x4000000000000i64) != 0 )
{
v20 = &PfnDb[(v19 >> 12) & 0xFFFFFFFFFi64];
HIDWORD(v82) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)&v20->u2, 0x3Fui64) )
{
do
KeYieldProcessorEx((UINT64 *)((char *)&v82 + 4));
while( v20->u2._bf_0 < 0 );
}
LODWORD(v21) = MI_READ_PTE_LOCK_FREE((INT64)PointerPte);
if( v21 == (void *)v16 )
{
if( (_MMPTE *)(v20->PteLong | 0x8000000000000000ui64) != PointerPte
&& (v20->u4._bf_0 & 0x1000000000i64) == 0 )
{
KeBugCheckEx(0x1Au, (PVOID)0x411, PointerPte, (PVOID)v16, v20->ListEntry.Blink);
}
v24.Long = (unsigned __int64)PointerPte->u;
Pml4eBase = MmGetPml4eBase();
PxeUserLimit = MmGetPxeUserLimit();
a5 = TrapInformation;
v12 = StoreInstruction;
v14 = (_MMPFN *)FaultingAddress;
goto LABEL_26;
}
_InterlockedAnd64(&v20->u2.Lock, 0x7FFFFFFFFFFFFFFFui64);
}
}
LODWORD(v22) = MI_READ_PTE_LOCK_FREE((INT64)PointerPte);
v16 = v22;
}
while( (v22 & 0x800) != 0 );
}
return -1073740748;
}
v24.Long = (unsigned __int64)PointerPte->u;
Pml4eBase = MmGetPml4eBase();
PxeUserLimit = MmGetPxeUserLimit();
v27.Long = (unsigned __int64)PointerPte->u;
if( *(&stru_140C4DB30 + 42) && (v24.Long & 0x10) == 0 )
v27.Long = v24.Long & ~*(&stru_140C4DB30 + 42);
v20 = &MmGetPfnDb()[(v27.Long >> 12) & 0xFFFFFFFFFi64];
LABEL_26:
if( (*((_BYTE *)&v20->u3 + 3) & 0x10) != 0 )
{
v28 = -1073740023;
LABEL_39:
_InterlockedAnd64(&v20->u2.Lock, 0x7FFFFFFFFFFFFFFFui64);
if( ProtoPfn )
MiUnlockProtoPoolPage((ULONG_PTR)ProtoPfn, 0x11u);
return v28;
}
v88 = v12 & 1;
if( (v12 & 1) != 0 && *(_BYTE *)(v12 & 0xFFFFFFFFFFFFFFFEui64) == 1 )
{
MiUpdatePfnPriority(v20, *(_DWORD *)((v12 & 0xFFFFFFFFFFFFFFFEui64) + 80) & 7, 0i64);
v28 = 0;
goto LABEL_39;
}
__incgsdword(0x2E98u);
v29 = *((_BYTE *)&v20->u3 + 2);
if( (v29 & 8) != 0 )
{
if( (MiFlags & 0x40000) != 0 && (v30 = v20->OriginalPte.u.Long >> 5, (v30 & 0x1F) == 0) && (v30 & 2) != 0
|| (v12 & 1) != 0
&& *(_BYTE *)(v12 & 0xFFFFFFFFFFFFFFFEui64) == 5
&& (*(_DWORD *)((v12 & 0xFFFFFFFFFFFFFFFEui64) + 56) & 0x20) != 0 )
{
*(_DWORD *)&v14[1].u3.ReferenceCount |= 0x80u;
v28 = -1073741801;
goto LABEL_39;
}
}
if( (v29 & 0x20) != 0 )
{
result = MiHandleCollidedFault(v14, PointerPte, (_MMPFN *)ProtoPfn, (INT64)v20, (INT64)a5, &v82);
if( (unsigned int)v82 <= 1 || result < 0 )
return result;
}
else
{
v85 = 0i64;
p_Support = &Support;
a6 = (_MI_FAULT_VA_LIST *)v24.Long;
result = MiHandleTransitionFault();
if( result < 0 )
return result;
if( v85 )
v20 = v85;
}
v33 = Vm;
v34 = *((_QWORD *)FaultingAddress + 2);
if( (v34 & 1) != 0 && *(_BYTE *)(v34 & 0xFFFFFFFFFFFFFFFEui64) == 4 )
{
v24.Long = -865i64;
PointerPte->u.Long = PointerPte->u.Long & 0xFFFFFFFFFFFFFC1Fui64 | 0x80;
}
if( ((v24.Long >> 5) & 0x1F) == 24 )
MiMakeProtoReadOnly(&PointerPte->u.Long, (INT64)v20);
v35.Long = (unsigned __int64)PointerPte->u;
v36.Long = (unsigned __int64)PointerPte->u;
if( *(&stru_140C4DB30 + 42) && (v35.Long & 0x10) == 0 )
v36.Long = v35.Long & ~*(&stru_140C4DB30 + 42);
v37 = v36.Long & 0xFFFFFFFFF000i64 | MmProtectToPteMask[(v35.Long >> 5) & 0x1F] & 0xFFFF000000000E7Fui64 | 0x21;
if( PointerPte < MmGetPteBase() || PointerPte > MmGetPteLimit() )
{
v39 = v37 | 0x100;
}
else
{
v38 = (__int64)(((_QWORD)PointerPte << 25) - ((_QWORD)MmGetPteBase() << 25)) >> 16;
if( PointerPte >= MmGetPdeBase() && PointerPte <= MmGetPdeLimit() )
{
if( PointerPte == MmGetPxeSelfRef() )
v37 |= 0x8000000000000000ui64;
else
v37 &= ~0x8000000000000000ui64;
if( MiUserPdeOrAbove((UINT64)PointerPte) )
v37 |= 4ui64;
}
if( PointerPte <= &MmGetPteBase()[0x7FFFFFFEFi64] )
v37 |= 4ui64;
v39 = v37 | 0x100;
if( !MiIsAddressGlobal(v38) )
v39 = (__int64)v31;
}
v40.Long = ZeroPte.u.Long;
v41 = v39 & 0xF0FFFFFFFFFFFFFFui64 | 0xA00000000000000i64;
v42 = *(_MI_PARTITION **)(*(&stru_140C4DB30 + 267) + 8 * (((unsigned __int64)v20->u4._bf_0 >> 39) & 0x3FF));
v43.Long = (unsigned __int64)v20->OriginalPte.u;
Partition = v42;
if( (v43.Long & 0x400) == 0 && (v43.Long & 4) != 0 && LOWORD(v43.Long) >> 12 == v42->Store.VirtualPageFileNumber )
{
MiCaptureDirtyBitToPfn();
v40.Long = v44.Long;
}
v45.Long = (unsigned __int64)v20->OriginalPte.u;
if( (v45.Long & 0x400) == 0 && (v45.Long & 0x4000000) != 0 )
v41 |= 0x40ui64;
if( (v41 & 0x800) != 0 )
{
v31 = FaultingAddress;
if( Vm )
{
LOBYTE(v46) = MiOkToSetPteDirtyForNotValidFault(v41, *(_QWORD *)FaultingAddress);
if( !v46 )
v33 = 0i64;
}
if( (*(_BYTE *)(&v20->u3 + 1) & 0x10) != 0 )
{
if( v33 || *v31 >= 0xFFFF800000000000ui64 )
goto LABEL_90;
}
else if( v33 )
{
LOBYTE(v47) = MI_PFN_IS_PROTO((_UNICODE_STRING *)v20, (_UNICODE_STRING *)v42, (UINT8)v31, v32);
if( !v47 )
{
MiCaptureDirtyBitToPfn();
v40.Long = v48.Long;
LABEL_90:
v41 |= 0x42ui64;
}
}
}
LOBYTE(v49) = MI_PFN_IS_PROTO((_UNICODE_STRING *)v20, (_UNICODE_STRING *)v42, (UINT8)v31, v32);
if( v49 )
{
v50 = v41;
if( PointerPte >= Pml4eBase
&& PointerPte <= PxeUserLimit
&& (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0 )
{
v50 = v41 | 0x8000000000000000ui64;
}
PointerPte->u.Long = v50;
}
_InterlockedAnd64(&v20->u2.Lock, 0x7FFFFFFFFFFFFFFFui64);
v53 = (_MMPFN *)ProtoPfn;
v54 = 0;
v55 = 1;
if( !ProtoPfn )
goto LABEL_146;
LODWORD(SpinCount) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)ProtoPfn + 6, 0x3Fui64) )
{
do
KeYieldProcessorEx(&SpinCount);
while( *((__int64 *)ProtoPfn + 3) < 0 );
}
*((_BYTE *)ProtoPfn + 34) &= ~0x20u;
v50 = *((unsigned __int16 *)ProtoPfn + 16);
if( !(_WORD)v50 )
MiBadRefCount((_MMPFN *)ProtoPfn);
v56 = (_WORD)v50 == 1;
LOWORD(v50) = v50 - 1;
*((_WORD *)ProtoPfn + 16) = v50;
if( v56 )
{
LOBYTE(v57) = MiIsPfnFileOnly((INT64)ProtoPfn);
if( v57 )
goto LABEL_144;
}
CurrentPrcb = *((_QWORD *)ProtoPfn + 5);
if( (CurrentPrcb & 0x1000000000i64) != 0 || (CurrentPrcb & 0x2000000000000i64) != 0 )
goto LABEL_145;
v58 = *((_QWORD *)ProtoPfn + 3) & 0x3FFFFFFFFFFFFFFFi64;
if( !(_WORD)v50 )
goto LABEL_114;
if( (_WORD)v50 != 1 )
{
if( (_WORD)v50 != 2 || !v58 )
goto LABEL_145;
LABEL_112:
if( (*((_BYTE *)ProtoPfn + 34) & 8) == 0 )
goto LABEL_145;
goto LABEL_113;
}
if( !v58 )
goto LABEL_112;
LABEL_113:
v55 = 0;
LABEL_114:
PteBase = MmGetPteBase();
v51 = *((_QWORD *)ProtoPfn + 1) | 0x8000000000000000ui64;
if( v51 > (unsigned __int64)&PteBase[0x7FFFFFFEFi64] || v51 < (unsigned __int64)PteBase )
{
v60 = *((_BYTE *)ProtoPfn + 35);
if( (v60 & 0x20) != 0 )
{
*((_BYTE *)ProtoPfn + 35) = v60 & 0xDF;
goto LABEL_143;
}
}
LOBYTE(v61) = MI_PFN_IS_PROTO((_UNICODE_STRING *)ProtoPfn, 0i64, *((_BYTE *)ProtoPfn + 8), (PWCHAR)CurrentPrcb);
if( v61 && (*((_DWORD *)ProtoPfn + 4) & 0x400i64) != 0 )
{
v50 = 1i64;
}
else if( v62 <= v64 && v62 >= (unsigned __int64)MmGetPteBase() && (*((_BYTE *)ProtoPfn + 35) & 0x20) != 0 )
{
v50 = 1i64;
}
else if( v55 == 1 && (v65 & 0x4000000000000000i64) != 0 )
{
v50 = 1i64;
}
CurrentPrcb = (v63 >> 39) & 0x3FF;
v66 = *(_MI_PARTITION **)(*(&stru_140C4DB30 + 267) + 8 * CurrentPrcb);
if( (_DWORD)v50 == 1 )
MiReturnCommit(*(_MI_PARTITION **)(*(&stru_140C4DB30 + 267) + 8 * CurrentPrcb), 1ui64);
v51 = 1i64;
if( v66 != &Irp )
goto LABEL_141;
CurrentPrcb = (__int64)KeGetCurrentPrcb();
v50 = *(int *)(CurrentPrcb + 33564);
if( (_DWORD)v50 == -1 )
goto LABEL_141;
if( v50 + 1 <= 0x100 )
{
do
{
v67 = _InterlockedCompareExchange((volatile signed __int32 *)(CurrentPrcb + 33564), v50 + 1, v50);
v56 = (_DWORD)v50 == v67;
v50 = v67;
if( v56 )
goto LABEL_142;
}
while( v67 != -1 && (unsigned __int64)(v67 + 1i64) <= 0x100 );
}
if( (int)v50 > 192
&& (_DWORD)v50 != -1
&& (_DWORD)v50 == _InterlockedCompareExchange((volatile signed __int32 *)(CurrentPrcb + 33564), 192, v50) )
{
v51 = (int)v50 - 192 + 1i64;
}
if( v51 )
LABEL_141:
LOBYTE(v51) = _InterlockedExchangeAdd64((volatile signed __int64 *)&v66->Vp.ResidentAvailablePages, v51);
LABEL_142:
v53 = (_MMPFN *)ProtoPfn;
LABEL_143:
if( v55 )
LABEL_144:
MiPfnReferenceCountIsZero(v53, v53 - MmGetPfnDb(), v51);
LABEL_145:
_InterlockedAnd64(&v53->u2.Lock, 0x7FFFFFFFFFFFFFFFui64);
LABEL_146:
if( v40.Long )
MiReleasePageFileInfo(Partition, (_MMPTE)v40.Long, 1ui64);
v68 = Support;
if( Support )
{
if( Support->WaitCount > 1 )
KeSetEvent((PRKEVENT)&Support->ListHead[2].Blink, 0, 0);
MiFreeInPageSupportBlock(v68);
}
LOBYTE(v69) = MI_PFN_IS_PROTO((_UNICODE_STRING *)v20, (_UNICODE_STRING *)v50, v51, (PWCHAR)CurrentPrcb);
if( v69 )
{
result = MiCompleteProtoPteFault(
(_MMSUPPORT_INSTANCE *)FaultingAddress,
v41,
Vm,
0i64,
StoreInstruction,
(UINT64)a6,
p_Support);
if( result < 0 )
return result;
}
else
{
v71 = (_BYTE *)(StoreInstruction & 0xFFFFFFFFFFFFFFFEui64);
if( v88 && *v71 == 4 )
{
LOBYTE(v72) = MiPteInShadowRange((UINT64)PointerPte);
if( v72 && (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0 )
v41 |= 0x8000000000000000ui64;
PointerPte->u.Long = v41;
}
else
{
if( v88 && *v71 == 3 )
{
v41 &= ~0x20ui64;
v54 = 1;
}
if( (*((_BYTE *)FaultingAddress + 69) & 8) != 0 )
{
v73 = *((_QWORD *)FaultingAddress + 2);
if( (v73 & 1) == 0 || *(_BYTE *)(v73 & 0xFFFFFFFFFFFFFFFEui64) != 2 )
v41 &= ~0x20ui64;
}
v74 = *((_BYTE *)FaultingAddress + 69);
if( (v74 & 5) == 4 && (v74 & 2) == 0 )
{
v75 = *((unsigned __int16 *)FaultingAddress + 33);
if( (_WORD)v75
&& (v75 + *((unsigned __int16 *)FaultingAddress + 32) != (((unsigned int)PointerPte >> 3) & 0x1FF)
|| (v74 & 0x10) == 0) )
{
MiEmptyDeferredWorkingSetEntries((INT64)FaultingAddress + 56);
}
v76 = *((_WORD *)FaultingAddress + 33);
if( v76 )
{
*((_WORD *)FaultingAddress + 33) = v76 + 1;
}
else
{
v77 = (_UNICODE_STRING *)*((unsigned __int8 *)FaultingAddress + 69);
*((_WORD *)FaultingAddress + 33) = 1;
*((_WORD *)FaultingAddress + 32) = ((unsigned int)PointerPte >> 3) & 0x1FF;
LOBYTE(v78) = MI_PFN_IS_PROTO((_UNICODE_STRING *)v20, v77, 0xFFu, v70);
if( v78 )
*((_BYTE *)FaultingAddress + 69) = v79 & 0xEF;
else
*((_BYTE *)FaultingAddress + 69) = v79 | 0x10;
}
v54 |= 4u;
}
LODWORD(a6) = v54;
if( !MiAllocateWsle(Vma, PointerPte, v20, 0i64, (_MMPTE)v41, a6) )
{
MiLockAndDecrementShareCount(v20, 0i64);
return -1073741801;
}
}
}
return 272;
}Referenced by:
MiDispatchFault
MiResolveProtoPteFault