Results 1 to 17 of 17

Thread: [RESOLVED, not possible] Can't get "Class" AddressOf to work

Threaded View

  1. #6
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,179

    Re: Can't get "Class" AddressOf to work

    Quote Originally Posted by Elroy View Post
    I'd really just like something with no thunk, no subclassing, no IDE protection that I could throw into a CLS module (or maybe a FRM or CTL module) and get addresses of internal procedures for quick callback things, and preserve the idea of keeping all related code together.
    If this was possible no one would bother writing thunks for this but directly solve the issue and continue churning code :-))

    TB has done this now. No extra thunking needed, just use lPfn = AddressOf MyInstance.MyMethod and you get an address to an instance-bound trampoline which can be used as along as the instance is alive.

    The trampoline must translate method signatures so that something like HRESULT MyMethod(MyClass *This, long dwData, long *RetVal) can be used to implement long MyCallback(long dwData) i.e. in methods the retval is actually an output param which is translated to a real retval.

    Btw, here is a minimal self-containing AddressOfMethod impl from MST, no IDE protection at all but MyCallback method must be public (can be hidden)

    Code:
    '--- Form1
    Option Explicit
    
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Private Declare Function VirtualAlloc Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
    Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
    Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
    
    Private Sub Form_Load()
        Dim lPfn            As Long
        
        lPfn = InitAddressOfMethod(Me, 1).MyCallback(0)
        Debug.Print Hex$(lPfn), Timer
    End Sub
    
    Public Function MyCallback(ByVal dwData As Long) As Long
    
    End Function
    
    Private Function InitAddressOfMethod(pObj As Object, ByVal MethodParamCount As Long) As Form1
        Dim STR_THUNK       As String: STR_THUNK = "6AAAAABag+oFV4v6ge9QEMEAgcekEcEAuP9EJAS5+QcAAPOri8LB4AgFuQAAAKuLwsHoGAUAjYEAq7gIAAArq7hEJASLq7hJCIsEq7iBi1Qkq4tEJAzB4AIFCIkCM6uLRCQMweASBcDCCACriTrHQgQBAAAAi0QkCIsAiUIIi0QkEIlCDIHqUBDBAIvCBTwRwQCri8IFUBHBAKuLwgVgEcEAq4vCBYQRwQCri8IFjBHBAKuLwgWUEcEAq4vCBZwRwQCri8IFpBHBALn5BwAAq4PABOL6i8dfgcJQEMEAi0wkEIkRK8LCEAAPHwCLVCQE/0IEi0QkDIkQM8DCDABmkItUJAT/QgSLQgTCBAAPHwCLVCQE/0oEi0IEg/gAfgPCBABZWotCDGgAgAAAagBSUf/gZpC4AUAAgMIIALgBQACAwhAAuAFAAIDCGAC4AUAAgMIkAA==" ' 25.3.2019 14:01:08
        Const THUNK_SIZE    As Long = 16728
        Dim hThunk          As Long
        Dim lSize           As Long
        
        hThunk = pvThunkAllocate(STR_THUNK, THUNK_SIZE)
        If hThunk = 0 Then
            Exit Function
        End If
        lSize = CallWindowProc(hThunk, ObjPtr(pObj), MethodParamCount, GetProcAddress(GetModuleHandle("kernel32"), "VirtualFree"), VarPtr(InitAddressOfMethod))
        Debug.Assert lSize = THUNK_SIZE
    End Function
    
    Private Function pvThunkAllocate(sText As String, Optional ByVal Size As Long) As Long
        Const MEM_COMMIT                    As Long = &H1000
        Const PAGE_EXECUTE_READWRITE        As Long = &H40
        Const SIGN_BIT                      As Long = &H80000000
        Static Map(0 To &H3FF) As Long
        Dim baInput()       As Byte
        Dim lIdx            As Long
        Dim lChar           As Long
        Dim lPtr            As Long
        
        pvThunkAllocate = VirtualAlloc(0, IIf(Size > 0, Size, (Len(sText) \ 4) * 3), MEM_COMMIT, PAGE_EXECUTE_READWRITE)
        If pvThunkAllocate = 0 Then
            Exit Function
        End If
        '--- init decoding maps
        If Map(65) = 0 Then
            baInput = StrConv("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", vbFromUnicode)
            For lIdx = 0 To UBound(baInput)
                lChar = baInput(lIdx)
                Map(&H0 + lChar) = lIdx * (2 ^ 2)
                Map(&H100 + lChar) = (lIdx And &H30) \ (2 ^ 4) Or (lIdx And &HF) * (2 ^ 12)
                Map(&H200 + lChar) = (lIdx And &H3) * (2 ^ 22) Or (lIdx And &H3C) * (2 ^ 6)
                Map(&H300 + lChar) = lIdx * (2 ^ 16)
            Next
        End If
        '--- base64 decode loop
        baInput = StrConv(Replace(Replace(sText, vbCr, vbNullString), vbLf, vbNullString), vbFromUnicode)
        lPtr = pvThunkAllocate
        For lIdx = 0 To UBound(baInput) - 3 Step 4
            lChar = Map(baInput(lIdx + 0)) Or Map(&H100 + baInput(lIdx + 1)) Or Map(&H200 + baInput(lIdx + 2)) Or Map(&H300 + baInput(lIdx + 3))
            Call CopyMemory(ByVal lPtr, lChar, 3)
            lPtr = (lPtr Xor SIGN_BIT) + 3 Xor SIGN_BIT
        Next
    End Function
    cheers,
    </wqw>

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