Threads are created by the kernel using the system call NtCreateThread or NtCreateThreadEx.
NtCreateThread(PHANDLE ThreadHandle,
ACCESS_MASK, DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
HANDLE ProcessHandle,
PCLIENT_ID ClientId,
PCONTEXT ThreadContext,
PUSER_STACK UserStack,
BOOLEAN CreateSuspended);
NtCreateThreadEx(PHANDLE hThread,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE, lpStartAddress,
LPVOID, lpParameter,
BOOL CreateSuspended,
ULONG StackZeroBits,
ULONG SizeOfStackCommit,
ULONG SizeOfStackReserve,
LPVOID lpBytesBuffer);
The PRE-Syscall handler of NtCreateThread and NtCreateThreadEx creates necessary structures for the new thread:
Should thread creation fail, then the POST-Syscall handler will free the allocated resources.
The PRE-Syscall handler modifies the argument lpParameter to point to a newly allocated structure containing:
It also modifies the 'lpStartAddress' parameter to point to the assembly stub 'thread_start_routine' that:
'thread_start_routine' sets up the thread state, initial registers and registers the client stack.
Threads end by calling the system call NtTerminateThread.
NtTerminateThread(HANDLE ThreadHandle, NTSTATUS ExitStatus);
This system call can be called either explicitly by the thread, or it its called by the library after returning from the thread main function.
In any case, this system call is the termination point of a thread. Note however that this call can terminate the current or any other thread of the current process. Here it starts to get tricky:
When terminating the current thread, the system call is not executed and instead the scheduler for that thread terminated. The thread is the current thread when ThreadHandle is either
In any other case, the system call can and will be executed synchronously.
Unlike POSIX platforms, there is no 'fork' or 'clone'. A new process is created by calling the system call NtCreateProcess passing it the name of an executable to run.
NtCreateProcess(OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ParentProcess,
IN BOOLEAN InheritObjectTable,
IN HANDLE SectionHandle OPTIONAL,
IN HANDLE DebugPort OPTIONAL,
IN HANDLE ExceptionPort OPTIONAL);
A process terminates by calling the system call NtTerminateProcess, either by calling any wrapper like 'ExitProcess', 'TerminateProcess' or 'exit', or by returning from the main function.
NtTerminateProcess(HANDLE ProcessHandle, NTSTATUS ExitStatus);
In any case, the system call NtTerminateProcess is the termination point of the process.
The system call can either terminate the current process or any other process running on the same machine. The process is the current process when ProcessHandle is either
Because we do not want the process to end when the client code calls NtTerminateProcess, the system call is not executed but instead the thread marked as 'exiting'.