| ||
To conclude this chapter, consider an example illustrating how a DLL created in Delphi can be used in an Assembly language program. I recently discovered an algorithm implemented in Delphi, which places a program shortcut on the desktop and simultaneously creates a menu item in the Start menu. I am not a great fan of Delphi; however, I was too short of time to implement the same algorithm in C language. Therefore, I simply created a DLL on the basis of the existing Delphi program and now actively use it when creating various Setup utilities.
This example assumes that four parameters are passed to the procedure: two references to the programs and the names of the desktop shortcut and menu item. If desired, you can extend the capabilities of this procedure. If you carefully review the Assembly module, you'll notice that calling this DLL from an Assembly program doesn't have any particular features.
library lnk; uses SysUtils, Classes, Windows, ShlObj, ActiveX, ComObj, Registry, syncobjs; procedure setup(prog:PChar; uns: PChar; jar:PChar; menu:PChar); stdcall; var MyObject : IUnknown; MySLink : IShellLink; MyPFile : IPersistFile; FileName : String; Directory : String; WFileName : WideString; MyReg : TRegIniFile; ps1, ps2, sn, path, s : string; nb : dword; handle : integer; l : DWORD; f : text; begin MyObject := CreateComObject(CLSID_ShellLink); MySLink := MyObject as IShellLink; MyPFile = MyObject as IPersistFile; FileName := prog; path := ExtractFilePath(FileName); with MySLink do begin SetArguments ("); SetPath(PChar(FileName)); SetWorkingDirectory(PChar(ExtractFilePath(FileName))); end; // First, create a desktop shortcut MyReg := TReginiFile.Create('software\MicroSoft\Windows\CurrentVersion \Explorer'); Directory := MyReg.ReadString('shell Folders', 'Desktop', ''); WFileName := Directory+'\'; WFileName := WFileName+jar; WFileName := WFileName+'.lnk'; MyPFile.Save(PWChar(WFileName), False); psl:=string(WFileName); // Create a menu item Directory := MyReg.ReadString('shell Folders', 'Programs', '')+'\'; Directory := Directory+menu; WFileName := Directory+'\'; WFileName := WFileName+jar; WFileName := WFileName+' .lnk'; CreateDir(Directory); ps2 := Directory+'\'; MyPFile.Save(PWChar(WFileName), False); //********************************** MyObject := CreateComObject (CLSID_ShellLink); MySLink:= MyObject as IShellLink; MyPFile := MyObject as IPersistFile; FileName := uns; path := ExtractFilePath(FileName); with MySLink do begin SetArguments(''); SetPath(PChar(FileName)); SetWorkingDirectory(PChar(ExtractFilePath(FileName))); end; WFileName := Directory+'\'; WFileName := WFileName+'UNFILES.lnk'; MyPFile.Save(PWChar(WFileName), False); MyReg.Free; // Create a file, in which the information required // to continue installation will be stored sn := path+'perebros.1k'; AssignFile(f, sn); rewrite(f); writeln(f, psl); writeln(f, ps2); close(f); end; //********************** Procedure DLLMain(r:DWORD); begin end; exports setup; begin DLLProc := @DLLMain; DLLMain(dll_Process_Attach); end.
; The SETUP.ASM file .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 c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib ELSE includelib c:\tasm32\lib\import32.lib EXTERN GetProcAddress:NEAR EXTERN LoadLibraryA:NEAR EXTERN FreeLibrary:NEAR EXTERN ExitProcess:NEAR EXTERN MessageBoxA:NEAR 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 'LNK.DLL', 0 HLIB DD ? PAR1 DB "C:\PROG\FILES.EXE", 0 PAR2 DB "C:\PROG\UNINST.EXE", 0 PAR3 DB "Universal search", 0 PAR4 DB "Universal search program", 0 NAMEPROC DB 'setup', 0 _DATA ENDS ; Code segment _TEXT SEGMENT ; [EBP+10H] ; Reserved parameter ; [EBP+0CH] ; Cause of the call ; [EBP+8] ; DLL module identifier START: ; Load the library PUSH OFFSET LIBR CALL LoadLibraryA@4 CMP EAX, 0 JE _ERR MOV HLIB, EAX ; Get the 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 OFFSET PAR4 PUSH OFFSET PAR3 PUSH OFFSET PAR2 PUSH OFFSET PAR1 CALL EAX ; Close the library ; The library will close automatically ; when exiting the program PUSH HLIB CALL FreeLibrary@4 ; Exit _EXIT: PUSH 0 CALL ExitProcess@4 _TEXT ENDS END START
To translate this program, issue the following commands using MASM32:
ml /c /coff /DMASM setup.asm link /subsystem:windows setup.obj
Issue the following commands using TASM32:
tasm32 /ml setup.asm tlink32 -aa setup.obj
To conclude this chapter, I would like to point out that not all possible problems related to using Assembly language with high-level languages have been covered here. However, if you carefully review the examples presented in this chapter, you'll be able to solve most such problems on your own.
| ||