1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 // Documentation pointers for recent work:
22 // https://www.codeproject.com/Articles/9014/Understanding-COM-Event-Handling
23 // https://blogs.msdn.microsoft.com/ericlippert/2005/02/15/why-does-wscript-connectobject-not-always-work/
25 #include "ole2uno.hxx"
30 #include <unordered_map>
33 #if defined _MSC_VER && defined __clang__
34 #pragma clang diagnostic push
35 #pragma clang diagnostic ignored "-Wall"
36 #pragma clang diagnostic ignored "-Wattributes"
37 #pragma clang diagnostic ignored "-Wdelete-incomplete"
38 #pragma clang diagnostic ignored "-Wdynamic-class-memaccess"
39 #pragma clang diagnostic ignored "-Wextra"
40 #pragma clang diagnostic ignored "-Wint-to-pointer-cast"
41 #pragma clang diagnostic ignored "-Winvalid-noreturn"
42 #pragma clang diagnostic ignored "-Wmicrosoft"
43 #pragma clang diagnostic ignored "-Wnon-pod-varargs"
44 #pragma clang diagnostic ignored "-Wnonportable-include-path"
45 #pragma clang diagnostic ignored "-Wsequence-point"
46 #pragma clang diagnostic ignored "-Wtypename-missing"
50 #if defined _MSC_VER && defined __clang__
51 #pragma clang diagnostic pop
55 #include <osl/diagnose.h>
56 #include <salhelper/simplereferenceobject.hxx>
57 #include <rtl/ref.hxx>
58 #include <rtl/ustring.hxx>
59 #include <sal/log.hxx>
60 #include <com/sun/star/beans/MethodConcept.hpp>
61 #include <com/sun/star/beans/PropertyConcept.hpp>
62 #include <com/sun/star/lang/NoSuchMethodException.hpp>
63 #include <com/sun/star/script/CannotConvertException.hpp>
64 #include <com/sun/star/script/FailReason.hpp>
65 #include <com/sun/star/reflection/theCoreReflection.hpp>
66 #include <com/sun/star/reflection/ParamInfo.hpp>
67 #include <com/sun/star/beans/XExactName.hpp>
68 #include <com/sun/star/container/NoSuchElementException.hpp>
69 #include <com/sun/star/container/XEnumeration.hpp>
70 #include <com/sun/star/container/XEnumerationAccess.hpp>
72 #include <com/sun/star/beans/XMaterialHolder.hpp>
73 #include <com/sun/star/script/XInvocation2.hpp>
74 #include <com/sun/star/script/MemberType.hpp>
75 #include <com/sun/star/reflection/XIdlReflection.hpp>
76 #include <ooo/vba/XCollection.hpp>
77 #include <ooo/vba/XConnectable.hpp>
78 #include <ooo/vba/XConnectionPoint.hpp>
79 #include <ooo/vba/XSink.hpp>
80 #include <ooo/vba/msforms/XCheckBox.hpp>
81 #include <osl/interlck.h>
82 #include <com/sun/star/uno/genfunc.h>
83 #include <comphelper/automationinvokedzone.hxx>
84 #include <comphelper/processfactory.hxx>
85 #include <comphelper/profilezone.hxx>
86 #include <comphelper/windowsdebugoutput.hxx>
87 #include <comphelper/windowserrorstring.hxx>
88 #include <o3tl/char16_t2wchar_t.hxx>
89 #include <o3tl/safeint.hxx>
91 #include "comifaces.hxx"
92 #include "jscriptclasses.hxx"
93 #include "unotypewrapper.hxx"
94 #include "oleobjw.hxx"
95 #include "unoobjw.hxx"
96 #include "servprov.hxx"
100 using namespace com::sun::star::uno
;
101 using namespace com::sun::star::beans
;
102 using namespace com::sun::star::container
;
103 using namespace com::sun::star::script
;
104 using namespace com::sun::star::lang
;
105 using namespace com::sun::star::bridge::ModelDependent
;
106 using namespace com::sun::star::reflection
;
108 std::unordered_map
<sal_uIntPtr
, WeakReference
<XInterface
> > UnoObjToWrapperMap
;
109 static bool writeBackOutParameter(VARIANTARG
* pDest
, VARIANT
* pSource
);
110 static bool writeBackOutParameter2( VARIANTARG
* pDest
, VARIANT
* pSource
);
111 static HRESULT
mapCannotConvertException(const CannotConvertException
&e
, unsigned int * puArgErr
);
113 /* Does not throw any exceptions.
114 Param pInfo can be NULL.
116 static void writeExcepinfo(EXCEPINFO
* pInfo
, const OUString
& message
)
118 if (pInfo
!= nullptr)
120 pInfo
->wCode
= UNO_2_OLE_EXCEPTIONCODE
;
121 pInfo
->bstrSource
= SysAllocString(L
"[automation bridge] ");
122 pInfo
->bstrDescription
= SysAllocString(o3tl::toW(message
.getStr()));
126 InterfaceOleWrapper::InterfaceOleWrapper( Reference
<XMultiServiceFactory
> const & xFactory
,
127 sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
128 UnoConversionUtilities
<InterfaceOleWrapper
>( xFactory
, unoWrapperClass
, comWrapperClass
),
129 m_defaultValueType( 0)
133 InterfaceOleWrapper::~InterfaceOleWrapper()
135 MutexGuard
guard(getBridgeMutex());
136 // remove entries in global map
137 auto it
= UnoObjToWrapperMap
.find( reinterpret_cast<sal_uIntPtr
>(m_xOrigin
.get()));
138 if(it
!= UnoObjToWrapperMap
.end())
139 UnoObjToWrapperMap
.erase(it
);
142 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::QueryInterface(REFIID riid
, void ** ppv
)
144 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
146 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::QueryInterface(" << riid
<< ")");
153 if(IsEqualIID(riid
, IID_IUnknown
))
156 *ppv
= static_cast<IUnknown
*>(static_cast<IDispatch
*>(this));
157 SAL_INFO("extensions.olebridge", " " << *ppv
);
159 else if (IsEqualIID(riid
, IID_IDispatch
))
162 *ppv
= static_cast<IDispatch
*>(this);
163 SAL_INFO("extensions.olebridge", " " << *ppv
);
165 else if (IsEqualIID(riid
, IID_IProvideClassInfo
))
167 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
168 if (!xConnectable
.is())
169 return E_NOINTERFACE
;
171 *ppv
= static_cast<IProvideClassInfo
*>(this);
172 SAL_INFO("extensions.olebridge", " " << *ppv
);
174 else if (IsEqualIID(riid
, IID_IConnectionPointContainer
))
176 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
177 if (!xConnectable
.is())
178 return E_NOINTERFACE
;
180 *ppv
= static_cast<IConnectionPointContainer
*>(this);
181 SAL_INFO("extensions.olebridge", " " << *ppv
);
183 else if( IsEqualIID( riid
, __uuidof( IUnoObjectWrapper
)))
186 *ppv
= static_cast<IUnoObjectWrapper
*>(this);
187 SAL_INFO("extensions.olebridge", " " << *ppv
);
194 COM_DECLSPEC_NOTHROW
STDMETHODIMP_(ULONG
) InterfaceOleWrapper::AddRef()
197 // does not need to guard because one should not rely on the return value of
202 COM_DECLSPEC_NOTHROW
STDMETHODIMP_(ULONG
) InterfaceOleWrapper::Release()
209 // IUnoObjectWrapper --------------------------------------------------------
210 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::getWrapperXInterface( Reference
<XInterface
>* pXInt
)
212 pXInt
->set( static_cast<XWeak
*>( this), UNO_QUERY
);
213 return pXInt
->is() ? S_OK
: E_FAIL
;
215 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::getOriginalUnoObject( Reference
<XInterface
>* pXInt
)
218 return m_xOrigin
.is() ? S_OK
: E_FAIL
;
220 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::getOriginalUnoStruct( Any
* pStruct
)
222 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
227 Reference
<XMaterialHolder
> xMatHolder( m_xInvocation
, UNO_QUERY
);
230 Any any
= xMatHolder
->getMaterial();
231 if( any
.getValueTypeClass() == TypeClass_STRUCT
)
241 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::GetTypeInfoCount( UINT
*pctinfo
)
243 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetTypeInfoCount");
255 class CXTypeInfo
: public ITypeInfo
,
256 public CComObjectRoot
259 enum class Kind
{ COCLASS
, MAIN
, OUTGOING
};
261 #if defined __clang__
262 #pragma clang diagnostic push
263 #pragma clang diagnostic ignored "-Wunused-function"
265 BEGIN_COM_MAP(CXTypeInfo
)
266 #if defined __clang__
267 #pragma clang diagnostic pop
269 COM_INTERFACE_ENTRY(ITypeInfo
)
270 #if defined __clang__
271 #pragma clang diagnostic push
272 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
273 #pragma clang diagnostic ignored "-Wunused-function"
276 #if defined __clang__
277 #pragma clang diagnostic pop
280 DECLARE_NOT_AGGREGATABLE(CXTypeInfo
)
282 virtual ~CXTypeInfo() {}
284 void InitForCoclass(Reference
<XInterface
> xOrigin
,
285 const OUString
& sImplementationName
,
287 Reference
<XMultiServiceFactory
> xMSF
);
288 void InitForClassItself(Reference
<XInterface
> xOrigin
,
289 const OUString
& sImplementationName
,
291 Reference
<XMultiServiceFactory
> xMSF
);
292 void InitForOutgoing(Reference
<XInterface
> xOrigin
,
293 const OUString
& sInterfaceName
,
295 Reference
<XMultiServiceFactory
> xMSF
,
297 virtual HRESULT STDMETHODCALLTYPE
GetTypeAttr(TYPEATTR
**ppTypeAttr
) override
;
298 virtual HRESULT STDMETHODCALLTYPE
GetTypeComp(ITypeComp
**ppTComp
) override
;
299 virtual HRESULT STDMETHODCALLTYPE
GetFuncDesc(UINT index
,
300 FUNCDESC
**ppFuncDesc
) override
;
301 virtual HRESULT STDMETHODCALLTYPE
GetVarDesc(UINT index
,
302 VARDESC
**ppVarDesc
) override
;
303 virtual HRESULT STDMETHODCALLTYPE
GetNames(MEMBERID memid
,
306 UINT
*pcNames
) override
;
307 virtual HRESULT STDMETHODCALLTYPE
GetRefTypeOfImplType(UINT index
,
308 HREFTYPE
*pRefType
) override
;
309 virtual HRESULT STDMETHODCALLTYPE
GetImplTypeFlags(UINT index
,
310 INT
*pImplTypeFlags
) override
;
311 virtual HRESULT STDMETHODCALLTYPE
GetIDsOfNames(LPOLESTR
*rgszNames
,
313 MEMBERID
*pMemId
) override
;
314 virtual HRESULT STDMETHODCALLTYPE
Invoke(PVOID pvInstance
,
317 DISPPARAMS
*pDispParams
,
319 EXCEPINFO
*pExcepInfo
,
320 UINT
*puArgErr
) override
;
321 virtual HRESULT STDMETHODCALLTYPE
GetDocumentation(MEMBERID memid
,
323 BSTR
*pBstrDocString
,
324 DWORD
*pdwHelpContext
,
325 BSTR
*pBstrHelpFile
) override
;
326 virtual HRESULT STDMETHODCALLTYPE
GetDllEntry(MEMBERID memid
,
330 WORD
*pwOrdinal
) override
;
331 virtual HRESULT STDMETHODCALLTYPE
GetRefTypeInfo(HREFTYPE hRefType
,
332 ITypeInfo
**ppTInfo
) override
;
333 virtual HRESULT STDMETHODCALLTYPE
AddressOfMember(MEMBERID memid
,
335 PVOID
*ppv
) override
;
336 virtual HRESULT STDMETHODCALLTYPE
CreateInstance(IUnknown
*pUnkOuter
,
338 PVOID
*ppvObj
) override
;
339 virtual HRESULT STDMETHODCALLTYPE
GetMops(MEMBERID memid
,
340 BSTR
*pBstrMops
) override
;
341 virtual HRESULT STDMETHODCALLTYPE
GetContainingTypeLib(ITypeLib
**ppTLib
,
342 UINT
*pIndex
) override
;
343 virtual void STDMETHODCALLTYPE
ReleaseTypeAttr(TYPEATTR
*pTypeAttr
) override
;
344 virtual void STDMETHODCALLTYPE
ReleaseFuncDesc(FUNCDESC
*pFuncDesc
) override
;
345 virtual void STDMETHODCALLTYPE
ReleaseVarDesc(VARDESC
*pVarDesc
) override
;
349 Reference
<XInterface
> mxOrigin
;
350 OUString msImplementationName
;
351 OUString msInterfaceName
;
353 Reference
<XMultiServiceFactory
> mxMSF
;
357 class CXTypeLib
: public ITypeLib
,
358 public CComObjectRoot
361 #if defined __clang__
362 #pragma clang diagnostic push
363 #pragma clang diagnostic ignored "-Wunused-function"
365 BEGIN_COM_MAP(CXTypeLib
)
366 #if defined __clang__
367 #pragma clang diagnostic pop
369 COM_INTERFACE_ENTRY(ITypeLib
)
370 #if defined __clang__
371 #pragma clang diagnostic push
372 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
373 #pragma clang diagnostic ignored "-Wunused-function"
376 #if defined __clang__
377 #pragma clang diagnostic pop
380 DECLARE_NOT_AGGREGATABLE(CXTypeLib
)
382 virtual ~CXTypeLib() {}
384 void Init(Reference
<XInterface
> xOrigin
,
385 const OUString
& sImplementationName
,
386 Reference
<XMultiServiceFactory
> xMSF
)
388 SAL_INFO("extensions.olebridge", this << "@CXTypeLib::Init for " << sImplementationName
);
390 msImplementationName
= sImplementationName
;
394 virtual UINT STDMETHODCALLTYPE
GetTypeInfoCount() override
396 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoCount");
400 virtual HRESULT STDMETHODCALLTYPE
GetTypeInfo(UINT
,
401 ITypeInfo
**) override
403 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfo: E_NOTIMPL");
407 virtual HRESULT STDMETHODCALLTYPE
GetTypeInfoType(UINT
,
410 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoType: E_NOTIMPL");
414 virtual HRESULT STDMETHODCALLTYPE
GetTypeInfoOfGuid(REFGUID guid
,
415 ITypeInfo
**ppTInfo
) override
417 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
419 SAL_INFO("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoOfGuid(" << guid
<< ")");
423 Reference
<ooo::vba::XConnectable
> xConnectable(mxOrigin
, UNO_QUERY
);
424 if (!xConnectable
.is())
425 return TYPE_E_ELEMENTNOTFOUND
;
428 if (SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(xConnectable
->getIID().pData
->buffer
), &aIID
)))
430 if (IsEqualIID(guid
, aIID
))
434 CComObject
<CXTypeInfo
>* pTypeInfo
;
436 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
442 pTypeInfo
->InitForCoclass(mxOrigin
, msImplementationName
, aIID
, mxMSF
);
444 *ppTInfo
= pTypeInfo
;
451 ooo::vba::TypeAndIID aTypeAndIID
= xConnectable
->GetConnectionPoint();
454 if (SUCCEEDED(IIDFromString((LPOLESTR
)aTypeAndIID
.IID
.pData
->buffer
, &aIID
)))
458 CComObject
<CXTypeInfo
>* pTypeInfo
;
460 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
466 pTypeInfo
->InitForOutgoing(mxOrigin
, msImplementationName
, aIID
, mxMSF
);
468 *ppTInfo
= pTypeInfo
;
473 SAL_WARN("extensions.olebridge", "Not implemented: GetTypeInfoOfGuid(" << guid
<< ")");
476 return TYPE_E_ELEMENTNOTFOUND
;
480 virtual HRESULT STDMETHODCALLTYPE
GetLibAttr(TLIBATTR
**) override
482 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetLibAttr: E_NOTIMPL");
486 virtual HRESULT STDMETHODCALLTYPE
GetTypeComp(ITypeComp
**) override
488 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeComp: E_NOTIMPL");
492 virtual HRESULT STDMETHODCALLTYPE
GetDocumentation(INT
,
498 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetDocumentation: E_NOTIMPL");
502 virtual HRESULT STDMETHODCALLTYPE
IsName(LPOLESTR
,
506 SAL_WARN("extensions.olebridge", this << "@CXTypeLib:IsName: E_NOTIMPL");
510 virtual HRESULT STDMETHODCALLTYPE
FindName(LPOLESTR
,
516 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::FindName: E_NOTIMPL");
520 virtual void STDMETHODCALLTYPE
ReleaseTLibAttr(TLIBATTR
*) override
522 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::ReleaseTLibAttr: E_NOTIMPL");
526 Reference
<XInterface
> mxOrigin
;
527 OUString msImplementationName
;
528 Reference
<XMultiServiceFactory
> mxMSF
;
533 void CXTypeInfo::InitForCoclass(Reference
<XInterface
> xOrigin
,
534 const OUString
& sImplementationName
,
536 Reference
<XMultiServiceFactory
> xMSF
)
538 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForCoclass(" << sImplementationName
<< "," << rIID
<< ")");
539 meKind
= Kind::COCLASS
;
541 msImplementationName
= sImplementationName
;
546 void CXTypeInfo::InitForClassItself(Reference
<XInterface
> xOrigin
,
547 const OUString
& sImplementationName
,
549 Reference
<XMultiServiceFactory
> xMSF
)
551 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForClassItself(" << sImplementationName
<< "," << rIID
<< ")");
554 msImplementationName
= sImplementationName
;
559 void CXTypeInfo::InitForOutgoing(Reference
<XInterface
> xOrigin
,
560 const OUString
& sInterfaceName
,
562 Reference
<XMultiServiceFactory
> xMSF
,
565 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForOutgoing(" << sInterfaceName
<< "," << rIID
<< ")");
566 meKind
= Kind::OUTGOING
;
568 msInterfaceName
= sInterfaceName
;
574 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetTypeAttr(TYPEATTR
**ppTypeAttr
)
576 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
578 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetTypeAttr");
583 assert(!IsEqualIID(maIID
, IID_NULL
));
585 TYPEATTR
*pTypeAttr
= new TYPEATTR
;
586 memset(pTypeAttr
, 0, sizeof(*pTypeAttr
));
588 pTypeAttr
->guid
= maIID
;
590 if (meKind
== Kind::COCLASS
)
592 pTypeAttr
->typekind
= TKIND_COCLASS
;
593 pTypeAttr
->cFuncs
= 0;
594 pTypeAttr
->cVars
= 0;
595 pTypeAttr
->cImplTypes
= 3;
596 pTypeAttr
->cbSizeVft
= 0;
597 pTypeAttr
->cbAlignment
= 8;
598 pTypeAttr
->wTypeFlags
= TYPEFLAG_FCANCREATE
;
600 else if (meKind
== Kind::MAIN
)
602 pTypeAttr
->typekind
= TKIND_DISPATCH
;
603 pTypeAttr
->cFuncs
= 10; // FIXME, dummy
604 pTypeAttr
->cVars
= 0;
605 pTypeAttr
->cImplTypes
= 1;
606 // FIXME: I think this is always supposed to be as if just for the seven methods in
608 pTypeAttr
->cbSizeVft
= 7 * sizeof(void*);
609 pTypeAttr
->cbAlignment
= 8;
610 pTypeAttr
->wTypeFlags
= TYPEFLAG_FHIDDEN
|TYPEFLAG_FDISPATCHABLE
;
612 else if (meKind
== Kind::OUTGOING
)
614 pTypeAttr
->typekind
= TKIND_DISPATCH
;
616 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
619 Reference
<XIdlClass
> xClass
= xRefl
->forName(maType
.getTypeName());
622 auto aMethods
= xClass
->getMethods();
623 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
624 aMethods
.getLength() > 0);
626 // Drop the three XInterface methods, add the three corresponding IUnknown ones plus the
627 // four IDispatch ones on top of that.
628 pTypeAttr
->cFuncs
= aMethods
.getLength() - 3 + 3 + 4;
629 pTypeAttr
->cVars
= 0;
630 pTypeAttr
->cImplTypes
= 1;
631 // FIXME: I think this, too, is always supposed to be as if just for the seven methods in
633 pTypeAttr
->cbSizeVft
= 7 * sizeof(void*);
634 pTypeAttr
->cbAlignment
= 8;
635 pTypeAttr
->wTypeFlags
= TYPEFLAG_FHIDDEN
|TYPEFLAG_FNONEXTENSIBLE
|TYPEFLAG_FDISPATCHABLE
;
640 pTypeAttr
->lcid
= LOCALE_USER_DEFAULT
;
641 pTypeAttr
->memidConstructor
= MEMBERID_NIL
;
642 pTypeAttr
->memidDestructor
= MEMBERID_NIL
;
643 // FIXME: Is this correct, just the vtable pointer, right?
644 pTypeAttr
->cbSizeInstance
= sizeof(void*);
645 pTypeAttr
->wMajorVerNum
= 0;
646 pTypeAttr
->wMinorVerNum
= 0;
647 pTypeAttr
->idldescType
.wIDLFlags
= IDLFLAG_NONE
;
649 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetTypeAttr: " << pTypeAttr
);
651 *ppTypeAttr
= pTypeAttr
;
656 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetTypeComp(ITypeComp
**)
658 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetTypeComp: E_NOTIMPL");
662 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetFuncDesc(UINT index
,
663 FUNCDESC
**ppFuncDesc
)
665 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
670 if (meKind
!= Kind::OUTGOING
)
675 *ppFuncDesc
= new FUNCDESC
;
676 (*ppFuncDesc
)->memid
= 0x60000000 + index
;
677 (*ppFuncDesc
)->lprgscode
= nullptr;
678 (*ppFuncDesc
)->lprgelemdescParam
= nullptr;
679 (*ppFuncDesc
)->funckind
= FUNC_DISPATCH
;
680 (*ppFuncDesc
)->invkind
= INVOKE_FUNC
;
681 (*ppFuncDesc
)->callconv
= CC_STDCALL
;
684 case 0: // QueryInterface
685 (*ppFuncDesc
)->cParams
= 2;
686 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
687 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
690 (*ppFuncDesc
)->cParams
= 0;
691 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
692 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_UI4
;
695 (*ppFuncDesc
)->cParams
= 1;
696 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
697 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_UI4
;
699 case 3: // GetTypeInfoCount
700 (*ppFuncDesc
)->cParams
= 1;
701 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
702 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
704 case 4: // GetTypeInfo
705 (*ppFuncDesc
)->cParams
= 3;
706 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
707 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
709 case 5: // GetIDsOfNames
710 (*ppFuncDesc
)->cParams
= 5;
711 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
712 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
715 (*ppFuncDesc
)->cParams
= 8;
716 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
717 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
720 (*ppFuncDesc
)->cParamsOpt
= 0;
721 (*ppFuncDesc
)->oVft
= index
* sizeof(void*);
722 (*ppFuncDesc
)->cScodes
= 0;
723 (*ppFuncDesc
)->wFuncFlags
= FUNCFLAG_FRESTRICTED
;
725 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetFuncDesc(" << index
<< "): S_OK: " << *ppFuncDesc
);
730 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
733 Reference
<XIdlClass
> xClass
= xRefl
->forName(maType
.getTypeName());
736 auto aMethods
= xClass
->getMethods();
737 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
738 aMethods
.getLength() > 0);
740 if (index
> o3tl::make_unsigned(aMethods
.getLength() - 3 + 3 + 4))
743 *ppFuncDesc
= new FUNCDESC
;
745 (*ppFuncDesc
)->memid
= index
- 6;
746 (*ppFuncDesc
)->lprgscode
= nullptr;
747 (*ppFuncDesc
)->lprgelemdescParam
= nullptr;
748 (*ppFuncDesc
)->funckind
= FUNC_DISPATCH
;
749 (*ppFuncDesc
)->invkind
= INVOKE_FUNC
;
750 (*ppFuncDesc
)->callconv
= CC_STDCALL
;
751 (*ppFuncDesc
)->cParams
= aMethods
[index
- 4]->getParameterInfos().getLength();
752 (*ppFuncDesc
)->cParamsOpt
= 0;
753 (*ppFuncDesc
)->oVft
= index
* sizeof(void*);
754 (*ppFuncDesc
)->cScodes
= 0;
755 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr; // ???
756 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
; // ???
757 (*ppFuncDesc
)->wFuncFlags
= 0;
759 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetFuncDesc(" << index
<< "): S_OK: " << *ppFuncDesc
);
764 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetVarDesc(UINT
,
767 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetVarDesc: E_NOTIMPL");
771 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetNames(MEMBERID memid
,
776 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
778 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetNames(" << memid
<< ")");
779 assert(meKind
!= Kind::COCLASS
);
793 if (meKind
== Kind::MAIN
)
795 SAL_WARN("extensions.olebridge", "GetNames() for MAIN not implemented");
799 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
802 Reference
<XIdlClass
> xClass
= xRefl
->forName(maType
.getTypeName());
805 auto aMethods
= xClass
->getMethods();
806 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
807 aMethods
.getLength() > 0);
809 // Subtract the three XInterface methods. Memid for the first following method is 1.
810 if (memid
> aMethods
.getLength() - 3)
813 SAL_INFO("extensions.olebridge", "..." << this << "@CXTypeInfo::GetNames(" << memid
<< "): " << aMethods
[memid
+ 2]->getName());
814 rgBstrNames
[0] = SysAllocString(reinterpret_cast<LPOLESTR
>(aMethods
[memid
+ 2]->getName().pData
->buffer
));
820 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetRefTypeOfImplType(UINT index
,
823 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetRefTypeOfImplType(" << index
<< ")");
828 assert(index
== 0 || index
== 1);
830 *pRefType
= 1000+index
;
835 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetImplTypeFlags(UINT index
,
838 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
840 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetImplTypeFlags(" << index
<< ")");
845 assert(meKind
== Kind::COCLASS
);
846 assert(index
== 0 || index
== 1);
849 *pImplTypeFlags
= IMPLTYPEFLAG_FDEFAULT
;
851 *pImplTypeFlags
= IMPLTYPEFLAG_FDEFAULT
|IMPLTYPEFLAG_FSOURCE
;
856 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetIDsOfNames(LPOLESTR
*,
860 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetIDsOfNames: E_NOTIMPL");
864 HRESULT STDMETHODCALLTYPE
CXTypeInfo::Invoke(PVOID
,
872 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::Invoke: E_NOTIMPL");
876 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetDocumentation(MEMBERID memid
,
878 BSTR
*pBstrDocString
,
879 DWORD
*pdwHelpContext
,
882 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
884 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetDocumentation(" << memid
<< ")");
888 if (memid
== MEMBERID_NIL
)
890 *pBstrName
= SysAllocString(o3tl::toW(msImplementationName
.getStr()));
892 else if (memid
== DISPID_VALUE
)
894 // MEMBERIDs are the same as DISPIDs, apparently?
895 *pBstrName
= SysAllocString(L
"Value");
899 // FIXME: Shouldn't we be able to know the names of the members of UNO interfaces?
900 *pBstrName
= SysAllocString(o3tl::toW(OUString("UnknownNameOfMember#" + OUString::number(memid
)).getStr()));
904 *pBstrDocString
= SysAllocString(L
"");
908 *pBstrHelpFile
= nullptr;
913 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetDllEntry(MEMBERID
,
919 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetDllEntry: E_NOTIMPL");
923 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetRefTypeInfo(HREFTYPE hRefType
,
926 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
928 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetRefTypeInfo(" << hRefType
<< ")");
933 // FIXME: Is it correct to assume that the only interfaces on which GetRefTypeInfo() would be
934 // called are those that implement ooo::vba::XConnectable?
936 Reference
<ooo::vba::XConnectable
> xConnectable(mxOrigin
, UNO_QUERY
);
937 if (!xConnectable
.is())
940 ooo::vba::TypeAndIID aTypeAndIID
= xConnectable
->GetConnectionPoint();
943 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(aTypeAndIID
.IID
.pData
->buffer
), &aIID
)))
948 CComObject
<CXTypeInfo
>* pTypeInfo
;
950 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
956 pTypeInfo
->InitForOutgoing(mxOrigin
, aTypeAndIID
.Type
.getTypeName(), aIID
, mxMSF
, aTypeAndIID
.Type
);
958 *ppTInfo
= pTypeInfo
;
963 HRESULT STDMETHODCALLTYPE
CXTypeInfo::AddressOfMember(MEMBERID
,
967 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::AddressOfMember: E_NOTIMPL");
971 HRESULT STDMETHODCALLTYPE
CXTypeInfo::CreateInstance(IUnknown
*,
975 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::CreateInstance: E_NOTIMPL");
979 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetMops(MEMBERID
,
982 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetMops: E_NOTIMPL");
986 // This is not actually called any more by my vbscript test after I added the IProvideClassInfo
987 // thing... so all the CXTypeLib stuff is dead code at the moment.
989 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetContainingTypeLib(ITypeLib
**ppTLib
,
992 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
994 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetContainingTypeLib");
996 if (!ppTLib
|| !pIndex
)
1001 CComObject
<CXTypeLib
>* pTypeLib
;
1003 ret
= CComObject
<CXTypeLib
>::CreateInstance(&pTypeLib
);
1009 pTypeLib
->Init(mxOrigin
, msImplementationName
, mxMSF
);
1016 void STDMETHODCALLTYPE
CXTypeInfo::ReleaseTypeAttr(TYPEATTR
*pTypeAttr
)
1018 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::ReleaseTypeAttr(" << pTypeAttr
<< ")");
1023 void STDMETHODCALLTYPE
CXTypeInfo::ReleaseFuncDesc(FUNCDESC
*pFuncDesc
)
1025 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::ReleaseFuncDesc(" << pFuncDesc
<< ")");
1030 void STDMETHODCALLTYPE
CXTypeInfo::ReleaseVarDesc(VARDESC
*)
1032 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::ReleaseVarDesc: E_NOTIMPL");
1035 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::GetTypeInfo(UINT iTInfo
, LCID
, ITypeInfo
** ppTInfo
)
1037 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
1039 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetTypeInfo(" << iTInfo
<< ")");
1047 // FIXME: This is surely incorrect. Why is being able to handle GetTypeInfo() here coupled to
1048 // being a source for outgoing events, i.e. implementing XConnectable? What would break if we
1049 // would use XInterfaceWithIID and its getIID instead?
1051 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
1052 if (!xConnectable
.is())
1055 OUString sIID
= xConnectable
->GetIIDForClassItselfNotCoclass();
1057 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(sIID
.pData
->buffer
), &aIID
)))
1062 CComObject
<CXTypeInfo
>* pTypeInfo
;
1064 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
1068 pTypeInfo
->AddRef();
1070 pTypeInfo
->InitForClassItself(m_xOrigin
, m_sImplementationName
, aIID
, m_smgr
);
1072 *ppTInfo
= pTypeInfo
;
1077 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::GetIDsOfNames(REFIID
/*riid*/,
1078 LPOLESTR
* rgszNames
,
1083 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
1088 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetIDsOfNames:");
1089 for (unsigned int i
= 0; i
< cNames
; ++i
)
1091 // Initialise returned rgdispid values.
1092 rgdispid
[i
] = DISPID_UNKNOWN
;
1094 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames
[i
])));
1097 HRESULT ret
= DISP_E_UNKNOWNNAME
;
1100 MutexGuard
guard( getBridgeMutex());
1102 // FIXME: Handle the cNames > 1 case? Note that the rest of the names mean the names of *arguments*.
1104 if( ! _wcsicmp( *rgszNames
, JSCRIPT_VALUE_FUNC
) ||
1105 ! _wcsicmp( *rgszNames
, BRIDGE_VALUE_FUNC
))
1107 *rgdispid
= DISPID_JSCRIPT_VALUE_FUNC
;
1110 else if( ! _wcsicmp( *rgszNames
, GET_STRUCT_FUNC
) ||
1111 ! _wcsicmp( *rgszNames
, BRIDGE_GET_STRUCT_FUNC
))
1113 *rgdispid
= DISPID_GET_STRUCT_FUNC
;
1116 else if( ! _wcsicmp( *rgszNames
, BRIDGE_CREATE_TYPE_FUNC
))
1118 *rgdispid
= DISPID_CREATE_TYPE_FUNC
;
1122 if (m_xInvocation
.is() && (cNames
> 0))
1124 OUString
name(o3tl::toU(rgszNames
[0]));
1125 NameToIdMap::iterator iter
= m_nameToDispIdMap
.find(name
);
1127 bool bIsMethod
= false;
1129 OUString exactName
= name
;
1131 if (iter
== m_nameToDispIdMap
.end())
1133 if (m_xExactName
.is())
1135 exactName
= m_xExactName
->getExactName(name
);
1136 if (exactName
.isEmpty())
1140 MemberInfo
d(0, exactName
);
1142 if (m_xInvocation
->hasProperty(exactName
))
1144 d
.flags
|= DISPATCH_PROPERTYGET
;
1145 d
.flags
|= DISPATCH_PROPERTYPUT
;
1146 d
.flags
|= DISPATCH_PROPERTYPUTREF
;
1149 if (m_xInvocation
->hasMethod(exactName
))
1151 d
.flags
|= DISPATCH_METHOD
;
1157 m_MemberInfos
.push_back(d
);
1158 iter
= m_nameToDispIdMap
.emplace(exactName
, static_cast<DISPID
>(m_MemberInfos
.size())).first
;
1160 if (exactName
!= name
)
1162 iter
= m_nameToDispIdMap
.emplace(name
, static_cast<DISPID
>(m_MemberInfos
.size())).first
;
1167 if (iter
== m_nameToDispIdMap
.end())
1169 ret
= DISP_E_UNKNOWNNAME
;
1170 SAL_INFO("extensions.olebridge", " " << name
<< ": UNKNOWN");
1174 rgdispid
[0] = (*iter
).second
;
1175 SAL_INFO("extensions.olebridge", " " << name
<< ": " << rgdispid
[0]);
1177 if (bIsMethod
&& cNames
> 1)
1179 Reference
<XIdlMethod
> xIdlMethod
;
1180 Reference
<XIntrospectionAccess
> xIntrospectionAccess
= m_xInvocation
->getIntrospection();
1183 if (xIntrospectionAccess
.is())
1184 xIdlMethod
= xIntrospectionAccess
->getMethod(exactName
, MethodConcept::ALL
);
1186 catch (const NoSuchMethodException
&)
1189 if (xIdlMethod
.is())
1191 auto aParamInfos
= xIdlMethod
->getParameterInfos();
1192 for (unsigned int i
= 1; i
< cNames
; ++i
)
1194 bool bFound
= false;
1195 for (int j
= 0; j
< aParamInfos
.getLength(); ++j
)
1197 if (aParamInfos
[j
].aName
.equalsIgnoreAsciiCase(o3tl::toU(rgszNames
[i
])))
1201 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames
[i
])) << ": " << rgdispid
[i
]);
1206 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames
[i
])) << ": NOT FOUND");
1211 // Return value should be S_OK only if *all* the names were found.
1213 for (i
= 0; i
< cNames
; ++i
)
1214 if (rgdispid
[i
] == DISPID_UNKNOWN
)
1221 catch(const BridgeRuntimeError
&)
1225 catch(const Exception
&)
1237 // Note: What the comments here say about JScript possibly holds for Automation clients in general,
1238 // like VBScript ones, too. Or not. Hard to say. What is the relevance of JScript nowadays anyway,
1239 // and can LO really be used from JScript code on web pages any longer?
1241 // "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts
1242 // The parameters "id", "wFlags" and "pdispparams" equal those as used in
1243 // IDispatch::Invoke. The function handles special JavaScript
1244 // cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent
1245 // an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object)
1246 // parameter (JavaScript Array object)
1247 // Because all those VT_DISPATCH objects need a different conversion
1248 // we have to find out what the object is supposed to be. The function does this
1249 // by either using type information or by help of a specialized ValueObject object.
1251 // A. Type Information
1253 // With the help of type information the kind of parameter can be exactly determined
1254 // and an appropriate conversion can be chosen. A problem arises if a method expects
1255 // an Any. Then the type info does not tell what the type of the value, that is kept
1256 // by the any, should be. In this situation the decision whether the param is a
1257 // sequence or an object is made upon the fact if the object has a property "0"
1258 // ( see function "isJScriptArray"). Since this is unsafe it is recommended to use
1259 // the JScript value objects within a JScript script on such an occasion.
1261 // B. JavaScript Value Object ( class JScriptValue )
1263 // A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the
1264 // IJScriptValue object interface. Such objects are provided by all UNO wrapper
1265 // objects used within a JScript script. To obtain an instance one has to call
1266 // "_GetValueObject() or Bridge_GetValueObject()" on a UNO wrapper object (class InterfaceOleWrapper).
1267 // A value object is appropriately initialized within the script and passed as
1268 // parameter to a UNO object method or property. The convertDispparamsArgs function
1269 // can easily find out that a param is such an object by querying for the
1270 // IJScriptValue interface. By this interface one the type and kind ( out, in/out)
1271 // can be determined and the right conversion can be applied.
1272 // Using ValueObjects we spare us the effort of acquiring and examining type information
1273 // in order to figure out what the an IDispatch parameter is meant for.
1275 // Normal JScript object parameter can be mixed with JScriptValue object. If an
1276 // VARIANT contains a VT_DISPATCH that is no JScriptValue than the type information
1277 // is used to find out about the required type.
1278 void InterfaceOleWrapper::convertDispparamsArgs(DISPID id
,
1279 unsigned short /*wFlags*/, DISPPARAMS
* pdispparams
, Sequence
<Any
>& rSeq
)
1281 // Parameters come in in reverse order in pdispparams. There might be less parameters than
1282 // expected. In that case, assume they are "optional" (but can't be marked as such in UNO IDL),
1283 // and fill in the rest with empty Anys. There might also be more than expected. In that case,
1284 // assume the oovbaapi UNO IDL hasn't kept up with added optional parameters in MSO, and just
1285 // ignore the extra ones, as long as they are empty.
1287 // An example: incoming parameters: <12, 13, "foo/bar.tem">
1289 // Expected parameters: (string filename, int something, int somethingElse, Any whatever, Any
1292 // Here the existing incoming parameters are placed in reverse order in the first three outgoing
1293 // parameters, and the rest of the outgoing parameters are kept as empty Anys.
1295 // Another example: incoming parameters: <EMPTY, TRUE>
1297 // Expected parameters: (bool flag)
1299 // Here the TRUE is passed as the sole outgoing parameter, and the incoming EMPTY is ignored.
1301 // Still an example: incoming parameters: <"foo.doc", TRUE>
1303 // Expected parameters: (bool flag)
1305 // This throws an error as the incoming string parameter presumably should do something important,
1306 // but there is no corresponding outgoing parameter.
1309 const int countIncomingArgs
= pdispparams
->cArgs
;
1311 //Get type information for the current call
1312 InvocationInfo info
;
1313 if( ! getInvocationInfoForCall( id
, info
))
1314 throw BridgeRuntimeError(
1315 "[automation bridge]InterfaceOleWrapper::convertDispparamsArgs \n"
1316 "Could not obtain type information for current call.");
1318 // Size rSeq according to the number of expected parameters.
1319 const int expectedArgs
= info
.aParamTypes
.getLength() + (info
.eMemberType
== MemberType_PROPERTY
? 1 : 0);
1320 rSeq
.realloc( expectedArgs
);
1321 Any
* pParams
= rSeq
.getArray();
1325 int outgoingArgIndex
= 0;
1327 // Go through incoming parameters in reverse order, i.e. in the order as declared in IDL
1328 for (int i
= std::max(countIncomingArgs
, expectedArgs
) - 1; i
>= 0; i
--)
1330 // Ignore too many parameters if they are VT_EMPTY anyway
1331 if ( outgoingArgIndex
>= expectedArgs
&& pdispparams
->rgvarg
[i
].vt
== VT_EMPTY
)
1334 // But otherwise too many parameters is an error
1335 if ( outgoingArgIndex
>= expectedArgs
)
1336 throw BridgeRuntimeError( "[automation bridge] Too many parameters" );
1338 if (info
.eMemberType
== MemberType_METHOD
&&
1339 info
.aParamModes
[ outgoingArgIndex
] == ParamMode_OUT
)
1345 if (i
< countIncomingArgs
)
1347 // A missing (and hopefully optional) arg (in the middle of the argument list) is passed
1349 if (pdispparams
->rgvarg
[i
].vt
== VT_ERROR
&& pdispparams
->rgvarg
[i
].scode
== DISP_E_PARAMNOTFOUND
)
1352 pParams
[ outgoingArgIndex
] = aEmpty
;
1357 if(convertValueObject( & pdispparams
->rgvarg
[i
], anyParam
))
1358 { //a param is a ValueObject and could be converted
1359 pParams
[ outgoingArgIndex
] = anyParam
;
1366 // A missing arg. Let's hope it is de facto optional (there is no way in UNO IDL to mark
1367 // a parameter as optional). The corresponding slot in pParams is already a void Any.
1368 // Here we don't increase outgoingArgIndex!
1372 // If the param is an out, in/out parameter in
1373 // JScript (Array object, with value at index 0) then we
1374 // extract Array[0] and put the value into varParam. At the end of the loop varParam
1375 // is converted if it contains a value otherwise the VARIANT from
1376 // DISPPARAMS is converted.
1377 CComVariant varParam
;
1379 // Check for JScript out and in/out paramsobjects (VT_DISPATCH).
1380 // To find them out we use typeinformation of the function being called.
1382 // No idea how this stuff, originally written for JScript, works for other Automation
1385 if( pdispparams
->rgvarg
[i
].vt
== VT_DISPATCH
)
1387 if( info
.eMemberType
== MemberType_METHOD
&& info
.aParamModes
[ outgoingArgIndex
] == ParamMode_INOUT
)
1390 // Index ( property) "0" contains the actual IN-param. The object is a JScript
1392 // Get the IN-param at index "0"
1393 IDispatch
* pdisp
= pdispparams
->rgvarg
[i
].pdispVal
;
1395 OLECHAR
const * sindex
= L
"0";
1397 DISPPARAMS noParams
= {nullptr,nullptr,0,0};
1398 if(SUCCEEDED( hr
= pdisp
->GetIDsOfNames( IID_NULL
, const_cast<OLECHAR
**>(&sindex
), 1, LOCALE_USER_DEFAULT
, &id2
)))
1399 hr
= pdisp
->Invoke( id2
, IID_NULL
, LOCALE_USER_DEFAULT
, DISPATCH_PROPERTYGET
,
1400 & noParams
, & varParam
, nullptr, nullptr);
1403 throw BridgeRuntimeError(
1404 "[automation bridge] Could not determine "
1405 "if the object has a member \"0\". Error: " +
1406 OUString::number(hr
));
1411 if( varParam
.vt
== VT_EMPTY
) // then it was no in/out parameter
1412 varParam
= pdispparams
->rgvarg
[i
];
1414 if(info
.eMemberType
== MemberType_METHOD
)
1415 variantToAny( & varParam
, anyParam
,
1416 info
.aParamTypes
[ outgoingArgIndex
]);
1417 else if(info
.eMemberType
== MemberType_PROPERTY
)
1418 variantToAny( & varParam
, anyParam
, info
.aType
);
1422 if (outgoingArgIndex
< expectedArgs
)
1423 pParams
[ outgoingArgIndex
]= anyParam
;
1425 }// end for / iterating over all parameters
1428 bool InterfaceOleWrapper::getInvocationInfoForCall( DISPID id
, InvocationInfo
& info
)
1430 bool bTypesAvailable
= false;
1432 if( !m_xInvocation
.is() )return false;
1433 Reference
<XInvocation2
> inv2( m_xInvocation
, UNO_QUERY
);
1436 // We need the name of the property or method to get its type information.
1437 // The name can be identified through the param "id"
1438 // that is kept as value in the map m_nameToDispIdMap.
1439 // Problem: the Windows JScript engine sometimes changes small letters to capital
1440 // letters as happens in xidlclass_obj.createObject( var) // in JScript.
1441 // IDispatch::GetIdsOfNames is then called with "CreateObject" !!!
1442 // m_nameToDispIdMap can contain several names for one DISPID but only one is
1443 // the exact one. If there's no m_xExactName and therefore no exact name then
1444 // there's only one entry in the map.
1445 OUString sMemberName
;
1447 auto ci1
= std::find_if(m_nameToDispIdMap
.cbegin(), m_nameToDispIdMap
.cend(),
1448 [&id
](const NameToIdMap::value_type
& nameToDispId
) { return nameToDispId
.second
== id
; }); // item is a pair<OUString, DISPID>
1449 if (ci1
!= m_nameToDispIdMap
.cend())
1450 sMemberName
= (*ci1
).first
;
1451 // Get information for the current call ( property or method).
1452 // There could be similar names which only differ in the cases
1453 // of letters. First we assume that the name which was passed into
1454 // GetIDsOfNames is correct. If we won't get information with that
1455 // name then we have the invocation service use the XExactName interface.
1456 bool validInfo
= true;
1457 InvocationInfo invInfo
;
1459 invInfo
= inv2
->getInfoForName( sMemberName
, false);
1461 catch(const IllegalArgumentException
&)
1468 invInfo
= inv2
->getInfoForName( sMemberName
, true);
1470 if( invInfo
.aName
.pData
)
1472 bTypesAvailable
= true;
1476 return bTypesAvailable
;
1479 // XBridgeSupplier2 ---------------------------------------------------
1480 // only bridges itself ( this instance of InterfaceOleWrapper)from UNO to IDispatch
1481 // If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper
1482 // can bridged to IDispatch ( if destModelType == OLE). The IDispatch is
1483 // implemented by this class.
1484 Any SAL_CALL
InterfaceOleWrapper::createBridge(const Any
& modelDepObject
,
1485 const Sequence
<sal_Int8
>& /*ProcessId*/,
1486 sal_Int16 sourceModelType
,
1487 sal_Int16 destModelType
)
1491 if( sourceModelType
== UNO
&& destModelType
== OLE
&&
1492 modelDepObject
.getValueTypeClass() == TypeClass_INTERFACE
)
1494 Reference
<XInterface
> xInt
;
1495 if( modelDepObject
>>= xInt
)
1497 if( xInt
== Reference
<XInterface
>( static_cast<XWeak
*>( this), UNO_QUERY
))
1499 VARIANT
*pVar
= static_cast<VARIANT
*>(CoTaskMemAlloc( sizeof( VARIANT
)));
1502 pVar
->vt
= VT_DISPATCH
;
1503 pVar
->pdispVal
= this;
1506 retAny
<<= reinterpret_cast< sal_uIntPtr
>( pVar
);
1515 // XInitialization --------------------------------------------------
1516 void SAL_CALL
InterfaceOleWrapper::initialize( const Sequence
< Any
>& aArguments
)
1518 switch( aArguments
.getLength() )
1520 case 2: // the object wraps a UNO struct
1521 aArguments
[0] >>= m_xInvocation
;
1522 aArguments
[1] >>= m_defaultValueType
;
1524 case 3: // the object wraps a UNO interface
1525 aArguments
[0] >>= m_xInvocation
;
1526 aArguments
[1] >>= m_xOrigin
;
1527 aArguments
[2] >>= m_defaultValueType
;
1529 Reference
<XServiceInfo
> xServiceInfo(m_xOrigin
, UNO_QUERY
);
1530 if (xServiceInfo
.is())
1531 m_sImplementationName
= xServiceInfo
->getImplementationName();
1533 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::initialize for "
1534 << (m_sImplementationName
.isEmpty()?"an unknown implementation":m_sImplementationName
));
1538 m_xExactName
.set( m_xInvocation
, UNO_QUERY
);
1541 Reference
< XInterface
> InterfaceOleWrapper::createUnoWrapperInstance()
1543 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper(
1544 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1545 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1548 Reference
<XInterface
> InterfaceOleWrapper::createComWrapperInstance()
1550 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper(
1551 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1552 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1555 // "getType" is used in convertValueObject to map the string denoting the type
1556 // to an actual Type object.
1557 bool getType( const BSTR name
, Type
& type
)
1560 typelib_TypeDescription
* pDesc
= nullptr;
1561 OUString
str(o3tl::toU(name
));
1562 typelib_typedescription_getByName( &pDesc
, str
.pData
);
1565 type
= Type( pDesc
->pWeakRef
);
1566 typelib_typedescription_release( pDesc
);
1572 static bool writeBackOutParameter2( VARIANTARG
* pDest
, VARIANT
* pSource
)
1577 // Handle JScriptValue objects and JScript out params ( Array object )
1578 CComVariant
varDest( *pDest
);
1580 if( SUCCEEDED( varDest
.ChangeType(VT_DISPATCH
)))
1582 CComPtr
<IDispatch
> spDispDest(varDest
.pdispVal
);
1584 // special Handling for a JScriptValue object
1585 CComQIPtr
<IJScriptValueObject
> spValueDest(spDispDest
);
1588 VARIANT_BOOL varBool
= VARIANT_FALSE
;
1589 if ((SUCCEEDED(hr
= spValueDest
->IsOutParam(&varBool
))
1590 && varBool
== VARIANT_TRUE
)
1591 || (SUCCEEDED(hr
= spValueDest
->IsInOutParam(&varBool
))
1592 && varBool
== VARIANT_TRUE
))
1594 if( SUCCEEDED( spValueDest
->Set( CComVariant(), *pSource
)))
1598 else if (pDest
->vt
== VT_DISPATCH
)// VT_DISPATCH -> JScript out param
1600 // We use IDispatchEx because its GetDispID function causes the creation
1601 // of a property if it does not exist already. This is convenient for
1602 // out parameters in JScript. Then the user must not specify property "0"
1604 CComQIPtr
<IDispatchEx
> spDispEx( spDispDest
);
1607 CComBSTR
nullProp(L
"0");
1609 if( SUCCEEDED( spDispEx
->GetDispID( nullProp
, fdexNameEnsure
, &dwDispID
)))
1611 DISPPARAMS dispparams
= {nullptr, nullptr, 1, 1};
1612 dispparams
.rgvarg
= pSource
;
1613 DISPID dispidPut
= DISPID_PROPERTYPUT
;
1614 dispparams
.rgdispidNamedArgs
= &dispidPut
;
1616 if (pSource
->vt
== VT_UNKNOWN
|| pSource
->vt
== VT_DISPATCH
||
1617 (pSource
->vt
& VT_ARRAY
) || (pSource
->vt
& VT_BYREF
))
1618 hr
= spDispEx
->InvokeEx(dwDispID
, LOCALE_USER_DEFAULT
, DISPATCH_PROPERTYPUTREF
,
1619 &dispparams
, nullptr, nullptr, nullptr);
1621 hr
= spDispEx
->InvokeEx(dwDispID
, LOCALE_USER_DEFAULT
, DISPATCH_PROPERTYPUT
,
1622 &dispparams
, nullptr, nullptr, nullptr);
1629 ret
= writeBackOutParameter( pDest
, pSource
);
1631 else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript
1632 { // param. The function checks itself for correct VBScript params
1633 ret
= writeBackOutParameter( pDest
, pSource
);
1638 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter.
1639 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT
1640 // Please note: VariantCopy doesn't free a VT_BYREF value
1641 // The out parameters are expected to have always a valid type
1642 static bool writeBackOutParameter(VARIANTARG
* pDest
, VARIANT
* pSource
)
1646 // Out parameter must be VT_BYREF
1647 if ((V_VT(pDest
) & VT_BYREF
) != 0 )
1649 VARTYPE oleTypeFlags
= V_VT(pSource
);
1651 // if caller accept VARIANT as out parameter, any value must be converted
1652 if (V_VT(pDest
) == (VT_VARIANT
| VT_BYREF
))
1654 // When the user provides a VARIANT rather than a concrete type
1655 // we just copy the source to the out, in/out parameter
1656 // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that
1657 // is contained in pDest are released by VariantCopy
1658 VariantCopy(V_VARIANTREF(pDest
), pSource
);
1663 // variantarg and variant must have same type
1664 if ((V_VT(pDest
) & oleTypeFlags
) == oleTypeFlags
)
1666 if ((oleTypeFlags
& VT_ARRAY
) != 0)
1669 if( *V_ARRAYREF(pDest
) != nullptr)
1670 hr
= SafeArrayCopyData( V_ARRAY(pSource
), *V_ARRAYREF(pDest
));
1673 hr
= SafeArrayCopy(V_ARRAY(pSource
), V_ARRAYREF(pDest
));
1680 switch (V_VT(pSource
))
1684 *V_I2REF(pDest
) = V_I2(pSource
);
1689 *V_I4REF(pDest
) = V_I4(pSource
);
1693 *V_R4REF(pDest
) = V_R4(pSource
);
1697 *V_R8REF(pDest
) = V_R8(pSource
);
1701 *V_CYREF(pDest
) = V_CY(pSource
);
1705 *V_DATEREF(pDest
) = V_DATE(pSource
);
1709 SysFreeString( *pDest
->pbstrVal
);
1711 *V_BSTRREF(pDest
) = SysAllocString(V_BSTR(pSource
));
1715 if (*V_DISPATCHREF(pDest
) != nullptr)
1716 (*V_DISPATCHREF(pDest
))->Release();
1718 *V_DISPATCHREF(pDest
) = V_DISPATCH(pSource
);
1720 if (*V_DISPATCHREF(pDest
) != nullptr)
1721 (*V_DISPATCHREF(pDest
))->AddRef();
1726 *V_ERRORREF(pDest
) = V_ERROR(pSource
);
1730 *V_BOOLREF(pDest
) = V_BOOL(pSource
);
1734 if (*V_UNKNOWNREF(pDest
) != nullptr)
1735 (*V_UNKNOWNREF(pDest
))->Release();
1737 *V_UNKNOWNREF(pDest
) = V_UNKNOWN(pSource
);
1739 if (*V_UNKNOWNREF(pDest
) != nullptr)
1740 (*V_UNKNOWNREF(pDest
))->AddRef();
1745 *V_I1REF(pDest
) = V_I1(pSource
);
1749 *V_UI1REF(pDest
) = V_UI1(pSource
);
1753 *V_UI2REF(pDest
) = V_UI2(pSource
);
1757 *V_UI4REF(pDest
) = V_UI4(pSource
);
1761 *V_INTREF(pDest
) = V_INT(pSource
);
1765 *V_UINTREF(pDest
) = V_UINT(pSource
);
1769 memcpy(pDest
->pdecVal
, pSource
, sizeof(DECIMAL
));
1779 // Handling of special cases
1780 // Destination and source types are different
1781 if( pDest
->vt
== (VT_BSTR
| VT_BYREF
)
1782 && pSource
->vt
== VT_I2
)
1784 // When the user provides a String as out our in/out parameter
1785 // and the type is char (TypeClass_CHAR) then we convert to a BSTR
1786 // instead of VT_I2 as is done otherwise
1787 OLECHAR buff
[]= {0,0};
1788 buff
[0]= pSource
->iVal
;
1790 SysFreeString( *pDest
->pbstrVal
);
1791 *pDest
->pbstrVal
= SysAllocString( buff
);
1800 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::Invoke(DISPID dispidMember
,
1804 DISPPARAMS
* pdispparams
,
1805 VARIANT
* pvarResult
,
1806 EXCEPINFO
* pexcepinfo
,
1809 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
1812 #if defined SAL_LOG_INFO
1814 for (unsigned int i
= 0; i
< pdispparams
->cArgs
; ++i
)
1818 std::stringstream aStringStream
;
1819 aStringStream
<< pdispparams
->rgvarg
[i
];
1820 sParams
+= OUString::createFromAscii(aStringStream
.str().c_str());
1824 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::Invoke(" << dispidMember
<< "," << sParams
<< ")");
1826 comphelper::ProfileZone
aZone("COM Bridge");
1831 bool bHandled
= false;
1832 ret
= InvokeGeneral( dispidMember
, wFlags
, pdispparams
, pvarResult
, pexcepinfo
,
1833 puArgErr
, bHandled
);
1837 if ((dispidMember
> 0) && (o3tl::make_unsigned(dispidMember
) <= m_MemberInfos
.size()) && m_xInvocation
.is())
1839 MemberInfo d
= m_MemberInfos
[dispidMember
- 1];
1840 DWORD flags
= wFlags
& d
.flags
;
1844 if ((flags
& DISPATCH_METHOD
) != 0)
1846 std::unique_ptr
<DISPPARAMS
> pNewDispParams
;
1847 std::vector
<VARIANTARG
> vNewArgs
;
1849 if (pdispparams
->cNamedArgs
> 0)
1851 // Convert named arguments to positional ones.
1855 // Function declaration (in pseudo-code):
1856 // int foo(int A, int B, optional int C, optional int D, optional int E, optional int F, optional int G)
1858 // Corresponding parameter numbers (DISPIDs):
1862 // foo(10, 20, E:=50, D:=40, F:=60)
1864 // That is, A and B are passed positionally, D, E, and F as named arguments,
1865 // and the optional C and G parameters are left out.
1867 // Incoming DISPPARAMS:
1868 // cArgs=5, cNamedArgs=3
1869 // rgvarg: [60, 40, 50, 20, 10]
1870 // rgdispidNamedArgs: [5, 3, 4]
1872 // We calculate nLowestNamedArgDispid = 3 and nHighestNamedArgDispid = 5.
1874 // Result of conversion, no named args:
1875 // cArgs=6, cNamedArgs=0
1876 // rgvarg: [60, 50, 40, DISP_E_PARAMNOTFOUND, 20, 10]
1878 // First find the lowest and highest DISPID of the named arguments.
1879 DISPID nLowestNamedArgDispid
= 1000000;
1880 DISPID nHighestNamedArgDispid
= -1;
1881 for (unsigned int i
= 0; i
< pdispparams
->cNamedArgs
; ++i
)
1883 if (pdispparams
->rgdispidNamedArgs
[i
] < nLowestNamedArgDispid
)
1884 nLowestNamedArgDispid
= pdispparams
->rgdispidNamedArgs
[i
];
1885 if (pdispparams
->rgdispidNamedArgs
[i
] > nHighestNamedArgDispid
)
1886 nHighestNamedArgDispid
= pdispparams
->rgdispidNamedArgs
[i
];
1889 // Make sure named arguments don't overlap with positional ones. The lowest
1890 // DISPID of the named arguments should be >= the number of positional
1892 if (nLowestNamedArgDispid
< static_cast<DISPID
>(pdispparams
->cArgs
- pdispparams
->cNamedArgs
))
1893 return DISP_E_NONAMEDARGS
;
1895 // Do the actual conversion.
1896 pNewDispParams
.reset(new DISPPARAMS
);
1897 vNewArgs
.resize(nHighestNamedArgDispid
+ 1);
1898 pNewDispParams
->rgvarg
= vNewArgs
.data();
1899 pNewDispParams
->rgdispidNamedArgs
= nullptr;
1900 pNewDispParams
->cArgs
= nHighestNamedArgDispid
+ 1;
1901 pNewDispParams
->cNamedArgs
= 0;
1903 // Initialise all parameter slots as missing
1904 for (int i
= 0; i
< nHighestNamedArgDispid
; ++i
)
1906 pNewDispParams
->rgvarg
[i
].vt
= VT_ERROR
;
1907 pNewDispParams
->rgvarg
[i
].scode
= DISP_E_PARAMNOTFOUND
;
1910 // Then set the value of those actually present.
1911 for (unsigned int i
= 0; i
< pdispparams
->cNamedArgs
; ++i
)
1912 pNewDispParams
->rgvarg
[nHighestNamedArgDispid
- pdispparams
->rgdispidNamedArgs
[i
]] = pdispparams
->rgvarg
[i
];
1914 const int nFirstUnnamedArg
= pdispparams
->cNamedArgs
+ (nLowestNamedArgDispid
-(pdispparams
->cArgs
- pdispparams
->cNamedArgs
));
1916 for (unsigned int i
= pdispparams
->cNamedArgs
; i
< pdispparams
->cArgs
; ++i
)
1917 pNewDispParams
->rgvarg
[nFirstUnnamedArg
+ (i
-pdispparams
->cNamedArgs
)] = pdispparams
->rgvarg
[i
];
1919 pdispparams
= pNewDispParams
.get();
1922 Sequence
<Any
> params
;
1924 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
1926 ret
= doInvoke(pdispparams
, pvarResult
,
1927 pexcepinfo
, puArgErr
, d
.name
, params
);
1929 else if ((flags
& DISPATCH_PROPERTYGET
) != 0)
1931 ret
= doGetProperty( pdispparams
, pvarResult
,
1932 pexcepinfo
, d
.name
);
1934 else if ((flags
& DISPATCH_PROPERTYPUT
) != 0 || (flags
& DISPATCH_PROPERTYPUTREF
) != 0)
1936 if (pdispparams
->cArgs
!= 1)
1937 ret
= DISP_E_BADPARAMCOUNT
;
1940 Sequence
<Any
> params
;
1941 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
1942 if(params
.getLength() > 0)
1943 ret
= doSetProperty( pdispparams
, pvarResult
, pexcepinfo
, puArgErr
, d
.name
, params
);
1945 ret
= DISP_E_BADVARTYPE
;
1950 ret
= DISP_E_MEMBERNOTFOUND
;
1953 ret
= DISP_E_MEMBERNOTFOUND
;
1955 catch(const BridgeRuntimeError
& e
)
1957 writeExcepinfo(pexcepinfo
, e
.message
);
1958 ret
= DISP_E_EXCEPTION
;
1960 catch(const Exception
& e
)
1962 OUString message
= "InterfaceOleWrapper::Invoke : \n" +
1964 writeExcepinfo(pexcepinfo
, message
);
1965 ret
= DISP_E_EXCEPTION
;
1969 writeExcepinfo(pexcepinfo
, "InterfaceOleWrapper::Invoke : \nUnexpected exception");
1970 ret
= DISP_E_EXCEPTION
;
1976 HRESULT
InterfaceOleWrapper::doInvoke( DISPPARAMS
* pdispparams
, VARIANT
* pvarResult
,
1977 EXCEPINFO
* pexcepinfo
, unsigned int * puArgErr
, OUString
& name
, Sequence
<Any
>& params
)
1984 Sequence
<sal_Int16
> outIndex
;
1985 Sequence
<Any
> outParams
;
1988 if (pdispparams
->cNamedArgs
> 0)
1989 return DISP_E_NONAMEDARGS
;
1991 // invoke method and take care of exceptions
1992 returnValue
= m_xInvocation
->invoke(name
,
1997 // try to write back out parameter
1998 if (outIndex
.getLength() > 0)
2000 const sal_Int16
* pOutIndex
= outIndex
.getConstArray();
2001 const Any
* pOutParams
= outParams
.getConstArray();
2003 for (sal_Int32 i
= 0; i
< outIndex
.getLength(); i
++)
2005 CComVariant variant
;
2006 // Currently a Sequence is converted to an SafeArray of VARIANTs.
2007 anyToVariant( &variant
, pOutParams
[i
]);
2009 // out parameter need special handling if they are VT_DISPATCH
2010 // and used in JScript
2011 int outindex
= pOutIndex
[i
];
2012 writeBackOutParameter2(&(pdispparams
->rgvarg
[pdispparams
->cArgs
- 1 - outindex
]),
2017 // write back return value
2018 if (pvarResult
!= nullptr)
2019 anyToVariant(pvarResult
, returnValue
);
2021 catch(const IllegalArgumentException
& e
) //XInvocation::invoke
2023 writeExcepinfo(pexcepinfo
, e
.Message
);
2024 ret
= DISP_E_TYPEMISMATCH
;
2026 catch(const CannotConvertException
& e
) //XInvocation::invoke
2028 writeExcepinfo(pexcepinfo
, e
.Message
);
2029 ret
= mapCannotConvertException( e
, puArgErr
);
2031 catch(const InvocationTargetException
& e
) //XInvocation::invoke
2033 const Any
& org
= e
.TargetException
;
2034 Exception excTarget
;
2037 org
.getValueType().getTypeName() + ": " + excTarget
.Message
;
2038 writeExcepinfo(pexcepinfo
, message
);
2039 ret
= DISP_E_EXCEPTION
;
2041 catch(const NoSuchMethodException
& e
) //XInvocation::invoke
2043 writeExcepinfo(pexcepinfo
, e
.Message
);
2044 ret
= DISP_E_MEMBERNOTFOUND
;
2046 catch(const BridgeRuntimeError
& e
)
2048 writeExcepinfo(pexcepinfo
, e
.message
);
2049 ret
= DISP_E_EXCEPTION
;
2051 catch(const Exception
& e
)
2053 OUString message
= "InterfaceOleWrapper::doInvoke : \n" +
2055 writeExcepinfo(pexcepinfo
, message
);
2056 ret
= DISP_E_EXCEPTION
;
2060 writeExcepinfo(pexcepinfo
, "InterfaceOleWrapper::doInvoke : \nUnexpected exception");
2061 ret
= DISP_E_EXCEPTION
;
2066 HRESULT
InterfaceOleWrapper::doGetProperty( DISPPARAMS
* /*pdispparams*/, VARIANT
* pvarResult
,
2067 EXCEPINFO
* pexcepinfo
, OUString
& name
)
2073 Any returnValue
= m_xInvocation
->getValue( name
);
2074 // write back return value
2076 anyToVariant(pvarResult
, returnValue
);
2078 catch(const UnknownPropertyException
& e
) //XInvocation::getValue
2080 writeExcepinfo(pexcepinfo
, e
.Message
);
2081 ret
= DISP_E_MEMBERNOTFOUND
;
2083 catch(const BridgeRuntimeError
& e
)
2085 writeExcepinfo(pexcepinfo
, e
.message
);
2086 ret
= DISP_E_EXCEPTION
;
2088 catch(const Exception
& e
)
2090 OUString message
= "InterfaceOleWrapper::doGetProperty : \n" +
2092 writeExcepinfo(pexcepinfo
, message
);
2096 writeExcepinfo(pexcepinfo
, "InterfaceOleWrapper::doInvoke : \nUnexpected exception");
2097 ret
= DISP_E_EXCEPTION
;
2102 HRESULT
InterfaceOleWrapper::doSetProperty( DISPPARAMS
* /*pdispparams*/, VARIANT
* /*pvarResult*/,
2103 EXCEPINFO
* pexcepinfo
, unsigned int * puArgErr
, OUString
& name
, Sequence
<Any
> const & params
)
2109 m_xInvocation
->setValue( name
, params
.getConstArray()[0]);
2111 catch(const UnknownPropertyException
&)
2113 ret
= DISP_E_MEMBERNOTFOUND
;
2115 catch(const CannotConvertException
&e
)
2117 ret
= mapCannotConvertException( e
, puArgErr
);
2119 catch(const InvocationTargetException
&e
)
2121 if (pexcepinfo
!= nullptr)
2123 Any org
= e
.TargetException
;
2125 pexcepinfo
->wCode
= UNO_2_OLE_EXCEPTIONCODE
;
2126 pexcepinfo
->bstrSource
= SysAllocString(L
"any ONE component");
2127 pexcepinfo
->bstrDescription
= SysAllocString(
2128 o3tl::toW(org
.getValueType().getTypeName().getStr()));
2130 ret
= DISP_E_EXCEPTION
;
2134 ret
= DISP_E_EXCEPTION
;
2141 class CXEnumVariant
: public IEnumVARIANT
,
2142 public CComObjectRoot
2146 : mnIndex(1) // ooo::vba::XCollection index starts at one
2150 virtual ~CXEnumVariant()
2154 #if defined __clang__
2155 #pragma clang diagnostic push
2156 #pragma clang diagnostic ignored "-Wunused-function"
2158 BEGIN_COM_MAP(CXEnumVariant
)
2159 #if defined __clang__
2160 #pragma clang diagnostic pop
2162 COM_INTERFACE_ENTRY(IEnumVARIANT
)
2163 #if defined __clang__
2164 #pragma clang diagnostic push
2165 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
2166 #pragma clang diagnostic ignored "-Wunused-function"
2169 #if defined __clang__
2170 #pragma clang diagnostic pop
2173 DECLARE_NOT_AGGREGATABLE(CXEnumVariant
)
2175 // Creates and initializes the enumerator
2176 void Init(InterfaceOleWrapper
* pInterfaceOleWrapper
,
2177 const Reference
<ooo::vba::XCollection
> xCollection
)
2179 mpInterfaceOleWrapper
= pInterfaceOleWrapper
;
2180 mxCollection
= xCollection
;
2184 virtual HRESULT STDMETHODCALLTYPE
Clone(IEnumVARIANT
**) override
2186 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Clone: E_NOTIMPL");
2190 virtual HRESULT STDMETHODCALLTYPE
Next(ULONG
const celt
,
2192 ULONG
*pCeltFetched
) override
2194 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2201 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): E_INVALIDARG");
2202 return E_INVALIDARG
;
2205 if (rgVar
== nullptr || (celt
!= 1 && pCeltFetched
== nullptr))
2207 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): E_FAIL");
2211 for (ULONG i
= 0; i
< celt
; i
++)
2212 VariantInit(&rgVar
[i
]);
2215 ULONG nReturned
= 0;
2218 if (mnIndex
> mxCollection
->getCount())
2220 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): got " << nReturned
<< ": S_FALSE");
2225 Any aElement
= mxCollection
->Item(aIndex
, Any());
2226 mpInterfaceOleWrapper
->anyToVariant(rgVar
, aElement
);
2227 // rgVar->pdispVal->AddRef(); ??
2235 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): S_OK");
2239 virtual HRESULT STDMETHODCALLTYPE
Reset() override
2241 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Reset: S_OK");
2246 virtual HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE
Skip(ULONG
const celt
) override
2248 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2254 if (mnIndex
> mxCollection
->getCount())
2256 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Skip(" << celt
<< "): skipped " << nSkipped
<< ": S_FALSE");
2262 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Skip(" << celt
<< "): S_OK");
2267 InterfaceOleWrapper
* mpInterfaceOleWrapper
;
2268 Reference
<ooo::vba::XCollection
> mxCollection
;
2272 class Sink
: public cppu::WeakImplHelper
<ooo::vba::XSink
>
2275 Sink(IUnknown
* pUnkSink
,
2276 Reference
<XMultiServiceFactory
> xMSF
,
2277 ooo::vba::TypeAndIID aTypeAndIID
,
2278 InterfaceOleWrapper
* pInterfaceOleWrapper
);
2281 void SAL_CALL
Call( const OUString
& Method
, Sequence
< Any
>& Arguments
) override
;
2284 IUnknown
* mpUnkSink
;
2285 Reference
<XMultiServiceFactory
> mxMSF
;
2286 ooo::vba::TypeAndIID maTypeAndIID
;
2287 InterfaceOleWrapper
* mpInterfaceOleWrapper
;
2292 Sink::Sink(IUnknown
* pUnkSink
,
2293 Reference
<XMultiServiceFactory
> xMSF
,
2294 ooo::vba::TypeAndIID aTypeAndIID
,
2295 InterfaceOleWrapper
* pInterfaceOleWrapper
) :
2296 mpUnkSink(pUnkSink
),
2298 maTypeAndIID(aTypeAndIID
),
2299 mpInterfaceOleWrapper(pInterfaceOleWrapper
)
2301 mpUnkSink
->AddRef();
2305 Sink::Call( const OUString
& Method
, Sequence
< Any
>& Arguments
)
2307 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method
<< ", " << Arguments
.getLength() << " arguments)");
2309 IDispatch
* pDispatch
;
2310 HRESULT nResult
= mpUnkSink
->QueryInterface(IID_IDispatch
, reinterpret_cast<void **>(&pDispatch
));
2311 if (!SUCCEEDED(nResult
))
2313 SAL_WARN("extensions.olebridge", "Sink::Call: Not IDispatch: " << WindowsErrorStringFromHRESULT(nResult
));
2317 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
2320 Reference
<XIdlClass
> xClass
= xRefl
->forName(maTypeAndIID
.Type
.getTypeName());
2321 assert(xClass
.is());
2323 auto aMethods
= xClass
->getMethods();
2324 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
2325 aMethods
.getLength() > 0);
2328 auto ArgumentsRange
= asNonConstRange(Arguments
);
2329 // Skip the three XInterface methods
2330 for (int i
= 3; i
< aMethods
.getLength(); i
++)
2332 if (aMethods
[i
]->getName() == Method
)
2334 // FIXME: Handle mismatch in type of actual argument and parameter of the method.
2336 // FIXME: Handle mismatch in number of arguments passed and actual number of parameters
2339 auto aParamInfos
= aMethods
[i
]->getParameterInfos();
2341 assert(Arguments
.getLength() == aParamInfos
.getLength());
2343 DISPPARAMS aDispParams
;
2344 aDispParams
.rgdispidNamedArgs
= nullptr;
2345 aDispParams
.cArgs
= Arguments
.getLength();
2346 aDispParams
.cNamedArgs
= 0;
2347 aDispParams
.rgvarg
= new VARIANT
[aDispParams
.cArgs
];
2348 for (unsigned j
= 0; j
< aDispParams
.cArgs
; j
++)
2350 VariantInit(aDispParams
.rgvarg
+j
);
2351 // Note: Reverse order of arguments in Arguments and aDispParams.rgvarg!
2352 const unsigned nIncomingArgIndex
= aDispParams
.cArgs
- j
- 1;
2353 mpInterfaceOleWrapper
->anyToVariant(aDispParams
.rgvarg
+j
, Arguments
[nIncomingArgIndex
]);
2355 // Handle OUT and INOUT arguments. For instance, the second ('Cancel') parameter to
2356 // DocumentBeforeClose() should be a VT_BYREF|VT_BOOL parameter. Need to handle that
2359 if (aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_OUT
||
2360 aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_INOUT
)
2362 switch (aDispParams
.rgvarg
[j
].vt
)
2365 aDispParams
.rgvarg
[j
].byref
= new SHORT(aDispParams
.rgvarg
[j
].iVal
);
2366 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2369 aDispParams
.rgvarg
[j
].byref
= new LONG(aDispParams
.rgvarg
[j
].lVal
);
2370 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2373 aDispParams
.rgvarg
[j
].byref
= new BSTR(aDispParams
.rgvarg
[j
].bstrVal
);
2374 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2377 aDispParams
.rgvarg
[j
].byref
= new VARIANT_BOOL(aDispParams
.rgvarg
[j
].boolVal
);
2378 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2381 assert(false && "Not handled yet");
2388 VariantInit(&aVarResult
);
2391 // In the case of a VBScript client, which uses "late binding", calling Invoke on the
2392 // sink it provides will cause a callback to our CXTypeInfo::GetNames for the given
2393 // member id, and in that we will tell it the name of the corresponding method, and the
2394 // client will know what event handler to invoke based on that name.
2396 // As the outgoing interfaces used (ooo::vba::word::XApplicationOutgoing and others) are
2397 // totally not stable and not published in any way, there can be no client that would
2398 // have done "compile-time binding" and where the sink would actually be an object with
2399 // a vtbl corresponding to the outgoing interface. Late binding clients that work like
2400 // VBScript is all we support.
2401 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method
<< "): Calling Invoke(" << nMemId
<< ")");
2403 nResult
= pDispatch
->Invoke(nMemId
, IID_NULL
, LOCALE_USER_DEFAULT
, DISPATCH_METHOD
, &aDispParams
, &aVarResult
, nullptr, &uArgErr
);
2404 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method
<< "): Invoke() returned");
2406 SAL_WARN_IF(!SUCCEEDED(nResult
), "extensions.olebridge", "Call to " << Method
<< " failed: " << WindowsErrorStringFromHRESULT(nResult
));
2408 // Undo VT_BYREF magic done above. Copy out parameters back to the Anys in Arguments
2409 for (unsigned j
= 0; j
< aDispParams
.cArgs
; j
++)
2411 const unsigned nIncomingArgIndex
= aDispParams
.cArgs
- j
- 1;
2412 if (aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_OUT
||
2413 aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_INOUT
)
2415 switch (aDispParams
.rgvarg
[j
].vt
)
2417 case VT_BYREF
|VT_I2
:
2419 SHORT
*pI
= static_cast<SHORT
*>(aDispParams
.rgvarg
[j
].byref
);
2420 ArgumentsRange
[nIncomingArgIndex
] <<= static_cast<sal_Int16
>(*pI
);
2424 case VT_BYREF
|VT_I4
:
2426 LONG
*pL
= static_cast<LONG
*>(aDispParams
.rgvarg
[j
].byref
);
2427 ArgumentsRange
[nIncomingArgIndex
] <<= static_cast<sal_Int32
>(*pL
);
2431 case VT_BYREF
|VT_BSTR
:
2433 BSTR
*pBstr
= static_cast<BSTR
*>(aDispParams
.rgvarg
[j
].byref
);
2434 ArgumentsRange
[nIncomingArgIndex
] <<= OUString(o3tl::toU(*pBstr
));
2435 // Undo SysAllocString() done in anyToVariant()
2436 SysFreeString(*pBstr
);
2440 case VT_BYREF
|VT_BOOL
:
2442 VARIANT_BOOL
*pBool
= static_cast<VARIANT_BOOL
*>(aDispParams
.rgvarg
[j
].byref
);
2443 ArgumentsRange
[nIncomingArgIndex
] <<= (*pBool
!= VARIANT_FALSE
);
2448 assert(false && "Not handled yet");
2454 switch (aDispParams
.rgvarg
[j
].vt
)
2457 // Undo SysAllocString() done in anyToVariant()
2458 SysFreeString(aDispParams
.rgvarg
[j
].bstrVal
);
2464 delete[] aDispParams
.rgvarg
;
2469 SAL_WARN("extensions.olebridge", "Sink::Call: Unknown method '" << Method
<< "'");
2474 class CXEnumConnections
: public IEnumConnections
,
2475 public CComObjectRoot
2482 virtual ~CXEnumConnections()
2486 #if defined __clang__
2487 #pragma clang diagnostic push
2488 #pragma clang diagnostic ignored "-Wunused-function"
2490 BEGIN_COM_MAP(CXEnumConnections
)
2491 #if defined __clang__
2492 #pragma clang diagnostic pop
2494 COM_INTERFACE_ENTRY(IEnumConnections
)
2495 #if defined __clang__
2496 #pragma clang diagnostic push
2497 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
2498 #pragma clang diagnostic ignored "-Wunused-function"
2501 #if defined __clang__
2502 #pragma clang diagnostic pop
2505 DECLARE_NOT_AGGREGATABLE(CXEnumConnections
)
2507 void Init(std::vector
<IUnknown
*>& rUnknowns
, std::vector
<DWORD
>& rCookies
)
2509 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Init");
2510 SAL_WARN_IF(rUnknowns
.size() != rCookies
.size(), "extensions.olebridge", "Vectors of different size");
2511 mvUnknowns
= rUnknowns
;
2512 mvCookies
= rCookies
;
2516 virtual HRESULT STDMETHODCALLTYPE
Next(ULONG cConnections
,
2518 ULONG
*pcFetched
) override
2520 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2524 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): E_POINTER");
2528 if (pcFetched
&& cConnections
!= 1)
2530 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): E_INVALIDARG");
2531 return E_INVALIDARG
;
2535 while (nFetched
< cConnections
&& mnIndex
< mvUnknowns
.size())
2537 rgcd
[nFetched
].pUnk
= mvUnknowns
[mnIndex
];
2538 rgcd
[nFetched
].pUnk
->AddRef();
2539 rgcd
[nFetched
].dwCookie
= mvCookies
[mnIndex
];
2543 if (nFetched
!= cConnections
)
2545 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): S_FALSE");
2547 *pcFetched
= nFetched
;
2550 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): S_OK");
2552 *pcFetched
= nFetched
;
2557 virtual HRESULT STDMETHODCALLTYPE
Skip(ULONG cConnections
) override
2559 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Skip(" << cConnections
<< "): E_NOTIMPL");
2564 virtual HRESULT STDMETHODCALLTYPE
Reset() override
2566 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Reset: E_NOTIMPL");
2571 virtual HRESULT STDMETHODCALLTYPE
Clone(IEnumConnections
** /* ppEnum */) override
2573 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Clone: E_NOTIMPL");
2579 std::vector
<IUnknown
*> mvUnknowns
;
2580 std::vector
<DWORD
> mvCookies
;
2584 class CXConnectionPoint
: public IConnectionPoint
,
2585 public CComObjectRoot
2588 #if defined __clang__
2589 #pragma clang diagnostic push
2590 #pragma clang diagnostic ignored "-Wunused-function"
2592 BEGIN_COM_MAP(CXConnectionPoint
)
2593 #if defined __clang__
2594 #pragma clang diagnostic pop
2596 COM_INTERFACE_ENTRY(IConnectionPoint
)
2597 #if defined __clang__
2598 #pragma clang diagnostic push
2599 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
2600 #pragma clang diagnostic ignored "-Wunused-function"
2603 #if defined __clang__
2604 #pragma clang diagnostic pop
2607 DECLARE_NOT_AGGREGATABLE(CXConnectionPoint
)
2609 virtual ~CXConnectionPoint() {}
2611 void Init(InterfaceOleWrapper
* pInterfaceOleWrapper
,
2612 Reference
<ooo::vba::XConnectionPoint
>& xCP
,
2613 Reference
<XMultiServiceFactory
>& xMSF
,
2614 ooo::vba::TypeAndIID aTypeAndIID
)
2616 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Init for " << pInterfaceOleWrapper
->getImplementationName());
2619 if (SUCCEEDED(QueryInterface(IID_IUnknown
, reinterpret_cast<void **>(&pUnknown
))))
2621 // In case QI for IUnknown returns a different pointer, but nah, it doesn't
2622 SAL_INFO("extensions.olebridge", " (IUnknown@" << pUnknown
<< ")");
2625 mpInterfaceOleWrapper
= pInterfaceOleWrapper
;
2628 maTypeAndIID
= aTypeAndIID
;
2631 virtual HRESULT STDMETHODCALLTYPE
GetConnectionInterface(IID
*pIID
) override
2633 SAL_WARN("extensions.olebridge", this << "@CXConnectionPoint::GetConnectionInterface(" << *pIID
<< "): E_NOTIMPL");
2640 virtual HRESULT STDMETHODCALLTYPE
GetConnectionPointContainer(IConnectionPointContainer
**) override
2642 SAL_WARN("extensions.olebridge", this << "@CXConnectionPoint::GetConnectionInterface: E_NOTIMPL");
2649 virtual HRESULT STDMETHODCALLTYPE
Advise(IUnknown
*pUnkSink
,
2650 DWORD
*pdwCookie
) override
2652 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2654 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Advise(" << pUnkSink
<< ")");
2659 Reference
<ooo::vba::XSink
> xSink(new Sink(pUnkSink
, mxMSF
, maTypeAndIID
, mpInterfaceOleWrapper
));
2661 mvISinks
.push_back(pUnkSink
);
2662 *pdwCookie
= mvISinks
.size();
2664 mvCookies
.push_back(mxCP
->Advise(xSink
));
2666 mvXSinks
.push_back(xSink
);
2668 SAL_INFO("extensions.olebridge", " *pdwCookie: " << *pdwCookie
);
2673 virtual HRESULT STDMETHODCALLTYPE
Unadvise(DWORD dwCookie
) override
2675 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2677 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Unadvise(" << dwCookie
<< ")");
2679 if (dwCookie
== 0 || dwCookie
> mvISinks
.size())
2682 mvISinks
[dwCookie
-1] = nullptr;
2684 mxCP
->Unadvise(mvCookies
[dwCookie
-1]);
2686 mvXSinks
[dwCookie
-1] = Reference
<ooo::vba::XSink
>();
2691 virtual HRESULT STDMETHODCALLTYPE
EnumConnections(IEnumConnections
**ppEnum
) override
2693 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2697 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::EnumConnections...");
2701 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: E_POINTER");
2705 CComObject
<CXEnumConnections
>* pEnumConnections
;
2707 nResult
= CComObject
<CXEnumConnections
>::CreateInstance(&pEnumConnections
);
2708 if (FAILED(nResult
))
2710 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: " << WindowsErrorStringFromHRESULT(nResult
));
2714 pEnumConnections
->AddRef();
2716 pEnumConnections
->Init(mvISinks
, mvCookies
);
2717 *ppEnum
= pEnumConnections
;
2719 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: S_OK");
2724 InterfaceOleWrapper
* mpInterfaceOleWrapper
;
2725 std::vector
<IUnknown
*> mvISinks
;
2726 std::vector
<Reference
<ooo::vba::XSink
>> mvXSinks
;
2727 std::vector
<DWORD
> mvCookies
;
2728 Reference
<XMultiServiceFactory
> mxMSF
;
2729 Reference
<ooo::vba::XConnectionPoint
> mxCP
;
2730 ooo::vba::TypeAndIID maTypeAndIID
;
2735 HRESULT
InterfaceOleWrapper::InvokeGeneral( DISPID dispidMember
, unsigned short wFlags
,
2736 DISPPARAMS
* pdispparams
, VARIANT
* pvarResult
, EXCEPINFO
* pexcepinfo
,
2737 unsigned int * /*puArgErr*/, bool& bHandled
)
2742 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation
2743 // is that we put an object into an Array object ( out parameter). We have to return
2744 // IDispatch otherwise the object cannot be accessed from the Script.
2745 if( dispidMember
== DISPID_VALUE
&& (wFlags
& DISPATCH_PROPERTYGET
) != 0
2746 && m_defaultValueType
!= VT_EMPTY
&& pvarResult
!= nullptr)
2748 // Special case hack: If it is a ScVbaCheckBox, return the boolean value
2749 Reference
<ooo::vba::msforms::XCheckBox
> xCheckBox(m_xOrigin
, UNO_QUERY
);
2753 Any aValue
= xCheckBox
->getValue();
2754 anyToVariant(pvarResult
, aValue
);
2759 if( m_defaultValueType
== VT_DISPATCH
)
2761 pvarResult
->vt
= VT_DISPATCH
;
2762 pvarResult
->pdispVal
= this;
2768 // function: _GetValueObject
2769 else if( dispidMember
== DISPID_JSCRIPT_VALUE_FUNC
)
2774 CComObject
< JScriptValue
>* pValue
;
2775 if( SUCCEEDED( CComObject
<JScriptValue
>::CreateInstance( &pValue
)))
2778 pvarResult
->vt
= VT_DISPATCH
;
2779 pvarResult
->pdispVal
= CComQIPtr
<IDispatch
>(pValue
->GetUnknown());
2783 ret
= DISP_E_EXCEPTION
;
2785 else if( dispidMember
== DISPID_GET_STRUCT_FUNC
)
2788 bool bStruct
= false;
2791 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(m_smgr
));
2792 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
2794 if( pdispparams
->cArgs
== 1 && SUCCEEDED( arg
.ChangeType( VT_BSTR
, &pdispparams
->rgvarg
[0])) )
2796 Reference
<XIdlClass
> classStruct
= xRefl
->forName(OUString(o3tl::toU(arg
.bstrVal
)));
2797 if( classStruct
.is())
2800 classStruct
->createObject( anyStruct
);
2802 anyToVariant( &var
, anyStruct
);
2804 if( var
.vt
== VT_DISPATCH
)
2806 VariantCopy( pvarResult
, & var
);
2811 ret
= bStruct
? S_OK
: DISP_E_EXCEPTION
;
2813 else if (dispidMember
== DISPID_CREATE_TYPE_FUNC
)
2818 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
2820 if( pdispparams
->cArgs
!= 1)
2821 return DISP_E_BADPARAMCOUNT
;
2822 if (FAILED( arg
.ChangeType( VT_BSTR
, &pdispparams
->rgvarg
[0])))
2823 return DISP_E_BADVARTYPE
;
2825 //check if the provided name represents a valid type
2827 if (!getType(arg
.bstrVal
, type
))
2829 writeExcepinfo(pexcepinfo
, OUString::Concat("[automation bridge] A UNO type with the name ") +
2830 o3tl::toU(arg
.bstrVal
) + " does not exist!");
2831 return DISP_E_EXCEPTION
;
2834 if (!createUnoTypeWrapper(arg
.bstrVal
, pvarResult
))
2836 writeExcepinfo(pexcepinfo
, "[automation bridge] InterfaceOleWrapper::InvokeGeneral\n"
2837 "Could not initialize UnoTypeWrapper object!");
2838 return DISP_E_EXCEPTION
;
2841 else if (dispidMember
== DISPID_NEWENUM
)
2847 Reference
< ooo::vba::XCollection
> xCollection(m_xOrigin
, UNO_QUERY
);
2848 if (!xCollection
.is())
2849 return DISP_E_MEMBERNOTFOUND
;
2851 CComObject
<CXEnumVariant
>* pEnumVar
;
2853 ret
= CComObject
<CXEnumVariant
>::CreateInstance(&pEnumVar
);
2859 pEnumVar
->Init(this, xCollection
);
2861 pvarResult
->vt
= VT_UNKNOWN
;
2862 pvarResult
->punkVal
= nullptr;
2864 ret
= pEnumVar
->QueryInterface(IID_IUnknown
, reinterpret_cast<void**>(&pvarResult
->punkVal
));
2867 pEnumVar
->Release();
2872 catch(const BridgeRuntimeError
& e
)
2874 writeExcepinfo(pexcepinfo
, e
.message
);
2875 ret
= DISP_E_EXCEPTION
;
2877 catch(const Exception
& e
)
2879 OUString message
= "InterfaceOleWrapper::InvokeGeneral : \n" +
2881 writeExcepinfo(pexcepinfo
, message
);
2882 ret
= DISP_E_EXCEPTION
;
2886 writeExcepinfo(pexcepinfo
, "InterfaceOleWrapper::InvokeGeneral : \nUnexpected exception");
2887 ret
= DISP_E_EXCEPTION
;
2892 STDMETHODIMP
InterfaceOleWrapper::GetDispID(BSTR
/*bstrName*/, DWORD
/*grfdex*/, DISPID __RPC_FAR
* /*pid*/)
2894 return ResultFromScode(E_NOTIMPL
);
2897 STDMETHODIMP
InterfaceOleWrapper::InvokeEx(
2898 /* [in] */ DISPID
/*id*/,
2899 /* [in] */ LCID
/*lcid*/,
2900 /* [in] */ WORD
/*wFlags*/,
2901 /* [in] */ DISPPARAMS __RPC_FAR
* /*pdp*/,
2902 /* [out] */ VARIANT __RPC_FAR
* /*pvarRes*/,
2903 /* [out] */ EXCEPINFO __RPC_FAR
* /*pei*/,
2904 /* [unique][in] */ IServiceProvider __RPC_FAR
* /*pspCaller*/)
2906 return ResultFromScode(E_NOTIMPL
);
2909 STDMETHODIMP
InterfaceOleWrapper::DeleteMemberByName(
2910 /* [in] */ BSTR
/*bstr*/,
2911 /* [in] */ DWORD
/*grfdex*/)
2913 return ResultFromScode(E_NOTIMPL
);
2916 STDMETHODIMP
InterfaceOleWrapper::DeleteMemberByDispID(DISPID
/*id*/)
2918 return ResultFromScode(E_NOTIMPL
);
2921 STDMETHODIMP
InterfaceOleWrapper::GetMemberProperties(
2922 /* [in] */ DISPID
/*id*/,
2923 /* [in] */ DWORD
/*grfdexFetch*/,
2924 /* [out] */ DWORD __RPC_FAR
* /*pgrfdex*/)
2926 return ResultFromScode(E_NOTIMPL
);
2929 STDMETHODIMP
InterfaceOleWrapper::GetMemberName(
2930 /* [in] */ DISPID
/*id*/,
2931 /* [out] */ BSTR __RPC_FAR
* /*pbstrName*/)
2933 return ResultFromScode(E_NOTIMPL
);
2936 STDMETHODIMP
InterfaceOleWrapper::GetNextDispID(
2937 /* [in] */ DWORD
/*grfdex*/,
2938 /* [in] */ DISPID
/*id*/,
2939 /* [out] */ DISPID __RPC_FAR
* /*pid*/)
2941 return ResultFromScode(E_NOTIMPL
);
2944 STDMETHODIMP
InterfaceOleWrapper::GetNameSpaceParent(
2945 /* [out] */ IUnknown __RPC_FAR
*__RPC_FAR
* /*ppunk*/)
2947 return ResultFromScode(E_NOTIMPL
);
2950 // IProvideClassInfo
2951 HRESULT STDMETHODCALLTYPE
InterfaceOleWrapper::GetClassInfo (
2952 /* [out] */ ITypeInfo
**ppTI
)
2954 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2956 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetClassInfo");
2961 Reference
<ooo::vba::XInterfaceWithIID
> xIID(m_xOrigin
, UNO_QUERY
);
2965 OUString sIID
= xIID
->getIID();
2967 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(sIID
.pData
->buffer
), &aIID
)))
2972 CComObject
<CXTypeInfo
>* pTypeInfo
;
2974 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
2978 pTypeInfo
->AddRef();
2980 pTypeInfo
->InitForCoclass(m_xOrigin
, m_sImplementationName
, aIID
, m_smgr
);
2987 // IConnectionPointContainer
2988 HRESULT STDMETHODCALLTYPE
InterfaceOleWrapper::EnumConnectionPoints(
2989 /* [out] */ IEnumConnectionPoints
**)
2991 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::EnumConnectionPoints");
2992 return ResultFromScode(E_NOTIMPL
);
2995 HRESULT STDMETHODCALLTYPE
InterfaceOleWrapper::FindConnectionPoint(
2996 /* [in] */ REFIID riid
,
2997 /* [out] */ IConnectionPoint
**ppCP
)
2999 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
3001 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::FindConnectionPoint(" << riid
<< ")");
3006 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
3008 // We checked already
3009 assert(xConnectable
.is());
3010 if (!xConnectable
.is())
3013 ooo::vba::TypeAndIID aTypeAndIID
= xConnectable
->GetConnectionPoint();
3016 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(aTypeAndIID
.IID
.pData
->buffer
), &aIID
)))
3017 return E_INVALIDARG
;
3019 if (!IsEqualIID(riid
, aIID
))
3020 return E_INVALIDARG
;
3022 Reference
<ooo::vba::XConnectionPoint
> xCP
= xConnectable
->FindConnectionPoint();
3024 return E_INVALIDARG
;
3028 CComObject
<CXConnectionPoint
>* pConnectionPoint
;
3030 ret
= CComObject
<CXConnectionPoint
>::CreateInstance(&pConnectionPoint
);
3034 pConnectionPoint
->AddRef();
3036 pConnectionPoint
->Init(this, xCP
, m_smgr
, aTypeAndIID
);
3038 *ppCP
= pConnectionPoint
;
3043 // UnoObjectWrapperRemoteOpt ---------------------------------------------------
3045 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference
<XMultiServiceFactory
> const & aFactory
,
3046 sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
3047 InterfaceOleWrapper( aFactory
, unoWrapperClass
, comWrapperClass
),
3052 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt()
3056 // UnoConversionUtilities
3057 Reference
< XInterface
> UnoObjectWrapperRemoteOpt::createUnoWrapperInstance()
3059 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
3060 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
3061 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
3064 COM_DECLSPEC_NOTHROW STDMETHODIMP
UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID
/*riid*/, LPOLESTR
* rgszNames
, UINT cNames
,
3065 LCID
/*lcid*/, DISPID
* rgdispid
)
3067 MutexGuard
guard( getBridgeMutex());
3071 HRESULT ret
= E_UNEXPECTED
;
3074 if( ! wcscmp( *rgszNames
, JSCRIPT_VALUE_FUNC
))
3076 *rgdispid
= DISPID_JSCRIPT_VALUE_FUNC
;
3079 else if( ! wcscmp( *rgszNames
, GET_STRUCT_FUNC
))
3081 *rgdispid
= DISPID_GET_STRUCT_FUNC
;
3085 if (m_xInvocation
.is() && (cNames
> 0))
3087 OUString
name(o3tl::toU(rgszNames
[0]));
3088 // has this name been determined as "bad"
3089 BadNameMap::iterator badIter
= m_badNameMap
.find( name
);
3090 if( badIter
== m_badNameMap
.end() )
3092 // name has not been bad before( member exists
3093 typedef NameToIdMap::iterator ITnames
;
3094 std::pair
< ITnames
, bool > pair_id
= m_nameToDispIdMap
.emplace(name
, m_currentId
++);
3095 // new ID inserted ?
3096 if( pair_id
.second
)
3097 {// yes, now create MemberInfo and ad to IdToMemberInfoMap
3098 MemberInfo
d(0, name
);
3099 m_idToMemberInfoMap
.emplace(m_currentId
- 1, d
);
3102 *rgdispid
= pair_id
.first
->second
;
3106 ret
= DISP_E_UNKNOWNNAME
;
3111 COM_DECLSPEC_NOTHROW STDMETHODIMP
UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember
, REFIID
/*riid*/, LCID
/*lcid*/, WORD wFlags
,
3112 DISPPARAMS
* pdispparams
, VARIANT
* pvarResult
, EXCEPINFO
* pexcepinfo
,
3115 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
3120 bool bHandled
= false;
3121 ret
= InvokeGeneral( dispidMember
, wFlags
, pdispparams
, pvarResult
, pexcepinfo
,
3122 puArgErr
, bHandled
);
3126 if ( dispidMember
> 0 && m_xInvocation
.is())
3129 IdToMemberInfoMap::iterator it_MemberInfo
= m_idToMemberInfoMap
.find( dispidMember
);
3130 if( it_MemberInfo
!= m_idToMemberInfoMap
.end() )
3132 MemberInfo
& info
= it_MemberInfo
->second
;
3134 Sequence
<Any
> params
; // holds converted any s
3136 { // DISPID called for the first time
3137 if( wFlags
== DISPATCH_METHOD
)
3139 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3141 if( FAILED( ret
= doInvoke( pdispparams
, pvarResult
,
3142 pexcepinfo
, puArgErr
, info
.name
, params
))
3143 && ret
== DISP_E_MEMBERNOTFOUND
)
3145 // try to get the exact name
3147 if (m_xExactName
.is())
3149 exactName
= m_xExactName
->getExactName( info
.name
);
3151 if( !exactName
.isEmpty() )
3153 if( SUCCEEDED( ret
= doInvoke( pdispparams
, pvarResult
,
3154 pexcepinfo
, puArgErr
, exactName
, params
)))
3155 info
.name
= exactName
;
3159 if( SUCCEEDED( ret
) )
3160 info
.flags
= DISPATCH_METHOD
;
3162 else if( wFlags
== DISPATCH_PROPERTYPUT
|| wFlags
== DISPATCH_PROPERTYPUTREF
)
3164 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3165 if( FAILED( ret
= doSetProperty( pdispparams
, pvarResult
,
3166 pexcepinfo
, puArgErr
, info
.name
, params
))
3167 && ret
== DISP_E_MEMBERNOTFOUND
)
3169 // try to get the exact name
3171 if (m_xExactName
.is())
3173 exactName
= m_xExactName
->getExactName( info
.name
);
3175 if( !exactName
.isEmpty() )
3177 if( SUCCEEDED( ret
= doSetProperty( pdispparams
, pvarResult
,
3178 pexcepinfo
, puArgErr
, exactName
, params
)))
3179 info
.name
= exactName
;
3183 if( SUCCEEDED( ret
) )
3184 info
.flags
= DISPATCH_PROPERTYPUT
| DISPATCH_PROPERTYGET
;
3186 else if( wFlags
== DISPATCH_PROPERTYGET
)
3188 if( FAILED( ret
= doGetProperty( pdispparams
, pvarResult
,
3189 pexcepinfo
, info
.name
))
3190 && ret
== DISP_E_MEMBERNOTFOUND
)
3192 // try to get the exact name
3194 if (m_xExactName
.is())
3196 exactName
= m_xExactName
->getExactName( info
.name
);
3198 if( !exactName
.isEmpty() )
3200 if( SUCCEEDED( ret
= doGetProperty( pdispparams
, pvarResult
,
3201 pexcepinfo
, exactName
)))
3202 info
.name
= exactName
;
3206 if( SUCCEEDED( ret
) )
3207 info
.flags
= DISPATCH_PROPERTYGET
| DISPATCH_PROPERTYPUT
;
3209 else if( wFlags
& DISPATCH_METHOD
&&
3210 (wFlags
& DISPATCH_PROPERTYPUT
|| wFlags
& DISPATCH_PROPERTYPUTREF
))
3214 // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT
3215 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3216 // try first as method
3217 if( FAILED( ret
= doInvoke( pdispparams
, pvarResult
,
3218 pexcepinfo
, puArgErr
, info
.name
, params
))
3219 && ret
== DISP_E_MEMBERNOTFOUND
)
3221 // try to get the exact name
3222 if (m_xExactName
.is())
3224 exactName
= m_xExactName
->getExactName( info
.name
);
3226 if( !exactName
.isEmpty() )
3228 if( SUCCEEDED( ret
= doInvoke( pdispparams
, pvarResult
,
3229 pexcepinfo
, puArgErr
, exactName
, params
)))
3230 info
.name
= exactName
;
3234 if( SUCCEEDED( ret
) )
3235 info
.flags
= DISPATCH_METHOD
;
3238 if( FAILED( ret
) && pdispparams
->cArgs
== 1)
3240 if( FAILED( ret
= doSetProperty( pdispparams
, pvarResult
,
3241 pexcepinfo
, puArgErr
, info
.name
, params
))
3242 && ret
== DISP_E_MEMBERNOTFOUND
)
3244 // try to get the exact name
3245 if( !exactName
.isEmpty() )
3247 if( SUCCEEDED( ret
= doSetProperty( pdispparams
, pvarResult
,
3248 pexcepinfo
, puArgErr
, exactName
, params
)))
3249 info
.name
= exactName
;
3252 if( SUCCEEDED( ret
) )
3253 info
.flags
= DISPATCH_PROPERTYPUT
| DISPATCH_PROPERTYGET
;
3256 else if( wFlags
& DISPATCH_METHOD
&& wFlags
& DISPATCH_PROPERTYGET
)
3259 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3261 if( FAILED( ret
= doInvoke( pdispparams
, pvarResult
,
3262 pexcepinfo
, puArgErr
, info
.name
, params
))
3263 && ret
== DISP_E_MEMBERNOTFOUND
)
3265 // try to get the exact name
3266 if (m_xExactName
.is())
3268 exactName
= m_xExactName
->getExactName( info
.name
);
3270 if( !exactName
.isEmpty() )
3272 if( SUCCEEDED( ret
= doInvoke( pdispparams
, pvarResult
,
3273 pexcepinfo
, puArgErr
, exactName
, params
)))
3274 info
.name
= exactName
;
3278 if( SUCCEEDED( ret
) )
3279 info
.flags
= DISPATCH_METHOD
;
3282 if( FAILED( ret
) && pdispparams
->cArgs
== 1)
3284 if( FAILED( ret
= doGetProperty( pdispparams
, pvarResult
,
3285 pexcepinfo
, info
.name
))
3286 && ret
== DISP_E_MEMBERNOTFOUND
)
3288 if( !exactName
.isEmpty() )
3290 if( SUCCEEDED( ret
= doSetProperty( pdispparams
, pvarResult
,
3291 pexcepinfo
, puArgErr
, exactName
, params
)))
3292 info
.name
= exactName
;
3295 if( SUCCEEDED( ret
) )
3296 info
.flags
= DISPATCH_PROPERTYGET
;
3300 // update information about this member
3301 if( ret
== DISP_E_MEMBERNOTFOUND
)
3303 // Remember the name as not existing
3304 // and remove the MemberInfo
3305 m_badNameMap
[info
.name
]= false;
3306 m_idToMemberInfoMap
.erase( it_MemberInfo
);
3308 } // if( ! info.flags )
3309 else // IdToMemberInfoMap contains a MemberInfo
3311 if( wFlags
& DISPATCH_METHOD
&& info
.flags
== DISPATCH_METHOD
)
3313 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3314 ret
= doInvoke( pdispparams
, pvarResult
,
3315 pexcepinfo
, puArgErr
, info
.name
, params
);
3317 else if( (wFlags
& DISPATCH_PROPERTYPUT
|| wFlags
& DISPATCH_PROPERTYPUTREF
) &&
3318 info
.flags
& DISPATCH_PROPERTYPUT
)
3320 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3321 ret
= doSetProperty( pdispparams
, pvarResult
,
3322 pexcepinfo
, puArgErr
, info
.name
, params
);
3324 else if( (wFlags
& DISPATCH_PROPERTYGET
) && ( info
.flags
& DISPATCH_PROPERTYGET
))
3326 ret
= doGetProperty( pdispparams
, pvarResult
,
3327 pexcepinfo
, info
.name
);
3331 ret
= DISP_E_MEMBERNOTFOUND
;
3334 }// if( it_MemberInfo != m_idToMemberInfoMap.end() )
3336 ret
= DISP_E_MEMBERNOTFOUND
;
3339 catch(const BridgeRuntimeError
& e
)
3341 writeExcepinfo(pexcepinfo
, e
.message
);
3342 ret
= DISP_E_EXCEPTION
;
3344 catch(const Exception
& e
)
3346 OUString message
= "UnoObjectWrapperRemoteOpt::Invoke : \n" +
3348 writeExcepinfo(pexcepinfo
, message
);
3349 ret
= DISP_E_EXCEPTION
;
3353 writeExcepinfo(pexcepinfo
, "UnoObjectWrapperRemoteOpt::Invoke : \nUnexpected exception");
3354 ret
= DISP_E_EXCEPTION
;
3360 HRESULT
UnoObjectWrapperRemoteOpt::methodInvoke( DISPID
/*dispidMember*/, DISPPARAMS
* /*pdispparams*/, VARIANT
* /*pvarResult*/,
3361 EXCEPINFO
* /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence
<Any
> const &)
3366 // The returned HRESULT is only appropriate for IDispatch::Invoke
3367 static HRESULT
mapCannotConvertException(const CannotConvertException
&e
, unsigned int * puArgErr
)
3370 bool bWriteIndex
= true;
3374 case FailReason::OUT_OF_RANGE
:
3375 ret
= DISP_E_OVERFLOW
;
3377 case FailReason::IS_NOT_NUMBER
:
3378 ret
= DISP_E_TYPEMISMATCH
;
3380 case FailReason::IS_NOT_ENUM
:
3381 ret
= DISP_E_TYPEMISMATCH
;
3383 case FailReason::IS_NOT_BOOL
:
3384 ret
= DISP_E_TYPEMISMATCH
;
3386 case FailReason::NO_SUCH_INTERFACE
:
3387 ret
= DISP_E_TYPEMISMATCH
;
3389 case FailReason::SOURCE_IS_NO_DERIVED_TYPE
:
3390 ret
= DISP_E_TYPEMISMATCH
;
3392 case FailReason::TYPE_NOT_SUPPORTED
:
3393 ret
= DISP_E_TYPEMISMATCH
;
3395 case FailReason::INVALID
:
3396 ret
= DISP_E_TYPEMISMATCH
;
3398 case FailReason::NO_DEFAULT_AVAILABLE
:
3399 ret
= DISP_E_BADPARAMCOUNT
;
3401 case FailReason::UNKNOWN
:
3410 if( bWriteIndex
&& puArgErr
!= nullptr)
3411 *puArgErr
= e
.ArgumentIndex
;
3415 // The function maps the TypeClass of the any to VARTYPE: If
3416 // the Any contains STRUCT or INTERFACE then the return value
3417 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper
3418 // and the result is put into the constructor of the uno - wrapper
3419 // object. If a client asks the object for DISPID_VALUE and this
3420 // function returned VT_DISPATCH then the IDispatch of the same
3421 // object is being returned.
3422 // See InterfaceOleWrapper::Invoke, InterfaceOleWrapper::m_defaultValueType
3423 VARTYPE
getVarType( const Any
& value
)
3425 VARTYPE ret
= VT_EMPTY
;
3427 switch ( value
.getValueTypeClass())
3429 case TypeClass_STRUCT
: ret
= VT_DISPATCH
; break;
3430 case TypeClass_INTERFACE
: ret
= VT_DISPATCH
; break;
3436 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */