Results 1 to 9 of 9

Thread: [RESOLVED] Call By Address

  1. #1

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Resolved [RESOLVED] Call By Address

    Okay, I think I've done this before, but I can't find it.

    Let's say I've got the following function (and I can't change it):

    Code:
    
    Public Function SomeProc(ByVal SomeLong As Long) As Long
        '
        ' Do Stuff.
        '
    End Function
    
    And now, I'm down in a procedure and all I've got is that function's address (via AddressOf).

    Also, and this is important, I just want to do this in the IDE.

    How can I call that function (again, no changes to arguments) when all I've got is its address?

    Thanks,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  2. #2
    Frenzied Member
    Join Date
    Apr 2012
    Posts
    1,253

    Re: Call By Address

    From memory, CallWindowProc should do the job. Lemme just check...

    EDIT:
    Can't find the code I thought I had, but it was something I played around with relating to this:

    http://www.vbforums.com/showthread.p...own-callbacks)
    Last edited by ColinE66; May 29th, 2018 at 01:39 PM.
    If you don't know where you're going, any road will take you there...

    My VB6 love-children: Vee-Hive and Vee-Launcher

  3. #3
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,055

    Re: Call By Address

    [...]
    Last edited by dz32; Apr 26th, 2019 at 11:18 AM.

  4. #4
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: Call By Address

    Yup, DispCallFunc is the standard (for VBA too). You can use it to call any Calling Convention, like C Dlls etc.
    LaVolpe,Schmidt,Trick and I have examples floating around.

    Some people also use Assembly thunks. I think Trick or Bonnie and Wqweto have examples of that somewhere. The thunks are very simple and low overhead (fast)

    I think Hacker posted a cool method on a russian VB site where you can patch up an API Declare, to point to your function too.
    Last edited by DEXWERX; May 29th, 2018 at 02:07 PM.

  5. #5

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Call By Address

    Yeah, I knew that CallWindowProc could do something similar. However, to use that, you must have your procedure set up as:

    Code:
    
    Public Sub Proc1(ByVal arg1 As Long, ByVal arg2 As Long, ByVal arg3 As Long, ByVal arg4 As Long)
    	'
    End Sub
    
    
    ' ********* or **********
    
    
    Public Function Proc2(ByVal arg1 As Long, ByVal arg2 As Long, ByVal arg3 As Long, ByVal arg4 As Long) As Long
    	'
    End Function
    
    
    And I'd rather not change how my procedure is declared. And yeah, I'm looking at FireHacker's stuff, but it's complicated. I need to figure out how to use DispCallFunc I suppose. Maybe LaVolpe will weigh in and give me some pointers.

    Thanks,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  6. #6
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,672

    Re: Call By Address

    http://www.vbforums.com/showthread.p...ons-by-pointer
    Code:
    Sub Main()
        
        PatchFunc AddressOf SomeProc_Proto
        
        ' // Call by pointer
        SomeProc_Proto AddressOf SomeProc, 1234
        
    End Sub
    
    Public Function SomeProc_Proto(ByVal pAddr As Long, ByVal SomeLong As Long) As Long
    End Function
    
    Public Function SomeProc(ByVal SomeLong As Long) As Long
        '
        ' Do Stuff.
        '
        MsgBox "By pointer " & SomeLong
        
    End Function
    With DispCallFunc:

    Code:
    Option Explicit
    
    Private Declare Function DispCallFunc Lib "oleaut32.dll" ( _
                             ByVal pvInstance As Long, _
                             ByVal FuncAddr As Long, _
                             ByVal CallConvention As Integer, _
                             ByVal rtnType As VbVarType, _
                             ByVal FuncArgsCnt As Long, _
                             ByRef FuncArgTypes As Any, _
                             ByRef FuncArgVarAddresses As Any, _
                             ByRef FuncResult As Any) As Long
    
    Sub Main()
        
        StdCall AddressOf SomeProc, vbLong, 1234&
        
    End Sub
    
    
    Public Function SomeProc(ByVal SomeLong As Long) As Long
        '
        ' Do Stuff.
        '
        MsgBox "By pointer " & SomeLong
        
    End Function
    
    Public Function StdCall(ByVal pAddr As Long, ByVal retType As VbVarType, ParamArray params()) As Variant
        Dim types()     As Integer
        Dim list()      As Long
        Dim param()     As Variant
        Dim pIndex      As Long
        Dim ptrList     As Long
        Dim ptrTypes    As Long
        Dim resultCall  As Long
    
        Const CC_STDCALL    As Long = 4
        
        If LBound(params) <= UBound(params) Then
            
            ReDim list(LBound(params) To UBound(params))
            ReDim types(LBound(params) To UBound(params))
            ReDim param(LBound(params) To UBound(params))
            
            For pIndex = LBound(params) To UBound(params)
            
                param(pIndex) = params(pIndex)
                list(pIndex) = VarPtr(param(pIndex))
                types(pIndex) = VarType(types(pIndex))
                
            Next
            
            ptrList = VarPtr(list(LBound(list)))
            ptrTypes = VarPtr(types(LBound(types)))
            
        End If
     
        resultCall = DispCallFunc(ByVal 0&, _
                                  pAddr, _
                                  CC_STDCALL, _
                                  retType, _
                                  UBound(params) - LBound(params) + 1, _
                                  ByVal ptrTypes, _
                                  ByVal ptrList, _
                                  StdCall)
                 
        If resultCall Then Err.Raise 5: Exit Function
        
    End Function
    With single param you can make it more shorter (from Multithreading code):
    Code:
    DispCallFunc(ByVal 0&, lpStartAddress, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(CVar(lpParameter)), CVar(0))

  7. #7

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Call By Address

    @Trick: Thank you! That's absolutely perfect.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  8. #8
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: [RESOLVED] Call By Address

    I shrinked Trick's trampoline factory a bit here with a single Currency var:

    thinBasic Code:
    1. Public Sub RtccPatchProto(ByVal pfn As Long) '--- Helper by The trick
    2.     Dim bInIDE          As Boolean
    3.  
    4.     Debug.Assert pvSetTrue(bInIDE)
    5.     If bInIDE Then
    6.         Call CopyMemory(pfn, ByVal UnsignedAdd(pfn, &H16), 4)
    7.     Else
    8.         Call VirtualProtect(pfn, 8, PAGE_EXECUTE_READWRITE, 0)
    9.     End If
    10.     ' 0:  58                      pop    eax
    11.     ' 1:  59                      pop    ecx
    12.     ' 2:  50                      push   eax
    13.     ' 3:  ff e1                   jmp    ecx
    14.     ' 5:  90                      nop
    15.     ' 6:  90                      nop
    16.     ' 7:  90                      nop
    17.     Call CopyMemory(ByVal pfn, -802975883527609.7192@, 8)
    18. End Sub
    ... and the proto routines can be self-patching like this:

    thinBasic Code:
    1. Public Function CallMul(ByVal pfn As Long, ByVal lFirst As Long, ByVal lSecond As Long) As Long
    2.     '--- on first call will self-patch to call `pfn` with args `lFirst` and `lSecond` directly
    3.     RtccPatchProto AddressOf Module1.CallMul
    4.     CallMul = CallMul(pfn, lFirst, lSecond)
    5. End Function
    ... to reduce initialization ceremony.

    cheers,
    </wqw>

  9. #9
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: [RESOLVED] Call By Address

    @wqweto nice. That's a lot like Curland's approach with the code in a single currency; even the assembly is similar Although Curland has a way of over complicating everything, by involving typelibs and interfaces, and patching vtables...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width