Processes and Threads in Win32

The Windows operating system manages execution through processes and threads. A process is an instance of a running program, containing its own memory space, resources, and security context. Threads are the smallest unit of execution within a process, allowing a single process to perform multiple tasks concurrently.

Understanding Processes

Every application you run on Windows, such as Notepad, your web browser, or a game, operates as a separate process. Each process has:

Key Win32 Process Functions

The Win32 API provides a rich set of functions for interacting with processes:

Creating Processes

The primary function for creating a new process is CreateProcess. It's a powerful function that allows specifying many details about the new process, including the executable name, command line arguments, environment variables, and security attributes.


BOOL CreateProcess(
  LPCTSTR               lpApplicationName,
  LPTSTR                lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL                  bInheritHandles,
  DWORD                 dwCreationFlags,
  LPVOID                lpEnvironment,
  LPCTSTR               lpCurrentDirectory,
  LPSTARTUPINFO         lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);
                

Key parameters include:

  • lpCommandLine: The command line to execute.
  • dwCreationFlags: Flags to control process creation (e.g., CREATE_SUSPENDED).
  • lpProcessInformation: A structure that receives information about the new process and its primary thread (handles, IDs).

Process Information

You can retrieve information about the current process or other processes using functions like:

  • GetCurrentProcess(): Returns a pseudo-handle to the current process.
  • OpenProcess(): Opens an existing process object to obtain a handle. Requires specifying the desired access rights (e.g., PROCESS_QUERY_INFORMATION).
  • GetProcessId(): Retrieves the process identifier for the specified handle.
  • GetExitCodeProcess(): Retrieves the exit code of a process.

HANDLE hProcess = GetCurrentProcess();
DWORD pid = GetProcessId(hProcess);
// Or to open another process:
HANDLE hOtherProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, otherPid);
                

Terminating Processes

You can terminate a process using TerminateProcess(). This is a forceful termination and should be used with caution as it doesn't allow the process to clean up resources.


BOOL success = TerminateProcess(hProcess, exitCode);
                

Understanding Threads

Threads are lightweight execution paths within a process. A process can have multiple threads running concurrently, enabling multitasking within a single application.

Key Win32 Thread Functions

Creating Threads

Threads are typically created using CreateThread(). This function allows you to specify the starting address of the thread's execution function and any parameters it needs.


HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  SIZE_T                dwStackSize,
  LPTHREAD_START_ROUTINE lpStartAddress,
  LPVOID                lpParameter,
  DWORD                 dwCreationFlags,
  LPDWORD               lpThreadId
);
                

lpStartAddress points to the function that the new thread will execute. The thread function typically has a signature like:


DWORD WINAPI MyThreadFunction(LPVOID lpParam);
                

Thread Synchronization

When multiple threads access shared resources, synchronization mechanisms are crucial to prevent race conditions and data corruption. Common synchronization objects include:

  • Mutexes (CreateMutex, ReleaseMutex): Allow only one thread to access a resource at a time.
  • Semaphores (CreateSemaphore, ReleaseSemaphore): Control access to a resource by a limited number of threads.
  • Events (CreateEvent, SetEvent, ResetEvent): Signal between threads.
  • Critical Sections (InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection): Lightweight synchronization for threads within the same process.

Example using a Critical Section:


CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);

// ... in thread function ...
EnterCriticalSection(&cs);
// Access shared data here
LeaveCriticalSection(&cs);
                

Thread Management

You can manage threads with functions like:

  • GetCurrentThreadId(): Retrieves the thread identifier of the calling thread.
  • Sleep(): Suspends the current thread for a specified interval.
  • WaitForSingleObject(): Waits until a specified object (like a thread handle) is in the signaled state.
  • ExitThread(): Terminates the current thread.

Inter-Process Communication (IPC)

While processes are isolated, they often need to communicate. The Win32 API offers various IPC mechanisms: