In that tutorial he shows how to create a simple dll and use its functions with LoadLibrary and GetProcAddress. In this tutorial I will show how to export your funtions by name and ordinal.
You can export your functions:
- by Name
- by Name and Ordinal
- by Ordinal only
When you export by name, your functions will be visible in the export table which allows you to call/invoke your dll functions as you would normally call/invoke functions in your program
When you export by ordinal, your functions name will not be visible in the export table and you will have to use LoadLibrary and GetProcAddress
Your dll will need an "entry point", this is the DllMain Callback function that Windows calls when it loads and unloads your dll. You can do all your initialization and cleanup here.
This function can be called anything you want as long as there is a corresponding end nameyouchose at the end of your code
This is an example:
.code SuperDuperEntryPoint proc hInstDLL:DWORD, fdwReason:DWORD, lpvReserved:DWORD mov eax, 1 ret SuperDuperEntryPoint endp ; your procs go here ; ... ; ... ; ... end SuperDuperEntryPoint
This is a brief explanation, for more info seach DllMain Callback on MSDN...
hInstDLL is the handle to your dll (its base address) that windows will pass to this function
fdwReason value will indicate why your dll entry point is being called, it can be 1 of 4 values:
Means your dll is being loaded, this is where you can do your initialization.
Means your dll did not load successfully, or it is being terminated. This is where you can do any cleanup if needed.
These are the same as the above but for multi-threaded dlls.
lpvReserved - this is just some extra info Windows will pass to your dll...
Basically, it will be NULL if FreeLibrary was called OR your dll failed to load. Non-NULL if your dll is terminating normally.
Here is the sample DLL:
include masm32rt.inc .data szLoading BYTE "Dll is loading", 0 szUnloading BYTE "Dll is un-loading", 0 szOrdinal BYTE "Look ma, I was called by ordinal!", 0 .data? hInst DWORD ? .code SuperDuperEntryPoint proc hInstDLL:DWORD, fdwReason:DWORD, lpvReserved:DWORD .if fdwReason == DLL_PROCESS_ATTACH invoke MessageBox, HWND_DESKTOP, offset szLoading, NULL, MB_OK push hInstDLL pop hInst mov eax, TRUE ret .elseif fdwReason == DLL_PROCESS_DETACH invoke MessageBox, HWND_DESKTOP, offset szUnloading, NULL, MB_OK .elseif fdwReason == DLL_THREAD_ATTACH .elseif fdwReason == DLL_THREAD_DETACH .endif ret SuperDuperEntryPoint endp Init proc mov eax, hInst ret Init endp TestProc1 proc lpString:DWORD invoke MessageBox, NULL, lpString, NULL, NULL ret TestProc1 endp ProcByOrdinal proc invoke MessageBox, NULL, offset szOrdinal, NULL, NULL ret ProcByOrdinal endp end SuperDuperEntryPoint
In DLL_PROCESS_ATTACH, I save the "Dll Handle" so I can pass this back to my app. I pass it back to my app by calling a function I created called Init.
TestProc1 will just display a messagebox with the text of the pointer passed to the proc.
ProcByOrdinal is exported by ordinal..
Now, in order for MASM to find your procs in the dll and to be able to just call/invoke these you will need a def file... The one for this sample looks like so:
LIBRARY SampleDll ; name of dll EXPORTS Init ; used to get dll handle TestProc1 ProcByOrdinal @100 NONAME ; exported by ordinal 100 only, no name in exort table
When you assemble and link your dll, the linker will create a lib file, include this in your app source. Here is a sample app to use this dll:
include masm32rt.inc includelib sampledll.lib Init PROTO TestProc1 PROTO :DWORD .data szHello BYTE "Hello there!", 0 .code UseDll: invoke Init mov esi, eax invoke TestProc1, offset szHello invoke GetProcAddress, esi, 100 call eax invoke ExitProcess, 0 end UseDll
Number of downloads: 568