How to get HMODULE of msvcr90.dll

Because Microsoft C++ Runtime library is distributed as a side-by-side assembly, GetModuleHandle and LoadLibrary is no longer available to locate the library within the process. Both API calls would return NULL handle.

HMODULE hModule = GetModuleHandle(_T("msvcr90.dll"));
HMODULE hModule = LoadLibrary(_T("msvcr90.dll"));

Still, how to locate the modules in order to, for example, be able to check DLL version? Process Status API (PSAPI) can help:

#include <psapi.h>
#pragma comment(lib, "psapi.lib")

...

DWORD nDataSize = 4 << 10; // 4K
EnumProcessModules(GetCurrentProcess(), NULL, 0, &nDataSize);
nDataSize += nDataSize / 2;
CTempBuffer<HMODULE> phModules;
ATLENSURE_THROW(phModules.AllocateBytes(nDataSize), E_OUTOFMEMORY);
if(EnumProcessModules(GetCurrentProcess(), phModules, nDataSize, &nDataSize))
{
    const SIZE_T nCount = nDataSize / sizeof *phModules;
    for(SIZE_T nIndex = 0; nIndex < nCount; nIndex++)
    {
        CPath sPath = _VersionInfoHelper::GetModulePath(phModules[nIndex]); // uses GetModuleFileName
        if(_tcsicmp(FindFileName(sPath), _T("msvcr90.dll")) == 0)
        {
            // NOTE: Here we found it
            ATLTRACE2(atlTraceGeneral, 2, _T("msvcr90.dll version is %s\n"), _VersionInfoHelper::GetVersionString(_VersionInfoHelper::GetFileVersion(sPath)));
            break;
        }
    }
}

6 Replies to “How to get HMODULE of msvcr90.dll”

  1. Actually, I guess one can use the GetModuleHandleEx with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS and with an address of a function defined in msvcr90.dll. The only limitation is XP+, which nowadays doesn’t seem so limiting, and anyway the SxS hadn’t been there beforehand…

  2. I thought about GetModuleHandleEx, but it does not look as a convenient wokraround. First of all, it limits to XP/Server 2003, which still can be an issue (there are still people with Windows 2000 around so you don’t always have an option just put it into production code).

    Second is that if you do something like

    HMODULE hModule = NULL;
    ATLVERIFY(GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR) &malloc, 0)); // malloc, errno, purecall etc.
    

    The address might still point to the image of your binary rather than directly to shared runtime DLL.

    And the last this is that it does not seem to work :)

  3. Hmm… That’s strange ;)
    I used it many times just this way (although not for the msvcrXX.dll modules, but who cares?)
    eax = 0 means the call failed, it might be interesting to see the GetLastError…

  4. … just checked on my XP Pro Sp3, VS 2008 with (LPCTSTR)&malloc.
    Got exactly the expected result.
    It must be something in your environment, although I can’t guess what it may be… Maybe it doesn’t like the hardcoded address that you specified?

  5. I was checking this with Windows 7. (LPCTSTR) &malloc expression itself pointed to address range of the executable, not the CRT DLL and failure to locate the DLL was more than expected. This is why I quick-hardcoded the address to at least get into the address range of interest.

  6. OK, GetModuleHandleEx/GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS works great. It was my problem with code with incorrect argument (third argument is zero on the screenshot above).

    &malloc still gives incorrect HMODULE for the reason mentioned above.

    Code snippet:

    HMODULE hModule1 = ...; // obtained using PSAPI code above
    
    HMODULE hModule2 = NULL;
    LPCTSTR pvMalloc = (LPCTSTR) &malloc;
    if(!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, pvMalloc, &hModule2))
        ATLTRACE2(atlTraceGeneral, 2, _T("hModule2 - GetModuleHandleEx's GetLastError() %d, pvMalloc 0x%p\n"), GetLastError(), pvMalloc);
    
    HMODULE hModule3 = NULL;
    LPCTSTR pvAddress = (LPCTSTR) ((LONG_PTR) hModule1 + 0x1234);
    if(!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, pvAddress, &hModule3))
        ATLTRACE2(atlTraceGeneral, 2, _T("hModule3 - GetModuleHandleEx's GetLastError() %d, pvAddress 0x%p\n"), GetLastError(), pvAddress);
    
    ATLTRACE2(atlTraceGeneral, 2, _T("hModule1 0x%p, hModule2 0x%p, hModule3 0x%p\n"), hModule1, hModule2, hModule3);
    

    Output:

    msvcr90.dll version is 9.0.30729.4974, sPath C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.4974_none_50940634bcb759cb\MSVCR90.dll, hModule1 0x00000000
    hModule1 0x721C0000, hModule2 0x00400000, hModule3 0x721C0000

Leave a Reply