PspExitThread

VOID __stdcall PspExitThread(INT64 ExitStatus){
  int v1; 
  _ETHREAD *CurrentThread; 
  _EPROCESS *v3; 
  _EPROCESS *v4; 
  _ADAPTER_OBJECT *LegacyPowerObject; 
  volatile signed __int64 *p_bf_0; 
  unsigned int v7; 
  _TERMINATION_PORT *TerminationPort; 
  _ADAPTER_OBJECT *v9; 
  NTSTATUS v10; 
  char v11; 
  unsigned int *Teb; 
  _EWOW64PROCESS *WoW64Process; 
  VOID *v14; 
  unsigned __int16 Machine; 
  _LARGE_INTEGER *v16; 
  _CONTEXT *SetContextState; 
  _LIST_ENTRY *Flink; 
  _LIST_ENTRY *p_ThreadListHead; 
  _LIST_ENTRY **p_Blink; 
  VOID *v21; 
  _INVERTED_FUNCTION_TABLE *InvertedFunctionTable; 
  NTSTATUS v23; 
  _TERMINATION_PORT *Next; 
  _DWORD *v25; 
  _DWORD *v26; 
  PKINTERRUPT_ROUTINE **v27; 
  UINT32 v28; 
  PKINTERRUPT_ROUTINE *v29; 
  _DWORD *v30; 
  INT64 v31; 
  INT64 v32; 
  _EJOB *v33; 
  _EJOB *v34; 
  int v35[8]; 
  PLARGE_INTEGER Timeout; 
  UINT64 RegionSize; 
  UINT64 v38; 
  PORT_MESSAGE RequestMessage[4]; 
  __int128 v40; 
  __int128 v41; 
  VOID *v42; 
  VOID *BaseAddress; 
  VOID *v44; 
  _EPROCESS *Process; 
  _ETHREAD *v46; 
  __int128 Parameters; 
  __int128 v48; 
  unsigned int ExitStatusa; 
  char v50; 
  _MDL *MemoryDescriptorList; 
  PVOID Object; 

  ExitStatusa = ExitStatus;
  v1 = ExitStatus;
  *(_OWORD *)RequestMessage = 0i64;
  v40 = 0i64;
  v41 = 0i64;
  v48 = 0i64;
  Parameters = 0i64;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  v46 = CurrentThread;
  Process = CurrentThread->Tcb.Process;
  v3 = Process;
  PspClearProcessThreadCidRefs(CurrentThread, CurrentThread->Cid.UniqueThread, CurrentThread);
  v4 = CurrentThread->Tcb.ApcState.Process;
  if( Process != v4 )
    KeBugCheckEx(5u, Process, v4, (PVOID)CurrentThread->Tcb.ApcStateIndex, CurrentThread);
  __writecr8(0i64);
  if( (CurrentThread->SameThreadPassiveFlags & 1) != 0 )
    KeBugCheckEx(0xE9u, CurrentThread, 0i64, 0i64, 0i64);
  if( CurrentThread->Tcb.WaitBlock[3].SpareLong )
    KeBugCheckEx(0x20u, 0i64, (PVOID)CurrentThread->Tcb.CombinedApcDisable, 0i64, (PVOID)1);
  if( CurrentThread->ChargeOnlySession )
  {
    KeSetThreadChargeOnlySchedulingGroup(&CurrentThread->Tcb, 0i64);
    ObfDereferenceObjectWithTag(CurrentThread->ChargeOnlySession, 0x79517350ui64);
    CurrentThread->ChargeOnlySession = 0i64;
  }
  PspEmptyPropertySet(&CurrentThread->PropertySet);
  PspRevertContainerImpersonation(CurrentThread);
  ExWaitForRundownProtectionRelease(&CurrentThread->RundownProtect);
  LegacyPowerObject = (_ADAPTER_OBJECT *)CurrentThread->LegacyPowerObject;
  if( LegacyPowerObject )
  {
    PopPowerRequestCleanUp((_PO_POWER_REQUEST *)CurrentThread->LegacyPowerObject);
    HalPutDmaAdapter(LegacyPowerObject);
    CurrentThread->LegacyPowerObject = 0i64;
  }
  v50 = 0;
  Object = 0i64;
  CurrentThread->ExitStatus = v1;
  --CurrentThread->Tcb.KernelApcDisable;
  if( (v3->Flags3 & 1) == 0 || v3->PicoContext )
    PspCallThreadNotifyRoutines(CurrentThread, 0, 0);
  p_bf_0 = &v3->ProcessLock._bf_0;
  ExAcquirePushLockExclusiveEx(&v3->ProcessLock, 0i64);
  if( --v3->ActiveThreads )
  {
    if( v1 != -1073741749 )
      v3->LastThreadExitStatus = v1;
  }
  else
  {
    _InterlockedOr((volatile signed __int32 *)&v3->1124, 0x2000008u);
    KeForceResumeProcess(&v3->Pcb);
    v50 = 1;
    if( v3->ExitStatus == 259 )
    {
      if( v1 == -1073741749 )
        v3->ExitStatus = v3->LastThreadExitStatus;
      else
        v3->ExitStatus = v1;
    }
    Flink = v3->ThreadListHead.Flink;
    if( Flink != &v3->ThreadListHead )
    {
      p_ThreadListHead = &v3->ThreadListHead;
      p_Blink = 0i64;
      do
      {
        if( &Flink[-79].Blink != (_LIST_ENTRY **)CurrentThread )
        {
          if( !BYTE4(Flink[-79].Blink) && ObReferenceObjectSafeWithTag((INT64)&Flink[-79].Blink, 1700033360i64) )
          {
            if( (_InterlockedExchangeAdd64(p_bf_0, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
              ExfTryToWakePushLock(&v3->ProcessLock);
            KeAbPostRelease(&v3->ProcessLock);
            KeLeaveCriticalRegionThread(&CurrentThread->Tcb);
            KeWaitForSingleObject((UINT64)&Flink[-79].Blink, 0, 0, 0, 0i64);
            if( p_Blink )
              ObfDereferenceObjectWithTag(p_Blink, 0x65547350ui64);
            p_Blink = &Flink[-79].Blink;
            --CurrentThread->Tcb.KernelApcDisable;
            ExAcquirePushLockExclusiveEx(&v3->ProcessLock, 0i64);
          }
          p_ThreadListHead = &v3->ThreadListHead;
        }
        Flink = Flink->Flink;
      }
      while( Flink != p_ThreadListHead );
      Object = p_Blink;
    }
  }
  if( (_InterlockedExchangeAdd64(p_bf_0, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
    ExfTryToWakePushLock(&v3->ProcessLock);
  KeAbPostRelease(&v3->ProcessLock);
  KeLeaveCriticalRegionThread(&CurrentThread->Tcb);
  if( Object )
    ObfDereferenceObjectWithTag(Object, 0x65547350ui64);
  if( CurrentThread->Silo != (_EJOB *)-3i64 )
  {
    LODWORD(v25) = PsAttachSiloToCurrentThread(-3i64);
    v26 = v25;
    LODWORD(v30) = HalSystemVectorDispatchEntry(v28, v27, v29);
    if( v26 == v30
      || (POBJECT_TYPE *)ObTypeIndexTable[(unsigned __int8)ObHeaderCookie ^ *((unsigned __int8 *)v26 - 24) ^ (unsigned __int64)(unsigned __int8)((unsigned __int16)((_WORD)v26 - 48) >> 8)] != PsJobType
      || (v26[331] & 2) == 0 )
    {
      KeBugCheckEx(0x1CBu, CurrentThread, v26, v3, (PVOID)1);
    }
    ObfDereferenceObjectWithTag(v26, 0x6D497350ui64);
  }
  if( v3->DebugPort && (CurrentThread->Tcb._bf_0 & 0x400) == 0 )
  {
    if( !v50 )
    {
      v7 = ExitStatusa;
      DbgkExitThread(ExitStatusa);
      goto LABEL_20;
    }
    DbgkExitProcess((unsigned int)v3->ExitStatus);
  }
  v7 = ExitStatusa;
LABEL_20:
  if( (*(_BYTE *)&v3->Pcb.SecureState & 1) != 0 )
  {
    MemoryDescriptorList = 0i64;
    if( (int)KeUnsecureThread(&MemoryDescriptorList) >= 0 )
    {
      MmUnlockPages((INT64)MemoryDescriptorList, v31, v32);
      ExFreePoolWithTag(MemoryDescriptorList, 0x65537350u);
    }
  }
  if( (_BYTE)KdDebuggerEnabled
    && (CurrentThread->CrossThreadFlags & 0x20) != 0
    && (CurrentThread->Tcb.Process->Flags & 0x40000008) == 0 )
  {
    LODWORD(v33) = PsGetProcessServerSilo((INT64)v3);
    LODWORD(Timeout) = v7;
    PspCatchCriticalBreak(
      (INT8 *)"Critical thread 0x%p(in %s) exited\n",
      CurrentThread,
      v3->ImageFileName,
      v33,
      (INT64)Timeout);
  }
  if( v50 && (v3->Flags & 0x2000) != 0 )
  {
    LODWORD(v34) = PsGetProcessServerSilo((INT64)v3);
    LODWORD(Timeout) = v7;
    PspCatchCriticalBreak((INT8 *)"Critical process 0x%p(%s) exited\n", v3, v3->ImageFileName, v34, (INT64)Timeout);
  }
  TerminationPort = CurrentThread->TerminationPort;
  if( TerminationPort )
  {
    RequestMessage[0] = 3145736;
    RequestMessage[1] = 6;
    *((_QWORD *)&v41 + 1) = CurrentThread->CreateTime.QuadPart;
    do
    {
      while( 1 )
      {
        v23 = LpcRequestPort(TerminationPort->Port, RequestMessage);
        if( v23 != -1073741801 && v23 != -1073741670 )
          break;
        KeDelayExecutionThread(0, 0, (_LARGE_INTEGER *)&unk_1400105B0);
      }
      HalPutDmaAdapter((PADAPTER_OBJECT)TerminationPort->Port);
      Next = TerminationPort->Next;
      ExFreePoolWithTag(TerminationPort, 0x70547350u);
      TerminationPort = Next;
    }
    while( Next );
  }
  if( (CurrentThread->CrossThreadFlags & 2) != 0 )
  {
    v9 = (_ADAPTER_OBJECT *)PsCaptureExceptionPort(v3);
    if( v9 )
    {
      RequestMessage[0] = 3145736;
      RequestMessage[1] = 6;
      *((_QWORD *)&v41 + 1) = CurrentThread->CreateTime.QuadPart;
      while( 1 )
      {
        v10 = LpcRequestPort(v9, RequestMessage);
        if( v10 != -1073741801 && v10 != -1073741670 )
          break;
        KeDelayExecutionThread(0, 0, (_LARGE_INTEGER *)&unk_1400105B0);
      }
      HalPutDmaAdapter(v9);
    }
  }
  if( CurrentThread->Tcb.WaitBlock[2].SparePtr )
  {
    *(_QWORD *)&Parameters = CurrentThread;
    DWORD2(Parameters) = 1;
    PsInvokeWin32Callout(Win32ThreadCallout, &Parameters, PsWin32SessionAttachNone, 0i64);
  }
  if( v50 && v3->Win32Process )
  {
    *(_QWORD *)&v48 = v3;
    DWORD2(v48) = 0;
    PsInvokeWin32Callout(Win32ProcessCallout, &v48, PsWin32SessionAttachNone, 0i64);
  }
  if( (*(&CurrentThread->Tcb.MiscFlags + 1) & 0x40) == 0 )
    KeBugCheckEx(0x94u, 0i64, CurrentThread, 0i64, 0i64);
  IoCancelThreadIo();
  ExTimerRundown();
  CmNotifyRunDown((__int64)CurrentThread);
  KiRundownMutants(KeGetCurrentThread());
  v11 = CurrentThread->Tcb.gap0[3];
  if( (v11 & 0x40) != 0 || v11 < 0 )
    PspUmsUnInitThread(&CurrentThread->Tcb);
  Teb = (unsigned int *)CurrentThread->Tcb.Teb;
  Object = Teb;
  if( Teb )
  {
    CurrentThread->Tcb.Teb = 0i64;
    --CurrentThread->Tcb.KernelApcDisable;
    _InterlockedOr(v35, 0);
    if( (CurrentThread->ThreadLock._bf_0 & 1) != 0 )
      ExfAcquireReleasePushLockExclusive(&CurrentThread->ThreadLock);
    KeLeaveCriticalRegionThread(&CurrentThread->Tcb);
    if( (CurrentThread->Tcb._bf_0 & 0x400) == 0 && (v3->Flags & 0x40000008) == 0 )
    {
      if( (CurrentThread->CrossThreadFlags & 2) != 0 )
      {
        v42 = (VOID *)*((_QWORD *)Teb + 655);
        BaseAddress = v42;
        RegionSize = 0i64;
        ZwFreeVirtualMemory((VOID *)0xFFFFFFFFFFFFFFFFi64, &BaseAddress, &RegionSize, 0x8000ui64);
        WoW64Process = v3->WoW64Process;
        if( WoW64Process )
        {
          Machine = WoW64Process->Machine;
          if( Machine == 332 || Machine == 452 )
          {
            v44 = (VOID *)Teb[2947];
            v38 = 0i64;
            ZwFreeVirtualMemory((VOID *)0xFFFFFFFFFFFFFFFFi64, &v44, &v38, 0x8000ui64);
          }
        }
      }
      v14 = (VOID *)*((_QWORD *)Teb + 725);
      if( v14 )
        ObCloseHandle(v14, 1);
      if( (CurrentThread->Tcb._bf_0 & 0x100000) != 0 && (CurrentThread->CrossThreadFlags & 2) != 0 )
        PspFreeCurrentThreadUserShadowStack();
      MmDeleteTeb((ULONG_PTR)v3, Teb);
    }
  }
  v16 = (_LARGE_INTEGER *)CurrentThread->gap438;
  if( KeQuerySystemTimeUnsafe() )
    KeQuerySystemTimePrecise((_LARGE_INTEGER *)CurrentThread->gap438);
  else
    *v16 = *(_LARGE_INTEGER *)&KUSER_SHARED_DATA.SystemTime.LowPart;
  if( v50 )
  {
    v3->ExitTime = *v16;
    PspExitProcess(1u, v3);
    v21 = PsReferencePrimaryToken(v3);
    if( SeAuditingWithTokenForSubcategory(134i64, (INT64)v21) )
      SeAuditProcessExit(v3, (unsigned int)v3->ExitStatus);
    ObFastDereferenceObject(&v3->Token, v21);
    ExWnfExitProcess(v3, 0i64);
    PspRundownSingleProcess(v3, 1u);
    LpcExitProcess(v3);
    InvertedFunctionTable = v3->InvertedFunctionTable;
    if( InvertedFunctionTable )
    {
      ExFreePoolWithTag(InvertedFunctionTable, 0);
      v3->InvertedFunctionTable = 0i64;
    }
  }
  KeRundownApcQueues(&CurrentThread->Tcb);
  if( CurrentThread->Tcb.SchedulerApc.SystemArgument2 && PspLegoNotifyRoutine )
    PspLegoNotifyRoutine(CurrentThread);
  SetContextState = CurrentThread->SetContextState;
  if( SetContextState )
  {
    ExFreePoolWithTag(SetContextState, 0x63537350u);
    CurrentThread->SetContextState = 0i64;
  }
  KeTerminateThread(&CurrentThread->Tcb);
}

Referenced by:

KiSchedulerApcTerminate
NtTerminateProcess
PspTerminateThreadByPointer