GetCurrentModuleHandle
Monday, March 21, 2011 12:01:00 AM
First note that HINSTANCE (or HMODULE) of the module (exe/dll/...) is simply a pointer to the address where the module has been loaded, the image base pointer. And it so happens that newer MSVC and MinGW linkers (and probably some others too) do export symbol called __ImageBase. If you are this lucky, the following implementation should be sufficient:
HINSTANCE GetCurrentModuleHandle () {
extern char __ImageBase;
return reinterpret_cast <HINSTANCE> (&__ImageBase);
}
This code will work for you if it don't err at compile (link) time.If you don't have this symbol available but can restrict your application to Windows XP and newer, there is GetModuleHandleEx flag GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS. Important thing is that you must pass an address that reside inside your image. Static variables and function pointers will usually work but consult manual to your compiler. Local variables that live on stack or heap-allocated pointers will not work. Rough approach to use this technique may look like this:
HINSTANCE GetCurrentModuleHandle () {
HMODULE hModule = NULL;
if (GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
reinterpret_cast <LPCTSTR>
(&GetCurrentModuleHandle),
&hModule)) {
return hModule;
} else {
return NULL;
};
}
And sometimes, when you need your program to work on Windows 2000, the PSAPI library and the EnumProcessModules function will come in handy. This is the hard way where you enumerate all modules in the process and compare their bounding addresses. My rough implementation follows to make the idea clearer:
HINSTANCE GetCurrentModuleHandle () {
// avoiding repeated calls and conversions in the algorithm below
// - p is the reference pointer that we are looking for
const HANDLE hHeap = GetProcessHeap ();
const HANDLE hProcess = GetCurrentProcess ();
const char * p = reinterpret_cast <const char *>
(&GetCurrentModuleHandle);
DWORD n = 0;
HINSTANCE hRetVal = NULL;
// determine number of bytes (n) required to list handles to all modules
if (EnumProcessModules (hProcess, NULL, 0u, &n)) {
// allocate space for the handles
if (HMODULE * hModules = (HMODULE *) HeapAlloc (hHeap, 0u, n)) {
// retrieve the handles
if (EnumProcessModules (hProcess, hModules, n, &n)) {
// adjust n to number of the handles
n /= sizeof (HMODULE);
for (unsigned int i = 0u; i < n; ++i) {
// retrieve also upper boundary of the module
MODULEINFO mi;
if (GetModuleInformation (hProcess, hModules [i],
&mi, sizeof mi)) {
const char * mp = static_cast <char *>
(mi.lpBaseOfDll);
// search is done when p belong to some module image
if (p >= mp && p < mp + mi.SizeOfImage) {
hRetVal = hModules [i];
break;
};
};
};
};
HeapFree (hHeap, 0u, hModules);
};
};
// hRetVal is NULL if API call failed or p wasn't found (unlikely)
return hRetVal;
}
And one last note: Putting this function into some common functionality DLL is not exactly bright idea :)

