Accessing the current module’s HINSTANCE from a static library


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 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 __ImageBase represents the DOS header of the module, which happens to be what a Win32 module begins with. In other words, it's the base address of the module. And the module base address is the same as its HINSTANCE.

So there's your HINSTANCE.

[Raymond is currently on vacation; this message was pre-recorded.]

Comments (21)
  1. Anonymous says:

    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.

  2. Anonymous says:

    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/

  3. Anonymous says:

    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… ;)

  4. Anonymous says:

    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 )

  5. Anonymous says:

    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.

  6. Anonymous says:

    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?

  7. Anonymous says:

    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.

  8. Anonymous says:

    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.

  9. Anonymous says:

    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…

  10. Anonymous says:

    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…

  11. Anonymous says:

    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?

  12. Anonymous says:

    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.

  13. Anonymous says:

    Although it’s also been shown that unless you have a popular application, they probably won’t turn on the compatibility shim for you.

  14. Anonymous says:

    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?

  15. Anonymous says:

    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.)

  16. Anonymous says:

    "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."

  17. Anonymous says:

    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.

  18. Anonymous says:

    Forget my last comment. It was something else.

  19. Anonymous says:

    Accessing the current module’s HINSTANCE from a static library

Comments are closed.