My Training Period: yy hours. Before you begin, read someinstruction here.
The expected abilities:
Note: For Multithreaded program examples, you have to set your project toMultithread project type.
Creating Processes
The CreateProcess() function creates a new process, which runs independently of the creating process. However, for simplicity, the relationship is referred to as a parent-child relationship. The following code fragment demonstrates how to create a process.
// ForWinXp #define _WIN32_WINNT 0x0501 #include <windows.h> #include <stdio.h>
int main() { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); // Start the child process. If not OK... if(!CreateProcess("C:\\WINDOWS\\system32\\cmd.exe",// module name. NULL, // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. 0, // No creation flags. NULL, // Use parent's environment block. NULL, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &pi) // Pointer to PROCESS_INFORMATION structure. )
|
// Then, give some prompt...
printf("\nSorry! CreateProcess() failed.\n\n");
//else, give some prompt...
else
{
printf("\nWell, CreateProcess() looks OK.\n");
printf("exit after 5000 ms...\n\n");
}
// Wait until child process exits after 5000 ms.
WaitForSingleObject(pi.hProcess, 5000);
printf("\n");
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
A sample output:
Verify through Windows Task Manager.
If CreateProcess() succeeds, it returns aPROCESS_INFORMATION structure containing handles and identifiers for the new process and its primary thread. The thread and process handles are created with full access rights, although access can be restricted if you specify security descriptors. When you no longer need these handles, close them by using theCloseHandle() function. You can also create a process using theCreateProcessAsUser() or CreateProcessWithLogonW() function. This allows you to specify the security context of the user account in which the process will execute.
Creating Threads
The CreateThread() function creates a new thread for a process. The creating thread must specify the starting address of the code that the new thread is to execute. Typically, the starting address isthe name of a function defined in the program code. This function takes a single parameter and returns aDWORD value. A process can have multiple threads simultaneously executing the same function. The following example demonstrates how to create a new thread that executes the locally defined function, MyThreadFunction().
// ForWinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <conio.h>
DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{
printf("The parameter: %d.\n", *(DWORD*)lpParam);
return 0;
}
int main(void)
{
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
// Let try a loop...
for(int x = 1; x <= 5; x++)
{
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
MyThreadFunction, // thread function
&dwThrdParam, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
// Check the return value for success. If something wrong...
if (hThread == NULL)
printf("CreateThread() failed, error: %d.\n", GetLastError());
//else, gives some prompt...
else
{
printf("It seems the CreateThread() is OK lol!\n");
printf("The thread ID: %d.\n", dwThreadId);
}
if (CloseHandle(hThread) != 0)
printf("Handle to thread closed successfully.\n");
}
return 0;
}
A sample output:
What a mess! Running the program for second time producing different output :o). Whatever, we just want to see some action here about creating threads.
For simplicity, this example passes a pointer to a value as an argument to the thread function. This could be a pointer to any type of data or structure, or it could be omitted altogether by passing a NULL pointer and deleting the references to the parameter in MyThreadFunction().It is risky to pass the address of a local variable if the creating thread exits before the new thread, because the pointer becomes invalid. Instead, either pass a pointer to dynamically allocated memory or make the creating thread wait for the new thread to terminate. Data can also be passed from the creating thread to the new thread using global variables. With global variables, it is usually necessary to synchronize access by multiple threads.
In processes where a thread might create multiple threads to execute the same code, it is inconvenient to use global variables. For example, a process that enables the user to open several files at the same time can create a new thread for each file, with each of the threads executing the same thread function. The creating thread can pass the unique information (such as the file name) required by each instance of the thread function as an argument. You cannot use a single global variable for this purpose, but you could use a dynamically allocated string buffer.The creating thread can use the arguments to CreateThread() to specify the following:
The security attributes for the handle to the new thread. These security attributes include an inheritance flag that determines whether the handle can be inherited by child processes. The security attributes also include a security descriptor, which the system uses to perform access checks on all subsequent uses of the thread's handle before access is granted.
The initial stack size of the new thread. The thread's stack is allocated automatically in the memory space of the process; the system increases the stack as needed and frees it when the thread terminates.
A creation flag that enables you to create the thread in a suspended state. When suspended, the thread does not run until theResumeThread() function is called.
You can also create a thread by calling the CreateRemoteThread() function. This function is used by debugger processes to create a thread that runs in the address space of the process being debugged.
Enumerating All Processes
Task Manager is an example of a program that enumerates all running processes. It is implemented using data from the performance registry. The following sample code uses the EnumProcesses() function to enumerate the current processes in the system. This method is easier than using the performance registry. Don’t forget to include thepsapi.lib library in your project. The steps are shown below.
Select and right click your project folder → Select the Properties context menu.
Or you can access the project properties page through the Project menu → your_project_name Properties... as shown below.
Select the Linker menu on the left pane → On the Additional Dependencies setting, click the ...
Manually, type the library name and click the OK button.
// ForWinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
void PrintProcessNameAndID(DWORD processID)
{
// Initialize or default to "unknown"
char szProcessName[MAX_PATH] = "<unknown>";
// Get a handle to the process.
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
// Get the process name.
if (hProcess != NULL)
{
HMODULE hMod;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
{
GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName));
}
}
// Print the process name and identifier.
printf("%-30s %5u\n", szProcessName, processID);
CloseHandle(hProcess);
}
int main()
{
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsignedint i;
// If fail...
if (!EnumProcesses(aProcesses,sizeof(aProcesses), &cbNeeded))
return 1;// or print some meaningful message...
else
printf("Enumprocesses() is OK.\n");
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name and process identifier for each process.
printf("Process Name Process ID\n");
printf("============ ==========\n");
for (i = 0; i < cProcesses; i++)
PrintProcessNameAndID(aProcesses[i]);
return 0;
}
A sample output:
Enumprocesses() is OK.
Process Name Process ID
============ ==========
<unknown> 0
<unknown> 4
smss.exe 468
<unknown> 528
winlogon.exe 552
services.exe 596
lsass.exe 608
svchost.exe 756
<unknown> 812
svchost.exe 848
<unknown> 900
<unknown> 1016
spoolsv.exe 1116
inetinfo.exe 1252
mdm.exe 1268
slserv.exe 1368
snmp.exe 1396
svchost.exe 1436
<unknown> 1780
Explorer.EXE 364
SOUNDMAN.EXE 444
uGuru.exe 460
AGRSMMSG.exe 312
PDVDServ.exe 496
OpwareSE2.exe 504
ctfmon.exe 524
msmsgs.exe 520
wscntfy.exe 612
acrotray.exe 720
uGuru_Event_Receiver.exe 880
GammaTray.exe 916
my015lit.exe 1164
NaturalColorLoad.exe 1216
WINWORD.EXE 2308
devenv.exe 3468
mspaint.exe 1088
vcspawn.exe 3284
myprocess.exe 3280
Press any key to continue
The main function obtains a list of processes by using the EnumProcesses() function. For each process, main calls the PrintProcessNameAndID() function, passing it the process identifier. PrintProcessNameAndID() in turn calls the OpenProcess() function to obtain the process handle. If OpenProcess() fails, the output shows the process name as <unknown>. For example,OpenProcess() fails for the Idle and CSRSS processes because their access restrictions prevent user-level code from opening them. Next, PrintProcessNameAndID() calls the EnumProcessModules() function to obtain the module handles. Finally, PrintProcessNameAndID() calls the GetModuleBaseName() function to obtain the name of the executable file and displays the name along with the process identifier.
Further reading and digging:
Microsoft C references, online MSDN.
Microsoft Visual C++, online MSDN.
ReactOS - Windows binary compatible OS - C/C++ source code repository, Doxygen.
Linux Access Control Lists (ACL) info can be found atAccess Control Lists.
For Multi-bytes, Unicode characters and Localization please refer to Locale, wide characters & Unicode (Story) and Windows users & groups programming tutorials (Implementation).
Structure, enum, union and typedef story can be found C/C++ struct, enum, union & typedef.
Check the best selling C / C++ and Windows books at Amazon.com.