Windows System Programming: Create / Terminate Threads
Tags: windows, systemprogramming, cpp
Published: 2020-10-30 13:20:56

Hi, I hope you are loving this series, if you aren't I would love to hear from you. 

Anyways, in previous post I have shown you how to work with processes in windows. Now in this post, I will show you how to create a thread inside a process. But before going further in coding, you should learn about threads.

A thread in operating system is an **independent entity which runs inside the process**. The program execution is considered as main thread, as because child threads are only created by processes and can be destroyed by them only. It **shares** some **resources** (like code, data and [virtual address space](https://en.wikipedia.org/wiki/Virtual_address_space)) of the process (main thread) **except STACK and CPU Registers**. As per MSDN, you can create max **2048** threads for a process. 

Read more about threads on MSDN &rarr; https://docs.microsoft.com/en-us/dotnet/standard/threading/threads-and-threading

You can create thread with [**CreateThread**](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread) function and terminate the thread with [**TerminateThread**](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminatethread) function, both are declared in [`processthreadsapi.h`](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/) and defined in [`Kernel32.lib`](https://en.wikipedia.org/wiki/Microsoft_Windows_library_files#KERNEL32.DLL)

```c++
HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  SIZE_T                  dwStackSize,
  LPTHREAD_START_ROUTINE  lpStartAddress,
  __drv_aliasesMem LPVOID lpParameter,
  DWORD                   dwCreationFlags,
  LPDWORD                 lpThreadId
);
```
Parameters description as follows
+ **lpThreadAttributes** &rarr; A pointer to a [SECURITY_ATTRIBUTES](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560\(v=vs.85\)). If this is `NULL`, the thread handle cannot be inherited by child process.
+ **dwStackSize** &rarr; The initial size of the stack, in bytes. For more information see [Thread Stack Size](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread). If this parameter is `0x0`, the new thread will use the default size for the executable.
+ **lpStartAddress** &rarr; A pointer to the application-defined thread call-back function. For more information see [ThreadProc](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms686736\(v=vs.85\))
+ **lpParameter** &rarr; A long void pointer to a variable to be passed to the thread. Since it is a void pointer, which means it will be _generic pointer_ and should be _dereferenced with particular type of data_. If you don't want to pass any data, it should be set to `NULL`.
+ **dwCreationFlags** &rarr; The flags that control the creation of the thread. Most of the time it will be `0x0`, which means the  thread will immediately after creation.
+ **lpThreadId** &rarr; A pointer to a variable that receives the thread identifier. If this is `NULL`, thread ID is not returned
```c++
BOOL TerminateThread(
  HANDLE hThread,
  DWORD  dwExitCode
);
```
Parameters description as follows
+ **hThread** rarr; A handle to the thread to be terminated with `THREAD_TERMINATE` access right
+ **dwExitCode** &rarr; The exit code for the thread.


Complete code as follows

```c++
#include <Windows.h>
#include <tchar.h>
#include <processthreadsapi.h>
#include <handleapi.h>
#include <synchapi.h>
#include <stdio.h>

// this is like call back function which is executed by create thread function
// WINAPI is the function signature
// LPVOID params will be NULL as, I have passed 4th parameter NULL in create thread function but is required for function definition
DWORD WINAPI Worker(LPVOID params) {

	// worker function body
	while (true)
	{
		_tprintf(_T("Running Thread\n"));
		Sleep(500);
	}

	return 0;
}

int _tmain(int argc, TCHAR** argv) {
	
	DWORD threadId;
	
	// creating thread
	// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread
	HANDLE hThread = CreateThread(NULL, 0x0, Worker, NULL, 0, &threadId);
	_tprintf(_T("Thread ID: %d\n"), threadId);
	_tprintf(_T("Enter 'q' to exit\n"));

	if (hThread == NULL || hThread == INVALID_HANDLE_VALUE) {
		_tprintf(_T("Unable to create thread\n"));
		return 1;
	}

	CHAR ch;
	while (true) {
		scanf_s("%c", &ch, 1);
		if (ch == 'q') {
#pragma warning(disable : 6258 6387 6001)
			// terminate the thread
			// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminatethread
			TerminateThread(hThread, 0x0);

#pragma warning(disable : 6387)
			// this is required as TerminateThread does not perform proper thread clean-up
			CloseHandle(hThread);
			
			// break out of loop
			_tprintf(_T("Thread is closed. Closing main application in 3 seconds\n"));
			Sleep(3000);
			break;
		}
	}
	
	return 0;
}
```
You might be wondering what does this `WINAPI` do. Read the [stackoverflow answer](https://stackoverflow.com/a/2348447) about this.

Thanks for reading this post. Follow the links to reach me

+ Email: tbhaxor@gmail.com
+ Twitter: [@tbhaxor](https://twitter.com/tbhaxor)
+ Facebook: [@tbhaxor](https://fb.com/tbhaxor)
+ GitHub: [@tbhaxor](https://github.com/tbhaxor)
+ LinkedIn: [@gurkirat--singh](https://www.linkedin.com/in/gurkirat--singh)
+ Instagram: [@_tbhaxor_](https://instagram.com/_tbhaxor_)