PspExitThread

VOID __stdcall PspExitThread(INT64 ExitStatus){
  int v1; 
  _ETHREAD *CurrentThread; 
  ULONG_PTR v3; 
  ULONG_PTR v4; 
  struct _DMA_ADAPTER *v5; 
  volatile signed __int64 *v6; 
  void *v7; 
  void *v8; 
  __int64 v9; 
  union _LARGE_INTEGER v10; 
  unsigned int v11; 
  _QWORD *v12; 
  struct _DMA_ADAPTER *v13; 
  struct _DMA_ADAPTER *v14; 
  int v15; 
  INT64 *v16; 
  char v17; 
  unsigned __int64 v18; 
  __int64 v19; 
  void *v20; 
  __int16 v21; 
  _QWORD *v22; 
  void *v23; 
  _QWORD *v24; 
  _QWORD *v25; 
  _QWORD *v26; 
  struct DMA_ADAPTER *v27; 
  void *v28; 
  int v29; 
  _QWORD *v30; 
  _EJOB *v31; 
  _EJOB *ProcessServerSilo; 
  _EJOB *v33; 
  int v34[8]; 
  PLARGE_INTEGER Timeout; 
  ULONG_PTR RegionSize; 
  ULONG_PTR v37; 
  __m256i v38; 
  __int128 v39; 
  void *v40; 
  PVOID BaseAddress; 
  PVOID v42; 
  ULONG_PTR v43; 
  _ETHREAD *v44; 
  __int128 v45; 
  __int128 v46; 
  unsigned int ExitStatusa; 
  char v48; 
  PMDL MemoryDescriptorList; 
  PVOID Object; 
  ExitStatusa = ExitStatus;
  v1 = ExitStatus;
  memset(&v38, 0, sizeof(v38));
  v39 = 0i64;
  v46 = 0i64;
  v45 = 0i64;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  v44 = CurrentThread;
  v43 = *((_QWORD *)CurrentThread + 68);
  v3 = v43;
  PspClearProcessThreadCidRefs(CurrentThread, *((PVOID *)CurrentThread + 144), CurrentThread);
  v4 = *((_QWORD *)CurrentThread + 23);
  if( v43 != v4 )
    KeBugCheckEx(5u, v43, v4, *((unsigned __int8 *)CurrentThread + 586), (ULONG_PTR)CurrentThread);
  __writecr8(0i64);
  if( (*((_DWORD *)CurrentThread + 325) & 1) != 0 )
    KeBugCheckEx(0xE9u, (ULONG_PTR)CurrentThread, 0i64, 0i64, 0i64);
  if( *((_DWORD *)CurrentThread + 121) )
    KeBugCheckEx(0x20u, 0i64, *((unsigned int *)CurrentThread + 121), 0i64, 1ui64);
  if( *((_QWORD *)CurrentThread + 155) )
  {
    KeSetThreadChargeOnlySchedulingGroup((_KTHREAD *)CurrentThread, 0i64);
    ObfDereferenceObjectWithTag(*((PVOID *)CurrentThread + 155), 0x79517350ui64);
    *((_QWORD *)CurrentThread + 155) = 0i64;
  }
  PspEmptyPropertySet((_PS_PROPERTY_SET *)((char *)CurrentThread + 1480));
  PspRevertContainerImpersonation((ULONG_PTR)CurrentThread);
  ExWaitForRundownProtectionRelease((EX_RUNDOWN_REF *)CurrentThread + 159);
  v5 = (struct _DMA_ADAPTER *)*((_QWORD *)CurrentThread + 156);
  if( v5 )
  {
    PopPowerRequestCleanUp(*((UINT64 **)CurrentThread + 156));
    HalPutDmaAdapter(v5);
    *((_QWORD *)CurrentThread + 156) = 0i64;
  }
  v48 = 0;
  Object = 0i64;
  *((_DWORD *)CurrentThread + 338) = v1;
  --*((_WORD *)CurrentThread + 242);
  if( (*(_DWORD *)(v3 + 2172) & 1) == 0 || *(_QWORD *)(v3 + 2240) )
    PspCallThreadNotifyRoutines(CurrentThread, 0, 0);
  v6 = (volatile signed __int64 *)(v3 + 1080);
  ExAcquirePushLockExclusiveEx(v3 + 1080, 0i64);
  if( --*(_DWORD *)(v3 + 1520) )
  {
    if( v1 != -1073741749 )
      *(_DWORD *)(v3 + 1532) = v1;
  }
  else
  {
    _InterlockedOr((volatile signed __int32 *)(v3 + 1124), 0x2000008u);
    KeForceResumeProcess((_KPROCESS *)v3);
    v48 = 1;
    if( *(_DWORD *)(v3 + 2004) == 259 )
    {
      if( v1 == -1073741749 )
        *(_DWORD *)(v3 + 2004) = *(_DWORD *)(v3 + 1532);
      else
        *(_DWORD *)(v3 + 2004) = v1;
    }
    v24 = *(_QWORD **)(v3 + 1504);
    if( v24 != (_QWORD *)(v3 + 1504) )
    {
      v25 = (_QWORD *)(v3 + 1504);
      v26 = 0i64;
      do
      {
        if( v24 - 157 != (_QWORD *)CurrentThread )
        {
          if( !*((_BYTE *)v24 - 1252) && ObReferenceObjectSafeWithTag(v24 - 157, 0x65547350ui64) )
          {
            if( (_InterlockedExchangeAdd64(v6, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
              ExfTryToWakePushLock((volatile INT64 *)(v3 + 1080));
            KeAbPostRelease((PVOID)(v3 + 1080));
            KeLeaveCriticalRegionThread((__int64)CurrentThread);
            KeWaitForSingleObject(v24 - 157, Executive, 0, 0, 0i64);
            if( v26 )
              ObfDereferenceObjectWithTag(v26, 0x65547350ui64);
            v26 = v24 - 157;
            --*((_WORD *)CurrentThread + 242);
            ExAcquirePushLockExclusiveEx(v3 + 1080, 0i64);
          }
          v25 = (_QWORD *)(v3 + 1504);
        }
        v24 = (_QWORD *)*v24;
      }
      while( v24 != v25 );
      Object = v26;
    }
  }
  if( (_InterlockedExchangeAdd64(v6, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
    ExfTryToWakePushLock((volatile INT64 *)(v3 + 1080));
  KeAbPostRelease((PVOID)(v3 + 1080));
  KeLeaveCriticalRegionThread((__int64)CurrentThread);
  if( Object )
    ObfDereferenceObjectWithTag(Object, 0x65547350ui64);
  v9 = 0i64;
  v10.QuadPart = -3i64;
  if( *((_QWORD *)CurrentThread + 193) != -3i64 )
    v9 = 1i64;
  if( (_BYTE)v9 )
  {
    v31 = PsAttachSiloToCurrentThread((_EJOB *)0xFFFFFFFFFFFFFFFDi64);
    if( v31 == (_EJOB *)HalSystemVectorDispatchEntry()
      || (POBJECT_TYPE *)ObTypeIndexTable[(unsigned __int8)ObHeaderCookie ^ LOBYTE(v31[-1].EnergyTrackingState.Value) ^ (unsigned __int64)(unsigned __int8)((unsigned __int16)((_WORD)v31 - 48) >> 8)] != PsJobType
      || (v31->JobFlags2 & 2) == 0 )
    {
      KeBugCheckEx(0x1CBu, (ULONG_PTR)CurrentThread, (ULONG_PTR)v31, v3, 1ui64);
    }
    ObfDereferenceObjectWithTag(v31, 0x6D497350ui64);
  }
  if( *(_QWORD *)(v3 + 1400) && (*((_DWORD *)CurrentThread + 29) & 0x400) == 0 )
  {
    if( !v48 )
    {
      v11 = ExitStatusa;
      DbgkExitThread(ExitStatusa);
      goto LABEL_22;
    }
    DbgkExitProcess(*(unsigned int *)(v3 + 2004));
  }
  v11 = ExitStatusa;
LABEL_22:
  if( (*(_BYTE *)(v3 + 992) & 1) != 0 )
  {
    MemoryDescriptorList = 0i64;
    if( (int)KeUnsecureThread(&MemoryDescriptorList) >= 0 )
    {
      MmUnlockPages(MemoryDescriptorList);
      ExFreePoolWithTag(MemoryDescriptorList, 0x65537350u);
    }
  }
  if( (_BYTE)KdDebuggerEnabled )
  {
    if( (*((_DWORD *)CurrentThread + 324) & 0x20) != 0 )
    {
      v10.QuadPart = *(unsigned int *)(*((_QWORD *)CurrentThread + 68) + 1124i64);
      if( (v10.LowPart & 0x40000008) == 0 )
      {
        ProcessServerSilo = (_EJOB *)PsGetProcessServerSilo(v3);
        LODWORD(Timeout) = v11;
        PspCatchCriticalBreak(
          (INT8 *)"Critical thread 0x%p(in %s) exited\n",
          CurrentThread,
          (UINT8 *)(v3 + 1448),
          ProcessServerSilo,
          (INT64)Timeout);
      }
    }
  }
  if( v48 && (*(_DWORD *)(v3 + 1124) & 0x2000) != 0 )
  {
    v33 = (_EJOB *)PsGetProcessServerSilo(v3);
    LODWORD(Timeout) = v11;
    PspCatchCriticalBreak(
      (INT8 *)"Critical process 0x%p(%s) exited\n",
      (PVOID)v3,
      (UINT8 *)(v3 + 1448),
      v33,
      (INT64)Timeout);
  }
  v12 = (_QWORD *)*((_QWORD *)CurrentThread + 139);
  if( v12 )
  {
    v38.m256i_i64[0] = 0x600300008i64;
    *((_QWORD *)&v39 + 1) = *((_QWORD *)CurrentThread + 134);
    do
    {
      while( 1 )
      {
        v29 = LpcRequestPort(v12[1], &v38);
        if( v29 != -1073741801 && v29 != -1073741670 )
          break;
        KeDelayExecutionThread(0, 0, (PLARGE_INTEGER)&PspShortTime);
      }
      HalPutDmaAdapter((PADAPTER_OBJECT)v12[1]);
      v30 = (_QWORD *)*v12;
      ExFreePoolWithTag(v12, 0x70547350u);
      v12 = v30;
    }
    while( v30 );
  }
  if( (*((_DWORD *)CurrentThread + 324) & 2) != 0 )
  {
    LODWORD(v13) = PsCaptureExceptionPort((_EPROCESS *)v3);
    v14 = v13;
    if( v13 )
    {
      v38.m256i_i64[0] = 0x600300008i64;
      *((_QWORD *)&v39 + 1) = *((_QWORD *)CurrentThread + 134);
      while( 1 )
      {
        v15 = LpcRequestPort((INT64)v14, &v38);
        if( v15 != -1073741801 && v15 != -1073741670 )
          break;
        KeDelayExecutionThread(0, 0, (PLARGE_INTEGER)&PspShortTime);
      }
      HalPutDmaAdapter(v14);
    }
  }
  if( *((_QWORD *)CurrentThread + 57) )
  {
    *(_QWORD *)&v45 = CurrentThread;
    DWORD2(v45) = 1;
    PsInvokeWin32Callout(1i64, &v45, 0i64, 0i64);
  }
  if( v48 && *(_QWORD *)(v3 + 1288) )
  {
    *(_QWORD *)&v46 = v3;
    DWORD2(v46) = 0;
    PsInvokeWin32Callout(0i64, &v46, 0i64, 0i64);
  }
  if( (*((_DWORD *)CurrentThread + 30) & 0x40) == 0 )
    KeBugCheckEx(0x94u, 0i64, (ULONG_PTR)CurrentThread, 0i64, 0i64);
  IoCancelThreadIo(v10, (void *)v9, v7, v8);
  ExTimerRundown();
  CmNotifyRunDown((__int64)CurrentThread);
  KiRundownMutants(KeGetCurrentThread());
  v17 = *((_BYTE *)CurrentThread + 3);
  if( (v17 & 0x40) != 0 || v17 < 0 )
    PspUmsUnInitThread(CurrentThread, v16);
  v18 = *((_QWORD *)CurrentThread + 30);
  Object = (PVOID)v18;
  if( v18 )
  {
    *((_QWORD *)CurrentThread + 30) = 0i64;
    --*((_WORD *)CurrentThread + 242);
    _InterlockedOr(v34, 0);
    if( (*((_QWORD *)CurrentThread + 160) & 1) != 0 )
      ExfAcquireReleasePushLockExclusive((char *)CurrentThread + 1280);
    KeLeaveCriticalRegionThread((__int64)CurrentThread);
    if( (*((_DWORD *)CurrentThread + 29) & 0x400) == 0 && (*(_DWORD *)(v3 + 1124) & 0x40000008) == 0 )
    {
      if( (*((_DWORD *)CurrentThread + 324) & 2) != 0 )
      {
        v40 = *(void **)(v18 + 5240);
        BaseAddress = v40;
        RegionSize = 0i64;
        ZwFreeVirtualMemory((PVOID)0xFFFFFFFFFFFFFFFFi64, &BaseAddress, &RegionSize, 0x8000ui64);
        v19 = *(_QWORD *)(v3 + 1408);
        if( v19 )
        {
          v21 = *(_WORD *)(v19 + 8);
          if( v21 == 332 || v21 == 452 )
          {
            v42 = (PVOID)*(unsigned int *)(v18 + 11788);
            v37 = 0i64;
            ZwFreeVirtualMemory((PVOID)0xFFFFFFFFFFFFFFFFi64, &v42, &v37, 0x8000ui64);
          }
        }
      }
      v20 = *(void **)(v18 + 5800);
      if( v20 )
        ObCloseHandle(v20, 1);
      if( (*((_DWORD *)CurrentThread + 29) & 0x100000) != 0 && (*((_DWORD *)CurrentThread + 324) & 2) != 0 )
        PspFreeCurrentThreadUserShadowStack();
      MmDeleteTeb(v3, v18);
    }
  }
  v22 = (_QWORD *)((char *)CurrentThread + 1080);
  if( KeQuerySystemTimeUnsafe() )
    KeQuerySystemTimePrecise((_LARGE_INTEGER *)CurrentThread + 135);
  else
    *v22 = *(_QWORD *)&KUSER_SHARED_DATA.SystemTime.LowPart;
  if( v48 )
  {
    *(_QWORD *)(v3 + 2112) = *v22;
    PspExitProcess(1, v3);
    v27 = (struct DMA_ADAPTER *)PsReferencePrimaryToken((PEPROCESS)v3);
    if( (unsigned __int8)SeAuditingWithTokenForSubcategory(0x86ui64, v27) )
      SeAuditProcessExit((_EPROCESS *)v3, *(_DWORD *)(v3 + 2004));
    ObFastDereferenceObject((INT64 *)(v3 + 1208), v27);
    ExWnfExitProcess(v3, 0i64);
    PspRundownSingleProcess(v3, 1);
    LpcExitProcess(v3);
    v28 = *(void **)(v3 + 2120);
    if( v28 )
    {
      ExFreePoolWithTag(v28, 0);
      *(_QWORD *)(v3 + 2120) = 0i64;
    }
  }
  KeRundownApcQueues((__int64)CurrentThread);
  if( *((_QWORD *)CurrentThread + 90) && PspLegoNotifyRoutine )
    PspLegoNotifyRoutine(CurrentThread);
  v23 = (void *)*((_QWORD *)CurrentThread + 195);
  if( v23 )
  {
    ExFreePoolWithTag(v23, 0x63537350u);
    *((_QWORD *)CurrentThread + 195) = 0i64;
  }
  KeTerminateThread((_KTHREAD *)CurrentThread);
}

Referenced by:

KiSchedulerApcTerminate
NtTerminateProcess
PspTerminateThreadByPointer