ISP – 3 rd Recitation “The joy of Windows API” Processes Threads Handles Relevant functions A simple code example
Process Wikipedia definition: A process is an instance of a computer program that is being sequentially executed by a computer system that has the ability to run several computer programs concurrently. A process runs in its own context and switching between processes requires context switching.
Thread Wikipedia definition: Threads are a way for a program to split itself into two or more simultaneously (or pseudo- simultaneously) running tasks. A thread is contained inside a process and different threads in the same process share some resources while different processes do not. Switching between threads of the same process requires less context switching.
An important reminder… This is not Physics… This is not Math… Programming languages and APIs, in particular, are made by humans. Understanding how to use it is important. Contemplating why something is done in a certain way and not differently is often futile.
Windows Objects and Signals Each resource the OS controls is considered an “object”. Examples: Processes, threads, mutexes, semaphores, etc. Each object is referred to in code by a “handle”. Each object can be in a signaled and non-signaled state. The meaning of the state changes for each object. Today we’re discussing processes Non-Signaled = Running Signaled = No longer running
Handle “Smart” pointer - an abstract reference to objects managed by the OS Handles don’t contain a memory address (unlike pointers). They contain a different numerical identifier. Handles should be stored, but they should never be directly changed by the programmer.
Creating a process Using CreateProcess(): Syntax : BOOL CreateProcess( LPCWSTR pszImageName, LPCWSTR pszCmdLine, LPSECURITY_ATTRIBUTES psaProcess, LPSECURITY_ATTRIBUTES psaThread, BOOL fInheritHandles, DWORD fdwCreate, LPVOID pvEnvironment, LPWSTR pszCurDir, LPSTARTUPINFOW psiStartInfo, LPPROCESS_INFORMATION pProcInfo ); Ouch… Thankfully, we don’t care about most of the parameters…
Creating a process Using createprocess(): Example : retVal=CreateProcess( NULL, // No module name (use command line). command, // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. NORMAL_PRIORITY_CLASS, // creation/priority flags. NULL, // Use parent's environment block. NULL, // Use parent's starting directory. &startinfo, // Pointer to STARTUPINFO structure. &procinfo // Pointer to PROCESS_INFORMATION structure. ) ; RED = Not too relevant for our purposes, can keep it like in this example Green = Interesting stuff we have to understand
Creating a process createprocess() interesting parameters: LPCWSTR pszCmdLineLPCWSTR pszCmdLine – A string containing the command line we’re going to execute to create the process. (“c:\isp\ex1.exe inf.txt opf.txt”) LPSTARTUPINFOW psiStartInfoLPSTARTUPINFOW psiStartInfo – A pointer to a STARTUPINFO struct variable containing various “Microsoft Windows” parameters. (window size, screen coordinates, etc) LPPROCESS_INFORMATION pProcInfoLPPROCESS_INFORMATION pProcInfo – A Pointer to a PROCESS_INFORMATION struct variable containing the handles and IDs of the process and thread that were just created. Input Output
PROCESS_INFORMATION Definition: typedef struct _PROCESS_INFORMATION { HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; } PROCESS_INFORMATION; hProcess - A handle to the newly created process. hThread - A handle to the primary thread of the newly created process. dwProcessId - A value that can be used to identify a process. dwThreadId - A value that can be used to identify a thread. Note : DWORD = 32bits unsinged integer
WaitForSingleObject() WaitForSingleObject() is used for waiting for an object to become “signaled”. Syntax : DWORD WaitForSingleObject( HANDLE hProcess, DWORD dwMilliseconds ); Reminder: Each object has a signaled and non signaled state and for each object the meaning is slightly different and depends on its function.
WaitForSingleObject() dwMilliseconds is a timeout period (in ms): 0 means that WaitForSingleObject() is used for polling the status. INFINITE means that our code is waiting for the object to become signaled, even infinitely. Other values are used as a timeout. If the object is not signaled then wait until signaled or timeout occurs. Return values : WAIT_OBJECT_0 (0) – The object is in a signaled state. WAIT_TIMEOUT (102h) – Timeout has elapsed, the object is nonsignaled. WAIT_FAILED (0xFFFFFFFF) – The function has failed
TerminateProcess() TerminateProcess() is used to brutally close a process. Syntax : BOOL TerminateProcess( HANDLE hProcess, UINT uExitCode ); Returns 0 if failed, nonzero if successful NOTE : Processes that end by themselves shouldn’t normally be terminated brutally like that.
GetExitCodeProcess() GetExitCodeProcess() tells us the exit code of a process. Syntax: BOOL CloseHandle(HANDLE hObject, *DWORD lpExitCode ); DWORD = unsigned long Note: lpExitCode gets the exit code value of the process as specified by the process itself or the TerminateProcess() function. If the process is still active, a value of STILL_ACTIVE (259) is returned.
CloseHandle() CloseHandle() is used to close a handle. Syntax: BOOL CloseHandle(HANDLE hObject ); Note: It’s imperative to close all handles of an object. If a handle remains, the OS continues to keep record of the object.