Toolhelp is an addon library for Windows 3.1. You can use toolhelp functions to enumerate processes, threads, modules and heaps. As such, it's a very valuable tool indeed. So when Windows 95 came out, toolhelp was integrated into the system. The version of toolhelp under Windows 95 is 32-bit so it's renamed to toolhelp32. However, toolhelp32 is not available on Windows NT 4.0.
Under the hood, toolhelp functions do their magic through intimate knowledge of the underlying operating system. In order to enumerate processes, they must know about the process databases. If you're interested in such information, you should read Windows 95 System Programming Secrets by Matt Pietrek.
We can divide functions in toolhelp32 into 4 groups:
The usage of each catergory is very similar so I'll show how to
use process and module enumeration functions.
I have written an example program with source code that enumerates
all processes and modules in each process. You can download the example
here
Before you can use toolhelp32 functions, you must get a handle to a snapshot. A snapshot tells toolhelp32 what you want it to do. You must call CreateToolhelp32Snapshot function to obtain the snapshot handle first. Its syntax is below:
This function takes two parameters:
dwFlags : Specify the type of snapshot you want.
For example if you want to enumerate processes, you should use TH32CS_SNAPPROCESS.
th32processID : The processID of the process which you want the function(s) to operate on. This parameter is used only when TH32CS_SNAPHEAPLIST or TH32CS_SNAPMODULE is specified because heaps and modules are dependent on processes. You can specify 0 as this parameter, which toolhelp32 will interpret as the processID of the current process.
CreateToolhelp32Snapshot returns a handle to the snapshot you request. After you're done with it, you must call CloseHandle to close it.
After we obtain the snapshot handle, we can call toolhelp32 functions.
I'll show how to enumerate processes first.
To enumerate processes, we must call CreateToolhelp32Snapshot
with TH32CS_SNAPPROCESS, and th32processID
should be zero. Then we call Process32First
to get the info on the first process and Process32Next
to retrieve the remaining process info. These functions are defined as follows:
hSnapshot : the snapshot handle from CreateToolhelp32Snapshot
lppe : pointer to a PROCESSENTRY32 structure which is defined like this:
PROCESSENTRY32 STRUCT DWORD
DWORD | ? | ; The size of this structure | |
DWORD | ? | ; The number of instances(?) | |
DWORD | ? | ; This process's processID | |
DWORD | ? | ; Default heap's ID | |
DWORD | ? | ; Associated exe's moduleID | |
DWORD | ? | ; Number of threads in the process | |
DWORD | ? | ; This process's parent processID | |
DWORD | ? | ; Base priority of process's threads | |
DWORD | ? | ; Reserved | |
db 260 dup | (?) | ; Full filename (including path) of the exe file that owns the process. |
Both Process32First and Process32Next
return TRUE if the operation is successful, FALSE if there's no process left to enumerate.
Let's see a code snippet :
.data
.data?
pe32 PROCESSENTRY32 <>
.code
Module enumeration is similar to the operation above but with a small difference: you must obtain the processID of the process you want to enumerate modules. You can use th32processID member from PROCESSENTRY32 structure as the second parameter of CreateToolhelp32Snapshot function. There are two functions that perform module enumeration:
hSnapshot : the snapshot handle.
lpme : pointer to a MODULEENTRY32 structure which is defined like this:
MODULEENTRY32 STRUCT DWORD
DWORD | ? | ; The size in bytes of this structure | |
DWORD | ? | ; This module | |
DWORD | ? | ; Owning process | |
DWORD | ? | ; Global usage count on the module | |
DWORD | ? | ; Module usage count in th32ProcessID's context | |
DWORD | ? | ; Base address of module in th32ProcessID's context | |
DWORD | ? | ; Size in bytes of module starting at modBaseAddr | |
DWORD | ? | ; The hModule of this module in th32ProcessID's context | |
db 256 dup | (?) | ; The module name (without path) | |
db 260 dup | (?) | ; The full path name of the module |
Like Process32First and Process32Next, the return value is TRUE if the operation is successful and FALSE if there's no module left to enumerate.
Now, let's see them in action. We'll enumerate all modules in the current process.
.data
.data
.code
The story with the thread enumeration functions is the same as module
functions. You have to specify the process which you want to enumerate
the threads.
The functions in toolhelp32 are now stored in kernel32.dll so you don't
need a separate dll for it. If you want similar functions under Windows
NT 4.0, you must use psapi.dll.