PsCallEnclave

INT64 __fastcall PsCallEnclave(INT64 a1, INT64 a2, INT64 a3, INT64 *a4){
  _ETHREAD *CurrentThread; 
  INT64 result; 
  __int64 v7; 
  INT64 v8; 
  UINT64 v9; 
  char *v10; 
  int EnclaveReturnFrame; 
  INT64 v12; 
  INT64 v13; 
  INT64 v14; 
  volatile signed __int64 *v15; 
  INT64 v16; 
  int v17; 
  PVOID v18; 
  int v19; 
  PVOID v20; 
  unsigned int v21; 
  int v22; 
  INT64 v23; 
  INT64 v24; 
  UINT64 v25; 
  INT64 v26; 
  int v27; 
  _QWORD *v28; 
  bool v29; 
  _QWORD *v30; 
  _QWORD *a6; 
  char a9; 
  char v34; 
  PVOID v35; 
  INT64 v36; 
  INT64 a5; 
  int v38; 
  PVOID P; 
  INT64 a7; 
  INT64 v41; 
  unsigned __int64 *v42; 
  INT64 v43; 
  INT64 v44; 
  _QWORD v45[10]; 
  UINT64 a2a; 
  INT64 v47; 
  NTSTATUS ExitStatus; 
  INT64 *v49; 
  v49 = a4;
  ExitStatus = a3;
  v47 = a2;
  a2a = a1;
  a5 = 0i64;
  v35 = 0i64;
  a7 = 0i64;
  v41 = 0i64;
  a9 = 0;
  v45[0] = 0i64;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  v45[1] = CurrentThread;
  v44 = 0i64;
  if( *((_BYTE *)CurrentThread + 562) != 1 )
    return 3221225711i64;
  if( a2a )
  {
    if( a2 )
      return 3221225712i64;
  }
  else if( a2 )
  {
    goto LABEL_9;
  }
  if( (ExitStatus & 0xFFFFFFFE) != 0 )
    return 3221225713i64;
LABEL_9:
  v7 = 0x7FFFFFFF0000i64;
  if( (unsigned __int64)a4 < 0x7FFFFFFF0000i64 )
    v7 = (__int64)a4;
  *(_QWORD *)v7 = *(_QWORD *)v7;
  a5 = *a4;
  v8 = *((_QWORD *)CurrentThread + 23);
  if( a2 )
  {
    result = PspSelectVsmEnclaveByNumber(v8, a2, (INT64 *)&v35);
    v9 = a2a;
  }
  else
  {
    v9 = a2a;
    result = MmSelectVsmEnclaveByAddress(v8, a2a, &v35);
  }
  if( (int)result < 0 )
    return result;
  v10 = (char *)v35;
  if( !*((_DWORD *)v35 + 10) )
  {
    EnclaveReturnFrame = -1073741816;
    goto LABEL_93;
  }
  if( *((_BYTE *)v35 + 76) )
  {
    --*((_WORD *)CurrentThread + 242);
    v15 = (volatile signed __int64 *)(v10 + 112);
    ExAcquirePushLockExclusiveEx((UINT64)(v10 + 112), 0i64);
    v42 = (unsigned __int64 *)(v10 + 104);
    v16 = *((_QWORD *)v10 + 13);
    while( v16 )
    {
      v22 = MiHotPatchImageTreeCompare(v9, v16);
      if( v22 >= 0 )
      {
        if( v22 <= 0 )
          break;
        v16 = *(_QWORD *)(v16 + 8);
      }
      else
      {
        v16 = *(_QWORD *)v16;
      }
    }
    if( (_InterlockedExchangeAdd64(v15, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
      ExfTryToWakePushLock((volatile INT64 *)v10 + 14);
    KeAbPostRelease(v10 + 112);
    KeLeaveCriticalRegionThread((__int64)CurrentThread);
    if( !v16 )
    {
      EnclaveReturnFrame = -1073741800;
      goto LABEL_92;
    }
    v43 = v16;
    goto LABEL_61;
  }
  LODWORD(v12) = PsGetBaseTrapFrame((INT64)CurrentThread);
  v44 = v12;
  --*((_WORD *)CurrentThread + 243);
  EnclaveReturnFrame = RtlPrepareEnclaveCall(
                         v12,
                         (INT64)a4,
                         v13,
                         v14,
                         (*((_DWORD *)CurrentThread + 29) & 0x100000) != 0,
                         &v41,
                         &a7);
  KiLeaveGuardedRegionUnsafe((__int64)CurrentThread);
  if( EnclaveReturnFrame < 0 )
    goto LABEL_93;
  --*((_WORD *)CurrentThread + 242);
  v15 = (volatile signed __int64 *)(v10 + 112);
  ExAcquirePushLockExclusiveEx((UINT64)(v10 + 112), 0i64);
  v42 = (unsigned __int64 *)(v10 + 104);
  v16 = *((_QWORD *)v10 + 13);
  while( v16 )
  {
    v17 = MiHotPatchImageTreeCompare((UINT64)CurrentThread, v16);
    if( v17 >= 0 )
    {
      if( v17 <= 0 )
        break;
      v16 = *(_QWORD *)(v16 + 8);
    }
    else
    {
      v16 = *(_QWORD *)v16;
    }
  }
  if( !v16 )
  {
    v18 = 0i64;
    P = 0i64;
    if( v47 )
    {
      EnclaveReturnFrame = -1073741584;
    }
    else
    {
      v19 = *((_DWORD *)v10 + 18);
      if( v19 )
      {
        *((_DWORD *)v10 + 18) = v19 - 1;
        EnclaveReturnFrame = 0;
      }
      else
      {
        EnclaveReturnFrame = PspPrepareEnclaveThreadWait((INT64)v10, &P);
        v18 = P;
      }
      if( EnclaveReturnFrame >= 0 && !v18 )
      {
LABEL_45:
        v16 = *((_QWORD *)v10 + 16);
        *((_QWORD *)v10 + 16) = *(_QWORD *)v16;
        *(_QWORD *)(v16 + 24) = CurrentThread;
        *(_QWORD *)(v16 + 32) = 0i64;
        goto LABEL_46;
      }
    }
    if( (_InterlockedExchangeAdd64(v15, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
      ExfTryToWakePushLock((volatile INT64 *)v10 + 14);
    KeAbPostRelease(v10 + 112);
    KeLeaveCriticalRegionThread((__int64)CurrentThread);
    if( EnclaveReturnFrame < 0 )
    {
LABEL_92:
      v10 = (char *)v35;
      goto LABEL_93;
    }
    v20 = P;
    v21 = KeWaitForSingleObject(
            (char *)P + 16,
            Executive,
            1,
            0,
            (PLARGE_INTEGER)((unsigned __int64)v45 & -(__int64)((ExitStatus & 1) != 0)));
    v10 = (char *)v35;
    if( v21 )
      EnclaveReturnFrame = PspRemoveEnclaveThreadWait((INT64)v35, (INT64 *)v20, v21);
    else
      EnclaveReturnFrame = *((_DWORD *)v20 + 10);
    ExFreePoolWithTag(v20, 0);
    if( EnclaveReturnFrame )
    {
      if( (unsigned int)(EnclaveReturnFrame - 257) > 1
        && EnclaveReturnFrame != -1073740526
        && EnclaveReturnFrame != 192 )
      {
        EnclaveReturnFrame = -1073741749;
      }
      goto LABEL_93;
    }
    --*((_WORD *)CurrentThread + 242);
    ExAcquirePushLockExclusiveEx((UINT64)v15, 0i64);
    goto LABEL_45;
  }
LABEL_46:
  v43 = v16;
  if( (_InterlockedExchangeAdd64(v15, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
    ExfTryToWakePushLock(v15);
  KeAbPostRelease((PVOID)v15);
  KeLeaveCriticalRegionThread((__int64)CurrentThread);
  if( *(_DWORD *)(v16 + 36) == -1 )
  {
    EnclaveReturnFrame = -1073741670;
    goto LABEL_92;
  }
LABEL_61:
  --*((_WORD *)CurrentThread + 243);
  *((_DWORD *)CurrentThread + 325) |= 0x200u;
  LODWORD(v36) = *(_DWORD *)(v16 + 32);
  v10 = (char *)v35;
  EnclaveReturnFrame = VslCallEnclave(
                         (INT64)v35,
                         &v36,
                         (INT64 *)&a2a,
                         (unsigned int)ExitStatus,
                         &a5,
                         &v41,
                         &a7,
                         &ExitStatus,
                         &a9);
  v38 = EnclaveReturnFrame;
  *((_DWORD *)CurrentThread + 325) &= ~0x200u;
  KiLeaveGuardedRegionUnsafe((__int64)CurrentThread);
  if( a9 )
    ZwTerminateProcess((PVOID)0xFFFFFFFFFFFFFFFFi64, (unsigned int)ExitStatus);
  if( EnclaveReturnFrame < 0 )
  {
    if( !v47 )
      goto LABEL_87;
    v25 = a2a;
    if( v47 )
      v25 = 0i64;
    a2a = v25;
  }
  v26 = a2a;
  if( !a2a )
  {
    *v49 = a5;
    if( v47 )
    {
      if( (*(_DWORD *)(v16 + 36))-- == 1 )
      {
        --*((_WORD *)CurrentThread + 242);
        ExAcquirePushLockExclusiveEx((UINT64)(v10 + 112), 0i64);
        RtlAvlRemoveNode((unsigned __int64 *)v10 + 13, (__int64 *)v16);
        if( (_InterlockedExchangeAdd64((volatile signed __int64 *)v10 + 14, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
          ExfTryToWakePushLock((volatile INT64 *)v10 + 14);
        KeAbPostRelease(v10 + 112);
        KeLeaveCriticalRegionThread((__int64)CurrentThread);
        v10 = (char *)v35;
      }
    }
    goto LABEL_87;
  }
  --*((_WORD *)CurrentThread + 243);
  LODWORD(a6) = ExitStatus;
  EnclaveReturnFrame = RtlCreateEnclaveReturnFrame(
                         v44,
                         v23,
                         v24,
                         *((_QWORD *)v10 + 1),
                         v26,
                         (UINT64)a6,
                         v41,
                         a7,
                         a5,
                         (*((_DWORD *)CurrentThread + 29) & 0x100000) != 0);
  KiLeaveGuardedRegionUnsafe((__int64)CurrentThread);
  if( v47 )
    goto LABEL_87;
  v27 = *(_DWORD *)(v16 + 36);
  if( v27 )
    goto LABEL_81;
  *(_DWORD *)(v16 + 32) = v36;
  --*((_WORD *)CurrentThread + 242);
  ExAcquirePushLockExclusiveEx((UINT64)v15, 0i64);
  v28 = (_QWORD *)*v42;
  v29 = 0;
  v34 = 0;
  if( !v28 )
    goto LABEL_78;
  while( (int)MiHotPatchImageTreeCompare((UINT64)CurrentThread, (INT64)v28) >= 0 )
  {
    v30 = (_QWORD *)v28[1];
    if( !v30 )
    {
      v29 = 1;
      v34 = 1;
      goto LABEL_78;
    }
LABEL_76:
    v28 = v30;
  }
  v30 = (_QWORD *)*v28;
  if( *v28 )
    goto LABEL_76;
  v29 = 0;
  v34 = 0;
LABEL_78:
  RtlAvlInsertNodeEx(v42, (__int64)v28, v29, (_QWORD *)v16);
  if( (_InterlockedExchangeAdd64(v15, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
    ExfTryToWakePushLock(v15);
  KeAbPostRelease((PVOID)v15);
  KeLeaveCriticalRegionThread((__int64)CurrentThread);
  v27 = *(_DWORD *)(v16 + 36);
  v10 = (char *)v35;
LABEL_81:
  *(_DWORD *)(v16 + 36) = v27 + 1;
LABEL_87:
  if( !v10[76] && !*(_DWORD *)(v16 + 36) )
  {
    --*((_WORD *)CurrentThread + 242);
    ExAcquirePushLockExclusiveEx((UINT64)(v10 + 112), 0i64);
    *(_QWORD *)v16 = *((_QWORD *)v10 + 16);
    *((_QWORD *)v10 + 16) = v16;
    PspReleaseEnclaveThread((INT64)v10);
    if( (_InterlockedExchangeAdd64((volatile signed __int64 *)v10 + 14, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
      ExfTryToWakePushLock((volatile INT64 *)v10 + 14);
    KeAbPostRelease(v10 + 112);
    KeLeaveCriticalRegionThread((__int64)CurrentThread);
    goto LABEL_92;
  }
LABEL_93:
  PsDereferenceVsmEnclave(v10);
  return(unsigned int)EnclaveReturnFrame;
}

Referenced by:

NtCallEnclave