VOID NTAPI PspSystemThreadStartup(IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext) { PETHREAD Thread; PSTRACE(PS_THREAD_DEBUG, "StartRoutine: %p StartContext: %p\n", StartRoutine, StartContext); /* Unlock the dispatcher Database */ KeLowerIrql(PASSIVE_LEVEL); Thread = PsGetCurrentThread(); /* Make sure the thread isn't gone */ _SEH2_TRY { if (!(Thread->Terminated) && !(Thread->DeadThread)) { /* Call the Start Routine */ StartRoutine(StartContext); } } _SEH2_EXCEPT(PspUnhandledExceptionInSystemThread(_SEH2_GetExceptionInformation())) { /* Bugcheck if we got here */ KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED); } _SEH2_END; /* Exit the thread */ PspTerminateThreadByPointer(Thread, STATUS_SUCCESS, TRUE); }
/* * @implemented */ NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus) { PETHREAD Thread = PsGetCurrentThread(); /* Make sure this is a system thread */ if (!Thread->SystemThread) return STATUS_INVALID_PARAMETER; /* Terminate it for real */ return PspTerminateThreadByPointer(Thread, ExitStatus, TRUE); }
NTSTATUS NTAPI PspTerminateProcess(IN PEPROCESS Process, IN NTSTATUS ExitStatus) { PETHREAD Thread; NTSTATUS Status = STATUS_NOTHING_TO_TERMINATE; PAGED_CODE(); PSTRACE(PS_KILL_DEBUG, "Process: %p ExitStatus: %d\n", Process, ExitStatus); PSREFTRACE(Process); /* Check if this is a Critical Process */ if (Process->BreakOnTermination) { /* Break to debugger */ PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n", Process, Process->ImageFileName); } /* Set the delete flag */ InterlockedOr((PLONG)&Process->Flags, PSF_PROCESS_DELETE_BIT); /* Get the first thread */ Thread = PsGetNextProcessThread(Process, NULL); while (Thread) { /* Kill it */ PspTerminateThreadByPointer(Thread, ExitStatus, FALSE); Thread = PsGetNextProcessThread(Process, Thread); /* We had at least one thread, so termination is OK */ Status = STATUS_SUCCESS; } /* Check if there was nothing to terminate or if we have a debug port */ if ((Status == STATUS_NOTHING_TO_TERMINATE) || (Process->DebugPort)) { /* Clear the handle table anyway */ ObClearProcessHandleTable(Process); } /* Return status */ return Status; }
NTSTATUS NTAPI NtTerminateThread(IN HANDLE ThreadHandle, IN NTSTATUS ExitStatus) { PETHREAD Thread; PETHREAD CurrentThread = PsGetCurrentThread(); NTSTATUS Status; PAGED_CODE(); PSTRACE(PS_KILL_DEBUG, "ThreadHandle: %p ExitStatus: %d\n", ThreadHandle, ExitStatus); /* Handle the special NULL case */ if (!ThreadHandle) { /* Check if we're the only thread left */ if (PsGetCurrentProcess()->ActiveThreads == 1) { /* This is invalid */ return STATUS_CANT_TERMINATE_SELF; } /* Terminate us directly */ goto TerminateSelf; } else if (ThreadHandle == NtCurrentThread()) { TerminateSelf: /* Terminate this thread */ return PspTerminateThreadByPointer(CurrentThread, ExitStatus, TRUE); } /* We are terminating another thread, get the Thread Object */ Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_TERMINATE, PsThreadType, KeGetPreviousMode(), (PVOID*)&Thread, NULL); if (!NT_SUCCESS(Status)) return Status; /* Check to see if we're running in the same thread */ if (Thread != CurrentThread) { /* Terminate it */ Status = PspTerminateThreadByPointer(Thread, ExitStatus, FALSE); /* Dereference the Thread and return */ ObDereferenceObject(Thread); } else { /* Dereference the thread and terminate ourselves */ ObDereferenceObject(Thread); goto TerminateSelf; } /* Return status */ return Status; }
/* * @implemented */ NTSTATUS NTAPI NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL, IN NTSTATUS ExitStatus) { NTSTATUS Status; PEPROCESS Process, CurrentProcess = PsGetCurrentProcess(); PETHREAD Thread, CurrentThread = PsGetCurrentThread(); BOOLEAN KillByHandle; PAGED_CODE(); PSTRACE(PS_KILL_DEBUG, "ProcessHandle: %p ExitStatus: %d\n", ProcessHandle, ExitStatus); /* Were we passed a process handle? */ if (ProcessHandle) { /* Yes we were, use it */ KillByHandle = TRUE; } else { /* We weren't... we assume this is suicide */ KillByHandle = FALSE; ProcessHandle = NtCurrentProcess(); } /* Get the Process Object */ Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_TERMINATE, PsProcessType, KeGetPreviousMode(), (PVOID*)&Process, NULL); if (!NT_SUCCESS(Status)) return(Status); /* Check if this is a Critical Process, and Bugcheck */ if (Process->BreakOnTermination) { /* Break to debugger */ PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n", Process, Process->ImageFileName); } /* Lock the Process */ if (!ExAcquireRundownProtection(&Process->RundownProtect)) { /* Failed to lock, fail */ ObDereferenceObject(Process); return STATUS_PROCESS_IS_TERMINATING; } /* Set the delete flag, unless the process is comitting suicide */ if (KillByHandle) PspSetProcessFlag(Process, PSF_PROCESS_DELETE_BIT); /* Get the first thread */ Status = STATUS_NOTHING_TO_TERMINATE; Thread = PsGetNextProcessThread(Process, NULL); if (Thread) { /* We know we have at least a thread */ Status = STATUS_SUCCESS; /* Loop and kill the others */ do { /* Ensure it's not ours*/ if (Thread != CurrentThread) { /* Kill it */ PspTerminateThreadByPointer(Thread, ExitStatus, FALSE); } /* Move to the next thread */ Thread = PsGetNextProcessThread(Process, Thread); } while (Thread); } /* Unlock the process */ ExReleaseRundownProtection(&Process->RundownProtect); /* Check if we are killing ourselves */ if (Process == CurrentProcess) { /* Also make sure the caller gave us our handle */ if (KillByHandle) { /* Dereference the process */ ObDereferenceObject(Process); /* Terminate ourselves */ PspTerminateThreadByPointer(CurrentThread, ExitStatus, TRUE); } } else if (ExitStatus == DBG_TERMINATE_PROCESS) { /* Disable debugging on this process */ DbgkClearProcessDebugObject(Process, NULL); } /* Check if there was nothing to terminate, or if we have a Debug Port */ if ((Status == STATUS_NOTHING_TO_TERMINATE) || ((Process->DebugPort) && (KillByHandle))) { /* Clear the handle table */ ObClearProcessHandleTable(Process); /* Return status now */ Status = STATUS_SUCCESS; } /* Decrease the reference count we added */ ObDereferenceObject(Process); /* Return status */ return Status; }
VOID NTAPI PspUserThreadStartup(IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext) { PETHREAD Thread; PTEB Teb; BOOLEAN DeadThread = FALSE; KIRQL OldIrql; PAGED_CODE(); PSTRACE(PS_THREAD_DEBUG, "StartRoutine: %p StartContext: %p\n", StartRoutine, StartContext); /* Go to Passive Level */ KeLowerIrql(PASSIVE_LEVEL); Thread = PsGetCurrentThread(); /* Check if the thread is dead */ if (Thread->DeadThread) { /* Remember that we're dead */ DeadThread = TRUE; } else { /* Get the Locale ID and save Preferred Proc */ Teb = NtCurrentTeb(); Teb->CurrentLocale = MmGetSessionLocaleId(); Teb->IdealProcessor = Thread->Tcb.IdealProcessor; } /* Check if this is a dead thread, or if we're hiding */ if (!(Thread->DeadThread) && !(Thread->HideFromDebugger)) { /* We're not, so notify the debugger */ DbgkCreateThread(Thread, StartContext); } /* Make sure we're not already dead */ if (!DeadThread) { /* Check if the Prefetcher is enabled */ if (CcPfEnablePrefetcher) { /* FIXME: Prepare to prefetch this process */ } /* Raise to APC */ KeRaiseIrql(APC_LEVEL, &OldIrql); /* Queue the User APC */ KiInitializeUserApc(KeGetExceptionFrame(&Thread->Tcb), KeGetTrapFrame(&Thread->Tcb), PspSystemDllEntryPoint, NULL, PspSystemDllBase, NULL); /* Lower it back to passive */ KeLowerIrql(PASSIVE_LEVEL); } else { /* We're dead, kill us now */ PspTerminateThreadByPointer(Thread, STATUS_THREAD_IS_TERMINATING, TRUE); } /* Do we have a cookie set yet? */ while (!SharedUserData->Cookie) { LARGE_INTEGER SystemTime; ULONG NewCookie; PKPRCB Prcb; /* Generate a new cookie */ KeQuerySystemTime(&SystemTime); Prcb = KeGetCurrentPrcb(); NewCookie = (Prcb->MmPageFaultCount ^ Prcb->InterruptTime ^ SystemTime.u.LowPart ^ SystemTime.u.HighPart ^ (ULONG)(ULONG_PTR)&SystemTime); /* Set the new cookie*/ InterlockedCompareExchange((LONG*)&SharedUserData->Cookie, NewCookie, 0); } }