I looked at iczelion 17 and just don't get it yet. I'd like to take some functions and put them in a dll.
Here is the make file:
NAME=DLLSkeleton
$(NAME).dll: $(NAME).obj
Link /DLL /DEF:$(NAME).def /SUBSYSTEM:WINDOWS /LIBPATH:c:\masm32\lib $(NAME).obj
$(NAME).obj: $(NAME).asm
ml /c /coff /Cp $(NAME).asm
Do I only need to use link to make a dll?
Can I trun objs and libs to dll?
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
AppName db "DLL Skeleton",0
HelloMsg db "Hello, you're calling a function in this DLL",0
LoadMsg db "The DLL is loaded",0
UnloadMsg db "The DLL is unloaded",0
ThreadCreated db "A thread is created in this process",0
ThreadDestroyed db "A thread is destroyed in this process",0
.code
DllEntry proc hInstance:HINSTANCE, reason:DWORD, reserved1:DWORD
.if reason==DLL_PROCESS_ATTACH
invoke MessageBox,NULL,addr LoadMsg,addr AppName,MB_OK
.elseif reason==DLL_PROCESS_DETACH
invoke MessageBox,NULL,addr UnloadMsg,addr AppName,MB_OK
.elseif reason==DLL_THREAD_ATTACH
invoke MessageBox,NULL,addr ThreadCreated,addr AppName,MB_OK
.else ; DLL_THREAD_DETACH
invoke MessageBox,NULL,addr ThreadDestroyed,addr AppName,MB_OK
.endif
mov eax,TRUE
ret
DllEntry Endp
TestHello proc
invoke MessageBox,NULL,addr HelloMsg,addr AppName,MB_OK
ret
TestHello endp
End DllEntry
I do not fully understand the "reason" part.
I see invoke for the reason code but I dint see any additional functions.
I'm trying to understand but it is not clear what is neccessarry and what in not in the example to me.
Thank you very much for any help.
The Dll entry of dlls is called on various occasions, and a "reason" is provided (by windows ?) It's not necessary to handle all the occurences, except when the reason is DLL_PROCESSATTACH. You mave to return eax=1 otherwise the dll loading will fail.
You can get rid of all the MessageBoxes there :bg
Just leave mov eax,TRUE and ret.
It's like a callback procedure, right guys ?
ThoughtCriminal,
Don't be afraid to read the DLL tutorial in the masm32 sdk, its there to be useful but the basics are,
The first procedure, commonly called the DLLmain or LIBmain but can be anything you like is there for the startup of the DLL and it is called by the OS when the DLL is first called. You can use it to initialise globals and set up more or less whatever you like. The procedures in the DLL are called directly by the caller of the DLL, not through the start procedure.
Now in the start procedure it can be called directly by the calling programs main process OR it can be called by a thread started in the caller and it is useful to know the difference so that you can if you like initialise in different ways.
The option to return ZERO is so you can test a condition on DLL startup and if you have a problem you can close down the DLL after displaying an error message. With a simple DLL you can just return non zero and it will start but the other options are there for more complex DLLs that have to be initialised in more complex ways.
I was able to get VS8 to build the example instead of using a bat file.
I should understand this soon...
Does this look okay for everything after .code?
; #########################################################################
;
; Build this DLL from the batch file called BldDLL.bat
;
; #########################################################################
.386
.model flat, stdcall
option casemap :none ; case sensitive
; #########################################################################
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
; #########################################################################
szText MACRO Name, Text:VARARG
LOCAL lbl
jmp lbl
Name db Text,0
lbl:
ENDM
m2m MACRO M1, M2
push M2
pop M1
ENDM
return MACRO arg
mov eax, arg
ret
ENDM
.code
; ##########################################################################
LibMain proc hInstDLL:DWORD, reason:DWORD, unused:DWORD
ret
LibMain Endp
; ##########################################################################
TestProc proc
jmp @F
MbTitle db "Test function",0
MbMsg db "This is tstdll.dll here",0
@@:
invoke MessageBox,NULL,addr MbMsg,addr MbTitle,MB_OK
ret
TestProc endp
[color=Red]next proc here
next proc here[/color]
etc......
; ##########################################################################
End LibMain
Why aren't you returning eax = 1 ?!
Did not see eax 1 in the Masm32 dll example. Maybe the reason message boxes had something to take care of that.
So I guess everything is okay except for not returning eax as 1.
Thanks for your help.
Quote from: ThoughtCriminal on September 30, 2009, 10:37:53 PM
Did not see eax 1 in the Masm32 dll example. Maybe the reason message boxes had something to take care of that.
So I guess everything is okay except for not returning eax as 1.
Thanks for your help.
Check the example again, if the reason is DLL_PROCESS_ATTACH, then it returns true, in other words eax = 1.
I'm talking about tstdll.asm
You don't have to check for the reason, but you should return with eax = 1.
I could repeat it all but the masm32 sdk has a tutorial on building a DLL in the tutorial directory that explains how they work and has a working example.
If you are not sure of the what and whys I would recommend that you take Hutch's working example from his excellent tutorial and slowly tweak it to do what you want. In general, you should be able to leave the example as is and add the procedures that will be called by the user. The DEF file is important. Without it being set up correctly, the prcedures will not be available for calling even if the DLL loads correctly. Every procedure that you want to make available for use MUST be exported.
Paul
Thanks for all your help. I just tested the MASM32 dll example code using VS8 to build it.
I like to dynamically link needed files like kernel32.dll. So I wrote a short program using Load Library and GetProCdress and the message boxes popped up fine.
I understand now how to make my own dlls.
Cool, but normally you don't need to dynamically load system dlls like kernel32.dll, user32.dll etc.
Your program is statically linked to them and during loading of your process the import table is filled with the addresses of the functions you use, as the linker has created the import table.
I have a inc file that is always first for one of my projects. I only import two functions
[
externdef _imp__GetProcAddress@8:NEAR
externdef _imp__LoadLibraryA@4:NEAR
/code]
Then i have a little function that let me plug in the dll and api I need.
It just the way I do things.