Enumerating All Processes

Task Manager is an example of a program that enumerates all running processes on Windows NT. 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.

#include <windows.h>
#include <stdio.h>
#include "psapi.h"

void PrintProcessNameAndID( DWORD processID )
{
    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 )
    {
        HMODULE hMod;
        DWORD cbNeeded;

        if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), 
             &cbNeeded) )
        {
            GetModuleBaseName( hProcess, hMod, szProcessName, 
                               sizeof(szProcessName) );
        }
    }

    // Print the process name and identifier.

    printf( "%s (Process ID: %u)\n", szProcessName, processID );

    CloseHandle( hProcess );
}

void main( )
{
    // Get the list of process identifiers.

    DWORD aProcesses[1024], cbNeeded, cProcesses;
    unsigned int i;

    if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
        return;

    // Calculate how many process identifiers were returned.

    cProcesses = cbNeeded / sizeof(DWORD);

    // Print the name and process identifier for each process.

    for ( i = 0; i < cProcesses; i++ )
        PrintProcessNameAndID( aProcesses[i] );
}

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 only the process identifier. 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.