MiGetPageChain

_MMPFN *__stdcall MiGetPageChain(
        PVOID *Partition,
        _MMSUPPORT_INSTANCE *Vm,
        UINT64 PreferredNode,
        UINT64 ProtectionCode,
        UINT64 InputGetPageFlags,
        UINT64 Alignment,
        UINT64 *NumberOfPages){
  _MI_PFN_CACHE_ATTRIBUTE v7; 
  ULONG_PTR *v9; 
  __int64 CurrentIrql; 
  struct _KPRCB *CurrentPrcb; 
  int NodeShiftedColor; 
  int v13; 
  _MMSUPPORT_INSTANCE *p_PageColor; 
  UINT64 v15; 
  UINT64 v16; 
  unsigned int v17; 
  UINT64 v18; 
  _MMPFN *v19; 
  unsigned __int64 v20; 
  int v21; 
  unsigned __int8 v22; 
  unsigned __int64 v23; 
  signed __int32 v24; 
  _KQUEUE *LargePage; 
  unsigned __int8 v26; 
  _MMPFN *PfnDb; 
  __int64 v28; 
  int v29; 
  signed __int32 v30; 
  unsigned int v31; 
  __int64 v32; 
  UINT64 v33; 
  __int64 v34; 
  __int64 v35; 
  __int64 v36; 
  int v37; 
  int v38; 
  __int64 v39; 
  int v40; 
  struct {unsigned __int16 ReferenceCount;} *v41; 
  _MI_PFN_CACHE_ATTRIBUTE v42; 
  UINT64 v43; 
  int v44; 
  __int64 v45; 
  __int64 v46; 
  int v47; 
  _KTBFLUSH_TYPE v48; 
  struct _KPRCB *v49; 
  _XSTATE_CONFIGURATION *v50; 
  __int64 HyperPte; 
  int v52; 
  int v53; 
  __int64 v54; 
  __int64 v55; 
  unsigned __int8 v56; 
  struct _KPRCB *v57; 
  _MI_ZERO_THREAD_CONTEXT *MmInternal; 
  UINT64 v59; 
  UINT64 v60; 
  char *v61; 
  UINT64 Phase0Mapping; 
  unsigned __int64 v63; 
  unsigned __int64 v64; 
  int v65; 
  unsigned __int64 Long; 
  int v67; 
  signed __int64 v68; 
  UINT64 v69; 
  signed __int64 v70; 
  signed __int64 v71; 
  int v72; 
  signed __int64 v73; 
  signed __int64 v74; 
  signed __int64 v75; 
  signed __int64 bf_0; 
  __int64 v77; 
  signed __int64 v78; 
  signed __int64 v79; 
  _DWORD *v80; 
  struct _KPRCB *v81; 
  volatile int DpcRequestSummary; 
  int v83; 
  char v84; 
  unsigned int v85; 
  _ETHREAD *NextThread; 
  _MI_PFN_CACHE_ATTRIBUTE v87; 
  signed __int32 v89[8]; 
  UINT8 v90; 
  _MI_PFN_CACHE_ATTRIBUTE CacheAttribute; 
  unsigned int v92; 
  int v93; 
  UINT64 PostZeroCount; 
  unsigned __int64 v95; 
  int v96; 
  ULONG_PTR *Partitiona; 
  __int64 v98; 
  unsigned __int64 v99; 
  int v100; 
  _MI_PFN_CACHE_ATTRIBUTE v101; 
  _MMSUPPORT_INSTANCE *v102; 
  __int64 v103; 
  UINT64 v104; 
  _MMPFN *PfnChain; 
  struct {unsigned __int16 ReferenceCount;} *v106; 
  __int64 v107; 
  INT64 v108; 
  __int64 v109; 
  UINT64 v110; 
  UINT64 *v111; 
  INT64 a6[2]; 
  __int128 v113; 
  __int128 v114; 
  __int128 v115; 
  __int128 v116; 
  __int128 v117; 
  __int128 v118; 
  __int128 v119; 
  __int128 v120; 
  __int64 PostZeroPages[16]; 

  v111 = NumberOfPages;
  v7 = (int)ProtectionCode;
  *(_OWORD *)a6 = 0i64;
  CacheAttribute = (int)ProtectionCode;
  v113 = 0i64;
  v108 = (INT64)Vm;
  v9 = (ULONG_PTR *)Partition;
  v114 = 0i64;
  Partitiona = (ULONG_PTR *)Partition;
  v115 = 0i64;
  v116 = 0i64;
  v117 = 0i64;
  v118 = 0i64;
  v119 = 0i64;
  v120 = 0i64;
  CurrentIrql = KeGetCurrentIrql();
  v98 = CurrentIrql;
  if( (_DWORD)PreferredNode )
  {
    CurrentPrcb = KeGetCurrentPrcb();
    NodeShiftedColor = ((_DWORD)PreferredNode - 1) << *(&stru_140C4DB30 + 156);
  }
  else
  {
    CurrentPrcb = *(&KiProcessorBlock + KeGetCurrentThread()->IdealProcessor);
    NodeShiftedColor = CurrentPrcb->NodeShiftedColor;
  }
  v13 = (1 << *(&stru_140C4DB30 + 157)) - 1;
  v96 = NodeShiftedColor;
  v93 = v13;
  if( !Vm || (p_PageColor = Vm, (Vm->Flags._bf_0 & 7u) >= 2) )
    p_PageColor = (_MMSUPPORT_INSTANCE *)&CurrentPrcb->PageColor;
  v15 = *NumberOfPages;
  v16 = Alignment;
  v17 = InputGetPageFlags & 0xFFFFF0FF;
  v102 = p_PageColor;
  v18 = 0xFFFFFFFFFi64;
  v92 = InputGetPageFlags & 0xFFFFF0FF;
  v19 = 0i64;
  v99 = v15;
  v20 = 0i64;
  v104 = 0xFFFFFFFFFi64;
  PfnChain = 0i64;
  LODWORD(PostZeroCount) = 0;
  v95 = 0i64;
  if( Alignment != -1i64 )
  {
    v17 = InputGetPageFlags & 0xFFFFB0FF | 0x4000;
    goto LABEL_33;
  }
  if( v15 < 0x10 )
  {
LABEL_33:
    if( v20 >= v15 )
      goto LABEL_141;
    v109 = v7;
    while( 1 )
    {
      v30 = v13 & _InterlockedExchangeAdd((volatile signed __int32 *)v102, 1u);
      v31 = v30 | v96;
      if( v16 == -1i64 )
        goto LABEL_149;
      v32 = 15i64;
      if( *(&stru_140C4DB30 + 66) < 0xFui64 )
        v32 = *(&stru_140C4DB30 + 66);
      v33 = v32 & v16;
      v31 = v33 | v31 & 0xFFFFFFF0;
      LODWORD(v34) = MiGetPage(v9, v31, v17);
      v103 = v34;
      v35 = v34;
      if( v34 == -1 )
        v17 &= ~0x4000u;
      v16 = v32 & (v33 + 1);
      v7 = CacheAttribute;
      Alignment = v16;
      if( v34 == -1 )
      {
LABEL_149:
        LODWORD(v36) = MiGetPage(Partitiona, v31, v17);
        v103 = v36;
        v35 = v36;
        if( v36 == -1 )
          goto LABEL_141;
      }
      v37 = v17 | 0x4000;
      if( v16 == -1i64 )
        v37 = v17;
      v92 = v37;
      v19 = &MmGetPfnDb()[v35];
      v38 = 1;
      v39 = *((unsigned __int8 *)&v19->u3 + 2) >> 6;
      v100 = v39;
      if( (_DWORD)v39 == v7 || ((unsigned __int8)((1 << v39) | (1 << v7)) & *(&stru_140C4DB30 + 488)) == 0 )
        break;
      v40 = PostZeroCount;
      PostZeroPages[(unsigned int)PostZeroCount] = v35;
      LODWORD(PostZeroCount) = v40 + 1;
      if( v40 == 15 )
      {
        MiPerformFinalZeroing(PostZeroPages, 0x10ui64, v7);
        LODWORD(PostZeroCount) = 0;
      }
LABEL_106:
      bf_0 = v19->u2._bf_0;
      v77 = v104 & 0xFFFFFFFFFi64;
      v78 = _InterlockedCompareExchange64(&v19->u2.Lock, v104 & 0xFFFFFFFFFi64 | bf_0 & 0xFFFFFFF000000000ui64, bf_0);
      if( bf_0 != v78 )
      {
        do
        {
          v79 = v78;
          v78 = _InterlockedCompareExchange64(&v19->u2.Lock, v77 | v78 & 0xFFFFFFF000000000ui64, v78);
        }
        while( v79 != v78 );
      }
      ++v20;
      v104 = v35;
      v95 = v20;
      if( (unsigned __int8)v98 >= 2u )
      {
        v80 = (_DWORD *)((char *)&stru_140C4DB30 + 6544);
        if( (*(_BYTE *)(v108 + 184) & 7) != 2 )
          v80 = (_DWORD *)(v108 + 192);
        if( (*v80 & 0x40000000) != 0 )
          goto LABEL_141;
        v81 = KeGetCurrentPrcb();
        DpcRequestSummary = v81->DpcRequestSummary;
        if( (DpcRequestSummary & 1) != 0 )
        {
          v83 = 1;
          if( v81->DpcTimeCount > 7 )
          {
            if( v81->QuantumEnd )
              goto LABEL_136;
LABEL_131:
            if( (DpcRequestSummary & 0x1E) != 0 )
            {
              v38 = 5;
              goto LABEL_136;
            }
            if( v81->CurrentThread != v81->IdleThread )
            {
              v38 = 6;
              goto LABEL_136;
            }
LABEL_135:
            _disable();
            v81->DpcWatchdogCount = 0;
            v81->DpcTimeCount = 0;
            KiResetGlobalDpcWatchdogProfiler((INT64)v81);
            _enable();
            v38 = 0;
            goto LABEL_136;
          }
LABEL_129:
          if( v81->DpcWatchdogCount > 7u )
          {
            if( v83 )
              goto LABEL_131;
            goto LABEL_135;
          }
        }
        else
        {
          v83 = 0;
          if( (DpcRequestSummary & 0x1E) != 0 )
          {
            v38 = 2;
          }
          else if( v81->QuantumEnd )
          {
            v38 = 3;
          }
          else
          {
            NextThread = v81->NextThread;
            if( !NextThread || NextThread == v81->CurrentThread )
              goto LABEL_129;
            v38 = 4;
          }
LABEL_136:
          if( v38 )
            goto LABEL_141;
        }
        v7 = CacheAttribute;
      }
      if( v20 >= v99 )
        goto LABEL_141;
      v16 = Alignment;
      v17 = v92;
      v9 = Partitiona;
      v13 = v93;
    }
    if( (*(_DWORD *)(&v19->3 + 1) & 0x3E0i64) != 0 && (InputGetPageFlags & 0x100) != 0 )
    {
      v41 = &v19->u3 + 1;
      v106 = &v19->u3 + 1;
      v42 = *((_DWORD *)&stru_140C4DB30 + 4 * v39 + v109 + 106);
      v101 = v42;
      if( v42 != (_DWORD)v39 )
        MiChangePageAttribute(v19, v42, 0i64);
      v43 = 0i64;
      if( KeGetCurrentPrcb()->HyperPte
        || (v43 = (UINT64)MiReservePtes((_MI_SYSTEM_PTE_TYPE *)((char *)&stru_140C4DB30 + 4432), 1ui64)) == 0 )
      {
        v90 = 17;
        v49 = KeGetCurrentPrcb();
        if( v49->HyperPte )
          v43 = 1i64;
        v50 = 0i64;
        v110 = v43;
        HyperPte = (__int64)v49->HyperPte;
        v107 = HyperPte;
        do
        {
          if( HyperPte )
          {
            v52 = 4;
            v53 = LOBYTE(v41->ReferenceCount) >> 6;
            if( !v53 || v53 == 3 )
            {
              v52 = 12;
            }
            else if( v53 == 2 )
            {
              v52 = 28;
            }
            LODWORD(v54) = MiMakeValidPte(0i64, v35, v52 | 0xA0000000);
            v55 = v54;
            v56 = KeGetCurrentIrql();
            __writecr8(2ui64);
            v57 = KeGetCurrentPrcb();
            v90 = v56;
            MmInternal = (_MI_ZERO_THREAD_CONTEXT *)v57->MmInternal;
            if( !MmInternal
              || (MiGetUltraMapping(MmInternal + 3112, 3i64),
                  v60 = v59,
                  v61 = (char *)MmGetPteBase() + ((v59 >> 9) & 0x7FFFFFFFF8i64),
                  *((_QWORD *)MmInternal + 1543) = v61,
                  !v59) )
            {
              v60 = ((unsigned __int64)v57->HyperPte & 0xFFFFFFFFFFFFF000ui64)
                  + (((__int64)v57->HyperPte & 0xFFF) << 12);
              v61 = (char *)MmGetPteBase() + ((v60 >> 9) & 0x7FFFFFFFF8i64);
            }
            if( v61 >= (char *)MmGetPml4eBase()
              && v61 <= (char *)MmGetPxeUserLimit()
              && (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0
              && (v55 & 1) != 0 )
            {
              v55 |= 0x8000000000000000ui64;
            }
            v41 = v106;
            *(_QWORD *)v61 = v55;
          }
          else
          {
            Phase0Mapping = (UINT64)MxGetPhase0Mapping();
            v60 = Phase0Mapping;
            if( !Phase0Mapping )
              KeBugCheckEx(0x1Au, (PVOID)0x3030305, (PVOID)v35, 0i64, 0i64);
            v50 = (_XSTATE_CONFIGURATION *)((char *)MmGetPteBase() + ((Phase0Mapping >> 9) & 0x7FFFFFFFF8i64));
            LODWORD(v63) = MiMakeValidPte(v50, v35, 2684354564i64);
            v64 = v63;
            LOBYTE(v65) = MiPteInShadowRange((UINT64)v50);
            if( v65 && (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0 && (v64 & 1) != 0 )
              v64 |= 0x8000000000000000ui64;
            v50->EnabledFeatures = v64;
          }
          KeZeroPages((VOID *)v60, 0x1000ui64);
          if( v107 )
          {
            MiUnmapPageInHyperSpaceWorker((VOID *)v60, v90, 0x80000000ui64);
          }
          else
          {
            Long = ZeroPte.u.Long;
            LOBYTE(v67) = MiPteInShadowRange((UINT64)v50);
            if( v67 && (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0 && (ZeroPte.u.Long & 1) != 0 )
              Long = ZeroPte.u.Long | 0x8000000000000000ui64;
            v50->EnabledFeatures = Long;
            KeFlushSingleTb(v60, FlushKernel, 1i64);
          }
          ++v35;
          v41 += 24;
          v106 = v41;
          HyperPte = v107;
        }
        while( v35 == v103 );
        v43 = v110;
        LODWORD(v39) = v100;
        v42 = v101;
        v35 = v103;
      }
      else
      {
        MiMakeProtectionPfnCompatible((_BYTE *)4, v19);
        LODWORD(v45) = MiMakeValidPte((_XSTATE_CONFIGURATION *)v43, v35, v44 | 0xA0000000);
        v46 = v45;
        LOBYTE(v47) = MiPteInShadowRange(v43);
        if( v47 && (KeGetCurrentThread()->ApcState.Process->Flags3 & 0x1000) != 0 && (v46 & 1) != 0 )
          v46 |= 0x8000000000000000ui64;
        *(_QWORD *)v43 = v46;
        KeZeroPages((VOID *)((__int64)((v43 << 25) - ((_QWORD)MmGetPteBase() << 25)) >> 16), 0x1000ui64);
        MiReleasePtes((_MI_SYSTEM_PTE_TYPE *)((char *)&stru_140C4DB30 + 4432), (_MMPTE *)v43, 1ui64, v48);
      }
      v7 = CacheAttribute;
      if( v42 != (_DWORD)v39 && v42 != CacheAttribute && v43 )
        MiChangePageAttribute(v19, (_MI_PFN_CACHE_ATTRIBUTE)v39, 0i64);
      v19->OriginalPte.u.Long &= 0xFFFFFFFFFFFFFC1Fui64;
      _InterlockedOr(v89, 0);
      v68 = v19->u2._bf_0;
      v69 = (KiTbFlushTimeStamp & 0xF) << 56;
      v70 = _InterlockedCompareExchange64(&v19->u2.Lock, v69 | v68 & 0xF0FFFFFFFFFFFFFFui64, v68);
      if( v68 != v70 )
      {
        do
        {
          v71 = v70;
          v70 = _InterlockedCompareExchange64(&v19->u2.Lock, v69 | v70 & 0xF0FFFFFFFFFFFFFFui64, v70);
        }
        while( v71 != v70 );
      }
      v20 = v95;
    }
    v72 = *((unsigned __int8 *)&v19->u3 + 2) >> 6;
    if( v72 != v7 )
    {
      if( v72 == 1
        || v72 != 3
        && (v84 = HIBYTE(v19->u2._bf_0) & 0xF,
            _InterlockedOr(v89, 0),
            v85 = ((_BYTE)KiTbFlushTimeStamp - v84) & 0xF,
            v85 <= 2)
        && ((v84 & 1) != 0 || v85 < 2) )
      {
        if( (*(_DWORD *)(&v19->3 + 1) & 0x3E0i64) != 0 )
          MiZeroPhysicalPage(v35, 1ui64, v7);
        v19->OriginalPte.u.Long = (unsigned __int64)PfnChain;
        PfnChain = v19;
LABEL_105:
        v38 = 1;
        goto LABEL_106;
      }
      MiChangePageAttribute(v19, v7, 4ui64);
    }
    v73 = v19->u2._bf_0;
    v74 = _InterlockedCompareExchange64(&v19->u2.Lock, v73 & 0xF0FFFFFFFFFFFFFFui64, v73);
    if( v73 != v74 )
    {
      do
      {
        v75 = v74;
        v74 = _InterlockedCompareExchange64(&v19->u2.Lock, v74 & 0xF0FFFFFFFFFFFFFFui64, v74);
      }
      while( v75 != v74 );
    }
    goto LABEL_105;
  }
  LODWORD(a6[1]) = 16;
  a6[0] = 1i64;
  v21 = 1;
  v22 = 17;
  v23 = v15;
  while( 1 )
  {
    v24 = v13 & _InterlockedExchangeAdd((volatile signed __int32 *)p_PageColor, 1u) | NodeShiftedColor;
    if( (unsigned __int8)CurrentIrql < 2u )
    {
      v22 = KeGetCurrentIrql();
      __writecr8(2ui64);
    }
    if( v23 < 0x200 || v21 != 1 )
      goto LABEL_18;
    LargePage = (_KQUEUE *)MiGetLargePage((INT64)v9, 1u, v7, v24, 4, (__int64)a6);
    if( !LargePage )
    {
      v9 = Partitiona;
LABEL_18:
      v21 = 2;
      LargePage = (_KQUEUE *)MiGetLargePage((INT64)v9, 2u, v7, v24, 4, (__int64)a6);
      if( !LargePage )
        goto LABEL_20;
    }
    MiConvertEntireLargePageToSmall(LargePage, v21, 2u, (_LARGE_INTEGER *)1, 0i64, 0i64);
LABEL_20:
    v26 = v98;
    if( (unsigned __int8)v98 < 2u )
      __writecr8(v22);
    if( !LargePage )
      goto LABEL_25;
    PfnDb = MmGetPfnDb();
    v28 = (LargePage - (_KQUEUE *)PfnDb) / 48;
    MiSetPfnBlink(&PfnDb[v28 - 1 + MiLargePageSizes[v21]], v18, 0i64);
    v18 = v28;
    v19 = (_MMPFN *)LargePage;
    v7 = CacheAttribute;
    v23 = v99 - (MiLargePageSizes[v21] + v95);
    p_PageColor = v102;
    v9 = Partitiona;
    v13 = v93;
    NodeShiftedColor = v96;
    v95 += MiLargePageSizes[v21];
    if( v23 < 0x10 )
      break;
    LOBYTE(CurrentIrql) = v98;
  }
  v26 = v98;
LABEL_25:
  v104 = v18;
  if( HIDWORD(a6[0]) )
    MiNotifyPageHeat(a6);
  if( v26 < 2u )
  {
    v20 = v95;
    goto LABEL_32;
  }
  LOBYTE(v29) = MiWorkingSetIsContended(v108);
  if( v29 )
  {
    v20 = v95;
  }
  else
  {
    v20 = v95;
    if( !(unsigned int)KeShouldYieldProcessor() )
    {
LABEL_32:
      v15 = v99;
      v13 = v93;
      v9 = Partitiona;
      v17 = v92;
      v16 = -1i64;
      goto LABEL_33;
    }
  }
LABEL_141:
  v87 = CacheAttribute;
  *v111 = v20;
  if( (_DWORD)PostZeroCount )
    MiPerformFinalZeroing(PostZeroPages, (unsigned int)PostZeroCount, v87);
  if( PfnChain )
    MiChangePageAttributeBatch(PfnChain, v87, ZeroPte);
  return v19;
}

Referenced by:

MiCreateSharedZeroPages
MiGetClusterPage
MiGetHardFaultPages
MiPfPrepareSequentialReadList
MiResolvePageFileFault
MiResolvePrivateZeroFault