Results 1 to 4 of 4

Thread: [RESOLVED] DispCallFunc on VB Classes

  1. #1

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Resolved [RESOLVED] DispCallFunc on VB Classes

    I have found very few examples of this API's usage and have found none that use it against a VB object, say a class, form, or usercontrol.

    It is a very interesting API and I'm trying to learn to use it.

    Here is an example, if anyone knows how to do this, please advise.

    Simply call a VB class/form's AddRef and Release to see if 1) you can get a return value and 2) don't crash VB.

    This may be partly my fault or misunderstanding of the ObjPtr.....
    Here's what I think is true: VarPtr(Object) > ObjPtr(Object) > Object VTable.

    If that's true, doesn't the QueryInterface, AddRef & Release occupy the 1st 3 entries in the VTable? If so, then I'm confused because I can't get that API to work correctly without crashing VB. Here is how I defined it and a sample call I was trying (it crashes VB).

    Edited:
    ObjPtr(Me) = [#1968616] which points to VTable which is also IUknown: [#196844]
    Dim IUnknownVar As IUnknown
    Set IUnknownVar=Me & ObjPtr(IUnknownVar) = [#1968644]
    Therefore, ObjPtr(Me) is a pointer directly to IUnknown
    Calling AddRef using DispCallFunc should not crash! But it does, ugh

    Code:
    Private Declare Sub DispCallFunc Lib "oleaut32" (ByVal PPV As Long, ByVal oVft As Long, ByVal cc As Long, ByVal rtTYP As VbVarType, ByVal paCNT As Long, ByVal paTypes As Long, ByVal paValues As Long, ByRef fuReturn As Variant)
    
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
    Code:
    ' Sample call using a form
        Const CC_STDCALL As Long = 4&
        Dim vTableAddr As Long, IID_AddRefOffset As Long, varRtn As Variant
        IID_AddRefOffset = 4&
        CopyMemory vTableAddr, ByVal ObjPtr(Me), 4&
        Call DispCallFunc(vTableAddr, IID_AddRefOffset, CC_STDCALL, _
                            vbLong, 0&, 0&, 0&, varRtn)
            Debug.Print "add "; varRtn
    Note: I have seen this API delcared both as function and sub; further confusing the issue. I have tried so many variations I think I am going around in circles. Hoping someone else will give it a valid go & report back.
    Last edited by LaVolpe; Dec 5th, 2008 at 10:29 AM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  2. #2

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: DispCallFunc on VB Classes

    Ugh is right, kept going around in circles. I needed to pass the ObjPtr and not the VTable to the function, it works as expected. Modified code follows as does the modified API declaration:

    Code:
    Private Declare Function DispCallFunc Lib "oleaut32" (ByVal PPV As Long, ByVal oVft As Long, ByVal cc As Long, ByVal rtTYP As VbVarType, ByVal paCNT As Long, ByVal paTypes As Long, ByVal paValues As Long, ByRef fuReturn As Variant) As Long
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
    Code:
    Private Sub Command1_Click()
    ' Sample call using a form
        Const CC_STDCALL As Long = 4&
        Dim IID_AddRefOffset As Long, varRtn As Variant
        Dim pUNK as Long
        IID_AddRefOffset = 4&
        pUNK = ObjPtr(Me)
        Call DispCallFunc(pUNK, IID_AddRefOffset, CC_STDCALL, _
                            vbLong, 0&, 0&, 0&, varRtn)
            Debug.Print "add "; varRtn
        Call DispCallFunc(pUNK, IID_AddRefOffset + 4&, CC_STDCALL, _
                            vbLong, 0&, 0&, 0&, varRtn)
            Debug.Print "del "; varRtn
    End Sub
    P.S. This API is really neat. Without the use of TLBs, I can acutally manipulate just about any Interface, already playing with IUknown, IDispatch, IPerPropertyBrowsing and more.
    Last edited by LaVolpe; Dec 6th, 2008 at 01:18 AM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: [RESOLVED] DispCallFunc on VB Classes

    Hi,

    I am trying to learn how to use DispCallFunc with Objects and I have found this interesting post .

    I have a simple Class that has one Public Method as follows (No other code in the class) :

    Class1 code:
    Code:
    Public Sub FirstMethod()
        MsgBox "hello"
    End Sub
    Now, in a Standard module, I have the following code to call the Class Method :
    Code:
    Private Declare PtrSafe Function DispCallFunc Lib "oleaut32" _
    (ByVal PPV As LongPtr, ByVal oVft As Long, ByVal cc As Long, ByVal rtTYP As VbVarType, _
    ByVal paCNT As Long, ByVal paTypes As LongPtr, ByVal paValues As LongPtr, ByRef fuReturn As Variant) As Long
    
    Private Sub Test()
    
        Const CC_STDCALL As Long = 4&
        Dim oClass As Class1
        Dim pUNK As LongPtr
        Dim IID_First_Method_Offset As Long, varRtn As Variant
       
        IID_First_Method_Offset = 7 '<== First Method after IUnknown and IDisPatch interfaces.
        Set oClass = New Class1
        pUNK = ObjPtr(oClass)
        
        Call DispCallFunc(pUNK, IID_First_Method_Offset, CC_STDCALL, _
                            vbEmpty, 0&, 0&, 0&, varRtn)
    End Sub
    When I execute the code, it crashes ... Do you know what I am doing wrong ?

    Note: The LongPtr var type is there instead of Long simply because I am using this in VBA 64bits (pointers are 64bit) .

    Regards.
    Last edited by JAAFAR; Jul 15th, 2017 at 09:58 AM.

  4. #4
    Fanatic Member
    Join Date
    Nov 2013
    Posts
    658

    Re: [RESOLVED] DispCallFunc on VB Classes

    Ok in case anyone is interested, here is the code that works :
    Code:
    Private Declare PtrSafe _
    Function DispCallFunc Lib "OleAut32.dll" ( _
        ByVal pvInstance As LongPtr, _
        ByVal oVft As LongPtr, _
        ByVal cc_ As Long, _
        ByVal vtReturn As Integer, _
        ByVal cActuals As Long, _
        ByRef prgvt As Integer, _
        ByRef prgpvarg As LongPtr, _
        ByRef pvargResult As Variant _
        ) As Long
    
    Private oClass As Class1
    
    Private Sub Test()
    
        Const CC_STDCALL As Long = 4&
        Dim pUNK As LongPtr
        Dim IID_First_Method_Offset As Long, varRtn As Variant
       
        IID_First_Method_Offset = 7 * 4 * 2 ' (7 (VTable index) * 4bytes * 2(LongLong win64))
        Set oClass = New Class1
        pUNK = ObjPtr(oClass)
        
        Call DispCallFunc(pUNK, IID_First_Method_Offset, CC_STDCALL, _
                            vbEmpty, 0&, 0&, 0&, varRtn)
    End Sub
    I was wrongly passing the Method offset as 7 which should be 7* 4(bytes) *2(Win64)

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