-1

I am trying to print and save the module names of a process.

But when printing the char array I get something that looks like an address.

#include <windows.h>
#include <TlHelp32.h>
#include <iostream>

int main() {

    MODULEENTRY32 me32;
    HWND hwnd = FindWindow(0, L"Window Name");
    DWORD dwPID;
    GetWindowThreadProcessId(hwnd, &dwPID);

    HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);

    me32.dwSize = sizeof(MODULEENTRY32);
    Module32First(hModuleSnap, &me32);
    std::cout << me32.szModule << std::endl;

    do
    {
        std::cout << me32.szModule << std::endl; // important line

    } while (Module32Next(hModuleSnap, &me32));

    return 0;
}

The output of this in my case was 00AFF53C for every module.

me32.szModule holds the name of the module as a char array.

Microsoft used the following in their example to convert and print the module name:

_tprintf( TEXT("\n\n MODULE NAME: %s"), me32.szModule );

But I think you can only use this to print the string.

So how do I convert and save the string in me32?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770

2 Answers2

2

Your project is being compiled with UNICODE defined (as evident by you being able to pass a wide string to FindWindow()). That causes Module32(First|Next) to map to Module32(First|Next)W, and MODULEENTRY32 to map to MODULEENTRY32W (and FindWindow() to map to FindWindowW()). Thus, the szModule field is a wchar_t[] array instead of a char[] array, like you are expecting. std::cout does not have an overload of operator<< for wchar_t data, only char data, but it has an overload for void*, and a fixed array decays into a pointer that can then be assigned to void*. That is why your code is printing out the string data as a memory address - you are printing out the address of the szModule field rather than its content.

You need to either:

  • use std::wcout instead, and preferably also explicitly use the W version of the API functions to match:

    #include <windows.h>
    #include <TlHelp32.h>
    #include <iostream>
    #include <string>
    
    int main() {
    
        MODULEENTRY32W me32;
        HWND hwnd = FindWindowW(0, L"Window Name");
        DWORD dwPID;
        GetWindowThreadProcessId(hwnd, &dwPID);
    
        HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
    
        me32.dwSize = sizeof(me32);
        if (Module32FirstW(hModuleSnap, &me32))
        {
            do
            {
                std::wstring moduleName = me32.szModule;
                std::wcout << moduleName << std::endl; // important line
            }
            while (Module32NextW(hModuleSnap, &me32));
        }
    
        return 0;
    }
    
  • explicitly use the A version of the API functions to match your use of std::cout:

    #include <windows.h>
    #include <TlHelp32.h>
    #include <iostream>
    #include <string>
    
    int main() {
    
        MODULEENTRY32A me32;
        HWND hwnd = FindWindow(0, L"Window Name");
        DWORD dwPID;
        GetWindowThreadProcessId(hwnd, &dwPID);
    
        HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
    
        me32.dwSize = sizeof(MODULEENTRY32A);
        if (Module32FirstA(hModuleSnap, &me32))
        {
            do
            {
                std::string moduleName = me32.szModule;
                std::cout << moduleName << std::endl; // important line
            }
            while (Module32NextA(hModuleSnap, &me32));
        }
    
        return 0;
    }
    
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

_tprintf() is a typedef for wprintf() if _UNICODE is defined, according to Microsoft's documentation.

Take a look at std::wcout.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
KostasRim
  • 2,053
  • 1
  • 16
  • 32