Code archives/Miscellaneous/Call dll at runtime (no not CallDLL).

This code has been declared by its author to be Public Domain code.

Download source code

Call dll at runtime (no not CallDLL). by Spinduluz2006
Ok this is something I found on my HD, it's not that old just that I forgotten I've done it.
Though I might as well share it with the community and with hopes that someone finds it usefull.

So what does this do?

Well it enables you to call dll functions during runtime.
First thing you have todo is to include "CallDLL.bb"

This file includes these functions.

CBegin() - Allocate data and and prepares a call
CEnd() - Free data and stuff
CPushInt(Value%) - Push an int on the stack
CPushFloat(Value#) - Push a float on the stack
CPushString(Value$) - Push a string on the stack
CPushBank(Value) - Push an allocated bank on the stack
ComCallInt%(Func,Method) - Make a call to an com object interface
returns an int
CallInt%(Func) - Make a call to a func (ret value int)
CallStr$(Func) - Same as above but returns a string
CallFloat#(Func) - yeah yeah returns a float

What you have to remember when pushing values to the stack is to do it like you would do in assembler.
In the reverse order. This is because the first value you put on the stack is actually the last that is retrived.

Lets for example make a function that displays the good old MessageBox.

Lets take a peek on MessageBox function first though.

int MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);

Example:
-----------------------------------------------------------

Include "CallDLL.bb"

Function MessageBox(hWnd%,Text_$,Caption$,uType%)

Local User32 = LoadDLL("User32.dll") ; LoadLibrary

if User32 = 0 Then RuntimeError("MessageBox : Failed to load User32.dll")

Local MsgBox = ProcDLL(User32,"MessageBoxA") ;GetProcAddress

CBegin()
CPushInt(uType) ;In the reverse order remeber?
CPushString(Caption)
CPushString(Text_)
CPushInt(hWnd)
;Since MessageBox returns an int we'll use CallInt
Local Ret = CallInt(Msgbox)
CEnd()
FreeDLL(User32)
Return Ret

End Function

Print MessageBox(0,"This is" + Chr(13) + "a test","Info",0)
WaitKey()

-----------------------------------------------------------

You can also make calls to Com objects using ComCallInt function.

So how do you do this?
Well lets take a look at the IUnknown interface methods and some of the IDirect3D9 methods.

(This is copied from d3d9.h)
STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE;
STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;

So lets say you make a call to Direct3D9Create create and it returns an interface address.
And you want to make a call Release.

Then all you have todo is to use ComCallInt,
i.e.
ComCallInt([Interface Address],8)

So why 8?

It's because it's the 3rd function in this interface.
QueryInterface is on 0 (ComCallInt([Addr],0)
AddRef is on 4 (ComCallInt([Addr],4)
Release on 8
RegisterSoftware on 12 ...
So on so forth, in other words [Address + Method * 4] (if you count QueryInterface as 0).

Well thats pretty much all folks. Hope it made sense.
And hope that the spacing isn't to f*cked up.

Ohh and this is rather untested (tested on 2 different computers).
So I take no responsibility of what this code might do to your computer and stuff.

Oh and I forgot to add the decl file needed for the extremly simple directx9 test that are in the zip.
(It creates an device and goes into fullscreen).
So I'll just add it to the code field below.

Oh and the blitzasm stuff is heavily based on Kevin Poole's stuff with my own additions.

Have fun...or not :-P , hope someone find this usefull.

Ahh well back to my wrestling match with Quaternions....

Download
.lib "d3d9.dll"
Direct3DCreate9_%(SDK%):"Direct3DCreate9"

Comments

None.

Code Archives Forum