PARENT PROCESS
|
+-- CreateProcessA/CreateProcessW/
| CreateProcessAsUserA/CreateProcessAsUserW/
| CreateProcessWithLogonW/CreateProcessWithTokenW
| |
| +-- CHILD already loaded with new program
|
+-- Parent monitors child (WaitForSingleObject/WaitForMultipleObjects)
|
+-- Parent closes handles (CloseHandle)
β Key points:
CreateProcess* functions β Create a new child process and
load the executable immediately (no separate exec call).WaitForSingleObject() or WaitForMultipleObjects().CloseHandle() on the process and thread handles to avoid leaks.CreateProcessA(), CreateProcessW(), etc.WaitForSingleObject(),
WaitForMultipleObjects().GetExitCodeProcess().CloseHandle().| Function | Purpose | Notes |
|---|---|---|
CreateProcessA() |
Create a process (ANSI version) | Traditional method for creating a process |
CreateProcessW() |
Create a process (Unicode version) | Use this for wide-character (UTF-16) strings |
CreateProcessAsUserA() |
Create a process as another user (ANSI version) | Requires impersonation |
CreateProcessAsUserW() |
Create a process as another user (Unicode version) | Requires impersonation |
CreateProcessWithLogonW() |
Create a process with logon credentials | Useful for impersonating a user with a password |
CreateProcessWithTokenW() |
Create a process with an access token | Used to launch a process under a token |
CreateProcessA()#include <windows.h>
int main() {
STARTUPINFO si = {0};
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
if (CreateProcessA(
"C:\\Windows\\System32\\notepad.exe", // Program to run
NULL, // Command line arguments
NULL, // Process attributes
NULL, // Thread attributes
FALSE, // Inherit handles?
0, // Creation flags
NULL, // Environment
NULL, // Current directory
&si, // Startup info
&pi // Process info
)) {
// Wait for the process to exit
WaitForSingleObject(pi.hProcess, INFINITE);
// Get exit code
DWORD exitCode;
GetExitCodeProcess(pi.hProcess, &exitCode);
printf("Exit code: %lu\n", exitCode);
// Clean up handles
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return 0;
}
CreateProcessW()#include <windows.h>
int main() {
STARTUPINFO si = {0};
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
if (CreateProcessW(
L"C:\\Windows\\System32\\notepad.exe", // Program to run
NULL, // Command line arguments
NULL, // Process attributes
NULL, // Thread attributes
FALSE, // Inherit handles?
0, // Creation flags
NULL, // Environment
NULL, // Current directory
&si, // Startup info
&pi // Process info
)) {
// Wait for the process to exit
WaitForSingleObject(pi.hProcess, INFINITE);
// Get exit code
DWORD exitCode;
GetExitCodeProcess(pi.hProcess, &exitCode);
printf("Exit code: %lu\n", exitCode);
// Clean up handles
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return 0;
}
CreateProcessA() but works with wide-character (UTF-16) paths
and command lines.CreateProcessAsUserA()#include <windows.h>
#include <userenv.h>
int main() {
HANDLE hToken;
STARTUPINFO si = {0};
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
// Assume the token is already opened as hToken
if (CreateProcessAsUserA(
hToken, // Access token for impersonation
"C:\\Windows\\System32\\notepad.exe", // Program to run
NULL, // Command line arguments
NULL, // Process attributes
NULL, // Thread attributes
FALSE, // Inherit handles?
0, // Creation flags
NULL, // Environment
NULL, // Current directory
&si, // Startup info
&pi // Process info
)) {
// Wait for the process to exit
WaitForSingleObject(pi.hProcess, INFINITE);
// Clean up handles
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return 0;
}
CreateProcessWithLogonW()#include <windows.h>
int main() {
if (CreateProcessWithLogonW(
L"user", // User name
NULL, // Domain (NULL for local machine)
L"password", // Password
LOGON_NETCREDENTIALS_ONLY, // Logon flags
L"C:\\Windows\\System32\\notepad.exe", // Program to run
NULL, // Command line arguments
0, // Creation flags
NULL, // Environment
NULL, // Current directory
NULL, // Startup info
NULL // Process information
)) {
printf("Process created successfully.\n");
}
return 0;
}
CreateProcessWithTokenW()#include <windows.h>
int main() {
HANDLE hToken;
// Assume hToken is obtained through OpenProcessToken, etc.
if (CreateProcessWithTokenW(
hToken, // Access token
LOGON_WITH_PROFILE, // Logon flags
NULL, // Application name
L"C:\\Windows\\System32\\notepad.exe", // Program to run
0, // Creation flags
NULL, // Environment
NULL, // Current directory
NULL, // Startup info
NULL // Process information
)) {
printf("Process created with token.\n");
}
return 0;
}
| Function | Purpose | Notes |
|---|---|---|
WaitForSingleObject() |
Wait for a single process to finish | Blocks until the specified process exits |
WaitForMultipleObjects() |
Wait for multiple processes to finish | Blocks until one or more processes finish |
GetExitCodeProcess() |
Retrieve the exit code of a process | Retrieves the termination status of a process |
WaitForSingleObject()#include <windows.h>
int main() {
HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid); // Get process handle
WaitForSingleObject(hProcess, INFINITE); // Wait until process exits
DWORD exitCode;
GetExitCodeProcess(hProcess, &exitCode); // Retrieve the exit code
CloseHandle(hProcess); // Close handle
printf("Exit code: %lu\n", exitCode);
return 0;
}
WaitForMultipleObjects()#include <windows.h>
int main() {
HANDLE hProcesses[2];
hProcesses[0] = OpenProcess(SYNCHRONIZE, FALSE, pid1);
hProcesses[1] = OpenProcess(SYNCHRONIZE, FALSE, pid2);
DWORD result = WaitForMultipleObjects(2, hProcesses, TRUE, INFINITE); // Wait for all processes
if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + 2) {
DWORD exitCode;
for (int i = 0; i < 2; ++i) {
GetExitCodeProcess(hProcesses[i], &exitCode);
printf("Process %d exit code: %lu\n", i, exitCode);
}
}
CloseHandle(hProcesses[0]);
CloseHandle(hProcesses[1]);
return 0;
}
GetExitCodeProcess()#include <windows.h>
int main() {
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
DWORD exitCode;
if (GetExitCodeProcess(hProcess, &exitCode)) {
printf("Exit Code: %lu\n", exitCode);
}
CloseHandle(hProcess);
return 0;
}
After creating processes and waiting for them, always ensure you clean up by closing
handles. This includes process and thread handles created by CreateProcess*()
functions.