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