-
Dec 4th, 2008, 10:22 PM
#1
[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.
-
Dec 5th, 2008, 10:33 AM
#2
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.
-
Jul 15th, 2017, 09:42 AM
#3
Fanatic Member
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.
-
Jul 15th, 2017, 10:58 PM
#4
Fanatic Member
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|