Date: | October 25, 2004 / year-entry #374 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20041025-00/?p=37483 |
Comments: | 21 |
Summary: | If you're writing a static library, you may have need to access the HINSTANCE of the module that you have been linked into. You could require that the module that links you in pass the HINSTANCE to a special initialization function, but odds are that people will forget to do this. If you are using... |
If you're writing a static library, you may have need to access
the If you are using a Microsoft linker, you can take advantage of a pseudovariable which the linker provides. EXTERN_C IMAGE_DOS_HEADER __ImageBase; #define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
The pseudovariable
So there's your [Raymond is currently on vacation; this message was pre-recorded.] |
Comments (21)
Comments are closed. |
That’s very cool. Is this actually documented somewhere though? I searched google and all I got were 4 hits on the web and 3 in groups.
And speaking of which, what do you think about the alternate technique using VirtualQuery (I can’t foresee why it could possibly fail):
http://www.codeguru.com/Cpp/W-P/dll/tips/article.php/c3635/
I’m surprised you’re advocating this (though I don’t know of an alternative – the only thing that springs to mind is GetModuleHandle, but if memory serves that’s different) – purely because I would have thought this would be an ‘implementation detail’, and so have severe compatibility implications.
But, as you’ve demonstrated on countless occasions, that’s something Microsoft prefers to deal with than let developers do… ;)
Does this code work for all versions of Windows?
I found this article, which implies it only works on new linkers
http://www.codeguru.com/Cpp/W-P/dll/tips/article.php/c3635/
Will ( HINSTANCE == HMODULE == base of process address ) space stay true in future versions of windows, or is it possible it may change?
Couldn’t you use GetModuleHandle(NULL) ? It looks like the only downside is that you can’t run on Win16, which I can live with.
Oh, and if you have a HWND from the application, you can always get the HINSTANCE with GetWindowLongPtr
GetWindowLongPtr( hwndApp, GWLP_HINSTANCE )
GetModuleHandle(NULL) is not the current module; it’s the exe module. If your code is statically linked into a DLL, this gets you the wrong handle.
The GetWindowLongPtr trick assumes that the app passed its own instance handle to CreateWindow. Very high likelihood but not foolproof. (It might be say a common dialog box, whose instance handle is comdlg32.dll.)
I always figured there should be a way to do the hinstance-as-base-address thingie, since the base address gets relocated with the rest of the DLL. A relocatable reference to an address at rva=0 should have done the trick, and with this pseudo-variable, it has been formalized.
Well, that begs the questions: what version of the Linker was this introduced with. And, where are its friends? That is, are there other interesting linker pseudovariables?
The method shown won’t work on Pocket PCs, since the instance handle isn’t the same as the base address. I guess it is a pointer to a system internal structure.
I’m surprised no one has mentioned the official way to do this yet: GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, &pObjectInModule, &handle). It requires XP or 2003, though; if it isn’t available I use the VirtualQuery() trick with my own function pointer.
Thanks!
Just like Chris, i’d like to know if there are any other (pseudo)variables like that. Can’t seem to find any documentation on that…
This /is/ linker specific.
The VirtualQuery() and base address == module handle assumption is unfortunately burned in too many places for it to ever be changed.
Re: GetModuleHandleEx():
Note that there’s a bug in this on XP RTM that messes up the loader’s DLL load ref counts. I think it’s fixed even in SP1. I’ll check with the guy who did it and write back later…
I am really surprised that you write something like this.
When we say anything like it, your reaction is always something like: This is not documented, it may not be true in future Windows version, your software will be broken, etc. etc., in short don’t do it.
What is different here?
How do we know which undocumented and implementation-dependent features we should be using and which ones not?
Henk, as Raymonds weblog basically proves, its safe to abuse anything thats easilly abusable, as you can be sure enough other developers ARE abusing it to guarantee its future abusability.
er. Im sure theres a better way of phrasing that.
Although it’s also been shown that unless you have a popular application, they probably won’t turn on the compatibility shim for you.
I’ve always wondered what the difference is between an HINSTANCE and an HMODULE. They both seem to be base addresses and the Win32 API sometimes seems to use them interchangeably. Is there a distinction or is this just some historical accident?
Adrian:
http://weblogs.asp.net/oldnewthing/archive/2004/06/14/155107.aspx
Re: GetModuleHandleEx(). The bug is actually in one of the internal helper functions used by GetModuleHandleEx() and it happens only if you pass a flag to that internal helper that GetModuleHandleEx() doesn’t pass, so GetModuleHandleEx() itself is safe. (Other callers of that internal helper are at risk though.)
"This is not documented…"
HINSTANCE = base address is documented
http://msdn.microsoft.com/library/en-us/dllproc/base/dllmain.asp – "Handle to the DLL module. The value is the base address of the DLL."
This trick does not seem to work on a Managed C++ dll. The linker generates the dll, but the CLR later refuses to load the assembly.
Forget my last comment. It was something else.
Accessing the current module’s HINSTANCE from a static library
PingBack from http://blog.m-ri.de/index.php/2007/12/12/die-unsitte-immer-getmodulehandlenull-fuer-hinstance-in-createwindow-und-registerclass-zu-verwenden/