MiProtectEnclavePages

NTSTATUS __stdcall MiProtectEnclavePages(
        PVOID StartingAddress,
        PVOID EndingAddress,
        UINT64 ProtectionMask,
        UINT64 EnclaveFlags,
        UINT64 *CapturedOldProtect,
        PVOID *ReturnedBaseAddress,
        UINT64 *ReturnedRegionSize){
  UINT64 v10; 
  int v11; 
  __int64 v12; 
  char *v13; 
  NTSTATUS result; 
  _QWORD *v15; 
  unsigned int v16; 
  unsigned int v17; 
  int v18; 
  _MMPTE *PteBase; 
  _XSTATE_CONFIGURATION *v20; 
  UINT64 v21; 
  unsigned __int64 v22; 
  unsigned __int64 v23; 
  unsigned int v24; 
  unsigned int v25; 
  VOID *v26; 
  UINT8 v27; 
  unsigned __int64 v28; 
  unsigned __int64 v29; 
  int v30; 
  UINT64 v31; 
  UINT64 v32; 
  UINT64 v33; 
  UINT64 v34; 
  UINT64 v35; 
  UINT64 v36; 
  __int64 v37; 
  NTSTATUS v38; 
  UINT64 v39; 
  unsigned __int64 v40; 
  UINT64 Flags; 
  UINT8 WsIrql; 
  UINT64 PageTableVirtualAddress; 
  NTSTATUS v44; 
  int v45; 
  unsigned int v46; 
  _MMSUPPORT_FULL *p_Vm; 
  UINT64 v48; 
  VOID *Va; 
  VOID *a2; 
  UINT64 v51; 
  INT64 v52; 
  UINT64 v53; 
  unsigned __int64 v54; 
  char *v55; 
  __int64 v56; 
  unsigned __int64 v57; 
  _QWORD *v58; 
  _DWORD *v59; 
  unsigned __int64 *v60; 
  _MI_TB_FLUSH_LIST TbFlushList[48]; 
  unsigned int a3; 
  _DWORD *v63; 
  UINT64 *v64; 
  _QWORD *v65; 

  v52 = ProtectionMask;
  v59 = v63;
  v60 = v64;
  v10 = EnclaveFlags;
  v58 = v65;
  v53 = EnclaveFlags;
  memset(TbFlushList, 0i64, 0xB8u);
  v11 = *(_DWORD *)(ProtectionMask + 64);
  if( (v11 & 1) != 0 )
  {
    v16 = (unsigned int)ReturnedRegionSize;
    LOBYTE(v17) = 0;
    v18 = a3 & 0x20000000;
    if( (a3 & 0x20000000) != 0 )
    {
      if( (a3 & 0x90000000) != 0 )
        return -1073741755;
    }
    else
    {
      if( (v11 & 2) == 0 || (*(_DWORD *)(v52 + 72) & 1) == 0 )
        return -1073741800;
      if( (a3 & 0x80000000) != 0 )
      {
        if( a3 == 0x80000000 && !(_DWORD)ReturnedBaseAddress )
        {
          LOBYTE(v17) = 8;
          goto LABEL_30;
        }
        return -1073741755;
      }
      if( (a3 & 0x10000000) != 0 )
      {
        if( a3 != 0x10000000 || (_DWORD)ReturnedBaseAddress )
          return -1073741755;
        LOBYTE(v17) = 0x80;
        goto LABEL_30;
      }
    }
    if( (unsigned int)ReturnedRegionSize > 7 && (_DWORD)ReturnedRegionSize != 24
      || ((unsigned __int8)ReturnedRegionSize & 5) == 5 )
    {
      return -1073741755;
    }
    if( (_DWORD)ReturnedRegionSize == 24 )
    {
      if( v18 )
        return -1073741755;
    }
    else
    {
      v17 = ((unsigned __int8)ReturnedRegionSize & 4 | 2u) >> 1;
      if( ((unsigned __int8)ReturnedRegionSize & 2) != 0 )
        LOBYTE(v17) = v17 | 4;
    }
LABEL_30:
    PteBase = MmGetPteBase();
    v20 = (_XSTATE_CONFIGURATION *)((char *)PteBase + ((v10 >> 9) & 0x7FFFFFFFF8i64));
    v44 = 0;
    v54 = (unsigned __int64)PteBase + (((unsigned __int64)CapturedOldProtect >> 9) & 0x7FFFFFFFF8i64);
    v56 = 0xFFFFFFFFi64;
    v21 = 0i64;
    v51 = 0i64;
    a2 = (VOID *)-1i64;
    p_Vm = &KeGetCurrentThread()->ApcState.Process->Vm;
    if( !v18 )
      v16 = (unsigned __int8)ReturnedRegionSize & 2 | 4;
    TbFlushList[0] = 1;
    LOWORD(TbFlushList[1]) = 0;
    *(_QWORD *)&TbFlushList[4] = 0i64;
    TbFlushList[2] = 20;
    *(_QWORD *)&TbFlushList[6] = 0i64;
    v45 = v18 != 0 ? 2 : 4;
    LODWORD(v22) = MiMakeValidPte(v20, -1i64, v16 | 0x80000000);
    v23 = v22;
    MiLockWorkingSetShared();
    v24 = 0;
    v25 = v45;
    v26 = (VOID *)(v53 & 0xFFFFFFFFFFFFF000ui64);
    WsIrql = v27;
    v28 = v54;
    v57 = v53 & 0xFFFFFFFFFFFFF000ui64;
    v46 = 0;
    while( 1 )
    {
      Va = v26;
      v29 = (unsigned __int64)v20;
      PageTableVirtualAddress = (UINT64)v20;
      if( (unsigned __int64)v20 <= v28 )
        break;
      v38 = v44;
LABEL_69:
      if( v38 < 0 || (++v24, v46 = v24, v24 >= v25) )
      {
LABEL_73:
        MiFlushEnclaveTb(TbFlushList, a2, a3);
        v39 = v51;
        if( v51 )
          MiUnlockPageTableInternal((INT64)p_Vm, v51);
        LOBYTE(v39) = WsIrql;
        MiUnlockWorkingSetShared(&p_Vm->Instance, v39);
        if( v38 >= 0 )
        {
          v38 = 0;
          *v59 = MmProtectToValue[(unsigned int)v56];
          v40 = ((unsigned __int64)CapturedOldProtect & 0xFFFFFFFFFFFFF000ui64) - v57;
          *v60 = v57;
          *v58 = v40 + 4096;
        }
        return v38;
      }
      v21 = v51;
      v26 = (VOID *)v57;
    }
    while( 1 )
    {
      if( (v29 & 0x78) != 0 || (_XSTATE_CONFIGURATION *)v29 == v20 )
        goto LABEL_44;
      LOBYTE(v30) = MiWorkingSetIsContended((INT64)p_Vm);
      if( v30 || (unsigned int)KeShouldYieldProcessor() )
        goto LABEL_40;
      if( v21 )
        break;
LABEL_46:
      MiFlushEnclaveTb(TbFlushList, a2, a3);
      a2 = (VOID *)-1i64;
      if( v21 )
        MiUnlockPageTableInternal((INT64)p_Vm, v21);
      v51 = (UINT64)MmGetPteBase() + ((PageTableVirtualAddress >> 9) & 0x7FFFFFFFF8i64);
      LODWORD(Flags) = 0;
      MiMakeSystemAddressValid(
        (VOID *)PageTableVirtualAddress,
        0i64,
        (*(_DWORD *)(v52 + 48) >> 12) & 0x3F,
        WsIrql,
        Flags);
      v29 = PageTableVirtualAddress;
LABEL_49:
      if( v46 )
      {
        if( v46 == v45 - 1 )
        {
          LODWORD(v35) = MI_READ_PTE_LOCK_FREE(v29);
          v48 = v35;
          v36 = v35;
          MiPteInShadowRange((UINT64)&v48);
          v37 = (v36 >> 12) & 0xFFFFFFFFFi64;
          MiUpdateEnclavePfnProtection(&MmGetPfnDb()[v37], v16);
          v23 = (v37 << 12) | v23 & 0xFFFF000000000FFFui64;
          LODWORD(Flags) = 0;
          MiWriteEnclavePte(PageTableVirtualAddress, v23, v52, 1i64, Flags);
          if( (MiFlags & 0x100) == 0 && (MiFlags & 0x200) == 0 || MI_TIGHTER_PERMISSIONS((_MMPTE)v48, (_MMPTE)v23) )
            MiInsertTbFlushEntry(TbFlushList, Va, 1ui64, 0i64);
          a2 = Va;
        }
        else if( v46 == 1 )
        {
          v44 = KeCanChangeEnclavePageProtection();
          if( v44 < 0 )
          {
            v28 = v54;
            v38 = -1073741800;
            v44 = -1073741800;
LABEL_68:
            v25 = v45;
            v24 = v46;
            goto LABEL_69;
          }
        }
        else
        {
          KeChangeEnclavePageProtection((__int64)Va, v17);
          KeTrackEnclaveTbFlush();
        }
        goto LABEL_63;
      }
      LODWORD(v32) = MI_READ_PTE_LOCK_FREE(v29);
      v48 = v32;
      v33 = v32;
      if( (v32 & 1) == 0 )
      {
        v38 = -1073741800;
        goto LABEL_73;
      }
      v34 = PageTableVirtualAddress;
      if( (_XSTATE_CONFIGURATION *)PageTableVirtualAddress == v20 )
      {
        MiPteInShadowRange((UINT64)&v48);
        v56 = (*((_DWORD *)&MmGetPfnDb()[(v33 >> 12) & 0xFFFFFFFFFi64].3 + 4) >> 5) & 0x1F;
LABEL_63:
        v34 = PageTableVirtualAddress;
      }
      Va = (char *)Va + 4096;
      v29 = v34 + 8;
      v28 = v54;
      PageTableVirtualAddress = v29;
      if( v29 > v54 )
      {
        v38 = v44;
        goto LABEL_68;
      }
      v21 = v51;
    }
    if( (unsigned int)MiPageTableLockIsContended((__int64)p_Vm, v21) )
    {
LABEL_40:
      MiFlushEnclaveTb(TbFlushList, a2, a3);
      a2 = (VOID *)-1i64;
      if( v21 )
      {
        MiUnlockPageTableInternal((INT64)p_Vm, v21);
        v21 = 0i64;
        v51 = 0i64;
      }
      LOBYTE(v31) = WsIrql;
      MiUnlockWorkingSetShared(&p_Vm->Instance, v31);
      MiLockWorkingSetShared();
    }
    v29 = PageTableVirtualAddress;
LABEL_44:
    if( v21 && (v29 & 0xFFF) != 0 )
      goto LABEL_49;
    goto LABEL_46;
  }
  v12 = *(_QWORD *)(ProtectionMask + 72);
  v13 = (char *)CapturedOldProtect - v10 + 1;
  v55 = v13;
  if( *(_BYTE *)(v12 + 76) && (a3 & 0x20000000) != 0 )
  {
    *v63 = 4;
    result = 0;
LABEL_7:
    v15 = v58;
    *v64 = v10;
    *v15 = v13;
    return result;
  }
  result = VslDebugProtectSecureProcessMemory(
             (__int64)StartingAddress,
             (__int64)EndingAddress,
             (__int64 *)&v53,
             (__int64 *)&v55,
             (unsigned int)ReturnedBaseAddress,
             v63);
  if( result >= 0 )
  {
    v13 = v55;
    v10 = v53;
    goto LABEL_7;
  }
  return result;
}

Referenced by:

MmProtectVirtualMemory