Creating a Dynamic Link Library

Now, it's time to consider some examples that illustrate DLL creation. Listing 16.1 provides an example of the simplest DLL. This DLL isn't doing anything useful. It is just loaded and then unloaded. Its entry procedure DLLP1 is called, and a normal Windows message will be generated. Pay attention to the processes of loading and unloading this library. Also note that the entry procedure must return a nonzero value. The DLLP1 procedure also processes one parameter traditionally passed through the stack.

Listing 16.1: The simplest dynamic link library
image from book
 .586P ; Flat memory model IFDEF MASM      .MODEL FLAT, stdcall ELSE     .MODEL FLAT ENDIF PUBLIC DLLP1 ; Constants ; These messages arrive ; when the DLL is opened DLL_PROCESS_DETACH    equ 0 DLL_PROCESS_ATTACH    equ 1 DLL_THREAD_ATTACH     equ 2 DLL_THREAD_DETACH     equ 3 IFDEF MASM ; MASM ; Prototypes of external procedures         EXTERN      MessageBoxA@16:NEAR ; INCLUDELIB directives for the linker         includelib c:\masm32\lib\user32.lib         includelib c:\masm32\lib\kernel32.lib ELSE ; TASM         EXTERN      MessageBoxA:NEAR         MessageBoxA@16 = MessageBoxA         includelib c:\tasm32\lib\import32.lib ENDIF ;----------------------- ; Data segment _DATA SEGMENT         TEXT1 DB 'Library's entry point', 0         TEXT2 DB 'Library's exit point', 0         MS    DB 'Message from the library', 0         TEXT  DB 'Calling a procedure from a DLL', 0 _DATA ENDS ; Code segment _TEXT SEGMENT ; [EBP+10H]   ; Reserved parameter ; [EBP+0CH]   ; Cause of the call ; [EBP+8]     ; Identifier of the DLL module DLLENTRY:        MOV    EAX, DWORD PTR [EBP+0CH]        CMP    EAX, 0        JNE    D1 ; Closing the library        PUSH   0        PUSH   OFFSET MS        PUSH   OFFSET TEXT2        PUSH   0        CALL   MessageBoxA@16        JMP    _EXIT D1:        CMP    EAX, 1        JNE    _EXIT ; Opening the library        PUSH   0        PUSH   OFFSET MS        PUSH   OFFSET TEXT1        PUSH   0        CALL   MessageBoxA@16 _EXIT:        MOV    EAX, 1        RET    12 ;------------------- ; [EBP+8]   ; Procedure parameter DLLP1 PROC EXPORT        PUSH   EBP        MOV    EBP, ESP        CMP    DWORD PTR [EBP+8], 1        JNE    _EX        PUSH   0        PUSH   OFFSET MS        PUSH   OFFSET TEXT        PUSH   0        CALL   MessageBoxA@l6 _EX:        POP    EBP        RET    4 DLLP1 ENDP _TEXT ENDS END DLLENTRY 
image from book
 

The program presented in Listing 16.1 can be translated using both MASM32 and TASM32. This point deserves more careful consideration. First, note that after the name of a procedure called from another module, the EXPORT keyword was inserted. This keyword is required for correct translation using MASM. For TASM, this keyword isn't required, but, fortunately, this translator doesn't notice the presence of any keywords after PROC . However, TASM requires the DLLP1 procedure to be defined as PUBLIC . Furthermore, for correct translation using TASM, it is necessary to create a DEF file and specify it in the command line for TLINK32. To create DLLs, the link linker requires the /DLL key to be specified in the link command line, and the LINK32 command line requires the -Tpd key (the -Tpe key is used by default). The /ENTRY:DLLENTRY key in the link command line can be omitted because the entry point is defined from the END DLLENTRY directive.

To translate the DLL from Listing 16.1, issue the following commands for MASM32:

 ml /c /coff /DMASM d1l1.asm link /subsystem:windows /DLL /ENTRY:DLLENTRY dll1.obj 

Issue the following commands for TASM32:

 tasm32 /ml dll1.asm tlink32 -aa -Tpd dlll.obj,,,,dlll.def 

The contents of the DLL1 .DEF file are as follows :

 EXPORTS DLLP1 

Listing 16.2 is the program that loads the DLL shown in Listing 16.1. This is an example of the late linking. First, it is necessary to load the library using the LoadLibrary function. Then, it is necessary to determine the procedure address using the GetProcAddress function, after which it is possible to call the library. As expected, MASM places _DLLP1@0 instead of DLLP1 into the library name. TASM, on the contrary, doesn't change the name. You must take this into account in the program. Also, it is necessary to account for the possibility of errors when calling the LoadLibrary and GetProcAddress functions. In this respect, consider the following sequence in which the LoadLibrary function searches for the library:

  1. Search the directory from which the program was started.

  2. Search the current directory.

  3. Search the system directory (determined using the GetsystemDirectory function).

  4. Search the Windows directory (determined using the GetwindowsDirectory function).

  5. Search the directories specified by the PATH environment variable.

In the end of the program, the DLL is unloaded from the memory. By the way, this is not necessary because this procedure is carried out automatically when exiting the program.

Listing 16.2: Calling the dynamic link library: Explicit linking
image from book
 .586P ; Flat memory model .MODEL FLAT, stdcall ; Constants ; Prototypes of external procedures IFDEF MASM ; MASM        EXTERN GetProcAddress@8:NEAR        EXTERN LoadLibraryA@4:NEAR        EXTERN FreeLibrary@4:NEAR        EXTERN ExitProcess@4:NEAR        EXTERN MessageBoxA@16:NEAR ; INCLUDELIB directives for the linker        includelib c:\masm32\lib\user32.lib        includelib c:\masm32\lib\kernel32.lib ELSE ; TASM        EXTERN GetProcAddress:NEAR        EXTERN LoadLibraryA:NEAR        EXTERN FreeLibrary:NEAR        EXTERN ExitProcess:NEAR        EXTERN MessageBoxA:NEAR ; INCLUDELIB directives for the linker        includelib c:\tasm32\lib\import32.lib        GetProcAddress@8 = GetProcAddress        LoadLibraryA@4 = LoadLibraryA        FreeLibrary@4 = FreeLibrary        ExitProcess@4 = ExitProcess        MessageBoxA@16 = MessageBoxA ENDIF ;---------------------------------------- ; Data segment _DATA SEGMENT        TXT DB 'DLL error', 0        MS DB 'Message', 0        LIBR DB 'DLL1.DLL', 0        HLIB DD ? IFDEF MASM        NAMEPROC DB '_DLLP1@O', 0 ELSE        NAMEPROC DB 'DLLP1', 0 ENDIF _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Load the library        PUSH  OFFSET LIBR        CALL  LoadLibraryA@4        CMP   EAX, 0        JE    _ERR        MOV   HLIB, EAX ; Get the procedure address        PUSH   OFFSET NAMEPROC        PUSH   HLIB        CALL   GetProcAddress@8        CMP    EAX, 0        JNE    YES_NAME ; Error message _ERR:        PUSH   0        PUSH   OFFSET MS        PUSH   OFFSET TXT        PUSH   0        CALL   MessageBoxA@16        JMP    _EXIT YES_NAME:        PUSH   1 ; Parameter        CALL   EAX ; Close the library        PUSH   HLIB        CALL   FreeLibrary@4 ; The library will be closed automatically ; when exiting the program ; Exit _EXIT:        PUSH   0        CALL   ExitProcess@4 _TEXT ENDS END START 
image from book
 

The program presented in Listing 16.2 is translated like any other normal program. For MASM32, use the following:

 ml /c /coff /DMASM dllex.asm     link /subsystem:windows dllex.obj 

For TASM32, use the following:

 tasm32 /ml dllex.asm     tlink32 -aa dllex.obj 


The Assembly Programming Master Book
The Assembly Programming Master Book
ISBN: 8170088178
EAN: 2147483647
Year: 2004
Pages: 140
Authors: Vlad Pirogov

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net