The advantage of using a true low level compiler shows when you need to
do something different from normal, where "method" based languages do
not give you the freedom to do unusual things, PowerBASIC has the low
level grunt needed to be original.
Below is the code for a different interface in a DLL, instead of having an
EXPORT for each function that is called, this design only has one which is
the despatch function which calls the required internal function and
passes back any return value to the calling EXE.
It allows very large parameter counts to be passed in a way that normal
functions find difficult to handle. This example is limited to 32 bit
return values but of course, the address of a different size parameter can
be used in the array or structure parameters for different size return
values.
It can use either an array or a structure to pass the parameters,
depending if you need different size parameters or not. The advantage of
an architecture of this type is that it does not require the operating
system to look up a large EXPORT table. A DLL of this type is also a lot
harder to hack as there is no EXPORT to look up.
There are 2 techniques used to get the parameters at the DLL function end,
the first uses inline asm to dereference the parameters, the second uses
the standard PowerBASIC pointers and is clean and easy to understand code.
This example is still a little rough around the edges and it needs to be
civilised some but it is a viable technique that can be done in the
current PowerBASIC DLL compiler.
James Fuller has a different design that is also original and that has a
number of advantages when understood, perhaps James if time allows would
make an example available as I am sure many would appreciate his design
work here.
Regards,
[email protected]
------------------
do something different from normal, where "method" based languages do
not give you the freedom to do unusual things, PowerBASIC has the low
level grunt needed to be original.
Below is the code for a different interface in a DLL, instead of having an
EXPORT for each function that is called, this design only has one which is
the despatch function which calls the required internal function and
passes back any return value to the calling EXE.
It allows very large parameter counts to be passed in a way that normal
functions find difficult to handle. This example is limited to 32 bit
return values but of course, the address of a different size parameter can
be used in the array or structure parameters for different size return
values.
It can use either an array or a structure to pass the parameters,
depending if you need different size parameters or not. The advantage of
an architecture of this type is that it does not require the operating
system to look up a large EXPORT table. A DLL of this type is also a lot
harder to hack as there is no EXPORT to look up.
There are 2 techniques used to get the parameters at the DLL function end,
the first uses inline asm to dereference the parameters, the second uses
the standard PowerBASIC pointers and is clean and easy to understand code.
This example is still a little rough around the edges and it needs to be
civilised some but it is a viable technique that can be done in the
current PowerBASIC DLL compiler.
James Fuller has a different design that is also original and that has a
number of advantages when understood, perhaps James if time allows would
make an example available as I am sure many would appreciate his design
work here.
Regards,
[email protected]
Code:
' Include file components TYPE IF1 par1 as DWORD par2 as DWORD par3 as DWORD par4 as DWORD END TYPE GLOBAL RemoteMessageBoxS as DWORD GLOBAL RemoteMessageBoxA as DWORD ' runtime code ' -------------------------- ' give DLL functions a name ' -------------------------- RemoteMessageBoxA = 1 RemoteMessageBoxS = 2 ' call the DLL functions LOCAL if1p as IF1 LOCAL mbMsg as ASCIIZ * 128 LOCAL mbTit as ASCIIZ * 128 Case 50 mbMsg = "This messagebox in displayed in iface.dll !!!" mbTit = "Parameters passed in structure" if1p.par1 = hWin if1p.par2 = VarPtr(mbMsg) if1p.par3 = VarPtr(mbTit) if1p.par4 = %MB_OK rv& = icall(RemoteMessageBoxS,VarPtr(if1p)) Case 51 mbMsg = "This messagebox in displayed in iface.dll !!!" mbTit = "Parameters passed in array" redim pars&(4) pars&(0) = hWin pars&(1) = VarPtr(mbMsg) pars&(2) = VarPtr(mbTit) pars&(3) = %MB_OK rv& = icall(RemoteMessageBoxA,VarPtr(pars&(0))) ' The basic despatch DLL interface ' ########################################################################### #COMPILE DLL #INCLUDE "d:\pb6\winapi\win32api.inc" GLOBAL hInstance as LONG ' the DLLs instance handle DECLARE FUNCTION One(ByVal Address as LONG) as LONG DECLARE FUNCTION Two(ByVal Address as DWORD) as LONG DECLARE FUNCTION Three(ByVal Address as LONG) as LONG DECLARE FUNCTION Four(ByVal Address as LONG) as LONG DECLARE FUNCTION Five(ByVal Address as LONG) as LONG ' ########################################################################### FUNCTION LibMain(BYVAL hInst AS LONG, _ BYVAL Reason AS LONG, _ BYVAL Reserved AS LONG) EXPORT AS LONG LOCAL RetVal as LONG Select Case Reason Case %DLL_PROCESS_ATTACH hInstance = hInst ' make DLL instance global RetVal = 1 ' needed so DLL will start ' ------------------- ' uncomment if needed ' ------------------- ' Case %DLL_PROCESS_DETACH ' Case %DLL_THREAD_ATTACH ' Case %DLL_THREAD_DETACH End Select FUNCTION = RetVal END FUNCTION ' ########################################################################### FUNCTION icall ALIAS "icall"(ByVal FuncNum as LONG, _ ByVal Address as LONG) EXPORT as LONG Select Case FuncNum Case 1 FUNCTION = One(Address) Case 2 FUNCTION = Two(Address) Case 3 FUNCTION = Three(Address) Case 4 FUNCTION = Four(Address) Case 5 FUNCTION = Five(Address) End Select FUNCTION = -1 '< function not supported END FUNCTION ' ########################################################################### FUNCTION One(ByVal Address as LONG) as LONG LOCAL par1 as LONG LOCAL par2 as LONG LOCAL par3 as LONG LOCAL par4 as LONG ! mov eax, Address ! mov ecx, [eax] ! mov par1, ecx ! mov ecx, [eax + 4] ! mov par2, ecx ! mov ecx, [eax + 8] ! mov par3, ecx ! mov ecx, [eax + 12] ! mov par4, ecx FUNCTION = MessageBox(par1,ByVal par2,ByVal par3,par4) END FUNCTION ' ########################################################################### FUNCTION Two(ByVal Address as DWORD) as LONG LOCAL par1 as DWORD PTR LOCAL par2 as DWORD PTR LOCAL par3 as DWORD PTR LOCAL par4 as DWORD PTR par1 = Address par2 = Address + 4 par3 = Address + 8 par4 = Address + 12 FUNCTION = MessageBox(@par1,ByVal @par2,ByVal @par3,@par4) END FUNCTION ' ########################################################################### FUNCTION Three(ByVal Address as LONG) as LONG FUNCTION = 0 END FUNCTION ' ########################################################################### FUNCTION Four(ByVal Address as LONG) as LONG FUNCTION = 0 END FUNCTION ' ########################################################################### FUNCTION Five(ByVal Address as LONG) as LONG FUNCTION = 0 END FUNCTION ' ###########################################################################
Comment