Accessing the current module’s HINSTANCE from a static library

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 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. asdf 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. asdf 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. Mo 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. Tom 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. Raymond Chen 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. Chris Becke 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. mfink 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. Phaeron 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. 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. 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. Henk Devos 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. Chris Becke 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. Scott 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. Adrian 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. Raymond Chen 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. Raymond Chen 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. 仙水 says:

    Accessing the current module’s HINSTANCE from a static library

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index