Once long time ago I was curious how to get a descriptor of the module mapped into memory (.exe or .dll), if its name and other attributes needed for using special API functions are unknown. If in the case of GetModuleHandle with zero parameter value the process or .exe descriptor is being returned, how to deal with .dll then? I didn't find a solution at that time, though now it seems a really simple task.

How To Get The HMODULE, HINSTANCE, or HANDLE From Static Library In C++

Variant 1.

GetModuleHandleEx. As you see from the title it's extended. The function takes on a flag value as one of parameters. Among its values GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS is presented. As far as I understood, it brings in a sense of order: I have a certain address in the executable code - I wish to know which module it belongs to. It ideally matches my task, when from static library in several dynamic modules I need to retrieve a descriptor of each one.

But MSDN writes:

Requirements 
Client: Requires Windows XP. 
Server: Requires Windows Server 2003. 
Header: Declared in Winbase.h; include Windows.h. 
Library: Use Kernel32.lib. 

Well, if so - then it's truth, though severe one.

Variant 2.

In the Internet I had come across the following:

// from ATL 7.0 sources
#ifndef _delayimp_h 
extern "C" IMAGE_DOS_HEADER __ImageBase; 
#endif 
.... 
HMODULE Module() 
{ 
// from ATL 7.0 sources 
  return reinterpret_cast(&__ImageBase); 
} 

Also works wonderful. However, it has restrictions on the compiler used. First, it must be MS compiler and second, not lower for the version 7.0. I.e. on MS VS 6.0 it's not a true already. Therefore...

Variant 3.

How system operates at LoadLibrary? It maps an executable file into the process memory. Then receives all the necessary structures from the header of PE file (on PE format please refer to the documentation - it can be found everywhere), one of which is IMAGE_NT_HEADERS32:: OptionalHeader:: SizeOfImage. Based on the value of this field, the loader allocates and transfers physical memory by means of unique universal tool, VirtualAlloc, to a certain block, to which it copies an image of the whole file to the addresses which are specified in the same PE header for each separate section. Further there is the usual routine work on loading additional functions from the table of import, correction of addresses and so on. Then the starting input point (Original Entry Point - OEP) is calculated and pass of control to OEP is performed. In the case of .dll this call leads via DLL startup code (you can view it in the dllcrt0.c file in the Studio) and finally brings to DLLMain if it exists.

So what does HMODULE, aka HINSTANCE, aka HANDLE mean for DLL module? It is a pointer to the block of memory allocated for image by VirtualAlloc function and provided to HMODULE.

We can be convinced of it after viewing in a debugger a piece of memory to which the value of HMODULE refers. It starts with

MZ...............@...........!..L.!
This program cannot be run in DOS mode.

Here it is, the beginning of PE header, namely its DOS section.

Thus, how to get HMODULE from static library? It is necessary to find only the beginning of the piece of virtual memory which had been allocated for the copy of PE module image. How to get it then? If there was a VirtualAlloc, then VirtualQuery will work fine. It takes on an optional address within the limits of the selected and handled region of physical memory and returns the next describing structure at that:

typedef struct _MEMORY_BASIC_INFORMATION { 
  PVOID BaseAddress; 
  PVOID AllocationBase; 
  DWORD AllocationProtect; 
  DWORD RegionSize; 
  DWORD State; 
  DWORD Protect; 
  DWORD Type; 
  } MEMORY_BASIC_INFORMATION; 
typedef MEMORY_BASIC_INFORMATION 
*PMEMORY_BASIC_INFORMATION;

Here the AllocationBase field catches our eyes. It contains the starting address of the allocated region. It's just what we need. This is how the extended function looks with consideration of the Variant 2:

#if _MSC_VER >= 1300  // for VC 7.0 
#ifndef _delayimp_h 
extern "C" IMAGE_DOS_HEADER __ImageBase; 
#endif
#endif
... 
HMODULE module() 
{ 
#if _MSC_VER < 1300  // earlier than .NET compiler (VC 6.0) 
    MEMORY_BASIC_INFORMATION mbi; 
    static int address; 
    ;::VirtualQuery(&address, &mbi, sizeof(mbi)); 
    return reinterpret_cast(mbi.AllocationBase); 
#else  // VC 7.0 
    // from ATL 7.0 sources 
  return reinterpret_cast(&__ImageBase); 
#endif 
} 
Subscribe to updates