• Welcome to Theos PowerBasic Museum 2017.

Invoke problem

Started by Lars Jäderberg, November 16, 2009, 01:30:01 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Lars Jäderberg

I have created an Excel instance with OLE API CoCreateInstance. Excel is now running but not visible. I have got the pointer ppApplication to _Application interface.

Now I want to make excel visible with _Application->Visible method (memid 0x22E)


invoke ppApplication.IDispatch.GetTypeInfo,0,0,addr ppTypeInfo
invoke ppTypeInfo.ITypeInfo.GetRefTypeOfImplType,-1,addr pRefType
invoke ppTypeInfo.ITypeInfo.GetRefTypeInfo,pRefType,addr ppRefTypeInfo
invoke ppRefTypeInfo.ITypeInfo.GetFuncDesc,index,addr ppFuncDesc


This tells me that Visible has two parameters (lcid and vt_bool).

To invoke the method


LOCAL dp:DISPPARAMS
LOCAL arrayParams[2]:dword

lea eax,arrayParams
mov dp.rgvarg,eax
mov dp.cArgs,2
mov dp.cNamedArgs,0
mov dp.rgdispidNamedArgs,0
lea edi,arrayParams
mov dword ptr [edi].VARIANT.vt,VT_BOOL
mov dword ptr [edi].VARIANT.boolVal,-1
add edi,sizeof VARIANT
mov dword ptr [edi].VARIANT.vt,VT_I4
mov dword ptr [edi].VARIANT.intVal,0

invoke ppRefTypeInfo.ITypeInfo.invoke,ppApplication,22Eh,DISPATCH_PROPERTYPUT,addr dp,0,0,0


Return value from invoking is not S_OK but 80004001

I have tryed different methods such as invoke ppApplication.IDispatch.invoke and VTBL


mov eax,ppApplication
mov edx,[eax]
mov ptrBool,-1
push ptrBool
push 0
push ppApplication
;call _Application.get_Visible
call dword ptr [edx+283*4]


Any ideas what I am doing wrong?

José Roca

#1
 
Excel can't be used with direct vtable calls because the methods of the dual interface that return pointers to other interfaces return a wrong pointer (e.g. to the dispatch interface ShapeNode instead of IShapeNode). Therefore, you have to use Invoke.

The problem that you are having when using Invoke is that the dispatch interface has not an lcid parameter. When you parse the type library, the vtable view returns two parameters, lcid and RHS, but when you parse it using the automation view, it returns only one parameter.

Therefore, you will have to use something like:


LOCAL dp:DISPPARAMS
LOCAL arrayParams[1]:dword

lea eax,arrayParams
mov dp.rgvarg,eax
mov dp.cArgs,1
mov dp.cNamedArgs,0
mov dp.rgdispidNamedArgs,0
lea edi,arrayParams
mov dword ptr [edi].VARIANT.vt,VT_BOOL
mov dword ptr [edi].VARIANT.boolVal,-1

invoke ppRefTypeInfo.ITypeInfo.invoke,ppApplication,22Eh,DISPATCH_PROPERTYPUT,addr dp,0,0,0


P.S. Be aware, that none of the dispatch methods of Excel has an lcid parameter.

Lars Jäderberg

Thank you for your reply. Much appreciated.

Dispinterface: Visible([in] VARIANT_BOOL rhs);
Interface: Visible([in, lcid] long lcid,[in] VARIANT_BOOL RHS);

I have got this code with Interface to work but not Dispinterface.

invoke CLSIDFromProgID,addr lpWideCharStr,addr ApplicationCLSID
invoke CoCreateInstance,addr ApplicationCLSID,0,CLSCTX_SERVER,addr IID__Application,addr ppv
mov eax,ppv
mov edx,[eax]
mov ptrBool,-1
push ptrBool ;ptr/VT_BOOL/
push 0 ;lcid
push ppv
;call _Application.put_Visible
call dword ptr [edx+283*4]

where ApplicationCLSID = 00024500-0000-0000-C000-000000000046, retrieved from API CLSIDFromProgID and
IID__Application = 000208D5-0000-0000-C000-000000000046 hardcoded (not what I want). Here I puched the lcid argument.

This does not work

invoke CLSIDFromProgID,addr lpWideCharStr,addr ApplicationCLSID
invoke GetIDispatch,addr IDispatchCLSID
invoke CoCreateInstance,addr ApplicationCLSID,0,CLSCTX_SERVER,addr IDispatchCLSID,addr ppv
invoke ppv.IDispatch.GetTypeInfo,3,0,0,addr ppTypeInfo
invoke ppTypeInfo.ITypeInfo.GetDocumentation,5,-1,addr var.bstrVal,0,0,0
invoke ppTypeInfo.ITypeInfo.GetTypeAttr,1,addr ppTypeAttr
invoke ppTypeInfo.ITypeInfo.GetRefTypeOfImplType,2,-1,addr pRefType
invoke ppTypeInfo.ITypeInfo.GetRefTypeInfo,2,pRefType,addr ppRefTypeInfo

lea eax,arrParams
mov dp.rgvarg,eax
mov dp.cArgs,1
mov dp.cNamedArgs,0
mov dp.rgdispidNamedArgs,0
lea edi,arrParams
mov dword ptr [edi].VARIANT.vt,VT_BOOL
mov dword ptr [edi].VARIANT.boolVal,-1
invoke ppTypeInfo.ITypeInfo.invoke,7,ppIDispatch,22Eh,DISPATCH_PROPERTYPUT,addr dp,0,0,0


Where IDispatchCLSID = 00020400-0000-0000-C000-000000000046, var.bstrVal = "_Application" and ppTypeAttr = 000208D5-0000-0000-C000-000000000046.

So this must be correct interface.

ITypeInfo.invoke generate an error 0x80004001 "Not implemented" both for ppRefTypeInfo and ppTypeInfo. Nothing is changed if I use the two arguments lcid and bool or only bool nor if I swap the two arguments.


José Roca

What does the "7" here?


invoke ppTypeInfo.ITypeInfo.invoke,7,ppIDispatch,22Eh,DISPATCH_PROPERTYPUT,addr dp,0,0,0


should be:


invoke ppTypeInfo.ITypeInfo.invoke,ppIDispatch,22Eh,DISPATCH_PROPERTYPUT,addr dp,0,0,0


Quote
I have got this code with Interface to work but not Dispinterface.

The methods of the CoClasses will work with direct calls, but as soon as you will call a method that should return a pointer to an interface it will no longer work because it will return to you a pointer to the IDispatch interface, that has not an vtable.

Lars Jäderberg

Sorry for the "7". The code I am writing in the post is simplifyed. I have a helpfunction with c-calling convention for all com methods and the "7" is the number of argument of the ITypeInfo.invoke method.

Thank you for your explaination of vtbl.

Back to ITypeInfo.invoke. Neither ppRefTypeInfo nor ppTypeInfo give the S_OK result but "Not implemented". So I am still stuck with this problem.

José Roca

Call GetIDsOfNames to retrieve the dispID instead of hardcoding it (22Eh). Believe it or not, the dispIDs are not always the same between different versions of Excel.

Lars Jäderberg

The member id is not hardcoded. It is retrieved from the actual version. However I tryed GetIDsOfNames and got a "Not implemented" error even for this method. What I understand from your answers my thinking is not totally wrong so I will go back to look into my code to see if I can find any cause to the error.

Lars Jäderberg

Now I got it to work. Thank you very much for your help.


invoke CLSIDFromProgID,addr lpWideCharStr,addr ApplicationCLSID
invoke GetIDispatch,addr IDispatchCLSID
invoke CoCreateInstance,addr ApplicationCLSID,0,CLSCTX_SERVER,addr IDispatchCLSID,addr ppv

lea eax,arrParams
mov dp.rgvarg,eax
mov dp.cArgs,1
mov dispidNamed,DISPID_PROPERTYPUT ;Specially for property put
mov dp.cNamedArgs,1
lea eax,dispidNamed
mov dp.rgdispidNamedArgs,eax
lea edi,arrParams
mov dword ptr [edi].VARIANT.vt,VT_BOOL
mov dword ptr [edi].VARIANT.boolVal,-1
invoke ppv.IDispatch.Invoke,22Eh,offset NullCLSID,0,DISPATCH_PROPERTYPUT,addr dp,0,0,0


You must consider if the method is a propterty put an load a named argument (DISPID_PROPERTYPUT).