PspGetSetContextInternal

VOID __fastcall PspGetSetContextInternal(_KAPC *Apc, VOID *OperationType){
  __int64 v2; 
  _CONTEXT *v5; 
  _ETHREAD *CurrentThread; 
  _KTRAP_FRAME *TrapFrame; 
  _QWORD *v8; 
  void(__fastcall *KernelRoutine)(_KAPC *, void(__fastcall **)(void *, void *, void *), void **, void **, void **); 
  INT64 v10; 
  INT64 v11; 
  _QWORD *i; 
  char v13; 
  _DWORD *Object; 
  INT64 v15; 
  signed int v16; 
  void(__fastcall *v17)(_KAPC *, void(__fastcall **)(void *, void *, void *), void **, void **, void **); 
  unsigned int v18; 
  signed int v19; 
  signed int v20; 
  _KAPC *v21; 
  INT64 CurrentUmsTeb; 
  CHAR DoesTebMatchThread; 
  INT64 v24; 
  CHAR v25; 
  signed int v26; 
  signed int updated; 
  _QWORD *j; 
  void(__fastcall *v29)(_KAPC *, void(__fastcall **)(void *, void *, void *), void **, void **, void **); 
  INT64 v30; 
  INT64 v31; 
  INT64 v32; 
  UINT64 v33; 
  UINT64 v34; 
  INT64 v35; 
  INT64 v36; 
  _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY *v37; 
  _ETHREAD **p_Thread; 
  void(__fastcall *v39)(_KAPC *, void(__fastcall **)(void *, void *, void *), void **, void **, void **); 
  INT64 v40; 
  INT64 v41; 
  INT64 v42; 
  INT64 v43; 
  INT64 v44; 
  UINT64 v45; 
  INT64 v46; 
  CHAR *v47; 
  INT64 v48; 
  _QWORD *v49; 
  char v50[3]; 
  int v51; 
  UINT64 HighLimit; 
  UINT64 LowLimit; 
  _KTRAP_FRAME *v54; 
  VOID *v55; 
  UINT64 v56[2]; 
  __int64 v57; 
  __int64 v58; 
  _INVERTED_FUNCTION_TABLE_ENTRY FunctionTableInfo; 
  INT64 v60[2]; 
  __int64 v61; 
  _KERNEL_STACK_SEGMENT LastSegment; 
  INT64 result[18]; 
  char v64; 
  UINT64 StackFrame; 
  char v66; 
  char v67; 
  char v68; 
  char v69; 
  char v70; 
  char v71; 
  char v72; 
  UINT64 ControlPc; 
  char v74; 
  char v75; 
  char v76; 
  char v77; 
  char v78; 
  char v79; 
  char v80; 
  char v81; 
  char v82; 
  char v83; 
  _MDL MemoryDescriptorList; 
  INT64 v85; 
  INT64 v86; 

  v49 = (_QWORD *)v2;
  v55 = OperationType;
  v57 = v2;
  v56[1] = (UINT64)Apc;
  memset(&MemoryDescriptorList.AllocationProcessorNumber, 0, 20);
  v85 = 0i64;
  v86 = 0i64;
  v54 = 0i64;
  v58 = 0i64;
  HighLimit = 0i64;
  LowLimit = 0i64;
  v50[0] = 0;
  v51 = 0;
  v5 = (_CONTEXT *)&Apc[1].Reserved[1];
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  if( !Apc[1].Type )
  {
    TrapFrame = CurrentThread->Tcb.TrapFrame;
    if( !TrapFrame || TrapFrame->SegCs != 16 )
    {
      Apc[1].SpareLong0 = -1073741823;
      v8 = (_QWORD *)v2;
LABEL_59:
      v21 = Apc;
      goto LABEL_60;
    }
    goto LABEL_29;
  }
  if( (CurrentThread->SameThreadPassiveFlags & 0x200) != 0 )
  {
    KernelRoutine = Apc[1].KernelRoutine;
    MemoryDescriptorList.Next = 0i64;
    MemoryDescriptorList.Size = 8 * (((unsigned __int16)(((unsigned __int16)KernelRoutine & 0xFFF) + 5327) >> 12) + 6);
    MemoryDescriptorList.MdlFlags = 0;
    MemoryDescriptorList.StartVa = (void *)((unsigned __int64)KernelRoutine & 0xFFFFFFFFFFFFF000ui64);
    MemoryDescriptorList.ByteOffset = (unsigned __int16)KernelRoutine & 0xFFF;
    MemoryDescriptorList.ByteCount = 1232;
    MmProbeAndLockPages(&MemoryDescriptorList, 0, IoModifyAccess);
    Apc[1].SpareLong0 = VslGetSetSecureContext((INT64)OperationType, (INT64)Apc[1].KernelRoutine, v85, v86);
    MmUnlockPages((INT64)&MemoryDescriptorList, v10, v11);
    goto LABEL_58;
  }
  for( i = CurrentThread->Tcb.InitialStack; (i[1] & 1) != 0; i = (_QWORD *)i[5] )
    ;
  TrapFrame = (_KTRAP_FRAME *)(i - 50);
  v13 = CurrentThread->Tcb.gap0[3];
  if( (v13 & 0x40) == 0 || (Object = CurrentThread->Tcb.WaitBlock[3].Object, (Object[20] & 4) == 0) )
  {
    if( v13 < 0 )
    {
      CurrentUmsTeb = KeGetCurrentUmsTeb(CurrentThread);
      DoesTebMatchThread = KeDoesTebMatchThread((INT64)CurrentThread, CurrentUmsTeb);
      v25 = DoesTebMatchThread;
      if( v55 )
      {
        updated = KeUpdatePrimaryThreadContext(v24, (_CONTEXT *)Apc[1].KernelRoutine);
        Apc[1].SpareLong0 = updated;
        if( !v25 || updated < 0 )
          goto LABEL_58;
      }
      else if( !DoesTebMatchThread )
      {
        v26 = KeBuildPrimaryThreadContext(v24, 0i64, (INT64)Apc[1].KernelRoutine, 1i64, 0i64, 0i64);
LABEL_26:
        Apc[1].SpareLong0 = v26;
        goto LABEL_58;
      }
    }
LABEL_29:
    if( (Apc[1].SpareByte0 & 2) != 0 )
    {
      if( RtlpGetStackLimits(&LowLimit, &HighLimit) )
      {
        memset(&LastSegment, 0, sizeof(LastSegment));
        FunctionTableInfo = *(_INVERTED_FUNCTION_TABLE_ENTRY *)&byte_140E00020;
        RtlpCaptureContext((INT64)result, v30, v31, v32, v40, v42, v44, v46, v48);
        v5->_Rsp = (unsigned __int64)&v64;
        v5->_Rsi = (unsigned __int64)&v66;
        v5->_Rdi = (unsigned __int64)&v67;
        v5->_R8 = (unsigned __int64)&v68;
        v5->_R13 = (unsigned __int64)&v69;
        v5->_R14 = (unsigned __int64)&v70;
        v5->_R15 = (unsigned __int64)&v71;
        v5->_Rip = (unsigned __int64)&v72;
        *(_QWORD *)&v5->ContextFlags = &v74;
        *(_QWORD *)&v5->SegCs = &v75;
        *(_QWORD *)&v5->SegGs = &v76;
        v5->Dr0 = (unsigned __int64)&v77;
        v5->Dr1 = (unsigned __int64)&v78;
        v5->Dr2 = (unsigned __int64)&v79;
        v5->Dr3 = (unsigned __int64)&v80;
        v5->Dr6 = (unsigned __int64)&v81;
        v5->Dr7 = (unsigned __int64)&v82;
        v5->_Rax = (unsigned __int64)&v83;
        v5->_Rbp = (unsigned __int64)&StackFrame;
        v33 = StackFrame;
        while( 1 )
        {
          v34 = ControlPc;
          if( ControlPc <= 0xFFFF800000000000ui64
            || !(unsigned __int8)RtlpIsFrameInBoundsEx(&LowLimit, v33, &HighLimit, &LastSegment) )
          {
            break;
          }
          v37 = RtlpLookupFunctionEntryForStackWalks(v34, &FunctionTableInfo, v35, v36, v41, v43, v45, v47);
          if( v37 )
          {
            if( (int)RtlpVirtualUnwind(
                        0i64,
                        (__int64)FunctionTableInfo.ImageBase,
                        v34,
                        (__int64)v37,
                        (__int64)result,
                        (__int64)v50,
                        (__int64)&v58,
                        (__int64)&v54,
                        (__int64)v5,
                        (__int64)&LowLimit,
                        (__int64)&HighLimit,
                        0i64) < 0 )
            {
              if( (_BYTE)KdDebuggerEnabled && !(_BYTE)KdDebuggerNotPresent )
                NT_ASSERT(
                  "*** Ps:  Context unwind failure
    A stack frame did not unwind properly
    Perform a stack trace to"
                  " find the culprit
    Use gh to continue!!
");
              goto LABEL_57;
            }
            v33 = StackFrame;
          }
          else
          {
            if( !FunctionTableInfo.ImageBase )
              goto LABEL_57;
            ControlPc = *(_QWORD *)StackFrame;
            v33 = StackFrame + 8;
            StackFrame += 8i64;
          }
          if( v54 == TrapFrame )
            goto LABEL_33;
        }
        if( (_BYTE)KdDebuggerEnabled && !(_BYTE)KdDebuggerNotPresent )
          NT_ASSERT(
            "*** Ps:  Context unwind failure
    A stack frame did not unwind properly
    Perform a stack trace to find "
            "the culprit
    Use gh to continue!!
");
      }
LABEL_57:
      Apc[1].SpareLong0 = -1073741823;
      goto LABEL_58;
    }
    for( j = CurrentThread->Tcb.InitialStack; (j[1] & 1) != 0; j = (_QWORD *)j[5] )
      ;
    v5->_Rsp = (unsigned __int64)(j - 58);
    v5->_Rdi = (unsigned __int64)(j - 56);
    v5->_R8 = (unsigned __int64)(j - 57);
    v5->_R13 = (unsigned __int64)(j - 55);
    v5->_R14 = (unsigned __int64)(j - 54);
    v5->_R15 = (unsigned __int64)(j - 53);
    v5->_Rip = (unsigned __int64)(j - 52);
    *(_QWORD *)&v5->ContextFlags = j - 84;
    *(_QWORD *)&v5->SegCs = j - 82;
    *(_QWORD *)&v5->SegGs = j - 80;
    v5->Dr0 = (unsigned __int64)(j - 78);
    v5->Dr1 = (unsigned __int64)(j - 76);
    v5->Dr2 = (unsigned __int64)(j - 74);
    v5->Dr3 = (unsigned __int64)(j - 72);
    v5->Dr6 = (unsigned __int64)(j - 70);
    v5->Dr7 = (unsigned __int64)(j - 68);
    v5->_Rax = (unsigned __int64)(j - 66);
    v5->_Rsi = (unsigned __int64)&TrapFrame->_Rbp;
LABEL_33:
    v29 = Apc[1].KernelRoutine;
    if( !v55 )
    {
      if( (*((_DWORD *)v29 + 12) & 0x100008) == 1048584 && Apc[1].Type == 1 )
        _fxsave((char *)v29 + 256);
      if( CurrentThread->SetContextState && Apc[1].Type == 1 )
      {
        v39 = Apc[1].KernelRoutine;
        PspGetContext(TrapFrame, v5);
        if( (CurrentThread->Tcb.gap0[3] & 8) != 0 )
        {
          RtlCopyContext(
            (_X86_NT5_CONTEXT *)v39,
            *((unsigned int *)v39 + 12),
            (_X86_NT5_CONTEXT *)CurrentThread->SetContextState);
          Apc[1].SpareLong0 = 0;
          goto LABEL_58;
        }
      }
      else
      {
        PspGetContext(TrapFrame, v5);
      }
      Apc[1].SpareLong0 = 0;
      goto LABEL_58;
    }
    if( Apc[1].Type != 1
      || (v56[0] = 0i64, v26 = KeVerifyContextXStateCetU((__int64)CurrentThread, v29, v56), v26 >= 0)
      && ((Apc[1].SpareByte0 & 4) == 0
       || (*(_OWORD *)v60 = 0i64,
           v61 = 0i64,
           LODWORD(v60[0]) = 3,
           v26 = KeVerifyContextIpForUserCet((INT64)CurrentThread, (INT64)Apc[1].KernelRoutine, v60, v56),
           v26 >= 0)) )
    {
      if( CurrentThread->SetContextState
        && Apc[1].Type == 1
        && ((Apc[1].SpareByte0 & 2) != 0 || (CurrentThread->Tcb.gap0[3] & 8) != 0) )
      {
        PspSetContextState((INT64)CurrentThread, (_CONTEXT *)Apc[1].KernelRoutine);
        Apc[1].SpareLong0 = 0;
      }
      else
      {
        PspSetContext((__int64)TrapFrame, (__int64)v5, (__int64)Apc[1].KernelRoutine, Apc[1].Type);
        Apc[1].SpareLong0 = 0;
      }
      goto LABEL_58;
    }
    goto LABEL_26;
  }
  v15 = *(_QWORD *)Object;
  v16 = PspRundownUmsThreadForApcDelivery(CurrentThread, &v51, *(_QWORD *)Object, 0);
  Apc[1].SpareLong0 = v16;
  if( v16 < 0 )
  {
LABEL_58:
    v8 = v49;
    goto LABEL_59;
  }
  v17 = Apc[1].KernelRoutine;
  if( OperationType )
  {
    v18 = PspSetUmsThreadContext((__int64)CurrentThread, (INT64)Apc[1].KernelRoutine, &v51);
  }
  else
  {
    v18 = 0;
    if( (v51 & 2) != 0 )
      v18 = KeCopyContextFromUmsContext((_CONTEXT *)v17, *(_QWORD *)CurrentThread->Tcb.WaitBlock[3].Object);
    else
      KeCopyContextFromUch((_CONTEXT *)v17, (INT64)CurrentThread->Tcb.WaitBlock[3].SparePtr);
  }
  Apc[1].SpareLong0 = v18;
  v19 = KeClearUmsThreadKernelLock(v15);
  if( v19 < 0 )
    Apc[1].SpareLong0 = v19;
  if( (v51 & 8) != 0 )
  {
    v20 = KeUpdateUmsThreadState(v15, 0i64, 1);
    v21 = Apc;
    if( v20 < 0 )
    {
      Apc[1].SpareLong0 = v20;
      v8 = v49;
      goto LABEL_60;
    }
  }
  else
  {
    v21 = Apc;
  }
  v8 = v49;
LABEL_60:
  p_Thread = &v21[1].Thread;
  if( (Apc[1].SpareByte0 & 1) == 0 )
    p_Thread = 0i64;
  *v8 = p_Thread;
}

Referenced by:

PspGetSetContextSpecialApc