C4Swimmers Newsletter  

(Tips) Understanding DLLs – Building them and Allowing External Calls to their Functions

Understanding DLLs – Building them and Allowing External Calls to their Functions

Introduction
In a generic sense of the term, a library is a collection of modules, each of which contains one or more functions or procedures which are packaged together so that they can be reused easily when needed and not used when not needed. There are application DLLs and system DLLs. Many system DLLs are called key system components (kernel32.dll, advapi32.dll, ntdll.dll, hal.dll, user32.dll, gdi32.dll, and so forth). If you have ever programmed in the C language, then you would know that unlike any object-oriented programming language, the basic unit of organization is the function; that C is a function, or procedural (not object) oriented language. The compiler will contain directives (included header files atop the body of the source code) that contain the prototypes of the predefined functions. The name of the header file is based on the type of those semantically-related functions defined in that header file.

These header files link together to form a static, not dynamic, library. The C compiler translates the human-readable source code into machine language. The output is a resource, or object, or module file. But even though the definitions of the functions are not included in the main body of the source code, the C compiler cannot generate the address of a function that it is not seeing. You pass the static library as input to the linker and the linker searches for all of the unresolved externals. This is why it is important to keep your source code files in the same working directory as the directory that contains the library (that contains the header definitions of the predefined functions). DLLs, on the other hand, differ. There is a separate link step for the DLL itself. When the DLL is linked, it will generate an import library. This import library enumerates by name (or sometimes number) all of the functions that are contained in that library.

Assume you have a graphical application and you call CreateWindow to put a window on the screen. When the compiler is generating that module, it doesn't know where CreateWindow is. So we build our application and we pass it our import library for user32.dll. There is no the implementation of a function in this import library. The import library communicates back to the call, stating that CreateWindow is the needed function and it lives in user32.dll. Rather than resolve CreateWindow to an absolute (relative) address, the compiler and linker create a slot in an import address table which is the location where later on, the loader will patch with the address of CreateWindow. So when your built application is loaded, Windows sees that you have some functions that depend on user32.dll. So it loads user32.dll in the process address space (where the code and data are mapped to both represent an instance of and run your application). Note that only pieces of the DLL are "virtually loaded": not the entire DLL. This can be a misunderstanding: a loaded executable means that only pieces of it are loaded, not the entire image. Only the needed pieces of are loaded. As more features are used in application, then more pieces of are loaded, as well as the appropriate DLLs. This is part of the Windows Memory Management mechanism – any memory that can be shared will be shared. Once Windows loads user32.dll into your address space, it knows where the address of CreateWindow is. It then goes to import address table to realize that it must resolve the address for CreateWindow, and it patches it at that point.

Read full article..
Courtesy : Codeproject.com