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