Option Explicit
Public Declare Function FreeLibrary Lib "kernel32" ( _
ByVal hLibModule As Long _
) As Long
Public Declare Function LoadLibrary Lib "kernel32" _
Alias "LoadLibraryA" ( _
ByVal lpLibFileName As String _
) As Long
Public Declare Function GetProcAddress Lib "kernel32" ( _
ByVal hModule As Long, _
ByVal lpProcName As String _
) As Long
Private Declare Function GetExitCodeThread Lib "kernel32" ( _
ByVal hThread As Long, _
lpExitCode As Long _
) As Long
Private Declare Function CreateThread Lib "kernel32" ( _
ByVal lpThreadAttributes As Long, _
ByVal dwStackSize As Long, _
ByVal lpStartAddress As Long, _
ByVal lpParameter As Long, _
ByVal dwCreationFlags As Long, _
lpThreadId As Long _
) As Long
Private Declare Function GlobalAlloc Lib "kernel32" ( _
ByVal Flags As Long, _
ByVal Size As Long _
) As Long
Private Declare Function GlobalFree Lib "kernel32" ( _
ByVal Mem As Long _
) As Long
Private Declare Function MoveMemory Lib "kernel32" _
Alias "RtlMoveMemory" ( _
ByRef Dest As Any, _
ByRef Src As Any, _
ByVal Size As Long _
) As Long
Private Const GMEM_FIXED As Long = 0&
Public Function CallFuncPtr( _
FuncPtr As Long, _
ParamArray Params() As Variant _
) As Long
Const MAX_CODESIZE As Long = 65536
Dim I As Long
Dim pCodeData As Long
Dim pParamData() As Long
Dim PC As Long
Dim Operand As Long
Dim RetValue As Long
Dim StrValue As String
Dim LongValue As Long
Dim dwThreadID As Long
Dim hThread As Long
Dim dwExit As Long
ReDim pParamData(UBound(Params)) As Long
pCodeData = GlobalAlloc(GMEM_FIXED, MAX_CODESIZE)
PC = pCodeData
AddByte PC, &H55
For I = UBound(Params) To 0 Step -1
If VarType(Params(I)) = vbString Then
pParamData(I) = GlobalAlloc(GMEM_FIXED, _
LenB(Params(I)))
StrValue = Params(I)
MoveMemory ByVal pParamData(I), _
ByVal StrValue, LenB(StrValue)
Operand = pParamData(I)
Else
Operand = Params(I)
End If
AddByte PC, &H68
AddLong PC, Operand
Next
AddByte PC, &HB8
AddLong PC, FuncPtr
AddInt PC, &HD0FF
AddByte PC, &HBA
AddLong PC, VarPtr(RetValue)
AddInt PC, &H289
AddByte PC, &H5D
AddInt PC, &HC033
AddByte PC, &HC2
AddInt PC, &H8
hThread = CreateThread(0, 0, pCodeData, _
0, 0, dwThreadID)
Do
' if exit code is 256 the thread is
' still running
GetExitCodeThread hThread, dwExit
If dwExit <> 259 Then Exit Do
DoEvents
Loop
GlobalFree pCodeData
For I = 0 To UBound(Params)
If pParamData(I) <> 0 Then
GlobalFree pParamData(I)
End If
Next
CallFuncPtr = RetValue
End Function
Private Sub AddByte(ByRef PC As Long, ByVal ByteValue As Byte)
MoveMemory ByVal PC, ByteValue, 1
PC = PC + 1
End Sub
Private Sub AddInt(ByRef PC As Long, ByVal IntValue As Integer)
MoveMemory ByVal PC, IntValue, 2
PC = PC + 2
End Sub
Private Sub AddLong(ByRef PC As Long, ByVal LongValue As Long)
MoveMemory ByVal PC, LongValue, 4
PC = PC + 4
End Sub
Public Sub Main()
Dim hDll As Long
Dim pMessageBox As Long
' get the address of MessageBoxA()
'
' user32 should already be loaded but
' we need its module handle
hDll = LoadLibrary("user32.dll") ' Loading User32.dll Library
pMessageBox = GetProcAddress(hDll, "MessageBoxA") ' Getting API Handle
' Calling our Function and running it in New Thread.
If CallFuncPtr(pMessageBox, 0, "MessageBoxA Test", "Test", 1) = 1 Then
MsgBox "You pressed Ok"
Else
MsgBox "You pressed Cance"
End If
' Free the Loaded Library User32.dll
FreeLibrary hDll
End Sub
Private Declare Function FreeLibrary Lib "kernel32" ( _
ByVal hLibModule As Long _
) As Long