Home > database >  How to list all modules of a certain process ID
How to list all modules of a certain process ID

Time:05-26

I've written a little program that lists all DLLs of a given process ID:

#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <memory>
#include <vector>
#include <charconv>

using namespace std;

using XHANDLE = unique_ptr<void, decltype([]( void *h ) { h && h != INVALID_HANDLE_VALUE && CloseHandle( (HANDLE)h ); })>;

vector<MODULEENTRY32W> getModules( DWORD dwProcessId );
[[noreturn]]
void throwSysErr( char const *str );

int main( int argc, char **argv )
{
    try
    {
        if( argc < 2 )
            return EXIT_FAILURE;
        DWORD dwProcesId =
            [&]() -> DWORD
            {
                DWORD dwRet = 0;
                if( from_chars_result fcr = from_chars( argv[1], argv[1]   strlen( argv[1] ), dwRet ); fcr.ec != errc() || *fcr.ptr )
                    throw system_error( (int)fcr.ec, generic_category(), "invalid process id" );
                return dwRet;
            }();
        for( MODULEENTRY32W const &me : getModules( dwProcesId ) )
            wcout << me.szExePath << endl;
    }
    catch( exception const &exc )
    {
        cout << exc.what() << endl;
    }
}

vector<MODULEENTRY32W> getModules( DWORD dwProcessId )
{
    constexpr char const *ERR_STR = "can't list modules";
    XHANDLE xhToolHelp( CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId ) );
    if( xhToolHelp.get() == INVALID_HANDLE_VALUE )
        throwSysErr( ERR_STR );
    vector<MODULEENTRY32W> ret;
    MODULEENTRY32W me;
    me.dwSize = sizeof me;
    if( !Module32FirstW( xhToolHelp.get(), &me ) )
        if( GetLastError() == ERROR_NO_MORE_FILES )
            return ret;
        else
            throwSysErr( ERR_STR );
    for( ; ; )
    {
        ret.emplace_back( me );
        me.dwSize = sizeof me;
        if( !Module32NextW( xhToolHelp.get(), &me ) )
            if( GetLastError() == ERROR_NO_MORE_FILES )
                return ret;
            else
                throwSysErr( ERR_STR );
    }
}

[[noreturn]]
void throwSysErr( char const *str )
{
    throw system_error( (int)GetLastError(), system_category(), str );
}

This does work correctly with most programs. I tried this with some process IDs running on my system. But for some 32 bit processes it lists only some essential DLLs. F.e. for Adobe Digital Editions (ADE) it lists:

C:\Program Files (x86)\Adobe Digital Editions\DigitalEditions.exe
C:\Windows\SYSTEM32\ntdll.dll
C:\Windows\System32\wow64.dll
C:\Windows\System32\wow64base.dll
C:\Windows\System32\wow64win.dll
C:\Windows\System32\wow64con.dll
C:\Windows\System32\wow64cpu.dll

For sure this process isn't only running on such a small number of DLLs.
What's going on with 32 bit processes processes like ADE ?

CodePudding user response:

The DLLs you have shown are all 64bit DLLs that are loaded into every 32bit process to run the WOW64 emulation. Since your app is using TH32CS_SNAPMODULE and displaying 64bit DLLs, that suggests your app is running as a 64bit process. The CreateToolhelp32Snapshot() documentation says:

TH32CS_SNAPMODULE
0x00000008

Includes all modules of the process specified in th32ProcessID in the snapshot. To enumerate the modules, see Module32First. If the function fails with ERROR_BAD_LENGTH, retry the function until it succeeds.

64-bit Windows:  Using this flag in a 32-bit process includes the 32-bit modules of the process specified in th32ProcessID, while using it in a 64-bit process includes the 64-bit modules. To include the 32-bit modules of the process specified in th32ProcessID from a 64-bit process, use the TH32CS_SNAPMODULE32 flag.

TH32CS_SNAPMODULE32
0x00000010

Includes all 32-bit modules of the process specified in th32ProcessID in the snapshot when called from a 64-bit process. This flag can be combined with TH32CS_SNAPMODULE or TH32CS_SNAPALL. If the function fails with ERROR_BAD_LENGTH, retry the function until it succeeds.

CodePudding user response:

You were all right. I now conditionally added TH32CS_SNAPMODULE32:

vector<MODULEENTRY32W> getModules( DWORD dwProcessId )
{
    constexpr char const *ERR_STR = "can't list modules";
    XHANDLE xhProcess( OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwProcessId ) );
    BOOL fWow64PRocess;
    if( !xhProcess.get() || !IsWow64Process( xhProcess.get(), &fWow64PRocess ) )
        throwSysErr( ERR_STR );
    XHANDLE xhToolHelp( CreateToolhelp32Snapshot( TH32CS_SNAPMODULE | (fWow64PRocess ? TH32CS_SNAPMODULE32 : 0), dwProcessId ) );
    if( xhToolHelp.get() == INVALID_HANDLE_VALUE )
        throwSysErr( ERR_STR );
    vector<MODULEENTRY32W> ret;
    MODULEENTRY32W me;
    me.dwSize = sizeof me;
    if( !Module32FirstW( xhToolHelp.get(), &me ) )
        if( GetLastError() == ERROR_NO_MORE_FILES )
            return ret;
        else
            throwSysErr( ERR_STR );
    for( ; ; )
    {
        ret.emplace_back( me );
        me.dwSize = sizeof me;
        if( !Module32NextW( xhToolHelp.get(), &me ) )
            if( GetLastError() == ERROR_NO_MORE_FILES )
                return ret;
            else
                throwSysErr( ERR_STR );
    }
}
  • Related