Introduction
Sooner or later many people (OK, maybe not so many) start thinking about loading a DLL without LoadLibrary(). It has only a few advantages and lots of inconvenience problems compared to a normal DLL so it has limited use. Still this tip can make good service as a tutorial if you want to understand what's going on behind the curtains...
Implementation
The most important steps of DLL loading are:
Mapping or loading the DLL into memory.
Relocating offsets in the DLL using the relocating table of the DLL (if present).
Resolving the dependencies of the DLL, loading other DLLs needed by this DLL and resolving the offset of the needed functions.
Calling its entrypoint (if present) with DLL_PROCESS_ATTACH parameter.
I wrote the code that performed these steps but then quickly found out something is not OK: This DLL doesn't have a valid HMODULE/HINSTANCE handle and many windows functions expect you to specify one (for example GetProcAddress(), CreateDialog(), and so on...). Actual the HINSTANCE handle of a module is nothing more than the address of the DOS/PE header of the loaded DLL in memory. I tried to pass this address to the functions but it didn't work because windows checks whether this handle is really a handle! This makes using manually loaded DLLs a bit harder! After this I wrote my own GetProcAddress() as well. Later I found out that I want to use dialog resources in the DLL and CreateDialog() also requires a module handle to get the dialog resources from the DLL. For this reason I invented my custom FindResource() function that works with manually loaded DLLs and it can be used to find dialog resources that can be passed to the CreateDialogIndirect() function. You can use other types of resources as well in manually loaded DLLs if you find a function for that resource that cooperates with FindResource(). In this tip you get the code for the manual DLL loader and GetProcAddress(), but I post here the resource related functions in another tip.
Limitations
The load DLL doesn't have a HMODULE so it makes life harder especially when its about resources.
The DllMain() doesn't receive DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications so don't use compiler supported TLS variables because they won't work!
If your DLL imports other DLLs, then the other DLLs are loaded with the WinAPI LoadLibrary(). This is actually not a limitation, just mentioned it for your information. Actually it would be useless to start loading for example kernel32.dll with manual dll loading, most system DLLs would probably disfunction/crash!
I've written my DLLs with /NODEFAULTLIB linker option that means you can't reach CRT functions and it reduces your DLL size considerably (like with 4K intros :-D). But then you have to go with pure WinAPI! Actually I haven't tried linking such DLLs with CRT lib because I was afraid that its initialization code would fail. Actually it might work, you should give it a try! This depends on your compiler version and its CRT! I think that CRT linking with dynamic library has more chances to succeed because then the dependency CRT DLL will be loaded with LoadLibrary()!
Using the code
Write your DLL in C/C++ without using CRT (link with /NODEFAULTLIB). Load your DLL with the LoadLibrary() code I provided. You can use my custom GetProcAddress() on the loaded DLL. If you want to use dialog resources then you can use the FindResource() function I provided in one of my other tips.
Sources:
Note that my sources were compiled with VC++6. most of these sources should compile with newer versions by issueing minor modifications.
load_dll.h
/*****************************************************************************/
/* load_dll.h (c) XeNotRoN 2002 */
/*---------------------------------------------------------------------------*/
/* Use these functions to load simple DLL files that have only data and code */
/* in their sections and do not take any advantage of other DLL */
/* functionality (TLS, resources) that require a windows HMODULE. You can */
/* import and export functions. Use the MyGetProcAddress() function to */
/* get the function addresses of a DLL that was loaded by these functions. */
/*****************************************************************************/
#ifndef load_dll_h
#define load_dll_h
#include <windows.h>
#include <stdio.h>
Read more: Codeproject
QR: