How can you get the instance handle of a DLL, if the function that you write is linked into the DLL but you have no access to hInstance
from the DllMain
? GetModuleHandle
only allows you to get the handle to the module that created the current process – in case you don’t know the path to the module (which we assume).
So let’s say you want to somehow get the instance handle but can’t use DllMain
for some reason. The solution is in using VirtualQuery
. We abuse a feature of static variables in PE executables. Unlike the usual stack variable (and various other options), those are located within the loaded image of the DLL. Here’s how it looks.
HMODULE GetMyModuleHandle() { static int s_somevar = 0; MEMORY_BASIC_INFORMATION mbi; if(!::VirtualQuery(&s_somevar, &mbi, sizeof(mbi))) { return NULL; } return static_cast(mbi.AllocationBase); }
If you have linked the CRT of Visual C++, you can get away with a simple reinterpret_cast<HMODULE>(&__ImageBase)
So don’t sweat it, as most people do whenever I quiz them about this
// Oliver
Awesome, great stuff Oliver! This is exactly what I needed and for an added bonus, it works! 😛
One thing of note is that you need to implement this entire function in the header file, and not just in a .c/.cpp file if you want the caller’s module returned. For instance, if you put the implementation above in a .c file in Shared.dll, and then include it’s prototype and call it from Caller.dll, you’ll get Shared.dll’s HMODULE (which might be what you want). If you want Caller.dll’s instance however, you need to implement the function in that module as well.
To allow me to implement this function once but use it in multiple different projects/binaries in the same solution, I used this function definition in module_utilities.h:
__forceinline HMODULE get_my_module_handle( void )
{
static int s_module_marker = 0;
MEMORY_BASIC_INFORMATION memory_basic_information;
if( !VirtualQuery( &s_module_marker, &memory_basic_information, sizeof( memory_basic_information ) ) )
{
return NULL;
}
return (HMODULE)memory_basic_information.AllocationBase;
}
Hi Zach, that’s true. This is what I meant by:
The limitation you mention, applies of course. But if one process has already the handle to another DLL it wouldn’t really have to query it. But there may be legit reasons to do so anyway.
// Oliver