Incorrect SymLoadModuleEx image name.

Aleksandr Kazakov 1 Reputation point

I'm trying to load module for dbghelp.dll in my code with SymSetOptions(SYMOPT_DEBUG):

TCHAR  szImageName[MAX_PATH] = TEXT("C:\\Windows\\SysWOW64\\dbghelp.dll");

            module = SymLoadModuleEx(hProcess,  // our unique id
                NULL,      // no open file handle to image
                szImageName,   // name of image to load
                NULL,      // no module name - dbghelp will get it
                0,         // no base address - dbghelp will get it
                0,         // no module size - dbghelp will get it
                NULL,      // no special MODLOAD_DATA structure
                0);        // flags

And the log information is:

DBGHELP: Symbol Search Path: .
10:52:39 +3 [base] DBGHELP: No header for C.  Searching for image on disk
10:52:39 +3 [base] DBGHELP: <>\C - file not found
10:52:39 +3 [base] DBGHELP: symsrv.dll load failure
10:52:39 +3 [base] DBGHELP: C not found in .
10:52:39 +3 [base] DBGHELP: C - no symbols loaded

Why is it looking for module with name C if I m passing the full path?

A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,591 questions
{count} votes

4 answers

Sort by: Most helpful
  1. RLWA32 41,831 Reputation points

    The docs indicate "To call the Unicode version of this function, define DBGHELP_TRANSLATE_TCHAR."

    Was this done?

  2. Minxin Yu 10,461 Reputation points Microsoft Vendor

    Hi, @Aleksandr Kazakov

    Processes explicitly linking to a DLL call GetProcAddress to obtain the address of an exported function in the DLL. Because you are calling the DLL function through a pointer and there is no compile-time type checking, make sure that the parameters to the function are correct so that you do not overstep the memory allocated on the stack and cause an access violation.

    For your reference: Dynamically load a function from a DLL
    Or implicit link: Walkthrough: Create and use your own Dynamic Link Library (C++)

    Best regards,

    Minxin Yu

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

  3. RLWA32 41,831 Reputation points

    The typedefs that you use for dynamically linking functions from dbghelp.dll are incorrect. They omit the __stdcall calling convention.

  4. RLWA32 41,831 Reputation points

    Following example uses dynamic linking with dbghelp.dll to invoke SymLoadModuleEx(W) depending on the character set setting.

    #define WIN32_LEAN_AND_MEAN  
    #include <Windows.h>  
    #ifdef UNICODE  
    #include <DbgHelp.h>  
    #include <stdio.h>  
    #include <tchar.h>  
    typedef decltype(SymInitialize) *SI;  
    typedef decltype(SymGetOptions) *SGO;  
    typedef decltype(SymSetOptions) *SSO;  
    typedef decltype(SymLoadModuleEx) *SLMX;  
    int main()  
        TCHAR szModule[]{ _T("C:\\Windows\\SysWOW64\\dbghelp.dll") };  
        // Set DLL search order so that Dbghelp.dll version from Windows SDK is loaded and symsrv.dll can be loaded  
        if (!SetDllDirectory(DBGHELPDLL))  
            _tprintf_s(_T("SetDllDirectory for %s failed with %d\n"), DBGHELPDLL, GetLastError());  
        HMODULE hMod = LoadLibrary(_T("dbghelp.dll"));  
        if (hMod)  
    #ifdef UNICODE		  
            SI siInitialize = reinterpret_cast<SI>(GetProcAddress(hMod, "SymInitializeW"));  
            SI siInitialize = reinterpret_cast<SI>(GetProcAddress(hMod, "SymInitialize"));  
            if (!siInitialize)  
                _tprintf_s(_T("GetProcAddress failed with code %d\n"), GetLastError());  
            SGO sgoGetOptions = reinterpret_cast<SGO>(GetProcAddress(hMod, "SymGetOptions"));  
            if (!sgoGetOptions)  
                _tprintf_s(_T("GetProcAddress failed with code %d\n"), GetLastError());  
            SSO ssoSetOptions = reinterpret_cast<SSO>(GetProcAddress(hMod, "SymSetOptions"));  
            if (!ssoSetOptions)  
                _tprintf_s(_T("GetProcAddress failed with code %d\n"), GetLastError());  
    #ifdef UNICODE  
            SLMX slmxLoadModuleEx = reinterpret_cast<SLMX>(GetProcAddress(hMod, "SymLoadModuleExW"));  
            SLMX slmxLoadModuleEx = reinterpret_cast<SLMX>(GetProcAddress(hMod, "SymLoadModuleEx"));  
            if (!slmxLoadModuleEx)  
                _tprintf_s(_T("GetProcAddress failed with code %d\n"), GetLastError());  
            if (siInitialize && sgoGetOptions && ssoSetOptions && slmxLoadModuleEx)  
                HANDLE hProcess = GetCurrentProcess();  
                auto ret = siInitialize(hProcess, NULL, FALSE);  
                if (ret)  
                    auto opts = sgoGetOptions();  
                    opts |= SYMOPT_DEBUG;  
                    auto base = slmxLoadModuleEx(hProcess, nullptr, szModule, nullptr, 0, 0, nullptr, 0);  
                    if (base)  
                        _tprintf_s(_T("%s load address is %#.16llx"), szModule, base);  
                        auto err = GetLastError();  
                        if (err == ERROR_SUCCESS)  
                            _tprintf_s(_T("%s already loaded\n"), szModule);  
                            _tprintf_s(_T("SymLoadModuleEx failed with code %d\n"), err);  
        return 0;  

    The DLL search path for the Windows SDK version of dbghelp.dll was set with a preprocessor macro -


    Debug output captured by Sysinternals DebugView utility -


    0 comments No comments