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>
90 #include <systools/win32/oleauto.hxx>
92 #include "comifaces.hxx"
93 #include "jscriptclasses.hxx"
94 #include "unotypewrapper.hxx"
95 #include "oleobjw.hxx"
96 #include "unoobjw.hxx"
97 #include "servprov.hxx"
100 using namespace cppu
;
101 using namespace com::sun::star::uno
;
102 using namespace com::sun::star::beans
;
103 using namespace com::sun::star::container
;
104 using namespace com::sun::star::script
;
105 using namespace com::sun::star::lang
;
106 using namespace com::sun::star::bridge::ModelDependent
;
107 using namespace com::sun::star::reflection
;
109 std::unordered_map
<sal_uIntPtr
, WeakReference
<XInterface
> > UnoObjToWrapperMap
;
110 static bool writeBackOutParameter(VARIANTARG
* pDest
, VARIANT
* pSource
);
111 static bool writeBackOutParameter2( VARIANTARG
* pDest
, VARIANT
* pSource
);
112 static HRESULT
mapCannotConvertException(const CannotConvertException
&e
, unsigned int * puArgErr
);
114 /* Does not throw any exceptions.
115 Param pInfo can be NULL.
117 static void writeExcepinfo(EXCEPINFO
* pInfo
, const OUString
& message
)
119 if (pInfo
!= nullptr)
121 pInfo
->wCode
= UNO_2_OLE_EXCEPTIONCODE
;
122 pInfo
->bstrSource
= SysAllocString(L
"[automation bridge] ");
123 pInfo
->bstrDescription
= sal::systools::BStr::newBSTR(message
);
127 InterfaceOleWrapper::InterfaceOleWrapper( Reference
<XMultiServiceFactory
> const & xFactory
,
128 sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
129 UnoConversionUtilities
<InterfaceOleWrapper
>( xFactory
, unoWrapperClass
, comWrapperClass
),
130 m_defaultValueType( 0)
134 InterfaceOleWrapper::~InterfaceOleWrapper()
136 MutexGuard
guard(getBridgeMutex());
137 // remove entries in global map
138 auto it
= UnoObjToWrapperMap
.find( reinterpret_cast<sal_uIntPtr
>(m_xOrigin
.get()));
139 if(it
!= UnoObjToWrapperMap
.end())
140 UnoObjToWrapperMap
.erase(it
);
143 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::QueryInterface(REFIID riid
, void ** ppv
)
145 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
147 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::QueryInterface(" << riid
<< ")");
154 if(IsEqualIID(riid
, IID_IUnknown
))
157 *ppv
= static_cast<IUnknown
*>(static_cast<IDispatch
*>(this));
158 SAL_INFO("extensions.olebridge", " " << *ppv
);
160 else if (IsEqualIID(riid
, IID_IDispatch
))
163 *ppv
= static_cast<IDispatch
*>(this);
164 SAL_INFO("extensions.olebridge", " " << *ppv
);
166 else if (IsEqualIID(riid
, IID_IProvideClassInfo
))
168 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
169 if (!xConnectable
.is())
170 return E_NOINTERFACE
;
172 *ppv
= static_cast<IProvideClassInfo
*>(this);
173 SAL_INFO("extensions.olebridge", " " << *ppv
);
175 else if (IsEqualIID(riid
, IID_IConnectionPointContainer
))
177 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
178 if (!xConnectable
.is())
179 return E_NOINTERFACE
;
181 *ppv
= static_cast<IConnectionPointContainer
*>(this);
182 SAL_INFO("extensions.olebridge", " " << *ppv
);
184 else if( IsEqualIID( riid
, __uuidof( IUnoObjectWrapper
)))
187 *ppv
= static_cast<IUnoObjectWrapper
*>(this);
188 SAL_INFO("extensions.olebridge", " " << *ppv
);
195 COM_DECLSPEC_NOTHROW
STDMETHODIMP_(ULONG
) InterfaceOleWrapper::AddRef()
198 // does not need to guard because one should not rely on the return value of
203 COM_DECLSPEC_NOTHROW
STDMETHODIMP_(ULONG
) InterfaceOleWrapper::Release()
210 // IUnoObjectWrapper --------------------------------------------------------
211 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::getWrapperXInterface( Reference
<XInterface
>* pXInt
)
213 pXInt
->set( static_cast<XWeak
*>( this), UNO_QUERY
);
214 return pXInt
->is() ? S_OK
: E_FAIL
;
216 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::getOriginalUnoObject( Reference
<XInterface
>* pXInt
)
219 return m_xOrigin
.is() ? S_OK
: E_FAIL
;
221 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::getOriginalUnoStruct( Any
* pStruct
)
223 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
228 Reference
<XMaterialHolder
> xMatHolder( m_xInvocation
, UNO_QUERY
);
231 Any any
= xMatHolder
->getMaterial();
232 if( any
.getValueTypeClass() == TypeClass_STRUCT
)
242 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::GetTypeInfoCount( UINT
*pctinfo
)
244 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetTypeInfoCount");
256 class CXTypeInfo
: public ITypeInfo
,
257 public CComObjectRoot
260 enum class Kind
{ COCLASS
, MAIN
, OUTGOING
};
262 #if defined __clang__
263 #pragma clang diagnostic push
264 #pragma clang diagnostic ignored "-Wunused-function"
266 BEGIN_COM_MAP(CXTypeInfo
)
267 #if defined __clang__
268 #pragma clang diagnostic pop
270 COM_INTERFACE_ENTRY(ITypeInfo
)
271 #if defined __clang__
272 #pragma clang diagnostic push
273 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
274 #pragma clang diagnostic ignored "-Wunused-function"
277 #if defined __clang__
278 #pragma clang diagnostic pop
281 DECLARE_NOT_AGGREGATABLE(CXTypeInfo
)
283 virtual ~CXTypeInfo() {}
285 void InitForCoclass(Reference
<XInterface
> xOrigin
,
286 const OUString
& sImplementationName
,
288 Reference
<XMultiServiceFactory
> xMSF
);
289 void InitForClassItself(Reference
<XInterface
> xOrigin
,
290 const OUString
& sImplementationName
,
292 Reference
<XMultiServiceFactory
> xMSF
);
293 void InitForOutgoing(Reference
<XInterface
> xOrigin
,
294 const OUString
& sInterfaceName
,
296 Reference
<XMultiServiceFactory
> xMSF
,
298 virtual HRESULT STDMETHODCALLTYPE
GetTypeAttr(TYPEATTR
**ppTypeAttr
) override
;
299 virtual HRESULT STDMETHODCALLTYPE
GetTypeComp(ITypeComp
**ppTComp
) override
;
300 virtual HRESULT STDMETHODCALLTYPE
GetFuncDesc(UINT index
,
301 FUNCDESC
**ppFuncDesc
) override
;
302 virtual HRESULT STDMETHODCALLTYPE
GetVarDesc(UINT index
,
303 VARDESC
**ppVarDesc
) override
;
304 virtual HRESULT STDMETHODCALLTYPE
GetNames(MEMBERID memid
,
307 UINT
*pcNames
) override
;
308 virtual HRESULT STDMETHODCALLTYPE
GetRefTypeOfImplType(UINT index
,
309 HREFTYPE
*pRefType
) override
;
310 virtual HRESULT STDMETHODCALLTYPE
GetImplTypeFlags(UINT index
,
311 INT
*pImplTypeFlags
) override
;
312 virtual HRESULT STDMETHODCALLTYPE
GetIDsOfNames(LPOLESTR
*rgszNames
,
314 MEMBERID
*pMemId
) override
;
315 virtual HRESULT STDMETHODCALLTYPE
Invoke(PVOID pvInstance
,
318 DISPPARAMS
*pDispParams
,
320 EXCEPINFO
*pExcepInfo
,
321 UINT
*puArgErr
) override
;
322 virtual HRESULT STDMETHODCALLTYPE
GetDocumentation(MEMBERID memid
,
324 BSTR
*pBstrDocString
,
325 DWORD
*pdwHelpContext
,
326 BSTR
*pBstrHelpFile
) override
;
327 virtual HRESULT STDMETHODCALLTYPE
GetDllEntry(MEMBERID memid
,
331 WORD
*pwOrdinal
) override
;
332 virtual HRESULT STDMETHODCALLTYPE
GetRefTypeInfo(HREFTYPE hRefType
,
333 ITypeInfo
**ppTInfo
) override
;
334 virtual HRESULT STDMETHODCALLTYPE
AddressOfMember(MEMBERID memid
,
336 PVOID
*ppv
) override
;
337 virtual HRESULT STDMETHODCALLTYPE
CreateInstance(IUnknown
*pUnkOuter
,
339 PVOID
*ppvObj
) override
;
340 virtual HRESULT STDMETHODCALLTYPE
GetMops(MEMBERID memid
,
341 BSTR
*pBstrMops
) override
;
342 virtual HRESULT STDMETHODCALLTYPE
GetContainingTypeLib(ITypeLib
**ppTLib
,
343 UINT
*pIndex
) override
;
344 virtual void STDMETHODCALLTYPE
ReleaseTypeAttr(TYPEATTR
*pTypeAttr
) override
;
345 virtual void STDMETHODCALLTYPE
ReleaseFuncDesc(FUNCDESC
*pFuncDesc
) override
;
346 virtual void STDMETHODCALLTYPE
ReleaseVarDesc(VARDESC
*pVarDesc
) override
;
350 Reference
<XInterface
> mxOrigin
;
351 OUString msImplementationName
;
352 OUString msInterfaceName
;
354 Reference
<XMultiServiceFactory
> mxMSF
;
358 class CXTypeLib
: public ITypeLib
,
359 public CComObjectRoot
362 #if defined __clang__
363 #pragma clang diagnostic push
364 #pragma clang diagnostic ignored "-Wunused-function"
366 BEGIN_COM_MAP(CXTypeLib
)
367 #if defined __clang__
368 #pragma clang diagnostic pop
370 COM_INTERFACE_ENTRY(ITypeLib
)
371 #if defined __clang__
372 #pragma clang diagnostic push
373 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
374 #pragma clang diagnostic ignored "-Wunused-function"
377 #if defined __clang__
378 #pragma clang diagnostic pop
381 DECLARE_NOT_AGGREGATABLE(CXTypeLib
)
383 virtual ~CXTypeLib() {}
385 void Init(Reference
<XInterface
> xOrigin
,
386 const OUString
& sImplementationName
,
387 Reference
<XMultiServiceFactory
> xMSF
)
389 SAL_INFO("extensions.olebridge", this << "@CXTypeLib::Init for " << sImplementationName
);
391 msImplementationName
= sImplementationName
;
395 virtual UINT STDMETHODCALLTYPE
GetTypeInfoCount() override
397 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoCount");
401 virtual HRESULT STDMETHODCALLTYPE
GetTypeInfo(UINT
,
402 ITypeInfo
**) override
404 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfo: E_NOTIMPL");
408 virtual HRESULT STDMETHODCALLTYPE
GetTypeInfoType(UINT
,
411 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoType: E_NOTIMPL");
415 virtual HRESULT STDMETHODCALLTYPE
GetTypeInfoOfGuid(REFGUID guid
,
416 ITypeInfo
**ppTInfo
) override
418 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
420 SAL_INFO("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoOfGuid(" << guid
<< ")");
424 Reference
<ooo::vba::XConnectable
> xConnectable(mxOrigin
, UNO_QUERY
);
425 if (!xConnectable
.is())
426 return TYPE_E_ELEMENTNOTFOUND
;
429 if (SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(xConnectable
->getIID().pData
->buffer
), &aIID
)))
431 if (IsEqualIID(guid
, aIID
))
435 CComObject
<CXTypeInfo
>* pTypeInfo
;
437 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
443 pTypeInfo
->InitForCoclass(mxOrigin
, msImplementationName
, aIID
, mxMSF
);
445 *ppTInfo
= pTypeInfo
;
452 ooo::vba::TypeAndIID aTypeAndIID
= xConnectable
->GetConnectionPoint();
455 if (SUCCEEDED(IIDFromString((LPOLESTR
)aTypeAndIID
.IID
.pData
->buffer
, &aIID
)))
459 CComObject
<CXTypeInfo
>* pTypeInfo
;
461 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
467 pTypeInfo
->InitForOutgoing(mxOrigin
, msImplementationName
, aIID
, mxMSF
);
469 *ppTInfo
= pTypeInfo
;
474 SAL_WARN("extensions.olebridge", "Not implemented: GetTypeInfoOfGuid(" << guid
<< ")");
477 return TYPE_E_ELEMENTNOTFOUND
;
481 virtual HRESULT STDMETHODCALLTYPE
GetLibAttr(TLIBATTR
**) override
483 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetLibAttr: E_NOTIMPL");
487 virtual HRESULT STDMETHODCALLTYPE
GetTypeComp(ITypeComp
**) override
489 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeComp: E_NOTIMPL");
493 virtual HRESULT STDMETHODCALLTYPE
GetDocumentation(INT
,
499 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetDocumentation: E_NOTIMPL");
503 virtual HRESULT STDMETHODCALLTYPE
IsName(LPOLESTR
,
507 SAL_WARN("extensions.olebridge", this << "@CXTypeLib:IsName: E_NOTIMPL");
511 virtual HRESULT STDMETHODCALLTYPE
FindName(LPOLESTR
,
517 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::FindName: E_NOTIMPL");
521 virtual void STDMETHODCALLTYPE
ReleaseTLibAttr(TLIBATTR
*) override
523 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::ReleaseTLibAttr: E_NOTIMPL");
527 Reference
<XInterface
> mxOrigin
;
528 OUString msImplementationName
;
529 Reference
<XMultiServiceFactory
> mxMSF
;
534 void CXTypeInfo::InitForCoclass(Reference
<XInterface
> xOrigin
,
535 const OUString
& sImplementationName
,
537 Reference
<XMultiServiceFactory
> xMSF
)
539 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForCoclass(" << sImplementationName
<< "," << rIID
<< ")");
540 meKind
= Kind::COCLASS
;
542 msImplementationName
= sImplementationName
;
547 void CXTypeInfo::InitForClassItself(Reference
<XInterface
> xOrigin
,
548 const OUString
& sImplementationName
,
550 Reference
<XMultiServiceFactory
> xMSF
)
552 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForClassItself(" << sImplementationName
<< "," << rIID
<< ")");
555 msImplementationName
= sImplementationName
;
560 void CXTypeInfo::InitForOutgoing(Reference
<XInterface
> xOrigin
,
561 const OUString
& sInterfaceName
,
563 Reference
<XMultiServiceFactory
> xMSF
,
566 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForOutgoing(" << sInterfaceName
<< "," << rIID
<< ")");
567 meKind
= Kind::OUTGOING
;
569 msInterfaceName
= sInterfaceName
;
575 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetTypeAttr(TYPEATTR
**ppTypeAttr
)
577 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
579 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetTypeAttr");
584 assert(!IsEqualIID(maIID
, IID_NULL
));
586 TYPEATTR
*pTypeAttr
= new TYPEATTR
;
587 memset(pTypeAttr
, 0, sizeof(*pTypeAttr
));
589 pTypeAttr
->guid
= maIID
;
591 if (meKind
== Kind::COCLASS
)
593 pTypeAttr
->typekind
= TKIND_COCLASS
;
594 pTypeAttr
->cFuncs
= 0;
595 pTypeAttr
->cVars
= 0;
596 pTypeAttr
->cImplTypes
= 3;
597 pTypeAttr
->cbSizeVft
= 0;
598 pTypeAttr
->cbAlignment
= 8;
599 pTypeAttr
->wTypeFlags
= TYPEFLAG_FCANCREATE
;
601 else if (meKind
== Kind::MAIN
)
603 pTypeAttr
->typekind
= TKIND_DISPATCH
;
604 pTypeAttr
->cFuncs
= 10; // FIXME, dummy
605 pTypeAttr
->cVars
= 0;
606 pTypeAttr
->cImplTypes
= 1;
607 // FIXME: I think this is always supposed to be as if just for the seven methods in
609 pTypeAttr
->cbSizeVft
= 7 * sizeof(void*);
610 pTypeAttr
->cbAlignment
= 8;
611 pTypeAttr
->wTypeFlags
= TYPEFLAG_FHIDDEN
|TYPEFLAG_FDISPATCHABLE
;
613 else if (meKind
== Kind::OUTGOING
)
615 pTypeAttr
->typekind
= TKIND_DISPATCH
;
617 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
620 Reference
<XIdlClass
> xClass
= xRefl
->forName(maType
.getTypeName());
623 auto aMethods
= xClass
->getMethods();
624 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
625 aMethods
.getLength() > 0);
627 // Drop the three XInterface methods, add the three corresponding IUnknown ones plus the
628 // four IDispatch ones on top of that.
629 pTypeAttr
->cFuncs
= aMethods
.getLength() - 3 + 3 + 4;
630 pTypeAttr
->cVars
= 0;
631 pTypeAttr
->cImplTypes
= 1;
632 // FIXME: I think this, too, is always supposed to be as if just for the seven methods in
634 pTypeAttr
->cbSizeVft
= 7 * sizeof(void*);
635 pTypeAttr
->cbAlignment
= 8;
636 pTypeAttr
->wTypeFlags
= TYPEFLAG_FHIDDEN
|TYPEFLAG_FNONEXTENSIBLE
|TYPEFLAG_FDISPATCHABLE
;
641 pTypeAttr
->lcid
= LOCALE_USER_DEFAULT
;
642 pTypeAttr
->memidConstructor
= MEMBERID_NIL
;
643 pTypeAttr
->memidDestructor
= MEMBERID_NIL
;
644 // FIXME: Is this correct, just the vtable pointer, right?
645 pTypeAttr
->cbSizeInstance
= sizeof(void*);
646 pTypeAttr
->wMajorVerNum
= 0;
647 pTypeAttr
->wMinorVerNum
= 0;
648 pTypeAttr
->idldescType
.wIDLFlags
= IDLFLAG_NONE
;
650 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetTypeAttr: " << pTypeAttr
);
652 *ppTypeAttr
= pTypeAttr
;
657 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetTypeComp(ITypeComp
**)
659 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetTypeComp: E_NOTIMPL");
663 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetFuncDesc(UINT index
,
664 FUNCDESC
**ppFuncDesc
)
666 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
671 if (meKind
!= Kind::OUTGOING
)
676 *ppFuncDesc
= new FUNCDESC
;
677 (*ppFuncDesc
)->memid
= 0x60000000 + index
;
678 (*ppFuncDesc
)->lprgscode
= nullptr;
679 (*ppFuncDesc
)->lprgelemdescParam
= nullptr;
680 (*ppFuncDesc
)->funckind
= FUNC_DISPATCH
;
681 (*ppFuncDesc
)->invkind
= INVOKE_FUNC
;
682 (*ppFuncDesc
)->callconv
= CC_STDCALL
;
685 case 0: // QueryInterface
686 (*ppFuncDesc
)->cParams
= 2;
687 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
688 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
691 (*ppFuncDesc
)->cParams
= 0;
692 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
693 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_UI4
;
696 (*ppFuncDesc
)->cParams
= 1;
697 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
698 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_UI4
;
700 case 3: // GetTypeInfoCount
701 (*ppFuncDesc
)->cParams
= 1;
702 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
703 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
705 case 4: // GetTypeInfo
706 (*ppFuncDesc
)->cParams
= 3;
707 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
708 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
710 case 5: // GetIDsOfNames
711 (*ppFuncDesc
)->cParams
= 5;
712 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
713 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
716 (*ppFuncDesc
)->cParams
= 8;
717 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
718 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
721 (*ppFuncDesc
)->cParamsOpt
= 0;
722 (*ppFuncDesc
)->oVft
= index
* sizeof(void*);
723 (*ppFuncDesc
)->cScodes
= 0;
724 (*ppFuncDesc
)->wFuncFlags
= FUNCFLAG_FRESTRICTED
;
726 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetFuncDesc(" << index
<< "): S_OK: " << *ppFuncDesc
);
731 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
734 Reference
<XIdlClass
> xClass
= xRefl
->forName(maType
.getTypeName());
737 auto aMethods
= xClass
->getMethods();
738 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
739 aMethods
.getLength() > 0);
741 if (index
> o3tl::make_unsigned(aMethods
.getLength() - 3 + 3 + 4))
744 *ppFuncDesc
= new FUNCDESC
;
746 (*ppFuncDesc
)->memid
= index
- 6;
747 (*ppFuncDesc
)->lprgscode
= nullptr;
748 (*ppFuncDesc
)->lprgelemdescParam
= nullptr;
749 (*ppFuncDesc
)->funckind
= FUNC_DISPATCH
;
750 (*ppFuncDesc
)->invkind
= INVOKE_FUNC
;
751 (*ppFuncDesc
)->callconv
= CC_STDCALL
;
752 (*ppFuncDesc
)->cParams
= aMethods
[index
- 4]->getParameterInfos().getLength();
753 (*ppFuncDesc
)->cParamsOpt
= 0;
754 (*ppFuncDesc
)->oVft
= index
* sizeof(void*);
755 (*ppFuncDesc
)->cScodes
= 0;
756 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr; // ???
757 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
; // ???
758 (*ppFuncDesc
)->wFuncFlags
= 0;
760 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetFuncDesc(" << index
<< "): S_OK: " << *ppFuncDesc
);
765 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetVarDesc(UINT
,
768 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetVarDesc: E_NOTIMPL");
772 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetNames(MEMBERID memid
,
777 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
779 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetNames(" << memid
<< ")");
780 assert(meKind
!= Kind::COCLASS
);
794 if (meKind
== Kind::MAIN
)
796 SAL_WARN("extensions.olebridge", "GetNames() for MAIN not implemented");
800 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
803 Reference
<XIdlClass
> xClass
= xRefl
->forName(maType
.getTypeName());
806 auto aMethods
= xClass
->getMethods();
807 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
808 aMethods
.getLength() > 0);
810 // Subtract the three XInterface methods. Memid for the first following method is 1.
811 if (memid
> aMethods
.getLength() - 3)
814 SAL_INFO("extensions.olebridge", "..." << this << "@CXTypeInfo::GetNames(" << memid
<< "): " << aMethods
[memid
+ 2]->getName());
815 rgBstrNames
[0] = sal::systools::BStr::newBSTR(aMethods
[memid
+ 2]->getName());
821 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetRefTypeOfImplType(UINT index
,
824 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetRefTypeOfImplType(" << index
<< ")");
829 assert(index
== 0 || index
== 1);
831 *pRefType
= 1000+index
;
836 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetImplTypeFlags(UINT index
,
839 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
841 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetImplTypeFlags(" << index
<< ")");
846 assert(meKind
== Kind::COCLASS
);
847 assert(index
== 0 || index
== 1);
850 *pImplTypeFlags
= IMPLTYPEFLAG_FDEFAULT
;
852 *pImplTypeFlags
= IMPLTYPEFLAG_FDEFAULT
|IMPLTYPEFLAG_FSOURCE
;
857 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetIDsOfNames(LPOLESTR
*,
861 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetIDsOfNames: E_NOTIMPL");
865 HRESULT STDMETHODCALLTYPE
CXTypeInfo::Invoke(PVOID
,
873 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::Invoke: E_NOTIMPL");
877 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetDocumentation(MEMBERID memid
,
879 BSTR
*pBstrDocString
,
880 DWORD
*pdwHelpContext
,
883 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
885 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetDocumentation(" << memid
<< ")");
889 if (memid
== MEMBERID_NIL
)
891 *pBstrName
= sal::systools::BStr::newBSTR(msImplementationName
);
893 else if (memid
== DISPID_VALUE
)
895 // MEMBERIDs are the same as DISPIDs, apparently?
896 *pBstrName
= SysAllocString(L
"Value");
900 // FIXME: Shouldn't we be able to know the names of the members of UNO interfaces?
901 *pBstrName
= sal::systools::BStr::newBSTR(Concat2View("UnknownNameOfMember#" + OUString::number(memid
)));
905 *pBstrDocString
= SysAllocString(L
"");
909 *pBstrHelpFile
= nullptr;
914 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetDllEntry(MEMBERID
,
920 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetDllEntry: E_NOTIMPL");
924 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetRefTypeInfo(HREFTYPE hRefType
,
927 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
929 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetRefTypeInfo(" << hRefType
<< ")");
934 // FIXME: Is it correct to assume that the only interfaces on which GetRefTypeInfo() would be
935 // called are those that implement ooo::vba::XConnectable?
937 Reference
<ooo::vba::XConnectable
> xConnectable(mxOrigin
, UNO_QUERY
);
938 if (!xConnectable
.is())
941 ooo::vba::TypeAndIID aTypeAndIID
= xConnectable
->GetConnectionPoint();
944 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(aTypeAndIID
.IID
.pData
->buffer
), &aIID
)))
949 CComObject
<CXTypeInfo
>* pTypeInfo
;
951 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
957 pTypeInfo
->InitForOutgoing(mxOrigin
, aTypeAndIID
.Type
.getTypeName(), aIID
, mxMSF
, aTypeAndIID
.Type
);
959 *ppTInfo
= pTypeInfo
;
964 HRESULT STDMETHODCALLTYPE
CXTypeInfo::AddressOfMember(MEMBERID
,
968 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::AddressOfMember: E_NOTIMPL");
972 HRESULT STDMETHODCALLTYPE
CXTypeInfo::CreateInstance(IUnknown
*,
976 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::CreateInstance: E_NOTIMPL");
980 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetMops(MEMBERID
,
983 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetMops: E_NOTIMPL");
987 // This is not actually called any more by my vbscript test after I added the IProvideClassInfo
988 // thing... so all the CXTypeLib stuff is dead code at the moment.
990 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetContainingTypeLib(ITypeLib
**ppTLib
,
993 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
995 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetContainingTypeLib");
997 if (!ppTLib
|| !pIndex
)
1002 CComObject
<CXTypeLib
>* pTypeLib
;
1004 ret
= CComObject
<CXTypeLib
>::CreateInstance(&pTypeLib
);
1010 pTypeLib
->Init(mxOrigin
, msImplementationName
, mxMSF
);
1017 void STDMETHODCALLTYPE
CXTypeInfo::ReleaseTypeAttr(TYPEATTR
*pTypeAttr
)
1019 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::ReleaseTypeAttr(" << pTypeAttr
<< ")");
1024 void STDMETHODCALLTYPE
CXTypeInfo::ReleaseFuncDesc(FUNCDESC
*pFuncDesc
)
1026 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::ReleaseFuncDesc(" << pFuncDesc
<< ")");
1031 void STDMETHODCALLTYPE
CXTypeInfo::ReleaseVarDesc(VARDESC
*)
1033 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::ReleaseVarDesc: E_NOTIMPL");
1036 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::GetTypeInfo(UINT iTInfo
, LCID
, ITypeInfo
** ppTInfo
)
1038 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
1040 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetTypeInfo(" << iTInfo
<< ")");
1048 // FIXME: This is surely incorrect. Why is being able to handle GetTypeInfo() here coupled to
1049 // being a source for outgoing events, i.e. implementing XConnectable? What would break if we
1050 // would use XInterfaceWithIID and its getIID instead?
1052 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
1053 if (!xConnectable
.is())
1056 OUString sIID
= xConnectable
->GetIIDForClassItselfNotCoclass();
1058 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(sIID
.pData
->buffer
), &aIID
)))
1063 CComObject
<CXTypeInfo
>* pTypeInfo
;
1065 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
1069 pTypeInfo
->AddRef();
1071 pTypeInfo
->InitForClassItself(m_xOrigin
, m_sImplementationName
, aIID
, m_smgr
);
1073 *ppTInfo
= pTypeInfo
;
1078 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::GetIDsOfNames(REFIID
/*riid*/,
1079 LPOLESTR
* rgszNames
,
1084 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
1089 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetIDsOfNames:");
1090 for (unsigned int i
= 0; i
< cNames
; ++i
)
1092 // Initialise returned rgdispid values.
1093 rgdispid
[i
] = DISPID_UNKNOWN
;
1095 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames
[i
])));
1098 HRESULT ret
= DISP_E_UNKNOWNNAME
;
1101 MutexGuard
guard( getBridgeMutex());
1103 // FIXME: Handle the cNames > 1 case? Note that the rest of the names mean the names of *arguments*.
1105 if( ! _wcsicmp( *rgszNames
, JSCRIPT_VALUE_FUNC
) ||
1106 ! _wcsicmp( *rgszNames
, BRIDGE_VALUE_FUNC
))
1108 *rgdispid
= DISPID_JSCRIPT_VALUE_FUNC
;
1111 else if( ! _wcsicmp( *rgszNames
, GET_STRUCT_FUNC
) ||
1112 ! _wcsicmp( *rgszNames
, BRIDGE_GET_STRUCT_FUNC
))
1114 *rgdispid
= DISPID_GET_STRUCT_FUNC
;
1117 else if( ! _wcsicmp( *rgszNames
, BRIDGE_CREATE_TYPE_FUNC
))
1119 *rgdispid
= DISPID_CREATE_TYPE_FUNC
;
1123 if (m_xInvocation
.is() && (cNames
> 0))
1125 OUString
name(o3tl::toU(rgszNames
[0]));
1126 NameToIdMap::iterator iter
= m_nameToDispIdMap
.find(name
);
1128 bool bIsMethod
= false;
1130 OUString exactName
= name
;
1132 if (iter
== m_nameToDispIdMap
.end())
1134 if (m_xExactName
.is())
1136 exactName
= m_xExactName
->getExactName(name
);
1137 if (exactName
.isEmpty())
1141 MemberInfo
d(0, exactName
);
1143 if (m_xInvocation
->hasProperty(exactName
))
1145 d
.flags
|= DISPATCH_PROPERTYGET
;
1146 d
.flags
|= DISPATCH_PROPERTYPUT
;
1147 d
.flags
|= DISPATCH_PROPERTYPUTREF
;
1150 if (m_xInvocation
->hasMethod(exactName
))
1152 d
.flags
|= DISPATCH_METHOD
;
1158 m_MemberInfos
.push_back(d
);
1159 iter
= m_nameToDispIdMap
.emplace(exactName
, static_cast<DISPID
>(m_MemberInfos
.size())).first
;
1161 if (exactName
!= name
)
1163 iter
= m_nameToDispIdMap
.emplace(name
, static_cast<DISPID
>(m_MemberInfos
.size())).first
;
1168 if (iter
== m_nameToDispIdMap
.end())
1170 ret
= DISP_E_UNKNOWNNAME
;
1171 SAL_INFO("extensions.olebridge", " " << name
<< ": UNKNOWN");
1175 rgdispid
[0] = (*iter
).second
;
1176 SAL_INFO("extensions.olebridge", " " << name
<< ": " << rgdispid
[0]);
1178 if (bIsMethod
&& cNames
> 1)
1180 Reference
<XIdlMethod
> xIdlMethod
;
1181 Reference
<XIntrospectionAccess
> xIntrospectionAccess
= m_xInvocation
->getIntrospection();
1184 if (xIntrospectionAccess
.is())
1185 xIdlMethod
= xIntrospectionAccess
->getMethod(exactName
, MethodConcept::ALL
);
1187 catch (const NoSuchMethodException
&)
1190 if (xIdlMethod
.is())
1192 auto aParamInfos
= xIdlMethod
->getParameterInfos();
1193 for (unsigned int i
= 1; i
< cNames
; ++i
)
1195 bool bFound
= false;
1196 for (int j
= 0; j
< aParamInfos
.getLength(); ++j
)
1198 if (aParamInfos
[j
].aName
.equalsIgnoreAsciiCase(o3tl::toU(rgszNames
[i
])))
1202 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames
[i
])) << ": " << rgdispid
[i
]);
1207 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames
[i
])) << ": NOT FOUND");
1212 // Return value should be S_OK only if *all* the names were found.
1214 for (i
= 0; i
< cNames
; ++i
)
1215 if (rgdispid
[i
] == DISPID_UNKNOWN
)
1222 catch(const BridgeRuntimeError
&)
1226 catch(const Exception
&)
1238 // Note: What the comments here say about JScript possibly holds for Automation clients in general,
1239 // like VBScript ones, too. Or not. Hard to say. What is the relevance of JScript nowadays anyway,
1240 // and can LO really be used from JScript code on web pages any longer?
1242 // "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts
1243 // The parameters "id", "wFlags" and "pdispparams" equal those as used in
1244 // IDispatch::Invoke. The function handles special JavaScript
1245 // cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent
1246 // an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object)
1247 // parameter (JavaScript Array object)
1248 // Because all those VT_DISPATCH objects need a different conversion
1249 // we have to find out what the object is supposed to be. The function does this
1250 // by either using type information or by help of a specialized ValueObject object.
1252 // A. Type Information
1254 // With the help of type information the kind of parameter can be exactly determined
1255 // and an appropriate conversion can be chosen. A problem arises if a method expects
1256 // an Any. Then the type info does not tell what the type of the value, that is kept
1257 // by the any, should be. In this situation the decision whether the param is a
1258 // sequence or an object is made upon the fact if the object has a property "0"
1259 // ( see function "isJScriptArray"). Since this is unsafe it is recommended to use
1260 // the JScript value objects within a JScript script on such an occasion.
1262 // B. JavaScript Value Object ( class JScriptValue )
1264 // A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the
1265 // IJScriptValue object interface. Such objects are provided by all UNO wrapper
1266 // objects used within a JScript script. To obtain an instance one has to call
1267 // "_GetValueObject() or Bridge_GetValueObject()" on a UNO wrapper object (class InterfaceOleWrapper).
1268 // A value object is appropriately initialized within the script and passed as
1269 // parameter to a UNO object method or property. The convertDispparamsArgs function
1270 // can easily find out that a param is such an object by querying for the
1271 // IJScriptValue interface. By this interface one the type and kind ( out, in/out)
1272 // can be determined and the right conversion can be applied.
1273 // Using ValueObjects we spare us the effort of acquiring and examining type information
1274 // in order to figure out what the an IDispatch parameter is meant for.
1276 // Normal JScript object parameter can be mixed with JScriptValue object. If an
1277 // VARIANT contains a VT_DISPATCH that is no JScriptValue than the type information
1278 // is used to find out about the required type.
1279 void InterfaceOleWrapper::convertDispparamsArgs(DISPID id
,
1280 unsigned short /*wFlags*/, DISPPARAMS
* pdispparams
, Sequence
<Any
>& rSeq
)
1282 // Parameters come in reverse order in pdispparams. There might be less parameters than
1283 // expected. In that case, assume they are "optional" (but can't be marked as such in UNO IDL),
1284 // and fill in the rest with empty Anys. There might also be more than expected. In that case,
1285 // assume the oovbaapi UNO IDL hasn't kept up with added optional parameters in MSO, and just
1286 // ignore the extra ones, as long as they are empty.
1288 // An example: incoming parameters: <12, 13, "foo/bar.tem">
1290 // Expected parameters: (string filename, int something, int somethingElse, Any whatever, Any
1293 // Here the existing incoming parameters are placed in reverse order in the first three outgoing
1294 // parameters, and the rest of the outgoing parameters are kept as empty Anys.
1296 // Another example: incoming parameters: <EMPTY, TRUE>
1298 // Expected parameters: (bool flag)
1300 // Here the TRUE is passed as the sole outgoing parameter, and the incoming EMPTY is ignored.
1302 // Still an example: incoming parameters: <"foo.doc", TRUE>
1304 // Expected parameters: (bool flag)
1306 // This throws an error as the incoming string parameter presumably should do something important,
1307 // but there is no corresponding outgoing parameter.
1310 const int countIncomingArgs
= pdispparams
->cArgs
;
1312 //Get type information for the current call
1313 InvocationInfo info
;
1314 if( ! getInvocationInfoForCall( id
, info
))
1315 throw BridgeRuntimeError(
1316 "[automation bridge]InterfaceOleWrapper::convertDispparamsArgs \n"
1317 "Could not obtain type information for current call.");
1319 // Size rSeq according to the number of expected parameters.
1320 const int expectedArgs
= info
.aParamTypes
.getLength() + (info
.eMemberType
== MemberType_PROPERTY
? 1 : 0);
1321 rSeq
.realloc( expectedArgs
);
1322 Any
* pParams
= rSeq
.getArray();
1326 int outgoingArgIndex
= 0;
1328 // Go through incoming parameters in reverse order, i.e. in the order as declared in IDL
1329 for (int i
= std::max(countIncomingArgs
, expectedArgs
) - 1; i
>= 0; i
--)
1331 // Ignore too many parameters if they are VT_EMPTY anyway
1332 if ( outgoingArgIndex
>= expectedArgs
&& pdispparams
->rgvarg
[i
].vt
== VT_EMPTY
)
1335 // But otherwise too many parameters is an error
1336 if ( outgoingArgIndex
>= expectedArgs
)
1337 throw BridgeRuntimeError( "[automation bridge] Too many parameters" );
1339 if (info
.eMemberType
== MemberType_METHOD
&&
1340 info
.aParamModes
[ outgoingArgIndex
] == ParamMode_OUT
)
1346 if (i
< countIncomingArgs
)
1348 // A missing (and hopefully optional) arg (in the middle of the argument list) is passed
1350 if (pdispparams
->rgvarg
[i
].vt
== VT_ERROR
&& pdispparams
->rgvarg
[i
].scode
== DISP_E_PARAMNOTFOUND
)
1353 pParams
[ outgoingArgIndex
] = aEmpty
;
1358 if(convertValueObject( & pdispparams
->rgvarg
[i
], anyParam
))
1359 { //a param is a ValueObject and could be converted
1360 pParams
[ outgoingArgIndex
] = anyParam
;
1367 // A missing arg. Let's hope it is de facto optional (there is no way in UNO IDL to mark
1368 // a parameter as optional). The corresponding slot in pParams is already a void Any.
1369 // Here we don't increase outgoingArgIndex!
1373 // If the param is an out, in/out parameter in
1374 // JScript (Array object, with value at index 0) then we
1375 // extract Array[0] and put the value into varParam. At the end of the loop varParam
1376 // is converted if it contains a value otherwise the VARIANT from
1377 // DISPPARAMS is converted.
1378 CComVariant varParam
;
1380 // Check for JScript out and in/out paramsobjects (VT_DISPATCH).
1381 // To find them out we use typeinformation of the function being called.
1383 // No idea how this stuff, originally written for JScript, works for other Automation
1386 if( pdispparams
->rgvarg
[i
].vt
== VT_DISPATCH
)
1388 if( info
.eMemberType
== MemberType_METHOD
&& info
.aParamModes
[ outgoingArgIndex
] == ParamMode_INOUT
)
1391 // Index ( property) "0" contains the actual IN-param. The object is a JScript
1393 // Get the IN-param at index "0"
1394 IDispatch
* pdisp
= pdispparams
->rgvarg
[i
].pdispVal
;
1396 OLECHAR
const * sindex
= L
"0";
1398 DISPPARAMS noParams
= {nullptr,nullptr,0,0};
1399 if(SUCCEEDED( hr
= pdisp
->GetIDsOfNames( IID_NULL
, const_cast<OLECHAR
**>(&sindex
), 1, LOCALE_USER_DEFAULT
, &id2
)))
1400 hr
= pdisp
->Invoke( id2
, IID_NULL
, LOCALE_USER_DEFAULT
, DISPATCH_PROPERTYGET
,
1401 & noParams
, & varParam
, nullptr, nullptr);
1404 throw BridgeRuntimeError(
1405 "[automation bridge] Could not determine "
1406 "if the object has a member \"0\". Error: " +
1407 OUString::number(hr
));
1412 if( varParam
.vt
== VT_EMPTY
) // then it was no in/out parameter
1413 varParam
= pdispparams
->rgvarg
[i
];
1415 if(info
.eMemberType
== MemberType_METHOD
)
1416 variantToAny( & varParam
, anyParam
,
1417 info
.aParamTypes
[ outgoingArgIndex
]);
1418 else if(info
.eMemberType
== MemberType_PROPERTY
)
1419 variantToAny( & varParam
, anyParam
, info
.aType
);
1423 if (outgoingArgIndex
< expectedArgs
)
1424 pParams
[ outgoingArgIndex
]= anyParam
;
1426 }// end for / iterating over all parameters
1429 bool InterfaceOleWrapper::getInvocationInfoForCall( DISPID id
, InvocationInfo
& info
)
1431 bool bTypesAvailable
= false;
1433 if( !m_xInvocation
.is() )return false;
1434 Reference
<XInvocation2
> inv2( m_xInvocation
, UNO_QUERY
);
1437 // We need the name of the property or method to get its type information.
1438 // The name can be identified through the param "id"
1439 // that is kept as value in the map m_nameToDispIdMap.
1440 // Problem: the Windows JScript engine sometimes changes small letters to capital
1441 // letters as happens in xidlclass_obj.createObject( var) // in JScript.
1442 // IDispatch::GetIdsOfNames is then called with "CreateObject" !!!
1443 // m_nameToDispIdMap can contain several names for one DISPID but only one is
1444 // the exact one. If there's no m_xExactName and therefore no exact name then
1445 // there's only one entry in the map.
1446 OUString sMemberName
;
1448 auto ci1
= std::find_if(m_nameToDispIdMap
.cbegin(), m_nameToDispIdMap
.cend(),
1449 [&id
](const NameToIdMap::value_type
& nameToDispId
) { return nameToDispId
.second
== id
; }); // item is a pair<OUString, DISPID>
1450 if (ci1
!= m_nameToDispIdMap
.cend())
1451 sMemberName
= (*ci1
).first
;
1452 // Get information for the current call ( property or method).
1453 // There could be similar names which only differ in the cases
1454 // of letters. First we assume that the name which was passed into
1455 // GetIDsOfNames is correct. If we won't get information with that
1456 // name then we have the invocation service use the XExactName interface.
1457 bool validInfo
= true;
1458 InvocationInfo invInfo
;
1460 invInfo
= inv2
->getInfoForName( sMemberName
, false);
1462 catch(const IllegalArgumentException
&)
1469 invInfo
= inv2
->getInfoForName( sMemberName
, true);
1471 if( invInfo
.aName
.pData
)
1473 bTypesAvailable
= true;
1477 return bTypesAvailable
;
1480 // XBridgeSupplier2 ---------------------------------------------------
1481 // only bridges itself ( this instance of InterfaceOleWrapper)from UNO to IDispatch
1482 // If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper
1483 // can bridged to IDispatch ( if destModelType == OLE). The IDispatch is
1484 // implemented by this class.
1485 Any SAL_CALL
InterfaceOleWrapper::createBridge(const Any
& modelDepObject
,
1486 const Sequence
<sal_Int8
>& /*ProcessId*/,
1487 sal_Int16 sourceModelType
,
1488 sal_Int16 destModelType
)
1492 if( sourceModelType
== UNO
&& destModelType
== OLE
&&
1493 modelDepObject
.getValueTypeClass() == TypeClass_INTERFACE
)
1495 Reference
<XInterface
> xInt
;
1496 if( modelDepObject
>>= xInt
)
1498 if( xInt
== Reference
<XInterface
>( static_cast<XWeak
*>( this), UNO_QUERY
))
1500 VARIANT
*pVar
= static_cast<VARIANT
*>(CoTaskMemAlloc( sizeof( VARIANT
)));
1503 pVar
->vt
= VT_DISPATCH
;
1504 pVar
->pdispVal
= this;
1507 retAny
<<= reinterpret_cast< sal_uIntPtr
>( pVar
);
1516 // XInitialization --------------------------------------------------
1517 void SAL_CALL
InterfaceOleWrapper::initialize( const Sequence
< Any
>& aArguments
)
1519 switch( aArguments
.getLength() )
1521 case 2: // the object wraps a UNO struct
1522 aArguments
[0] >>= m_xInvocation
;
1523 aArguments
[1] >>= m_defaultValueType
;
1525 case 3: // the object wraps a UNO interface
1526 aArguments
[0] >>= m_xInvocation
;
1527 aArguments
[1] >>= m_xOrigin
;
1528 aArguments
[2] >>= m_defaultValueType
;
1530 Reference
<XServiceInfo
> xServiceInfo(m_xOrigin
, UNO_QUERY
);
1531 if (xServiceInfo
.is())
1532 m_sImplementationName
= xServiceInfo
->getImplementationName();
1534 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::initialize for "
1535 << (m_sImplementationName
.isEmpty()?"an unknown implementation":m_sImplementationName
));
1539 m_xExactName
.set( m_xInvocation
, UNO_QUERY
);
1542 Reference
< XInterface
> InterfaceOleWrapper::createUnoWrapperInstance()
1544 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper(
1545 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1546 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1549 Reference
<XInterface
> InterfaceOleWrapper::createComWrapperInstance()
1551 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper(
1552 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1553 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1556 // "getType" is used in convertValueObject to map the string denoting the type
1557 // to an actual Type object.
1558 bool getType( const BSTR name
, Type
& type
)
1561 typelib_TypeDescription
* pDesc
= nullptr;
1562 OUString
str(o3tl::toU(name
));
1563 typelib_typedescription_getByName( &pDesc
, str
.pData
);
1566 type
= Type( pDesc
->pWeakRef
);
1567 typelib_typedescription_release( pDesc
);
1573 static bool writeBackOutParameter2( VARIANTARG
* pDest
, VARIANT
* pSource
)
1578 // Handle JScriptValue objects and JScript out params ( Array object )
1579 CComVariant
varDest( *pDest
);
1581 if( SUCCEEDED( varDest
.ChangeType(VT_DISPATCH
)))
1583 CComPtr
<IDispatch
> spDispDest(varDest
.pdispVal
);
1585 // special Handling for a JScriptValue object
1586 CComQIPtr
<IJScriptValueObject
> spValueDest(spDispDest
);
1589 VARIANT_BOOL varBool
= VARIANT_FALSE
;
1590 if ((SUCCEEDED(hr
= spValueDest
->IsOutParam(&varBool
))
1591 && varBool
== VARIANT_TRUE
)
1592 || (SUCCEEDED(hr
= spValueDest
->IsInOutParam(&varBool
))
1593 && varBool
== VARIANT_TRUE
))
1595 if( SUCCEEDED( spValueDest
->Set( CComVariant(), *pSource
)))
1599 else if (pDest
->vt
== VT_DISPATCH
)// VT_DISPATCH -> JScript out param
1601 // We use IDispatchEx because its GetDispID function causes the creation
1602 // of a property if it does not exist already. This is convenient for
1603 // out parameters in JScript. Then the user must not specify property "0"
1605 CComQIPtr
<IDispatchEx
> spDispEx( spDispDest
);
1608 CComBSTR
nullProp(L
"0");
1610 if( SUCCEEDED( spDispEx
->GetDispID( nullProp
, fdexNameEnsure
, &dwDispID
)))
1612 DISPPARAMS dispparams
= {nullptr, nullptr, 1, 1};
1613 dispparams
.rgvarg
= pSource
;
1614 DISPID dispidPut
= DISPID_PROPERTYPUT
;
1615 dispparams
.rgdispidNamedArgs
= &dispidPut
;
1617 if (pSource
->vt
== VT_UNKNOWN
|| pSource
->vt
== VT_DISPATCH
||
1618 (pSource
->vt
& VT_ARRAY
) || (pSource
->vt
& VT_BYREF
))
1619 hr
= spDispEx
->InvokeEx(dwDispID
, LOCALE_USER_DEFAULT
, DISPATCH_PROPERTYPUTREF
,
1620 &dispparams
, nullptr, nullptr, nullptr);
1622 hr
= spDispEx
->InvokeEx(dwDispID
, LOCALE_USER_DEFAULT
, DISPATCH_PROPERTYPUT
,
1623 &dispparams
, nullptr, nullptr, nullptr);
1630 ret
= writeBackOutParameter( pDest
, pSource
);
1632 else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript
1633 { // param. The function checks itself for correct VBScript params
1634 ret
= writeBackOutParameter( pDest
, pSource
);
1639 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter.
1640 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT
1641 // Please note: VariantCopy doesn't free a VT_BYREF value
1642 // The out parameters are expected to have always a valid type
1643 static bool writeBackOutParameter(VARIANTARG
* pDest
, VARIANT
* pSource
)
1647 // Out parameter must be VT_BYREF
1648 if ((V_VT(pDest
) & VT_BYREF
) != 0 )
1650 VARTYPE oleTypeFlags
= V_VT(pSource
);
1652 // if caller accept VARIANT as out parameter, any value must be converted
1653 if (V_VT(pDest
) == (VT_VARIANT
| VT_BYREF
))
1655 // When the user provides a VARIANT rather than a concrete type
1656 // we just copy the source to the out, in/out parameter
1657 // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that
1658 // is contained in pDest are released by VariantCopy
1659 VariantCopy(V_VARIANTREF(pDest
), pSource
);
1664 // variantarg and variant must have same type
1665 if ((V_VT(pDest
) & oleTypeFlags
) == oleTypeFlags
)
1667 if ((oleTypeFlags
& VT_ARRAY
) != 0)
1670 if( *V_ARRAYREF(pDest
) != nullptr)
1671 hr
= SafeArrayCopyData( V_ARRAY(pSource
), *V_ARRAYREF(pDest
));
1674 hr
= SafeArrayCopy(V_ARRAY(pSource
), V_ARRAYREF(pDest
));
1681 switch (V_VT(pSource
))
1685 *V_I2REF(pDest
) = V_I2(pSource
);
1690 *V_I4REF(pDest
) = V_I4(pSource
);
1694 *V_R4REF(pDest
) = V_R4(pSource
);
1698 *V_R8REF(pDest
) = V_R8(pSource
);
1702 *V_CYREF(pDest
) = V_CY(pSource
);
1706 *V_DATEREF(pDest
) = V_DATE(pSource
);
1710 SysFreeString( *pDest
->pbstrVal
);
1712 *V_BSTRREF(pDest
) = SysAllocString(V_BSTR(pSource
));
1716 if (*V_DISPATCHREF(pDest
) != nullptr)
1717 (*V_DISPATCHREF(pDest
))->Release();
1719 *V_DISPATCHREF(pDest
) = V_DISPATCH(pSource
);
1721 if (*V_DISPATCHREF(pDest
) != nullptr)
1722 (*V_DISPATCHREF(pDest
))->AddRef();
1727 *V_ERRORREF(pDest
) = V_ERROR(pSource
);
1731 *V_BOOLREF(pDest
) = V_BOOL(pSource
);
1735 if (*V_UNKNOWNREF(pDest
) != nullptr)
1736 (*V_UNKNOWNREF(pDest
))->Release();
1738 *V_UNKNOWNREF(pDest
) = V_UNKNOWN(pSource
);
1740 if (*V_UNKNOWNREF(pDest
) != nullptr)
1741 (*V_UNKNOWNREF(pDest
))->AddRef();
1746 *V_I1REF(pDest
) = V_I1(pSource
);
1750 *V_UI1REF(pDest
) = V_UI1(pSource
);
1754 *V_UI2REF(pDest
) = V_UI2(pSource
);
1758 *V_UI4REF(pDest
) = V_UI4(pSource
);
1762 *V_INTREF(pDest
) = V_INT(pSource
);
1766 *V_UINTREF(pDest
) = V_UINT(pSource
);
1770 memcpy(pDest
->pdecVal
, pSource
, sizeof(DECIMAL
));
1780 // Handling of special cases
1781 // Destination and source types are different
1782 if( pDest
->vt
== (VT_BSTR
| VT_BYREF
)
1783 && pSource
->vt
== VT_I2
)
1785 // When the user provides a String as out our in/out parameter
1786 // and the type is char (TypeClass_CHAR) then we convert to a BSTR
1787 // instead of VT_I2 as is done otherwise
1788 OLECHAR buff
[]= {0,0};
1789 buff
[0]= pSource
->iVal
;
1791 SysFreeString( *pDest
->pbstrVal
);
1792 *pDest
->pbstrVal
= SysAllocString( buff
);
1801 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::Invoke(DISPID dispidMember
,
1805 DISPPARAMS
* pdispparams
,
1806 VARIANT
* pvarResult
,
1807 EXCEPINFO
* pexcepinfo
,
1810 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
1813 #if defined SAL_LOG_INFO
1815 for (unsigned int i
= 0; i
< pdispparams
->cArgs
; ++i
)
1819 std::stringstream aStringStream
;
1820 aStringStream
<< pdispparams
->rgvarg
[i
];
1821 sParams
+= OUString::createFromAscii(aStringStream
.str());
1825 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::Invoke(" << dispidMember
<< "," << sParams
<< ")");
1827 comphelper::ProfileZone
aZone("COM Bridge");
1832 bool bHandled
= false;
1833 ret
= InvokeGeneral( dispidMember
, wFlags
, pdispparams
, pvarResult
, pexcepinfo
,
1834 puArgErr
, bHandled
);
1838 if ((dispidMember
> 0) && (o3tl::make_unsigned(dispidMember
) <= m_MemberInfos
.size()) && m_xInvocation
.is())
1840 MemberInfo d
= m_MemberInfos
[dispidMember
- 1];
1841 DWORD flags
= wFlags
& d
.flags
;
1845 if ((flags
& DISPATCH_METHOD
) != 0)
1847 std::unique_ptr
<DISPPARAMS
> pNewDispParams
;
1848 std::vector
<VARIANTARG
> vNewArgs
;
1850 if (pdispparams
->cNamedArgs
> 0)
1852 // Convert named arguments to positional ones.
1856 // Function declaration (in pseudo-code):
1857 // int foo(int A, int B, optional int C, optional int D, optional int E, optional int F, optional int G)
1859 // Corresponding parameter numbers (DISPIDs):
1863 // foo(10, 20, E:=50, D:=40, F:=60)
1865 // That is, A and B are passed positionally, D, E, and F as named arguments,
1866 // and the optional C and G parameters are left out.
1868 // Incoming DISPPARAMS:
1869 // cArgs=5, cNamedArgs=3
1870 // rgvarg: [60, 40, 50, 20, 10]
1871 // rgdispidNamedArgs: [5, 3, 4]
1873 // We calculate nLowestNamedArgDispid = 3 and nHighestNamedArgDispid = 5.
1875 // Result of conversion, no named args:
1876 // cArgs=6, cNamedArgs=0
1877 // rgvarg: [60, 50, 40, DISP_E_PARAMNOTFOUND, 20, 10]
1879 // First find the lowest and highest DISPID of the named arguments.
1880 DISPID nLowestNamedArgDispid
= 1000000;
1881 DISPID nHighestNamedArgDispid
= -1;
1882 for (unsigned int i
= 0; i
< pdispparams
->cNamedArgs
; ++i
)
1884 if (pdispparams
->rgdispidNamedArgs
[i
] < nLowestNamedArgDispid
)
1885 nLowestNamedArgDispid
= pdispparams
->rgdispidNamedArgs
[i
];
1886 if (pdispparams
->rgdispidNamedArgs
[i
] > nHighestNamedArgDispid
)
1887 nHighestNamedArgDispid
= pdispparams
->rgdispidNamedArgs
[i
];
1890 // Make sure named arguments don't overlap with positional ones. The lowest
1891 // DISPID of the named arguments should be >= the number of positional
1893 if (nLowestNamedArgDispid
< static_cast<DISPID
>(pdispparams
->cArgs
- pdispparams
->cNamedArgs
))
1894 return DISP_E_NONAMEDARGS
;
1896 // Do the actual conversion.
1897 pNewDispParams
.reset(new DISPPARAMS
);
1898 vNewArgs
.resize(nHighestNamedArgDispid
+ 1);
1899 pNewDispParams
->rgvarg
= vNewArgs
.data();
1900 pNewDispParams
->rgdispidNamedArgs
= nullptr;
1901 pNewDispParams
->cArgs
= nHighestNamedArgDispid
+ 1;
1902 pNewDispParams
->cNamedArgs
= 0;
1904 // Initialise all parameter slots as missing
1905 for (int i
= 0; i
< nHighestNamedArgDispid
; ++i
)
1907 pNewDispParams
->rgvarg
[i
].vt
= VT_ERROR
;
1908 pNewDispParams
->rgvarg
[i
].scode
= DISP_E_PARAMNOTFOUND
;
1911 // Then set the value of those actually present.
1912 for (unsigned int i
= 0; i
< pdispparams
->cNamedArgs
; ++i
)
1913 pNewDispParams
->rgvarg
[nHighestNamedArgDispid
- pdispparams
->rgdispidNamedArgs
[i
]] = pdispparams
->rgvarg
[i
];
1915 const int nFirstUnnamedArg
= pdispparams
->cNamedArgs
+ (nLowestNamedArgDispid
-(pdispparams
->cArgs
- pdispparams
->cNamedArgs
));
1917 for (unsigned int i
= pdispparams
->cNamedArgs
; i
< pdispparams
->cArgs
; ++i
)
1918 pNewDispParams
->rgvarg
[nFirstUnnamedArg
+ (i
-pdispparams
->cNamedArgs
)] = pdispparams
->rgvarg
[i
];
1920 pdispparams
= pNewDispParams
.get();
1923 Sequence
<Any
> params
;
1925 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
1927 ret
= doInvoke(pdispparams
, pvarResult
,
1928 pexcepinfo
, puArgErr
, d
.name
, params
);
1930 else if ((flags
& DISPATCH_PROPERTYGET
) != 0)
1932 ret
= doGetProperty( pdispparams
, pvarResult
,
1933 pexcepinfo
, d
.name
);
1935 else if ((flags
& DISPATCH_PROPERTYPUT
) != 0 || (flags
& DISPATCH_PROPERTYPUTREF
) != 0)
1937 if (pdispparams
->cArgs
!= 1)
1938 ret
= DISP_E_BADPARAMCOUNT
;
1941 Sequence
<Any
> params
;
1942 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
1943 if(params
.getLength() > 0)
1944 ret
= doSetProperty( pdispparams
, pvarResult
, pexcepinfo
, puArgErr
, d
.name
, params
);
1946 ret
= DISP_E_BADVARTYPE
;
1951 ret
= DISP_E_MEMBERNOTFOUND
;
1954 ret
= DISP_E_MEMBERNOTFOUND
;
1956 catch(const BridgeRuntimeError
& e
)
1958 writeExcepinfo(pexcepinfo
, e
.message
);
1959 ret
= DISP_E_EXCEPTION
;
1961 catch(const Exception
& e
)
1963 OUString message
= "InterfaceOleWrapper::Invoke : \n" +
1965 writeExcepinfo(pexcepinfo
, message
);
1966 ret
= DISP_E_EXCEPTION
;
1970 writeExcepinfo(pexcepinfo
, "InterfaceOleWrapper::Invoke : \nUnexpected exception");
1971 ret
= DISP_E_EXCEPTION
;
1977 HRESULT
InterfaceOleWrapper::doInvoke( DISPPARAMS
* pdispparams
, VARIANT
* pvarResult
,
1978 EXCEPINFO
* pexcepinfo
, unsigned int * puArgErr
, OUString
& name
, Sequence
<Any
>& params
)
1985 Sequence
<sal_Int16
> outIndex
;
1986 Sequence
<Any
> outParams
;
1989 if (pdispparams
->cNamedArgs
> 0)
1990 return DISP_E_NONAMEDARGS
;
1992 // invoke method and take care of exceptions
1993 returnValue
= m_xInvocation
->invoke(name
,
1998 // try to write back out parameter
1999 if (outIndex
.getLength() > 0)
2001 const sal_Int16
* pOutIndex
= outIndex
.getConstArray();
2002 const Any
* pOutParams
= outParams
.getConstArray();
2004 for (sal_Int32 i
= 0; i
< outIndex
.getLength(); i
++)
2006 CComVariant variant
;
2007 // Currently a Sequence is converted to an SafeArray of VARIANTs.
2008 anyToVariant( &variant
, pOutParams
[i
]);
2010 // out parameter need special handling if they are VT_DISPATCH
2011 // and used in JScript
2012 int outindex
= pOutIndex
[i
];
2013 writeBackOutParameter2(&(pdispparams
->rgvarg
[pdispparams
->cArgs
- 1 - outindex
]),
2018 // write back return value
2019 if (pvarResult
!= nullptr)
2020 anyToVariant(pvarResult
, returnValue
);
2022 catch(const IllegalArgumentException
& e
) //XInvocation::invoke
2024 writeExcepinfo(pexcepinfo
, e
.Message
);
2025 ret
= DISP_E_TYPEMISMATCH
;
2027 catch(const CannotConvertException
& e
) //XInvocation::invoke
2029 writeExcepinfo(pexcepinfo
, e
.Message
);
2030 ret
= mapCannotConvertException( e
, puArgErr
);
2032 catch(const InvocationTargetException
& e
) //XInvocation::invoke
2034 const Any
& org
= e
.TargetException
;
2035 Exception excTarget
;
2038 org
.getValueTypeName() + ": " + excTarget
.Message
;
2039 writeExcepinfo(pexcepinfo
, message
);
2040 ret
= DISP_E_EXCEPTION
;
2042 catch(const NoSuchMethodException
& e
) //XInvocation::invoke
2044 writeExcepinfo(pexcepinfo
, e
.Message
);
2045 ret
= DISP_E_MEMBERNOTFOUND
;
2047 catch(const BridgeRuntimeError
& e
)
2049 writeExcepinfo(pexcepinfo
, e
.message
);
2050 ret
= DISP_E_EXCEPTION
;
2052 catch(const Exception
& e
)
2054 OUString message
= "InterfaceOleWrapper::doInvoke : \n" +
2056 writeExcepinfo(pexcepinfo
, message
);
2057 ret
= DISP_E_EXCEPTION
;
2061 writeExcepinfo(pexcepinfo
, "InterfaceOleWrapper::doInvoke : \nUnexpected exception");
2062 ret
= DISP_E_EXCEPTION
;
2067 HRESULT
InterfaceOleWrapper::doGetProperty( DISPPARAMS
* /*pdispparams*/, VARIANT
* pvarResult
,
2068 EXCEPINFO
* pexcepinfo
, OUString
& name
)
2074 Any returnValue
= m_xInvocation
->getValue( name
);
2075 // write back return value
2077 anyToVariant(pvarResult
, returnValue
);
2079 catch(const UnknownPropertyException
& e
) //XInvocation::getValue
2081 writeExcepinfo(pexcepinfo
, e
.Message
);
2082 ret
= DISP_E_MEMBERNOTFOUND
;
2084 catch(const BridgeRuntimeError
& e
)
2086 writeExcepinfo(pexcepinfo
, e
.message
);
2087 ret
= DISP_E_EXCEPTION
;
2089 catch(const Exception
& e
)
2091 OUString message
= "InterfaceOleWrapper::doGetProperty : \n" +
2093 writeExcepinfo(pexcepinfo
, message
);
2097 writeExcepinfo(pexcepinfo
, "InterfaceOleWrapper::doInvoke : \nUnexpected exception");
2098 ret
= DISP_E_EXCEPTION
;
2103 HRESULT
InterfaceOleWrapper::doSetProperty( DISPPARAMS
* /*pdispparams*/, VARIANT
* /*pvarResult*/,
2104 EXCEPINFO
* pexcepinfo
, unsigned int * puArgErr
, OUString
& name
, Sequence
<Any
> const & params
)
2110 m_xInvocation
->setValue( name
, params
.getConstArray()[0]);
2112 catch(const UnknownPropertyException
&)
2114 ret
= DISP_E_MEMBERNOTFOUND
;
2116 catch(const CannotConvertException
&e
)
2118 ret
= mapCannotConvertException( e
, puArgErr
);
2120 catch(const InvocationTargetException
&e
)
2122 if (pexcepinfo
!= nullptr)
2124 Any org
= e
.TargetException
;
2126 pexcepinfo
->wCode
= UNO_2_OLE_EXCEPTIONCODE
;
2127 pexcepinfo
->bstrSource
= SysAllocString(L
"any ONE component");
2128 pexcepinfo
->bstrDescription
= SysAllocString(
2129 o3tl::toW(org
.getValueTypeName().getStr()));
2131 ret
= DISP_E_EXCEPTION
;
2135 ret
= DISP_E_EXCEPTION
;
2142 class CXEnumVariant
: public IEnumVARIANT
,
2143 public CComObjectRoot
2147 : mnIndex(1) // ooo::vba::XCollection index starts at one
2151 virtual ~CXEnumVariant()
2155 #if defined __clang__
2156 #pragma clang diagnostic push
2157 #pragma clang diagnostic ignored "-Wunused-function"
2159 BEGIN_COM_MAP(CXEnumVariant
)
2160 #if defined __clang__
2161 #pragma clang diagnostic pop
2163 COM_INTERFACE_ENTRY(IEnumVARIANT
)
2164 #if defined __clang__
2165 #pragma clang diagnostic push
2166 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
2167 #pragma clang diagnostic ignored "-Wunused-function"
2170 #if defined __clang__
2171 #pragma clang diagnostic pop
2174 DECLARE_NOT_AGGREGATABLE(CXEnumVariant
)
2176 // Creates and initializes the enumerator
2177 void Init(InterfaceOleWrapper
* pInterfaceOleWrapper
,
2178 const Reference
<ooo::vba::XCollection
> xCollection
)
2180 mpInterfaceOleWrapper
= pInterfaceOleWrapper
;
2181 mxCollection
= xCollection
;
2185 virtual HRESULT STDMETHODCALLTYPE
Clone(IEnumVARIANT
**) override
2187 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Clone: E_NOTIMPL");
2191 virtual HRESULT STDMETHODCALLTYPE
Next(ULONG
const celt
,
2193 ULONG
*pCeltFetched
) override
2195 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2202 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): E_INVALIDARG");
2203 return E_INVALIDARG
;
2206 if (rgVar
== nullptr || (celt
!= 1 && pCeltFetched
== nullptr))
2208 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): E_FAIL");
2212 for (ULONG i
= 0; i
< celt
; i
++)
2213 VariantInit(&rgVar
[i
]);
2216 ULONG nReturned
= 0;
2219 if (mnIndex
> mxCollection
->getCount())
2221 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): got " << nReturned
<< ": S_FALSE");
2226 Any aElement
= mxCollection
->Item(aIndex
, Any());
2227 mpInterfaceOleWrapper
->anyToVariant(rgVar
, aElement
);
2228 // rgVar->pdispVal->AddRef(); ??
2236 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): S_OK");
2240 virtual HRESULT STDMETHODCALLTYPE
Reset() override
2242 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Reset: S_OK");
2247 virtual HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE
Skip(ULONG
const celt
) override
2249 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2255 if (mnIndex
> mxCollection
->getCount())
2257 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Skip(" << celt
<< "): skipped " << nSkipped
<< ": S_FALSE");
2263 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Skip(" << celt
<< "): S_OK");
2268 InterfaceOleWrapper
* mpInterfaceOleWrapper
;
2269 Reference
<ooo::vba::XCollection
> mxCollection
;
2273 class Sink
: public cppu::WeakImplHelper
<ooo::vba::XSink
>
2276 Sink(IUnknown
* pUnkSink
,
2277 Reference
<XMultiServiceFactory
> xMSF
,
2278 ooo::vba::TypeAndIID aTypeAndIID
,
2279 InterfaceOleWrapper
* pInterfaceOleWrapper
);
2282 void SAL_CALL
Call( const OUString
& Method
, Sequence
< Any
>& Arguments
) override
;
2285 IUnknown
* mpUnkSink
;
2286 Reference
<XMultiServiceFactory
> mxMSF
;
2287 ooo::vba::TypeAndIID maTypeAndIID
;
2288 InterfaceOleWrapper
* mpInterfaceOleWrapper
;
2293 Sink::Sink(IUnknown
* pUnkSink
,
2294 Reference
<XMultiServiceFactory
> xMSF
,
2295 ooo::vba::TypeAndIID aTypeAndIID
,
2296 InterfaceOleWrapper
* pInterfaceOleWrapper
) :
2297 mpUnkSink(pUnkSink
),
2299 maTypeAndIID(aTypeAndIID
),
2300 mpInterfaceOleWrapper(pInterfaceOleWrapper
)
2302 mpUnkSink
->AddRef();
2306 Sink::Call( const OUString
& Method
, Sequence
< Any
>& Arguments
)
2308 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method
<< ", " << Arguments
.getLength() << " arguments)");
2310 IDispatch
* pDispatch
;
2311 HRESULT nResult
= mpUnkSink
->QueryInterface(IID_IDispatch
, reinterpret_cast<void **>(&pDispatch
));
2312 if (!SUCCEEDED(nResult
))
2314 SAL_WARN("extensions.olebridge", "Sink::Call: Not IDispatch: " << WindowsErrorStringFromHRESULT(nResult
));
2318 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
2321 Reference
<XIdlClass
> xClass
= xRefl
->forName(maTypeAndIID
.Type
.getTypeName());
2322 assert(xClass
.is());
2324 auto aMethods
= xClass
->getMethods();
2325 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
2326 aMethods
.getLength() > 0);
2329 auto ArgumentsRange
= asNonConstRange(Arguments
);
2330 // Skip the three XInterface methods
2331 for (int i
= 3; i
< aMethods
.getLength(); i
++)
2333 if (aMethods
[i
]->getName() == Method
)
2335 // FIXME: Handle mismatch in type of actual argument and parameter of the method.
2337 // FIXME: Handle mismatch in number of arguments passed and actual number of parameters
2340 auto aParamInfos
= aMethods
[i
]->getParameterInfos();
2342 assert(Arguments
.getLength() == aParamInfos
.getLength());
2344 DISPPARAMS aDispParams
;
2345 aDispParams
.rgdispidNamedArgs
= nullptr;
2346 aDispParams
.cArgs
= Arguments
.getLength();
2347 aDispParams
.cNamedArgs
= 0;
2348 aDispParams
.rgvarg
= new VARIANT
[aDispParams
.cArgs
];
2349 for (unsigned j
= 0; j
< aDispParams
.cArgs
; j
++)
2351 VariantInit(aDispParams
.rgvarg
+j
);
2352 // Note: Reverse order of arguments in Arguments and aDispParams.rgvarg!
2353 const unsigned nIncomingArgIndex
= aDispParams
.cArgs
- j
- 1;
2354 mpInterfaceOleWrapper
->anyToVariant(aDispParams
.rgvarg
+j
, Arguments
[nIncomingArgIndex
]);
2356 // Handle OUT and INOUT arguments. For instance, the second ('Cancel') parameter to
2357 // DocumentBeforeClose() should be a VT_BYREF|VT_BOOL parameter. Need to handle that
2360 if (aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_OUT
||
2361 aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_INOUT
)
2363 switch (aDispParams
.rgvarg
[j
].vt
)
2366 aDispParams
.rgvarg
[j
].byref
= new SHORT(aDispParams
.rgvarg
[j
].iVal
);
2367 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2370 aDispParams
.rgvarg
[j
].byref
= new LONG(aDispParams
.rgvarg
[j
].lVal
);
2371 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2374 aDispParams
.rgvarg
[j
].byref
= new BSTR(aDispParams
.rgvarg
[j
].bstrVal
);
2375 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2378 aDispParams
.rgvarg
[j
].byref
= new VARIANT_BOOL(aDispParams
.rgvarg
[j
].boolVal
);
2379 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2382 assert(false && "Not handled yet");
2389 VariantInit(&aVarResult
);
2392 // In the case of a VBScript client, which uses "late binding", calling Invoke on the
2393 // sink it provides will cause a callback to our CXTypeInfo::GetNames for the given
2394 // member id, and in that we will tell it the name of the corresponding method, and the
2395 // client will know what event handler to invoke based on that name.
2397 // As the outgoing interfaces used (ooo::vba::word::XApplicationOutgoing and others) are
2398 // totally not stable and not published in any way, there can be no client that would
2399 // have done "compile-time binding" and where the sink would actually be an object with
2400 // a vtbl corresponding to the outgoing interface. Late binding clients that work like
2401 // VBScript is all we support.
2402 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method
<< "): Calling Invoke(" << nMemId
<< ")");
2404 nResult
= pDispatch
->Invoke(nMemId
, IID_NULL
, LOCALE_USER_DEFAULT
, DISPATCH_METHOD
, &aDispParams
, &aVarResult
, nullptr, &uArgErr
);
2405 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method
<< "): Invoke() returned");
2407 SAL_WARN_IF(!SUCCEEDED(nResult
), "extensions.olebridge", "Call to " << Method
<< " failed: " << WindowsErrorStringFromHRESULT(nResult
));
2409 // Undo VT_BYREF magic done above. Copy out parameters back to the Anys in Arguments
2410 for (unsigned j
= 0; j
< aDispParams
.cArgs
; j
++)
2412 const unsigned nIncomingArgIndex
= aDispParams
.cArgs
- j
- 1;
2413 if (aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_OUT
||
2414 aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_INOUT
)
2416 switch (aDispParams
.rgvarg
[j
].vt
)
2418 case VT_BYREF
|VT_I2
:
2420 SHORT
*pI
= static_cast<SHORT
*>(aDispParams
.rgvarg
[j
].byref
);
2421 ArgumentsRange
[nIncomingArgIndex
] <<= static_cast<sal_Int16
>(*pI
);
2425 case VT_BYREF
|VT_I4
:
2427 LONG
*pL
= static_cast<LONG
*>(aDispParams
.rgvarg
[j
].byref
);
2428 ArgumentsRange
[nIncomingArgIndex
] <<= static_cast<sal_Int32
>(*pL
);
2432 case VT_BYREF
|VT_BSTR
:
2434 BSTR
*pBstr
= static_cast<BSTR
*>(aDispParams
.rgvarg
[j
].byref
);
2435 ArgumentsRange
[nIncomingArgIndex
] <<= OUString(o3tl::toU(*pBstr
));
2436 // Undo SysAllocString() done in anyToVariant()
2437 SysFreeString(*pBstr
);
2441 case VT_BYREF
|VT_BOOL
:
2443 VARIANT_BOOL
*pBool
= static_cast<VARIANT_BOOL
*>(aDispParams
.rgvarg
[j
].byref
);
2444 ArgumentsRange
[nIncomingArgIndex
] <<= (*pBool
!= VARIANT_FALSE
);
2449 assert(false && "Not handled yet");
2455 switch (aDispParams
.rgvarg
[j
].vt
)
2458 // Undo SysAllocString() done in anyToVariant()
2459 SysFreeString(aDispParams
.rgvarg
[j
].bstrVal
);
2465 delete[] aDispParams
.rgvarg
;
2470 SAL_WARN("extensions.olebridge", "Sink::Call: Unknown method '" << Method
<< "'");
2475 class CXEnumConnections
: public IEnumConnections
,
2476 public CComObjectRoot
2483 virtual ~CXEnumConnections()
2487 #if defined __clang__
2488 #pragma clang diagnostic push
2489 #pragma clang diagnostic ignored "-Wunused-function"
2491 BEGIN_COM_MAP(CXEnumConnections
)
2492 #if defined __clang__
2493 #pragma clang diagnostic pop
2495 COM_INTERFACE_ENTRY(IEnumConnections
)
2496 #if defined __clang__
2497 #pragma clang diagnostic push
2498 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
2499 #pragma clang diagnostic ignored "-Wunused-function"
2502 #if defined __clang__
2503 #pragma clang diagnostic pop
2506 DECLARE_NOT_AGGREGATABLE(CXEnumConnections
)
2508 void Init(std::vector
<IUnknown
*>& rUnknowns
, std::vector
<DWORD
>& rCookies
)
2510 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Init");
2511 SAL_WARN_IF(rUnknowns
.size() != rCookies
.size(), "extensions.olebridge", "Vectors of different size");
2512 mvUnknowns
= rUnknowns
;
2513 mvCookies
= rCookies
;
2517 virtual HRESULT STDMETHODCALLTYPE
Next(ULONG cConnections
,
2519 ULONG
*pcFetched
) override
2521 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2525 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): E_POINTER");
2529 if (pcFetched
&& cConnections
!= 1)
2531 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): E_INVALIDARG");
2532 return E_INVALIDARG
;
2536 while (nFetched
< cConnections
&& mnIndex
< mvUnknowns
.size())
2538 rgcd
[nFetched
].pUnk
= mvUnknowns
[mnIndex
];
2539 rgcd
[nFetched
].pUnk
->AddRef();
2540 rgcd
[nFetched
].dwCookie
= mvCookies
[mnIndex
];
2544 if (nFetched
!= cConnections
)
2546 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): S_FALSE");
2548 *pcFetched
= nFetched
;
2551 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): S_OK");
2553 *pcFetched
= nFetched
;
2558 virtual HRESULT STDMETHODCALLTYPE
Skip(ULONG cConnections
) override
2560 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Skip(" << cConnections
<< "): E_NOTIMPL");
2565 virtual HRESULT STDMETHODCALLTYPE
Reset() override
2567 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Reset: E_NOTIMPL");
2572 virtual HRESULT STDMETHODCALLTYPE
Clone(IEnumConnections
** /* ppEnum */) override
2574 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Clone: E_NOTIMPL");
2580 std::vector
<IUnknown
*> mvUnknowns
;
2581 std::vector
<DWORD
> mvCookies
;
2585 class CXConnectionPoint
: public IConnectionPoint
,
2586 public CComObjectRoot
2589 #if defined __clang__
2590 #pragma clang diagnostic push
2591 #pragma clang diagnostic ignored "-Wunused-function"
2593 BEGIN_COM_MAP(CXConnectionPoint
)
2594 #if defined __clang__
2595 #pragma clang diagnostic pop
2597 COM_INTERFACE_ENTRY(IConnectionPoint
)
2598 #if defined __clang__
2599 #pragma clang diagnostic push
2600 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
2601 #pragma clang diagnostic ignored "-Wunused-function"
2604 #if defined __clang__
2605 #pragma clang diagnostic pop
2608 DECLARE_NOT_AGGREGATABLE(CXConnectionPoint
)
2610 virtual ~CXConnectionPoint() {}
2612 void Init(InterfaceOleWrapper
* pInterfaceOleWrapper
,
2613 Reference
<ooo::vba::XConnectionPoint
>& xCP
,
2614 Reference
<XMultiServiceFactory
>& xMSF
,
2615 ooo::vba::TypeAndIID aTypeAndIID
)
2617 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Init for " << pInterfaceOleWrapper
->getImplementationName());
2620 if (SUCCEEDED(QueryInterface(IID_IUnknown
, reinterpret_cast<void **>(&pUnknown
))))
2622 // In case QI for IUnknown returns a different pointer, but nah, it doesn't
2623 SAL_INFO("extensions.olebridge", " (IUnknown@" << pUnknown
<< ")");
2626 mpInterfaceOleWrapper
= pInterfaceOleWrapper
;
2629 maTypeAndIID
= aTypeAndIID
;
2632 virtual HRESULT STDMETHODCALLTYPE
GetConnectionInterface(IID
*pIID
) override
2634 SAL_WARN("extensions.olebridge", this << "@CXConnectionPoint::GetConnectionInterface(" << *pIID
<< "): E_NOTIMPL");
2641 virtual HRESULT STDMETHODCALLTYPE
GetConnectionPointContainer(IConnectionPointContainer
**) override
2643 SAL_WARN("extensions.olebridge", this << "@CXConnectionPoint::GetConnectionInterface: E_NOTIMPL");
2650 virtual HRESULT STDMETHODCALLTYPE
Advise(IUnknown
*pUnkSink
,
2651 DWORD
*pdwCookie
) override
2653 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2655 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Advise(" << pUnkSink
<< ")");
2660 Reference
<ooo::vba::XSink
> xSink(new Sink(pUnkSink
, mxMSF
, maTypeAndIID
, mpInterfaceOleWrapper
));
2662 mvISinks
.push_back(pUnkSink
);
2663 *pdwCookie
= mvISinks
.size();
2665 mvCookies
.push_back(mxCP
->Advise(xSink
));
2667 mvXSinks
.push_back(xSink
);
2669 SAL_INFO("extensions.olebridge", " *pdwCookie: " << *pdwCookie
);
2674 virtual HRESULT STDMETHODCALLTYPE
Unadvise(DWORD dwCookie
) override
2676 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2678 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Unadvise(" << dwCookie
<< ")");
2680 if (dwCookie
== 0 || dwCookie
> mvISinks
.size())
2683 mvISinks
[dwCookie
-1] = nullptr;
2685 mxCP
->Unadvise(mvCookies
[dwCookie
-1]);
2687 mvXSinks
[dwCookie
-1] = Reference
<ooo::vba::XSink
>();
2692 virtual HRESULT STDMETHODCALLTYPE
EnumConnections(IEnumConnections
**ppEnum
) override
2694 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2698 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::EnumConnections...");
2702 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: E_POINTER");
2706 CComObject
<CXEnumConnections
>* pEnumConnections
;
2708 nResult
= CComObject
<CXEnumConnections
>::CreateInstance(&pEnumConnections
);
2709 if (FAILED(nResult
))
2711 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: " << WindowsErrorStringFromHRESULT(nResult
));
2715 pEnumConnections
->AddRef();
2717 pEnumConnections
->Init(mvISinks
, mvCookies
);
2718 *ppEnum
= pEnumConnections
;
2720 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: S_OK");
2725 InterfaceOleWrapper
* mpInterfaceOleWrapper
;
2726 std::vector
<IUnknown
*> mvISinks
;
2727 std::vector
<Reference
<ooo::vba::XSink
>> mvXSinks
;
2728 std::vector
<DWORD
> mvCookies
;
2729 Reference
<XMultiServiceFactory
> mxMSF
;
2730 Reference
<ooo::vba::XConnectionPoint
> mxCP
;
2731 ooo::vba::TypeAndIID maTypeAndIID
;
2736 HRESULT
InterfaceOleWrapper::InvokeGeneral( DISPID dispidMember
, unsigned short wFlags
,
2737 DISPPARAMS
* pdispparams
, VARIANT
* pvarResult
, EXCEPINFO
* pexcepinfo
,
2738 unsigned int * /*puArgErr*/, bool& bHandled
)
2743 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation
2744 // is that we put an object into an Array object ( out parameter). We have to return
2745 // IDispatch otherwise the object cannot be accessed from the Script.
2746 if( dispidMember
== DISPID_VALUE
&& (wFlags
& DISPATCH_PROPERTYGET
) != 0
2747 && m_defaultValueType
!= VT_EMPTY
&& pvarResult
!= nullptr)
2749 // Special case hack: If it is a ScVbaCheckBox, return the boolean value
2750 Reference
<ooo::vba::msforms::XCheckBox
> xCheckBox(m_xOrigin
, UNO_QUERY
);
2754 Any aValue
= xCheckBox
->getValue();
2755 anyToVariant(pvarResult
, aValue
);
2760 if( m_defaultValueType
== VT_DISPATCH
)
2762 pvarResult
->vt
= VT_DISPATCH
;
2763 pvarResult
->pdispVal
= this;
2769 // function: _GetValueObject
2770 else if( dispidMember
== DISPID_JSCRIPT_VALUE_FUNC
)
2775 CComObject
< JScriptValue
>* pValue
;
2776 if( SUCCEEDED( CComObject
<JScriptValue
>::CreateInstance( &pValue
)))
2779 pvarResult
->vt
= VT_DISPATCH
;
2780 pvarResult
->pdispVal
= CComQIPtr
<IDispatch
>(pValue
->GetUnknown());
2784 ret
= DISP_E_EXCEPTION
;
2786 else if( dispidMember
== DISPID_GET_STRUCT_FUNC
)
2789 bool bStruct
= false;
2792 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(m_smgr
));
2793 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
2795 if( pdispparams
->cArgs
== 1 && SUCCEEDED( arg
.ChangeType( VT_BSTR
, &pdispparams
->rgvarg
[0])) )
2797 Reference
<XIdlClass
> classStruct
= xRefl
->forName(OUString(o3tl::toU(arg
.bstrVal
)));
2798 if( classStruct
.is())
2801 classStruct
->createObject( anyStruct
);
2803 anyToVariant( &var
, anyStruct
);
2805 if( var
.vt
== VT_DISPATCH
)
2807 VariantCopy( pvarResult
, & var
);
2812 ret
= bStruct
? S_OK
: DISP_E_EXCEPTION
;
2814 else if (dispidMember
== DISPID_CREATE_TYPE_FUNC
)
2819 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
2821 if( pdispparams
->cArgs
!= 1)
2822 return DISP_E_BADPARAMCOUNT
;
2823 if (FAILED( arg
.ChangeType( VT_BSTR
, &pdispparams
->rgvarg
[0])))
2824 return DISP_E_BADVARTYPE
;
2826 //check if the provided name represents a valid type
2828 if (!getType(arg
.bstrVal
, type
))
2830 writeExcepinfo(pexcepinfo
, OUString::Concat("[automation bridge] A UNO type with the name ") +
2831 o3tl::toU(arg
.bstrVal
) + " does not exist!");
2832 return DISP_E_EXCEPTION
;
2835 if (!createUnoTypeWrapper(arg
.bstrVal
, pvarResult
))
2837 writeExcepinfo(pexcepinfo
, "[automation bridge] InterfaceOleWrapper::InvokeGeneral\n"
2838 "Could not initialize UnoTypeWrapper object!");
2839 return DISP_E_EXCEPTION
;
2842 else if (dispidMember
== DISPID_NEWENUM
)
2848 Reference
< ooo::vba::XCollection
> xCollection(m_xOrigin
, UNO_QUERY
);
2849 if (!xCollection
.is())
2850 return DISP_E_MEMBERNOTFOUND
;
2852 CComObject
<CXEnumVariant
>* pEnumVar
;
2854 ret
= CComObject
<CXEnumVariant
>::CreateInstance(&pEnumVar
);
2860 pEnumVar
->Init(this, xCollection
);
2862 pvarResult
->vt
= VT_UNKNOWN
;
2863 pvarResult
->punkVal
= nullptr;
2865 ret
= pEnumVar
->QueryInterface(IID_IUnknown
, reinterpret_cast<void**>(&pvarResult
->punkVal
));
2868 pEnumVar
->Release();
2873 catch(const BridgeRuntimeError
& e
)
2875 writeExcepinfo(pexcepinfo
, e
.message
);
2876 ret
= DISP_E_EXCEPTION
;
2878 catch(const Exception
& e
)
2880 OUString message
= "InterfaceOleWrapper::InvokeGeneral : \n" +
2882 writeExcepinfo(pexcepinfo
, message
);
2883 ret
= DISP_E_EXCEPTION
;
2887 writeExcepinfo(pexcepinfo
, "InterfaceOleWrapper::InvokeGeneral : \nUnexpected exception");
2888 ret
= DISP_E_EXCEPTION
;
2893 STDMETHODIMP
InterfaceOleWrapper::GetDispID(BSTR
/*bstrName*/, DWORD
/*grfdex*/, DISPID __RPC_FAR
* /*pid*/)
2895 return ResultFromScode(E_NOTIMPL
);
2898 STDMETHODIMP
InterfaceOleWrapper::InvokeEx(
2899 /* [in] */ DISPID
/*id*/,
2900 /* [in] */ LCID
/*lcid*/,
2901 /* [in] */ WORD
/*wFlags*/,
2902 /* [in] */ DISPPARAMS __RPC_FAR
* /*pdp*/,
2903 /* [out] */ VARIANT __RPC_FAR
* /*pvarRes*/,
2904 /* [out] */ EXCEPINFO __RPC_FAR
* /*pei*/,
2905 /* [unique][in] */ IServiceProvider __RPC_FAR
* /*pspCaller*/)
2907 return ResultFromScode(E_NOTIMPL
);
2910 STDMETHODIMP
InterfaceOleWrapper::DeleteMemberByName(
2911 /* [in] */ BSTR
/*bstr*/,
2912 /* [in] */ DWORD
/*grfdex*/)
2914 return ResultFromScode(E_NOTIMPL
);
2917 STDMETHODIMP
InterfaceOleWrapper::DeleteMemberByDispID(DISPID
/*id*/)
2919 return ResultFromScode(E_NOTIMPL
);
2922 STDMETHODIMP
InterfaceOleWrapper::GetMemberProperties(
2923 /* [in] */ DISPID
/*id*/,
2924 /* [in] */ DWORD
/*grfdexFetch*/,
2925 /* [out] */ DWORD __RPC_FAR
* /*pgrfdex*/)
2927 return ResultFromScode(E_NOTIMPL
);
2930 STDMETHODIMP
InterfaceOleWrapper::GetMemberName(
2931 /* [in] */ DISPID
/*id*/,
2932 /* [out] */ BSTR __RPC_FAR
* /*pbstrName*/)
2934 return ResultFromScode(E_NOTIMPL
);
2937 STDMETHODIMP
InterfaceOleWrapper::GetNextDispID(
2938 /* [in] */ DWORD
/*grfdex*/,
2939 /* [in] */ DISPID
/*id*/,
2940 /* [out] */ DISPID __RPC_FAR
* /*pid*/)
2942 return ResultFromScode(E_NOTIMPL
);
2945 STDMETHODIMP
InterfaceOleWrapper::GetNameSpaceParent(
2946 /* [out] */ IUnknown __RPC_FAR
*__RPC_FAR
* /*ppunk*/)
2948 return ResultFromScode(E_NOTIMPL
);
2951 // IProvideClassInfo
2952 HRESULT STDMETHODCALLTYPE
InterfaceOleWrapper::GetClassInfo (
2953 /* [out] */ ITypeInfo
**ppTI
)
2955 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2957 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetClassInfo");
2962 Reference
<ooo::vba::XInterfaceWithIID
> xIID(m_xOrigin
, UNO_QUERY
);
2966 OUString sIID
= xIID
->getIID();
2968 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(sIID
.pData
->buffer
), &aIID
)))
2973 CComObject
<CXTypeInfo
>* pTypeInfo
;
2975 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
2979 pTypeInfo
->AddRef();
2981 pTypeInfo
->InitForCoclass(m_xOrigin
, m_sImplementationName
, aIID
, m_smgr
);
2988 // IConnectionPointContainer
2989 HRESULT STDMETHODCALLTYPE
InterfaceOleWrapper::EnumConnectionPoints(
2990 /* [out] */ IEnumConnectionPoints
**)
2992 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::EnumConnectionPoints");
2993 return ResultFromScode(E_NOTIMPL
);
2996 HRESULT STDMETHODCALLTYPE
InterfaceOleWrapper::FindConnectionPoint(
2997 /* [in] */ REFIID riid
,
2998 /* [out] */ IConnectionPoint
**ppCP
)
3000 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
3002 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::FindConnectionPoint(" << riid
<< ")");
3007 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
3009 // We checked already
3010 assert(xConnectable
.is());
3011 if (!xConnectable
.is())
3014 ooo::vba::TypeAndIID aTypeAndIID
= xConnectable
->GetConnectionPoint();
3017 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(aTypeAndIID
.IID
.pData
->buffer
), &aIID
)))
3018 return E_INVALIDARG
;
3020 if (!IsEqualIID(riid
, aIID
))
3021 return E_INVALIDARG
;
3023 Reference
<ooo::vba::XConnectionPoint
> xCP
= xConnectable
->FindConnectionPoint();
3025 return E_INVALIDARG
;
3029 CComObject
<CXConnectionPoint
>* pConnectionPoint
;
3031 ret
= CComObject
<CXConnectionPoint
>::CreateInstance(&pConnectionPoint
);
3035 pConnectionPoint
->AddRef();
3037 pConnectionPoint
->Init(this, xCP
, m_smgr
, aTypeAndIID
);
3039 *ppCP
= pConnectionPoint
;
3044 // UnoObjectWrapperRemoteOpt ---------------------------------------------------
3046 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference
<XMultiServiceFactory
> const & aFactory
,
3047 sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
3048 InterfaceOleWrapper( aFactory
, unoWrapperClass
, comWrapperClass
),
3053 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt()
3057 // UnoConversionUtilities
3058 Reference
< XInterface
> UnoObjectWrapperRemoteOpt::createUnoWrapperInstance()
3060 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
3061 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
3062 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
3065 COM_DECLSPEC_NOTHROW STDMETHODIMP
UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID
/*riid*/, LPOLESTR
* rgszNames
, UINT cNames
,
3066 LCID
/*lcid*/, DISPID
* rgdispid
)
3068 MutexGuard
guard( getBridgeMutex());
3072 HRESULT ret
= E_UNEXPECTED
;
3075 if( ! wcscmp( *rgszNames
, JSCRIPT_VALUE_FUNC
))
3077 *rgdispid
= DISPID_JSCRIPT_VALUE_FUNC
;
3080 else if( ! wcscmp( *rgszNames
, GET_STRUCT_FUNC
))
3082 *rgdispid
= DISPID_GET_STRUCT_FUNC
;
3086 if (m_xInvocation
.is() && (cNames
> 0))
3088 OUString
name(o3tl::toU(rgszNames
[0]));
3089 // has this name been determined as "bad"
3090 BadNameMap::iterator badIter
= m_badNameMap
.find( name
);
3091 if( badIter
== m_badNameMap
.end() )
3093 // name has not been bad before( member exists
3094 typedef NameToIdMap::iterator ITnames
;
3095 std::pair
< ITnames
, bool > pair_id
= m_nameToDispIdMap
.emplace(name
, m_currentId
++);
3096 // new ID inserted ?
3097 if( pair_id
.second
)
3098 {// yes, now create MemberInfo and ad to IdToMemberInfoMap
3099 MemberInfo
d(0, name
);
3100 m_idToMemberInfoMap
.emplace(m_currentId
- 1, d
);
3103 *rgdispid
= pair_id
.first
->second
;
3107 ret
= DISP_E_UNKNOWNNAME
;
3112 COM_DECLSPEC_NOTHROW STDMETHODIMP
UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember
, REFIID
/*riid*/, LCID
/*lcid*/, WORD wFlags
,
3113 DISPPARAMS
* pdispparams
, VARIANT
* pvarResult
, EXCEPINFO
* pexcepinfo
,
3116 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
3121 bool bHandled
= false;
3122 ret
= InvokeGeneral( dispidMember
, wFlags
, pdispparams
, pvarResult
, pexcepinfo
,
3123 puArgErr
, bHandled
);
3127 if ( dispidMember
> 0 && m_xInvocation
.is())
3130 IdToMemberInfoMap::iterator it_MemberInfo
= m_idToMemberInfoMap
.find( dispidMember
);
3131 if( it_MemberInfo
!= m_idToMemberInfoMap
.end() )
3133 MemberInfo
& info
= it_MemberInfo
->second
;
3135 Sequence
<Any
> params
; // holds converted any s
3137 { // DISPID called for the first time
3138 if( wFlags
== DISPATCH_METHOD
)
3140 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3142 if( FAILED( ret
= doInvoke( pdispparams
, pvarResult
,
3143 pexcepinfo
, puArgErr
, info
.name
, params
))
3144 && ret
== DISP_E_MEMBERNOTFOUND
)
3146 // try to get the exact name
3148 if (m_xExactName
.is())
3150 exactName
= m_xExactName
->getExactName( info
.name
);
3152 if( !exactName
.isEmpty() )
3154 if( SUCCEEDED( ret
= doInvoke( pdispparams
, pvarResult
,
3155 pexcepinfo
, puArgErr
, exactName
, params
)))
3156 info
.name
= exactName
;
3160 if( SUCCEEDED( ret
) )
3161 info
.flags
= DISPATCH_METHOD
;
3163 else if( wFlags
== DISPATCH_PROPERTYPUT
|| wFlags
== DISPATCH_PROPERTYPUTREF
)
3165 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3166 if( FAILED( ret
= doSetProperty( pdispparams
, pvarResult
,
3167 pexcepinfo
, puArgErr
, info
.name
, params
))
3168 && ret
== DISP_E_MEMBERNOTFOUND
)
3170 // try to get the exact name
3172 if (m_xExactName
.is())
3174 exactName
= m_xExactName
->getExactName( info
.name
);
3176 if( !exactName
.isEmpty() )
3178 if( SUCCEEDED( ret
= doSetProperty( pdispparams
, pvarResult
,
3179 pexcepinfo
, puArgErr
, exactName
, params
)))
3180 info
.name
= exactName
;
3184 if( SUCCEEDED( ret
) )
3185 info
.flags
= DISPATCH_PROPERTYPUT
| DISPATCH_PROPERTYGET
;
3187 else if( wFlags
== DISPATCH_PROPERTYGET
)
3189 if( FAILED( ret
= doGetProperty( pdispparams
, pvarResult
,
3190 pexcepinfo
, info
.name
))
3191 && ret
== DISP_E_MEMBERNOTFOUND
)
3193 // try to get the exact name
3195 if (m_xExactName
.is())
3197 exactName
= m_xExactName
->getExactName( info
.name
);
3199 if( !exactName
.isEmpty() )
3201 if( SUCCEEDED( ret
= doGetProperty( pdispparams
, pvarResult
,
3202 pexcepinfo
, exactName
)))
3203 info
.name
= exactName
;
3207 if( SUCCEEDED( ret
) )
3208 info
.flags
= DISPATCH_PROPERTYGET
| DISPATCH_PROPERTYPUT
;
3210 else if( wFlags
& DISPATCH_METHOD
&&
3211 (wFlags
& DISPATCH_PROPERTYPUT
|| wFlags
& DISPATCH_PROPERTYPUTREF
))
3215 // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT
3216 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3217 // try first as method
3218 if( FAILED( ret
= doInvoke( pdispparams
, pvarResult
,
3219 pexcepinfo
, puArgErr
, info
.name
, params
))
3220 && ret
== DISP_E_MEMBERNOTFOUND
)
3222 // try to get the exact name
3223 if (m_xExactName
.is())
3225 exactName
= m_xExactName
->getExactName( info
.name
);
3227 if( !exactName
.isEmpty() )
3229 if( SUCCEEDED( ret
= doInvoke( pdispparams
, pvarResult
,
3230 pexcepinfo
, puArgErr
, exactName
, params
)))
3231 info
.name
= exactName
;
3235 if( SUCCEEDED( ret
) )
3236 info
.flags
= DISPATCH_METHOD
;
3239 if( FAILED( ret
) && pdispparams
->cArgs
== 1)
3241 if( FAILED( ret
= doSetProperty( pdispparams
, pvarResult
,
3242 pexcepinfo
, puArgErr
, info
.name
, params
))
3243 && ret
== DISP_E_MEMBERNOTFOUND
)
3245 // try to get the exact name
3246 if( !exactName
.isEmpty() )
3248 if( SUCCEEDED( ret
= doSetProperty( pdispparams
, pvarResult
,
3249 pexcepinfo
, puArgErr
, exactName
, params
)))
3250 info
.name
= exactName
;
3253 if( SUCCEEDED( ret
) )
3254 info
.flags
= DISPATCH_PROPERTYPUT
| DISPATCH_PROPERTYGET
;
3257 else if( wFlags
& DISPATCH_METHOD
&& wFlags
& DISPATCH_PROPERTYGET
)
3260 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3262 if( FAILED( ret
= doInvoke( pdispparams
, pvarResult
,
3263 pexcepinfo
, puArgErr
, info
.name
, params
))
3264 && ret
== DISP_E_MEMBERNOTFOUND
)
3266 // try to get the exact name
3267 if (m_xExactName
.is())
3269 exactName
= m_xExactName
->getExactName( info
.name
);
3271 if( !exactName
.isEmpty() )
3273 if( SUCCEEDED( ret
= doInvoke( pdispparams
, pvarResult
,
3274 pexcepinfo
, puArgErr
, exactName
, params
)))
3275 info
.name
= exactName
;
3279 if( SUCCEEDED( ret
) )
3280 info
.flags
= DISPATCH_METHOD
;
3283 if( FAILED( ret
) && pdispparams
->cArgs
== 1)
3285 if( FAILED( ret
= doGetProperty( pdispparams
, pvarResult
,
3286 pexcepinfo
, info
.name
))
3287 && ret
== DISP_E_MEMBERNOTFOUND
)
3289 if( !exactName
.isEmpty() )
3291 if( SUCCEEDED( ret
= doSetProperty( pdispparams
, pvarResult
,
3292 pexcepinfo
, puArgErr
, exactName
, params
)))
3293 info
.name
= exactName
;
3296 if( SUCCEEDED( ret
) )
3297 info
.flags
= DISPATCH_PROPERTYGET
;
3301 // update information about this member
3302 if( ret
== DISP_E_MEMBERNOTFOUND
)
3304 // Remember the name as not existing
3305 // and remove the MemberInfo
3306 m_badNameMap
[info
.name
]= false;
3307 m_idToMemberInfoMap
.erase( it_MemberInfo
);
3309 } // if( ! info.flags )
3310 else // IdToMemberInfoMap contains a MemberInfo
3312 if( wFlags
& DISPATCH_METHOD
&& info
.flags
== DISPATCH_METHOD
)
3314 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3315 ret
= doInvoke( pdispparams
, pvarResult
,
3316 pexcepinfo
, puArgErr
, info
.name
, params
);
3318 else if( (wFlags
& DISPATCH_PROPERTYPUT
|| wFlags
& DISPATCH_PROPERTYPUTREF
) &&
3319 info
.flags
& DISPATCH_PROPERTYPUT
)
3321 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3322 ret
= doSetProperty( pdispparams
, pvarResult
,
3323 pexcepinfo
, puArgErr
, info
.name
, params
);
3325 else if( (wFlags
& DISPATCH_PROPERTYGET
) && ( info
.flags
& DISPATCH_PROPERTYGET
))
3327 ret
= doGetProperty( pdispparams
, pvarResult
,
3328 pexcepinfo
, info
.name
);
3332 ret
= DISP_E_MEMBERNOTFOUND
;
3335 }// if( it_MemberInfo != m_idToMemberInfoMap.end() )
3337 ret
= DISP_E_MEMBERNOTFOUND
;
3340 catch(const BridgeRuntimeError
& e
)
3342 writeExcepinfo(pexcepinfo
, e
.message
);
3343 ret
= DISP_E_EXCEPTION
;
3345 catch(const Exception
& e
)
3347 OUString message
= "UnoObjectWrapperRemoteOpt::Invoke : \n" +
3349 writeExcepinfo(pexcepinfo
, message
);
3350 ret
= DISP_E_EXCEPTION
;
3354 writeExcepinfo(pexcepinfo
, "UnoObjectWrapperRemoteOpt::Invoke : \nUnexpected exception");
3355 ret
= DISP_E_EXCEPTION
;
3361 HRESULT
UnoObjectWrapperRemoteOpt::methodInvoke( DISPID
/*dispidMember*/, DISPPARAMS
* /*pdispparams*/, VARIANT
* /*pvarResult*/,
3362 EXCEPINFO
* /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence
<Any
> const &)
3367 // The returned HRESULT is only appropriate for IDispatch::Invoke
3368 static HRESULT
mapCannotConvertException(const CannotConvertException
&e
, unsigned int * puArgErr
)
3371 bool bWriteIndex
= true;
3375 case FailReason::OUT_OF_RANGE
:
3376 ret
= DISP_E_OVERFLOW
;
3378 case FailReason::IS_NOT_NUMBER
:
3379 ret
= DISP_E_TYPEMISMATCH
;
3381 case FailReason::IS_NOT_ENUM
:
3382 ret
= DISP_E_TYPEMISMATCH
;
3384 case FailReason::IS_NOT_BOOL
:
3385 ret
= DISP_E_TYPEMISMATCH
;
3387 case FailReason::NO_SUCH_INTERFACE
:
3388 ret
= DISP_E_TYPEMISMATCH
;
3390 case FailReason::SOURCE_IS_NO_DERIVED_TYPE
:
3391 ret
= DISP_E_TYPEMISMATCH
;
3393 case FailReason::TYPE_NOT_SUPPORTED
:
3394 ret
= DISP_E_TYPEMISMATCH
;
3396 case FailReason::INVALID
:
3397 ret
= DISP_E_TYPEMISMATCH
;
3399 case FailReason::NO_DEFAULT_AVAILABLE
:
3400 ret
= DISP_E_BADPARAMCOUNT
;
3402 case FailReason::UNKNOWN
:
3411 if( bWriteIndex
&& puArgErr
!= nullptr)
3412 *puArgErr
= e
.ArgumentIndex
;
3416 // The function maps the TypeClass of the any to VARTYPE: If
3417 // the Any contains STRUCT or INTERFACE then the return value
3418 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper
3419 // and the result is put into the constructor of the uno - wrapper
3420 // object. If a client asks the object for DISPID_VALUE and this
3421 // function returned VT_DISPATCH then the IDispatch of the same
3422 // object is being returned.
3423 // See InterfaceOleWrapper::Invoke, InterfaceOleWrapper::m_defaultValueType
3424 VARTYPE
getVarType( const Any
& value
)
3426 VARTYPE ret
= VT_EMPTY
;
3428 switch ( value
.getValueTypeClass())
3430 case TypeClass_STRUCT
: ret
= VT_DISPATCH
; break;
3431 case TypeClass_INTERFACE
: ret
= VT_DISPATCH
; break;
3437 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */