The process status application programming interface (PSAPI) is a helper library that makes it easier for you to obtain information about processes and device drivers. These functions are available in Psapi.dll (you must include the Psapi.lib in your project). The same information is generally available through the performance data in the registry.
The process status API (PSAPI) provides sets of functions for retrieving the following information:
The following sections explain the detail of the process information that can be extracted by PSAPI.
The system maintains a list of running processes. You can retrieve the identifiers for these processes by calling the EnumProcesses() function. This function fills an array of DWORD values with the identifiers of all processes in the system. Many functions in PSAPI require a process handle. To obtain a process handle for a running process, pass its process identifier (obtained from EnumProcesses()) to the OpenProcess() function. Remember to call the CloseHandle() function when you are finished with the process handle.
A module is an executable file or DLL. Each process consists of one or more modules. You can retrieve the list of module handles for a process by calling the EnumProcessModules() function. This function fills an array of HMODULE values with the module handles for the specified process. The first module is the executable file. Remember that these module handles are most likely from some other process, so you cannot use them with functions such as GetModuleFileName(). However, you can use PSAPI functions to obtain information about a module from another process. The following procedure describes how to obtain module information from another process. To obtain module information from another process
If an application requires module information for the current process, it should use the GetModuleFileName() function instead of the PSAPI module functions. This helps application performance in two ways:
The GetModuleBaseName() and GetModuleFileNameEx() functions are primarily designed for use by debuggers and similar applications that must extract module information from another process. If the module list in the target process is corrupted or is not yet initialized, or if the module list changes during the function call as a result of DLLs being loaded or unloaded, these functions may fail or return incorrect information.
Device Driver Information
Device drivers and modules are similar in that they are both based on PE (Portable Executable format) files. However, while each process has its own private list of loaded modules, device drivers have modules that are global to the system. Therefore, PSAPI has specific functions for obtaining the list of device drivers and their names. You can retrieve the load address for each device driver by calling the EnumDeviceDrivers() function. This function fills an array of LPVOID values with the load addresses of all device drivers in the system. The GetDeviceDriverBaseName() function takes a driver load address as input and fills in a buffer with the base name of the driver (for example, Win32k.sys). A related function, GetDeviceDriverFileName(), takes the same parameters and returns the path to the device driver (for example, C:\Windows\System32\Win32k.sys).
Process Memory Usage Information
The GetProcessMemoryInfo() function takes a process handle as input and fills a PROCESS_MEMORY_COUNTERS structure with information about the memory statistics for the process. The cb member receives the size of the structure. The PageFaultCount member receives the number of page faults. The remaining members receive the current and peak memory usage in the following categories:
The working set is the amount of memory physically mapped to the process context at a given time. Memory in the paged pool is system memory that can be transferred to the paging file on disk (paged) when it is not being used. Memory in the nonpaged pool is system memory that cannot be paged to disk as long as the corresponding objects are allocated. The pagefile usage represents how much memory is set aside for the process in the system paging file. When memory usage is too high, the virtual memory manager pages selected memory to disk. When a thread needs a page that is not in memory, the memory manager reloads it from the paging file.
Working Set Information
The working set of a process is the amount of memory physically mapped to its process context. PSAPI enables you to take snapshots of the working set or to monitor the working set. The QueryWorkingSet() or QueryWorkingSetEx() function fills a buffer with a snapshot of the information for every page in the current working set of the specified process. The function reports only those pages that are physically present at the exact moment it is called. You can use working set monitoring to find out how much additional RAM a particular operation takes (for example, saving a file). To begin monitoring the working set, call the InitializeProcessForWsWatch() function. Not all processes let you read their working set information, so be sure that the function returns a nonzero value before you continue. Next, call the GetWsChanges() function. This function reports only the pages that have been loaded in memory since you began monitoring the working set. The function returns data in an array of PSAPI_WS_WATCH_INFORMATION structures, one structure for each new page added to the working set of the process. The structure tells you which pages are in memory, and what caused the system to page them in. The EmptyWorkingSet() function takes a process handle. It removes as many pages as possible from the process working set. This operation is useful primarily for testing and tuning. Note that the SetProcessWorkingSetSize() function does the same thing if you pass it -1 for the minimum and maximum sizes.
Memory-Mapped File Information
A memory-mapped file (or file mapping) is the result of associating a file's contents with a portion of the virtual address space of a process. It can be used to share a file or memory between two or more processes. The GetMappedFileName() function receives a process handle and a pointer to an address as input. If the address is within a memory-mapped file in the virtual address space of the process, the function returns the name of the memory-mapped file. The file names returned by GetMappedFileName() use device form, rather than drive letters. For example, the file name c:\winnt\system32\ctype.nls would look like this in device form: