PspGetSetContextInternal

VOID __fastcall PspGetSetContextInternal(KAPC *Apc, VOID *OperationType){
  __int64 v2; 
  void(__fastcall **p_RundownRoutine)(_KAPC *); 
  _ETHREAD *CurrentThread; 
  INT64 v7; 
  _QWORD *v8; 
  void(__fastcall *KernelRoutine)(_KAPC *, void(__fastcall **)(void *, void *, void *), void **, void **, void **); 
  __int64 i; 
  char v11; 
  __int64 v12; 
  INT64 v13; 
  signed int v14; 
  void(__fastcall *v15)(_KAPC *, void(__fastcall **)(void *, void *, void *), void **, void **, void **); 
  unsigned int v16; 
  signed int v17; 
  signed int v18; 
  KAPC *v19; 
  unsigned __int64 CurrentUmsTeb; 
  CHAR DoesTebMatchThread; 
  INT64 v22; 
  CHAR v23; 
  signed int v24; 
  signed int updated; 
  __int64 j; 
  void(__fastcall *v27)(_KAPC *, void(__fastcall **)(void *, void *, void *), void **, void **, void **); 
  INT64 v28; 
  INT64 v29; 
  INT64 v30; 
  UINT64 v31; 
  PVOID v32; 
  UINT64 *v33; 
  _ETHREAD **p_Thread; 
  _CONTEXT *v35; 
  INT64 v36; 
  INT64 v37; 
  INT64 v38; 
  INT64 v39; 
  INT64 v40; 
  _QWORD *v41; 
  char v42[3]; 
  int a2; 
  UINT64 HighLimit; 
  UINT64 LowLimit; 
  __int64 v46; 
  VOID *v47; 
  _QWORD a3[2]; 
  __int64 v49; 
  __int64 v50; 
  INT64 v51[2]; 
  __int64 v52; 
  INT64 v53[2]; 
  __int64 v54; 
  UINT64 v55[2]; 
  __int128 v56; 
  INT64 result[18]; 
  char v58; 
  UINT64 v59; 
  char v60; 
  char v61; 
  char v62; 
  char v63; 
  char v64; 
  char v65; 
  char v66; 
  PVOID EndingAddress; 
  char v68; 
  char v69; 
  char v70; 
  char v71; 
  char v72; 
  char v73; 
  char v74; 
  char v75; 
  char v76; 
  char v77; 
  struct _MDL MemoryDescriptorList; 
  INT64 v79; 
  INT64 v80; 
  v41 = (_QWORD *)v2;
  v47 = OperationType;
  v49 = v2;
  a3[1] = Apc;
  memset(&MemoryDescriptorList.AllocationProcessorNumber, 0, 20);
  v79 = 0i64;
  v80 = 0i64;
  v46 = 0i64;
  v50 = 0i64;
  HighLimit = 0i64;
  LowLimit = 0i64;
  v42[0] = 0;
  a2 = 0;
  p_RundownRoutine = &Apc[1].RundownRoutine;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  if( !Apc[1].Type )
  {
    v7 = *((_QWORD *)CurrentThread + 18);
    if( !v7 || *(_WORD *)(v7 + 368) != 16 )
    {
      Apc[1].SpareLong0 = -1073741823;
      v8 = (_QWORD *)v2;
LABEL_59:
      v19 = Apc;
      goto LABEL_60;
    }
    goto LABEL_29;
  }
  if( (*((_DWORD *)CurrentThread + 325) & 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, v79, v80);
    MmUnlockPages(&MemoryDescriptorList);
    goto LABEL_58;
  }
  for( i = *((_QWORD *)CurrentThread + 5); (*(_BYTE *)(i + 8) & 1) != 0; i = *(_QWORD *)(i + 40) )
    ;
  v7 = i - 400;
  v11 = *((_BYTE *)CurrentThread + 3);
  if( (v11 & 0x40) == 0 || (v12 = *((_QWORD *)CurrentThread + 62), (*(_DWORD *)(v12 + 80) & 4) == 0) )
  {
    if( v11 < 0 )
    {
      CurrentUmsTeb = KeGetCurrentUmsTeb((__int64)CurrentThread);
      DoesTebMatchThread = KeDoesTebMatchThread((INT64)CurrentThread, CurrentUmsTeb);
      v23 = DoesTebMatchThread;
      if( v47 )
      {
        updated = KeUpdatePrimaryThreadContext(v22, (CONTEXT *)Apc[1].KernelRoutine);
        Apc[1].SpareLong0 = updated;
        if( !v23 || updated < 0 )
          goto LABEL_58;
      }
      else if( !DoesTebMatchThread )
      {
        v24 = KeBuildPrimaryThreadContext(v22, 0i64, (INT64)Apc[1].KernelRoutine, 1i64, 0i64, 0i64);
LABEL_26:
        Apc[1].SpareLong0 = v24;
        goto LABEL_58;
      }
    }
LABEL_29:
    if( (Apc[1].SpareByte0 & 2) != 0 )
    {
      if( RtlpGetStackLimits(&LowLimit, &HighLimit) )
      {
        *(_OWORD *)v55 = 0i64;
        v56 = 0i64;
        *(_OWORD *)v51 = *(_OWORD *)&xmmword_140E00020;
        v52 = qword_140E00030;
        RtlpCaptureContext((INT64)result, v28, v29, v30, v36, v37, v38, v39, v40);
        p_RundownRoutine[19] = (void(__fastcall *)(_KAPC *))&v58;
        p_RundownRoutine[21] = (void(__fastcall *)(_KAPC *))&v60;
        p_RundownRoutine[22] = (void(__fastcall *)(_KAPC *))&v61;
        p_RundownRoutine[23] = (void(__fastcall *)(_KAPC *))&v62;
        p_RundownRoutine[28] = (void(__fastcall *)(_KAPC *))&v63;
        p_RundownRoutine[29] = (void(__fastcall *)(_KAPC *))&v64;
        p_RundownRoutine[30] = (void(__fastcall *)(_KAPC *))&v65;
        p_RundownRoutine[31] = (void(__fastcall *)(_KAPC *))&v66;
        p_RundownRoutine[6] = (void(__fastcall *)(_KAPC *))&v68;
        p_RundownRoutine[7] = (void(__fastcall *)(_KAPC *))&v69;
        p_RundownRoutine[8] = (void(__fastcall *)(_KAPC *))&v70;
        p_RundownRoutine[9] = (void(__fastcall *)(_KAPC *))&v71;
        p_RundownRoutine[10] = (void(__fastcall *)(_KAPC *))&v72;
        p_RundownRoutine[11] = (void(__fastcall *)(_KAPC *))&v73;
        p_RundownRoutine[12] = (void(__fastcall *)(_KAPC *))&v74;
        p_RundownRoutine[13] = (void(__fastcall *)(_KAPC *))&v75;
        p_RundownRoutine[14] = (void(__fastcall *)(_KAPC *))&v76;
        p_RundownRoutine[15] = (void(__fastcall *)(_KAPC *))&v77;
        p_RundownRoutine[20] = (void(__fastcall *)(_KAPC *))&v59;
        v31 = v59;
        while( 1 )
        {
          v32 = EndingAddress;
          if( (unsigned __int64)EndingAddress <= 0xFFFF800000000000ui64
            || !RtlpIsFrameInBoundsEx(&LowLimit, v31, &HighLimit, v55) )
          {
            break;
          }
          v33 = RtlpLookupFunctionEntryForStackWalks(v32, (INT64)v51);
          if( v33 )
          {
            if( (int)RtlpVirtualUnwind(
                        0,
                        v51[1],
                        (unsigned __int64)v32,
                        (__int64)v33,
                        (__int64)result,
                        (__int64)v42,
                        (__int64)&v50,
                        (__int64)&v46,
                        (__int64)p_RundownRoutine,
                        (__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;
            }
            v31 = v59;
          }
          else
          {
            if( !v51[1] )
              goto LABEL_57;
            EndingAddress = *(PVOID *)v59;
            v31 = v59 + 8;
            v59 += 8i64;
          }
          if( v46 == v7 )
            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 = *((_QWORD *)CurrentThread + 5); (*(_BYTE *)(j + 8) & 1) != 0; j = *(_QWORD *)(j + 40) )
      ;
    p_RundownRoutine[19] = (void(__fastcall *)(_KAPC *))(j - 464);
    p_RundownRoutine[22] = (void(__fastcall *)(_KAPC *))(j - 448);
    p_RundownRoutine[23] = (void(__fastcall *)(_KAPC *))(j - 456);
    p_RundownRoutine[28] = (void(__fastcall *)(_KAPC *))(j - 440);
    p_RundownRoutine[29] = (void(__fastcall *)(_KAPC *))(j - 432);
    p_RundownRoutine[30] = (void(__fastcall *)(_KAPC *))(j - 424);
    p_RundownRoutine[31] = (void(__fastcall *)(_KAPC *))(j - 416);
    p_RundownRoutine[6] = (void(__fastcall *)(_KAPC *))(j - 672);
    p_RundownRoutine[7] = (void(__fastcall *)(_KAPC *))(j - 656);
    p_RundownRoutine[8] = (void(__fastcall *)(_KAPC *))(j - 640);
    p_RundownRoutine[9] = (void(__fastcall *)(_KAPC *))(j - 624);
    p_RundownRoutine[10] = (void(__fastcall *)(_KAPC *))(j - 608);
    p_RundownRoutine[11] = (void(__fastcall *)(_KAPC *))(j - 592);
    p_RundownRoutine[12] = (void(__fastcall *)(_KAPC *))(j - 576);
    p_RundownRoutine[13] = (void(__fastcall *)(_KAPC *))(j - 560);
    p_RundownRoutine[14] = (void(__fastcall *)(_KAPC *))(j - 544);
    p_RundownRoutine[15] = (void(__fastcall *)(_KAPC *))(j - 528);
    p_RundownRoutine[21] = (void(__fastcall *)(_KAPC *))(v7 + 344);
LABEL_33:
    v27 = Apc[1].KernelRoutine;
    if( !v47 )
    {
      if( (*((_DWORD *)v27 + 12) & 0x100008) == 1048584 && Apc[1].Type == 1 )
        _fxsave((char *)v27 + 256);
      if( *((_QWORD *)CurrentThread + 195) && Apc[1].Type == 1 )
      {
        v35 = (_CONTEXT *)Apc[1].KernelRoutine;
        PspGetContext((_DEVICE_OBJECT *)v7);
        if( (*((_BYTE *)CurrentThread + 3) & 8) != 0 )
        {
          RtlCopyContext(v35, v35->ContextFlags, *((_CONTEXT **)CurrentThread + 195));
          Apc[1].SpareLong0 = 0;
          goto LABEL_58;
        }
      }
      else
      {
        PspGetContext((_DEVICE_OBJECT *)v7);
      }
      Apc[1].SpareLong0 = 0;
      goto LABEL_58;
    }
    if( Apc[1].Type != 1
      || (a3[0] = 0i64, v24 = KeVerifyContextXStateCetU((INT64)CurrentThread, v27, a3), v24 >= 0)
      && ((Apc[1].SpareByte0 & 4) == 0
       || (*(_OWORD *)v53 = 0i64,
           v54 = 0i64,
           LODWORD(v53[0]) = 3,
           v24 = KeVerifyContextIpForUserCet((INT64)CurrentThread, (INT64)Apc[1].KernelRoutine, v53, a3),
           v24 >= 0)) )
    {
      if( *((_QWORD *)CurrentThread + 195)
        && Apc[1].Type == 1
        && ((Apc[1].SpareByte0 & 2) != 0 || (*((_BYTE *)CurrentThread + 3) & 8) != 0) )
      {
        PspSetContextState((INT64)CurrentThread, (CONTEXT *)Apc[1].KernelRoutine);
        Apc[1].SpareLong0 = 0;
      }
      else
      {
        PspSetContext(v7, (INT64)p_RundownRoutine, (INT64)Apc[1].KernelRoutine, Apc[1].Type);
        Apc[1].SpareLong0 = 0;
      }
      goto LABEL_58;
    }
    goto LABEL_26;
  }
  v13 = *(_QWORD *)v12;
  v14 = PspRundownUmsThreadForApcDelivery((INT64)CurrentThread, &a2, *(_QWORD *)v12, 0);
  Apc[1].SpareLong0 = v14;
  if( v14 < 0 )
  {
LABEL_58:
    v8 = v41;
    goto LABEL_59;
  }
  v15 = Apc[1].KernelRoutine;
  if( OperationType )
  {
    v16 = PspSetUmsThreadContext((INT64)CurrentThread, (INT64)Apc[1].KernelRoutine, &a2);
  }
  else
  {
    v16 = 0;
    if( (a2 & 2) != 0 )
      v16 = KeCopyContextFromUmsContext((CONTEXT *)v15, **((_QWORD **)CurrentThread + 62));
    else
      KeCopyContextFromUch((CONTEXT *)v15, *((_QWORD *)CurrentThread + 63));
  }
  Apc[1].SpareLong0 = v16;
  v17 = KeClearUmsThreadKernelLock(v13);
  if( v17 < 0 )
    Apc[1].SpareLong0 = v17;
  if( (a2 & 8) != 0 )
  {
    v18 = KeUpdateUmsThreadState(v13, 0i64, 1);
    v19 = Apc;
    if( v18 < 0 )
    {
      Apc[1].SpareLong0 = v18;
      v8 = v41;
      goto LABEL_60;
    }
  }
  else
  {
    v19 = Apc;
  }
  v8 = v41;
LABEL_60:
  p_Thread = &v19[1].Thread;
  if( (Apc[1].SpareByte0 & 1) == 0 )
    p_Thread = 0i64;
  *v8 = p_Thread;
}

Referenced by:

PspGetSetContextSpecialApc