|
-
Sep 26th, 2022, 03:08 AM
#6
Re: Can't get "Class" AddressOf to work
 Originally Posted by Elroy
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>
Last edited by wqweto; Sep 26th, 2022 at 03:13 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|