MiGetPageChain

_MMPFN *__fastcall MiGetPageChain(
        _MI_PARTITION *Partition,
        _MMSUPPORT_INSTANCE *Vm,
        UINT64 PreferredNode,
        UINT64 ProtectionCode,
        UINT64 InputGetPageFlags,
        UINT64 Alignment,
        UINT64 *NumberOfPages){
  _MI_PFN_CACHE_ATTRIBUTE v7; 
  _MI_PARTITION *v9; 
  __int64 CurrentIrql; 
  struct _KPRCB *CurrentPrcb; 
  int v12; 
  int v13; 
  _MMSUPPORT_INSTANCE *v14; 
  UINT64 v15; 
  UINT64 v16; 
  unsigned int v17; 
  UINT64 v18; 
  KQUEUE *v19; 
  unsigned __int64 v20; 
  int v21; 
  unsigned __int8 v22; 
  unsigned __int64 v23; 
  unsigned __int32 v24; 
  KQUEUE *LargePage; 
  unsigned __int8 v26; 
  _MMPFN *PfnDb; 
  __int64 v28; 
  signed __int32 v29; 
  unsigned int v30; 
  __int64 v31; 
  UINT64 v32; 
  UINT64 Page; 
  __int64 v34; 
  int v35; 
  int v36; 
  __int64 v37; 
  int v38; 
  char *v39; 
  unsigned int v40; 
  INT64 v41; 
  int ProtectionPfnCompatible; 
  struct _KPRCB *v43; 
  UINT64 *v44; 
  __int64 v45; 
  int v46; 
  int v47; 
  UINT64 ValidPte; 
  unsigned __int8 v49; 
  struct _KPRCB *v50; 
  __int64 v51; 
  unsigned __int64 UltraMapping; 
  UINT64 *v53; 
  unsigned __int64 Phase0Mapping; 
  signed __int64 v55; 
  UINT64 v56; 
  signed __int64 v57; 
  signed __int64 v58; 
  int v59; 
  signed __int64 v60; 
  signed __int64 v61; 
  signed __int64 v62; 
  signed __int64 Flink; 
  __int64 v64; 
  signed __int64 v65; 
  signed __int64 v66; 
  LONG *v67; 
  struct _KPRCB *v68; 
  int v69; 
  int v70; 
  char v71; 
  unsigned int v72; 
  __int64 v73; 
  _MI_PFN_CACHE_ATTRIBUTE v74; 
  signed __int32 v76[8]; 
  ULONG_PTR BugCheckParameter4; 
  UINT8 v78; 
  _MI_PFN_CACHE_ATTRIBUTE v79; 
  unsigned int v80; 
  int v81; 
  UINT64 v82; 
  unsigned __int64 v83; 
  int v84; 
  _MI_PARTITION *Partitiona; 
  __int64 v86; 
  unsigned __int64 v87; 
  int v88; 
  unsigned int v89; 
  _MMSUPPORT_INSTANCE *v90; 
  UINT64 v91; 
  UINT64 v92; 
  _LIST_ENTRY *v93; 
  char *v94; 
  __int64 v95; 
  INT64 v96; 
  __int64 v97; 
  INT64 v98; 
  UINT64 *v99; 
  INT64 a6[2]; 
  __int128 v101; 
  __int128 v102; 
  __int128 v103; 
  __int128 v104; 
  __int128 v105; 
  __int128 v106; 
  __int128 v107; 
  __int128 v108; 
  __int64 v109[16]; 
  v99 = NumberOfPages;
  v7 = (int)ProtectionCode;
  *(_OWORD *)a6 = 0i64;
  v79 = (int)ProtectionCode;
  v101 = 0i64;
  v96 = (INT64)Vm;
  v9 = Partition;
  v102 = 0i64;
  Partitiona = Partition;
  v103 = 0i64;
  v104 = 0i64;
  v105 = 0i64;
  v106 = 0i64;
  v107 = 0i64;
  v108 = 0i64;
  CurrentIrql = KeGetCurrentIrql();
  v86 = CurrentIrql;
  if( (_DWORD)PreferredNode )
  {
    CurrentPrcb = KeGetCurrentPrcb();
    v12 = ((_DWORD)PreferredNode - 1) << byte_140C4DBCC;
  }
  else
  {
    CurrentPrcb = *(&KiProcessorBlock + *((unsigned int *)KeGetCurrentThread() + 147));
    v12 = *((_DWORD *)CurrentPrcb + 8134);
  }
  v13 = (1 << byte_140C4DBCD) - 1;
  v84 = v12;
  v81 = v13;
  if( !Vm || (v14 = Vm, (*(_BYTE *)&Vm->Flags.0 & 7u) >= 2) )
    v14 = (_MMSUPPORT_INSTANCE *)((char *)CurrentPrcb + 32528);
  v15 = *NumberOfPages;
  v16 = Alignment;
  v17 = InputGetPageFlags & 0xFFFFF0FF;
  v90 = v14;
  v18 = 0xFFFFFFFFFi64;
  v80 = InputGetPageFlags & 0xFFFFF0FF;
  v19 = 0i64;
  v87 = v15;
  v20 = 0i64;
  v92 = 0xFFFFFFFFFi64;
  v93 = 0i64;
  LODWORD(v82) = 0;
  v83 = 0i64;
  if( Alignment != -1i64 )
  {
    v17 = InputGetPageFlags & 0xFFFFB0FF | 0x4000;
    goto LABEL_33;
  }
  if( v15 < 0x10 )
  {
LABEL_33:
    if( v20 >= v15 )
      goto LABEL_129;
    v97 = v7;
    while( 1 )
    {
      v29 = v13 & _InterlockedExchangeAdd((volatile signed __int32 *)v90, 1u);
      v30 = v29 | v84;
      if( v16 == -1i64 )
        goto LABEL_137;
      v31 = 15i64;
      if( (unsigned int)dword_140C4DC38 < 0xFui64 )
        v31 = (unsigned int)dword_140C4DC38;
      v32 = v31 & v16;
      v30 = v32 | v30 & 0xFFFFFFF0;
      Page = MiGetPage(v9, v30, v17);
      v91 = Page;
      v34 = Page;
      if( Page == -1i64 )
        v17 &= ~0x4000u;
      v16 = v31 & (v32 + 1);
      v7 = v79;
      Alignment = v16;
      if( Page == -1i64 )
      {
LABEL_137:
        v91 = MiGetPage(Partitiona, v30, v17);
        v34 = v91;
        if( v91 == -1i64 )
          goto LABEL_129;
      }
      v35 = v17 | 0x4000;
      if( v16 == -1i64 )
        v35 = v17;
      v80 = v35;
      v19 = (KQUEUE *)((char *)MmGetPfnDb() + 48 * v34);
      v36 = 1;
      v37 = BYTE2(v19->EntryListHead.Blink) >> 6;
      v88 = v37;
      if( (_DWORD)v37 == v7 || ((unsigned __int8)((1 << v37) | (1 << v7)) & (unsigned __int8)byte_140C4DD18) == 0 )
        break;
      v38 = v82;
      v109[(unsigned int)v82] = v34;
      LODWORD(v82) = v38 + 1;
      if( v38 == 15 )
      {
        MiPerformFinalZeroing((UINT64 *)v109, 0x10ui64, (unsigned int)v7);
        LODWORD(v82) = 0;
      }
LABEL_94:
      Flink = (signed __int64)v19->EntryListHead.Flink;
      v64 = v92 & 0xFFFFFFFFFi64;
      v65 = _InterlockedCompareExchange64(
              (volatile signed __int64 *)&v19->EntryListHead,
              v92 & 0xFFFFFFFFFi64 | Flink & 0xFFFFFFF000000000ui64,
              Flink);
      if( Flink != v65 )
      {
        do
        {
          v66 = v65;
          v65 = _InterlockedCompareExchange64(
                  (volatile signed __int64 *)&v19->EntryListHead,
                  v64 | v65 & 0xFFFFFFF000000000ui64,
                  v65);
        }
        while( v66 != v65 );
      }
      ++v20;
      v92 = v34;
      v83 = v20;
      if( (unsigned __int8)v86 >= 2u )
      {
        v67 = &dword_140C4F4C0;
        if( (*(_BYTE *)(v96 + 184) & 7) != 2 )
          v67 = (LONG *)(v96 + 192);
        if( (*v67 & 0x40000000) != 0 )
          goto LABEL_129;
        v68 = KeGetCurrentPrcb();
        v69 = *((_DWORD *)v68 + 3147);
        if( (v69 & 1) != 0 )
        {
          v70 = 1;
          if( *((_DWORD *)v68 + 8103) > 7u )
          {
            if( *((_BYTE *)v68 + 12585) )
              goto LABEL_124;
LABEL_119:
            if( (v69 & 0x1E) != 0 )
            {
              v36 = 5;
              goto LABEL_124;
            }
            if( *((_QWORD *)v68 + 1) != *((_QWORD *)v68 + 3) )
            {
              v36 = 6;
              goto LABEL_124;
            }
LABEL_123:
            _disable();
            *((_DWORD *)v68 + 7931) = 0;
            *((_DWORD *)v68 + 8103) = 0;
            KiResetGlobalDpcWatchdogProfiler((INT64)v68);
            _enable();
            v36 = 0;
            goto LABEL_124;
          }
LABEL_117:
          if( *((_DWORD *)v68 + 7931) > 7u )
          {
            if( v70 )
              goto LABEL_119;
            goto LABEL_123;
          }
        }
        else
        {
          v70 = 0;
          if( (v69 & 0x1E) != 0 )
          {
            v36 = 2;
          }
          else if( *((_BYTE *)v68 + 12585) )
          {
            v36 = 3;
          }
          else
          {
            v73 = *((_QWORD *)v68 + 2);
            if( !v73 || v73 == *((_QWORD *)v68 + 1) )
              goto LABEL_117;
            v36 = 4;
          }
LABEL_124:
          if( v36 )
            goto LABEL_129;
        }
        v7 = v79;
      }
      if( v20 >= v87 )
        goto LABEL_129;
      v16 = Alignment;
      v17 = v80;
      v9 = Partitiona;
      v13 = v81;
    }
    if( ((__int64)v19->Header.WaitListHead.Blink & 0x3E0i64) != 0 && (InputGetPageFlags & 0x100) != 0 )
    {
      v39 = (char *)&v19->EntryListHead.Blink + 2;
      v94 = (char *)&v19->EntryListHead.Blink + 2;
      v40 = dword_140C4DCD8[4 * v37 + v97];
      v89 = v40;
      if( v40 != (_DWORD)v37 )
        MiChangePageAttribute((INT64)v19, v40, 0);
      v41 = 0i64;
      if( *((_QWORD *)KeGetCurrentPrcb() + 4160) || (v41 = MiReservePtes((INT64)&qword_140C4EC80, 1ui64)) == 0 )
      {
        v78 = 17;
        v43 = KeGetCurrentPrcb();
        if( *((_QWORD *)v43 + 4160) )
          v41 = 1i64;
        v44 = 0i64;
        v98 = v41;
        v45 = *((_QWORD *)v43 + 4160);
        v95 = v45;
        do
        {
          if( v45 )
          {
            v46 = 4;
            v47 = (unsigned __int8)*v39 >> 6;
            if( !v47 || v47 == 3 )
            {
              v46 = 12;
            }
            else if( v47 == 2 )
            {
              v46 = 28;
            }
            ValidPte = MiMakeValidPte(0i64, v34, v46 | 0xA0000000);
            v49 = KeGetCurrentIrql();
            __writecr8(2ui64);
            v50 = KeGetCurrentPrcb();
            v78 = v49;
            v51 = *((_QWORD *)v50 + 4095);
            if( !v51
              || (UltraMapping = MiGetUltraMapping((unsigned __int64 *)(v51 + 12448), 3u, 1i64, 0),
                  v53 = (UINT64 *)((char *)MmGetPteBase() + ((UltraMapping >> 9) & 0x7FFFFFFFF8i64)),
                  *(_QWORD *)(v51 + 12344) = v53,
                  !UltraMapping) )
            {
              UltraMapping = (*((_QWORD *)v50 + 4160) & 0xFFFFFFFFFFFFF000ui64)
                           + ((*((_QWORD *)v50 + 4160) & 0xFFFi64) << 12);
              v53 = (UINT64 *)((char *)MmGetPteBase() + ((UltraMapping >> 9) & 0x7FFFFFFFF8i64));
            }
            if( v53 >= (UINT64 *)MmGetPml4eBase()
              && v53 <= (UINT64 *)MmGetPxeUserLimit()
              && (*(_DWORD *)(*((_QWORD *)KeGetCurrentThread() + 23) + 2172i64) & 0x1000) != 0
              && (ValidPte & 1) != 0 )
            {
              ValidPte |= 0x8000000000000000ui64;
            }
            v39 = v94;
            *v53 = ValidPte;
          }
          else
          {
            Phase0Mapping = (unsigned __int64)MxGetPhase0Mapping();
            UltraMapping = Phase0Mapping;
            if( !Phase0Mapping )
              KeBugCheckEx(0x1Au, 0x3030305ui64, v34, 0i64, 0i64);
            v44 = (UINT64 *)((char *)MmGetPteBase() + ((Phase0Mapping >> 9) & 0x7FFFFFFFF8i64));
            *v44 = MiMakeValidPte((UINT64)v44, v34, 2684354564i64);
          }
          KeZeroPages((PVOID)UltraMapping, 0x1000ui64);
          if( v95 )
          {
            MiUnmapPageInHyperSpaceWorker((PVOID)UltraMapping, v78, 0x80000000ui64);
          }
          else
          {
            *v44 = ZeroPte;
            KeFlushSingleTb(UltraMapping, 0i64, 1i64);
          }
          ++v34;
          v39 += 48;
          v94 = v39;
          v45 = v95;
        }
        while( v34 == v91 );
        v41 = v98;
        LODWORD(v37) = v88;
        v40 = v89;
        v34 = v91;
      }
      else
      {
        ProtectionPfnCompatible = MiMakeProtectionPfnCompatible(4ui64, (_MMPFN *)v19);
        *(_QWORD *)v41 = MiMakeValidPte(v41, v34, ProtectionPfnCompatible | 0xA0000000);
        KeZeroPages((PVOID)(((v41 << 25) - ((_QWORD)MmGetPteBase() << 25)) >> 16), 0x1000ui64);
        MiReleasePtes((INT64)&qword_140C4EC80, v41, 1ui64);
      }
      v7 = v79;
      if( v40 != (_DWORD)v37 && v40 != v79 && v41 )
        MiChangePageAttribute((INT64)v19, (unsigned int)v37, 0);
      v19->Header.WaitListHead.Blink = (_LIST_ENTRY *)((unsigned __int64)v19->Header.WaitListHead.Blink & 0xFFFFFFFFFFFFFC1Fui64);
      _InterlockedOr(v76, 0);
      v55 = (signed __int64)v19->EntryListHead.Flink;
      v56 = (KiTbFlushTimeStamp & 0xF) << 56;
      v57 = _InterlockedCompareExchange64(
              (volatile signed __int64 *)&v19->EntryListHead,
              v56 | v55 & 0xF0FFFFFFFFFFFFFFui64,
              v55);
      if( v55 != v57 )
      {
        do
        {
          v58 = v57;
          v57 = _InterlockedCompareExchange64(
                  (volatile signed __int64 *)&v19->EntryListHead,
                  v56 | v57 & 0xF0FFFFFFFFFFFFFFui64,
                  v57);
        }
        while( v58 != v57 );
      }
      v20 = v83;
    }
    v59 = BYTE2(v19->EntryListHead.Blink) >> 6;
    if( v59 != v7 )
    {
      if( v59 == 1
        || v59 != 3
        && (v71 = HIBYTE(v19->EntryListHead.Flink) & 0xF,
            _InterlockedOr(v76, 0),
            v72 = ((_BYTE)KiTbFlushTimeStamp - v71) & 0xF,
            v72 <= 2)
        && ((v71 & 1) != 0 || v72 < 2) )
      {
        if( ((__int64)v19->Header.WaitListHead.Blink & 0x3E0i64) != 0 )
          MiZeroPhysicalPage(v34, 1ui64, v7);
        v19->Header.WaitListHead.Blink = v93;
        v93 = (_LIST_ENTRY *)v19;
LABEL_93:
        v36 = 1;
        goto LABEL_94;
      }
      MiChangePageAttribute((INT64)v19, (unsigned int)v7, 4);
    }
    v60 = (signed __int64)v19->EntryListHead.Flink;
    v61 = _InterlockedCompareExchange64(
            (volatile signed __int64 *)&v19->EntryListHead,
            v60 & 0xF0FFFFFFFFFFFFFFui64,
            v60);
    if( v60 != v61 )
    {
      do
      {
        v62 = v61;
        v61 = _InterlockedCompareExchange64(
                (volatile signed __int64 *)&v19->EntryListHead,
                v61 & 0xF0FFFFFFFFFFFFFFui64,
                v61);
      }
      while( v62 != v61 );
    }
    goto LABEL_93;
  }
  LODWORD(a6[1]) = 16;
  a6[0] = 1i64;
  v21 = 1;
  v22 = 17;
  v23 = v15;
  while( 1 )
  {
    v24 = v13 & _InterlockedExchangeAdd((volatile signed __int32 *)v14, 1u) | v12;
    if( (unsigned __int8)CurrentIrql < 2u )
    {
      v22 = KeGetCurrentIrql();
      __writecr8(2ui64);
    }
    if( v23 < 0x200 || v21 != 1 )
      goto LABEL_18;
    LODWORD(BugCheckParameter4) = 4;
    LargePage = (KQUEUE *)MiGetLargePage((INT64)v9, 1ui64, (unsigned int)v7, v24, BugCheckParameter4, (INT64)a6);
    if( !LargePage )
    {
      v9 = Partitiona;
LABEL_18:
      v21 = 2;
      LODWORD(BugCheckParameter4) = 4;
      LargePage = (KQUEUE *)MiGetLargePage((INT64)v9, 2ui64, (unsigned int)v7, v24, BugCheckParameter4, (INT64)a6);
      if( !LargePage )
        goto LABEL_20;
    }
    MiConvertEntireLargePageToSmall(LargePage, v21, 2u, (LARGE_INTEGER *)1, 0i64, 0i64);
LABEL_20:
    v26 = v86;
    if( (unsigned __int8)v86 < 2u )
      __writecr8(v22);
    if( !LargePage )
      goto LABEL_25;
    PfnDb = MmGetPfnDb();
    v28 = ((char *)LargePage - (char *)PfnDb) / 48;
    MiSetPfnBlink((_MMPFN *)((char *)PfnDb + 48 * v28 + 48 * MiLargePageSizes[v21] - 48), v18, 0i64);
    v18 = v28;
    v19 = LargePage;
    v7 = v79;
    v23 = v87 - (MiLargePageSizes[v21] + v83);
    v14 = v90;
    v9 = Partitiona;
    v13 = v81;
    v12 = v84;
    v83 += MiLargePageSizes[v21];
    if( v23 < 0x10 )
      break;
    LOBYTE(CurrentIrql) = v86;
  }
  v26 = v86;
LABEL_25:
  v92 = v18;
  if( HIDWORD(a6[0]) )
    MiNotifyPageHeat(a6);
  if( v26 < 2u )
  {
    v20 = v83;
    goto LABEL_32;
  }
  if( MiWorkingSetIsContended(v96) )
  {
    v20 = v83;
  }
  else
  {
    v20 = v83;
    if( !KeShouldYieldProcessor() )
    {
LABEL_32:
      v15 = v87;
      v13 = v81;
      v9 = Partitiona;
      v17 = v80;
      v16 = -1i64;
      goto LABEL_33;
    }
  }
LABEL_129:
  v74 = v79;
  *v99 = v20;
  if( (_DWORD)v82 )
    MiPerformFinalZeroing((UINT64 *)v109, (unsigned int)v82, (unsigned int)v74);
  if( v93 )
    MiChangePageAttributeBatch((INT64)v93, (_BYTE *)(unsigned int)v74, ZeroPte);
  return(_MMPFN *)v19;
}

Referenced by:

MiCreateSharedZeroPages
MiGetClusterPage
MiGetHardFaultPages
MiPfPrepareSequentialReadList
MiResolvePageFileFault
MiResolvePrivateZeroFault