KeFixUserSwitchContext

VOID **__fastcall KeFixUserSwitchContext(INT64 a1, INT64 a2, INT64 a3, _CONTEXT *a4){
  VOID **result; 
  VOID *v5; 
  unsigned __int64 v8; 
  VOID *v9; 
  bool v10; 
  unsigned __int64 Rip; 
  bool v12; 
  void *retaddr; 

  result = &retaddr;
  v5 = (VOID *)KeUmsThreadYield;
  v8 = KeUmsExecuteYieldThreadEnd;
  if( a3 )
  {
    result = *(VOID ***)(a3 + 80);
    v9 = result[45];
    if( (unsigned __int64)v9 >= KeExecuteUmsThread )
    {
      v10 = (unsigned __int64)v9 <= KeUmsThreadYield;
      if( (unsigned __int64)v9 >= KeUmsThreadYield )
        goto LABEL_6;
      LODWORD(result) = KiRestoreUchFromUmsContext(a1, a3, a2);
    }
    v10 = v9 <= v5;
LABEL_6:
    if( !v10 && (unsigned __int64)v9 < v8 )
    {
      result = *(VOID ***)(a3 + 80);
      result[45] = v5;
    }
    return result;
  }
  Rip = a4->_Rip;
  if( Rip < KeExecuteUmsThread )
    goto LABEL_12;
  v12 = Rip <= KeUmsThreadYield;
  if( Rip < KeUmsThreadYield )
  {
    LODWORD(result) = KeCopyContextFromUmsContext(a4, a2);
LABEL_12:
    v12 = Rip <= (unsigned __int64)v5;
  }
  if( !v12 && Rip < v8 )
    a4->_Rip = (unsigned __int64)v5;
  return result;
}

Referenced by:

KiSwapToUmsThread
PspDisassociateUmsThreadFromPrimary