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 "-Wnon-virtual-dtor"
45 #pragma clang diagnostic ignored "-Wnonportable-include-path"
46 #pragma clang diagnostic ignored "-Wsequence-point"
47 #pragma clang diagnostic ignored "-Wtypename-missing"
51 #if defined _MSC_VER && defined __clang__
52 #pragma clang diagnostic pop
56 #include <osl/diagnose.h>
57 #include <salhelper/simplereferenceobject.hxx>
58 #include <rtl/ref.hxx>
59 #include <rtl/ustring.hxx>
60 #include <tools/diagnose_ex.h>
61 #include <sal/log.hxx>
62 #include <com/sun/star/beans/MethodConcept.hpp>
63 #include <com/sun/star/beans/PropertyConcept.hpp>
64 #include <com/sun/star/frame/Desktop.hpp>
65 #include <com/sun/star/frame/TerminationVetoException.hpp>
66 #include <com/sun/star/frame/XTerminateListener.hpp>
67 #include <com/sun/star/lang/NoSuchMethodException.hpp>
68 #include <com/sun/star/script/CannotConvertException.hpp>
69 #include <com/sun/star/script/FailReason.hpp>
70 #include <com/sun/star/reflection/theCoreReflection.hpp>
71 #include <com/sun/star/reflection/ParamInfo.hpp>
72 #include <com/sun/star/beans/XExactName.hpp>
73 #include <com/sun/star/container/NoSuchElementException.hpp>
74 #include <com/sun/star/container/XEnumeration.hpp>
75 #include <com/sun/star/container/XEnumerationAccess.hpp>
77 #include <com/sun/star/beans/XMaterialHolder.hpp>
78 #include <com/sun/star/script/XInvocation2.hpp>
79 #include <com/sun/star/script/MemberType.hpp>
80 #include <com/sun/star/reflection/XIdlReflection.hpp>
81 #include <ooo/vba/XCollection.hpp>
82 #include <ooo/vba/XConnectable.hpp>
83 #include <ooo/vba/XConnectionPoint.hpp>
84 #include <ooo/vba/XSink.hpp>
85 #include <ooo/vba/msforms/XCheckBox.hpp>
86 #include <osl/interlck.h>
87 #include <com/sun/star/uno/genfunc.h>
88 #include <comphelper/automationinvokedzone.hxx>
89 #include <comphelper/asyncquithandler.hxx>
90 #include <comphelper/processfactory.hxx>
91 #include <comphelper/profilezone.hxx>
92 #include <comphelper/windowsdebugoutput.hxx>
93 #include <comphelper/windowserrorstring.hxx>
94 #include <o3tl/char16_t2wchar_t.hxx>
96 #include "comifaces.hxx"
97 #include "jscriptclasses.hxx"
98 #include "unotypewrapper.hxx"
99 #include "oleobjw.hxx"
100 #include "unoobjw.hxx"
101 #include "servprov.hxx"
105 using namespace cppu
;
106 using namespace com::sun::star::uno
;
107 using namespace com::sun::star::beans
;
108 using namespace com::sun::star::container
;
109 using namespace com::sun::star::script
;
110 using namespace com::sun::star::lang
;
111 using namespace com::sun::star::bridge::ModelDependent
;
112 using namespace com::sun::star::reflection
;
114 std::unordered_map
<sal_uIntPtr
, WeakReference
<XInterface
> > UnoObjToWrapperMap
;
115 static bool writeBackOutParameter(VARIANTARG
* pDest
, VARIANT
* pSource
);
116 static bool writeBackOutParameter2( VARIANTARG
* pDest
, VARIANT
* pSource
);
117 static HRESULT
mapCannotConvertException(const CannotConvertException
&e
, unsigned int * puArgErr
);
119 class TerminationVetoer
: public WeakImplHelper
<css::frame::XTerminateListener
>
130 Reference
< css::frame::XDesktop
> xDesktop
=
131 css::frame::Desktop::create( comphelper::getProcessComponentContext() );
132 xDesktop
->addTerminateListener( this );
134 catch ( const Exception
& )
136 DBG_UNHANDLED_EXCEPTION("extensions.olebridge");
141 static rtl::Reference
< TerminationVetoer
> get()
143 static TerminationVetoer
* pInstance
= new TerminationVetoer
;
144 static rtl::Reference
< TerminationVetoer
> aInstance( pInstance
);
149 // XTerminateListener
150 void SAL_CALL
queryTermination( const EventObject
& ) override
152 SAL_INFO("extensions.olebridge", "TerminationVetoer::queryTermination: count=" << mnCount
);
153 // Always veto termination while an OLE object is active, except if it is an OLE object that
154 // has asked us to quit.
155 if (!AsyncQuitHandler::instance().IsForceQuit() && mnCount
> 0)
157 SAL_INFO("extensions.olebridge", "TerminationVetoer::queryTermination: Throwing!");
158 throw css::frame::TerminationVetoException();
162 void SAL_CALL
notifyTermination( const EventObject
& ) override
168 void SAL_CALL
disposing( const css::lang::EventObject
& ) override
174 /* Does not throw any exceptions.
175 Param pInfo can be NULL.
177 static void writeExcepinfo(EXCEPINFO
* pInfo
, const OUString
& message
)
179 if (pInfo
!= nullptr)
181 pInfo
->wCode
= UNO_2_OLE_EXCEPTIONCODE
;
182 pInfo
->bstrSource
= SysAllocString(L
"[automation bridge] ");
183 pInfo
->bstrDescription
= SysAllocString(o3tl::toW(message
.getStr()));
187 InterfaceOleWrapper::InterfaceOleWrapper( Reference
<XMultiServiceFactory
> const & xFactory
,
188 sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
189 UnoConversionUtilities
<InterfaceOleWrapper
>( xFactory
, unoWrapperClass
, comWrapperClass
),
190 m_defaultValueType( 0)
192 TerminationVetoer::get()->mnCount
++;
193 SAL_INFO("extensions.olebridge", "InterfaceOleWrapper CTOR, count=" << TerminationVetoer::get()->mnCount
);
196 InterfaceOleWrapper::~InterfaceOleWrapper()
198 MutexGuard
guard(getBridgeMutex());
199 // remove entries in global map
200 auto it
= UnoObjToWrapperMap
.find( reinterpret_cast<sal_uIntPtr
>(m_xOrigin
.get()));
201 if(it
!= UnoObjToWrapperMap
.end())
202 UnoObjToWrapperMap
.erase(it
);
204 TerminationVetoer::get()->mnCount
--;
205 SAL_INFO("extensions.olebridge", "InterfaceOleWrapper DTOR, count=" << TerminationVetoer::get()->mnCount
);
208 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::QueryInterface(REFIID riid
, void ** ppv
)
210 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
212 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::QueryInterface(" << riid
<< ")");
219 if(IsEqualIID(riid
, IID_IUnknown
))
222 *ppv
= static_cast<IUnknown
*>(static_cast<IDispatch
*>(this));
223 SAL_INFO("extensions.olebridge", " " << *ppv
);
225 else if (IsEqualIID(riid
, IID_IDispatch
))
228 *ppv
= static_cast<IDispatch
*>(this);
229 SAL_INFO("extensions.olebridge", " " << *ppv
);
231 else if (IsEqualIID(riid
, IID_IProvideClassInfo
))
233 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
234 if (!xConnectable
.is())
235 return E_NOINTERFACE
;
237 *ppv
= static_cast<IProvideClassInfo
*>(this);
238 SAL_INFO("extensions.olebridge", " " << *ppv
);
240 else if (IsEqualIID(riid
, IID_IConnectionPointContainer
))
242 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
243 if (!xConnectable
.is())
244 return E_NOINTERFACE
;
246 *ppv
= static_cast<IConnectionPointContainer
*>(this);
247 SAL_INFO("extensions.olebridge", " " << *ppv
);
249 else if( IsEqualIID( riid
, __uuidof( IUnoObjectWrapper
)))
252 *ppv
= static_cast<IUnoObjectWrapper
*>(this);
253 SAL_INFO("extensions.olebridge", " " << *ppv
);
260 COM_DECLSPEC_NOTHROW
STDMETHODIMP_(ULONG
) InterfaceOleWrapper::AddRef()
263 // does not need to guard because one should not rely on the return value of
268 COM_DECLSPEC_NOTHROW
STDMETHODIMP_(ULONG
) InterfaceOleWrapper::Release()
275 // IUnoObjectWrapper --------------------------------------------------------
276 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::getWrapperXInterface( Reference
<XInterface
>* pXInt
)
278 pXInt
->set( static_cast<XWeak
*>( this), UNO_QUERY
);
279 return pXInt
->is() ? S_OK
: E_FAIL
;
281 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::getOriginalUnoObject( Reference
<XInterface
>* pXInt
)
284 return m_xOrigin
.is() ? S_OK
: E_FAIL
;
286 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::getOriginalUnoStruct( Any
* pStruct
)
288 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
293 Reference
<XMaterialHolder
> xMatHolder( m_xInvocation
, UNO_QUERY
);
296 Any any
= xMatHolder
->getMaterial();
297 if( any
.getValueTypeClass() == TypeClass_STRUCT
)
307 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::GetTypeInfoCount( UINT
*pctinfo
)
309 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetTypeInfoCount");
319 class CXTypeInfo
: public ITypeInfo
,
320 public CComObjectRoot
323 enum class Kind
{ COCLASS
, MAIN
, OUTGOING
};
325 #if defined __clang__
326 #pragma clang diagnostic push
327 #pragma clang diagnostic ignored "-Wunused-function"
329 BEGIN_COM_MAP(CXTypeInfo
)
330 #if defined __clang__
331 #pragma clang diagnostic pop
333 COM_INTERFACE_ENTRY(ITypeInfo
)
334 #if defined __clang__
335 #pragma clang diagnostic push
336 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
337 #pragma clang diagnostic ignored "-Wunused-function"
340 #if defined __clang__
341 #pragma clang diagnostic pop
344 DECLARE_NOT_AGGREGATABLE(CXTypeInfo
)
346 virtual ~CXTypeInfo() {}
348 void InitForCoclass(Reference
<XInterface
> xOrigin
,
349 const OUString
& sImplementationName
,
351 Reference
<XMultiServiceFactory
> xMSF
);
352 void InitForClassItself(Reference
<XInterface
> xOrigin
,
353 const OUString
& sImplementationName
,
355 Reference
<XMultiServiceFactory
> xMSF
);
356 void InitForOutgoing(Reference
<XInterface
> xOrigin
,
357 const OUString
& sInterfaceName
,
359 Reference
<XMultiServiceFactory
> xMSF
,
361 virtual HRESULT STDMETHODCALLTYPE
GetTypeAttr(TYPEATTR
**ppTypeAttr
) override
;
362 virtual HRESULT STDMETHODCALLTYPE
GetTypeComp(ITypeComp
**ppTComp
) override
;
363 virtual HRESULT STDMETHODCALLTYPE
GetFuncDesc(UINT index
,
364 FUNCDESC
**ppFuncDesc
) override
;
365 virtual HRESULT STDMETHODCALLTYPE
GetVarDesc(UINT index
,
366 VARDESC
**ppVarDesc
) override
;
367 virtual HRESULT STDMETHODCALLTYPE
GetNames(MEMBERID memid
,
370 UINT
*pcNames
) override
;
371 virtual HRESULT STDMETHODCALLTYPE
GetRefTypeOfImplType(UINT index
,
372 HREFTYPE
*pRefType
) override
;
373 virtual HRESULT STDMETHODCALLTYPE
GetImplTypeFlags(UINT index
,
374 INT
*pImplTypeFlags
) override
;
375 virtual HRESULT STDMETHODCALLTYPE
GetIDsOfNames(LPOLESTR
*rgszNames
,
377 MEMBERID
*pMemId
) override
;
378 virtual HRESULT STDMETHODCALLTYPE
Invoke(PVOID pvInstance
,
381 DISPPARAMS
*pDispParams
,
383 EXCEPINFO
*pExcepInfo
,
384 UINT
*puArgErr
) override
;
385 virtual HRESULT STDMETHODCALLTYPE
GetDocumentation(MEMBERID memid
,
387 BSTR
*pBstrDocString
,
388 DWORD
*pdwHelpContext
,
389 BSTR
*pBstrHelpFile
) override
;
390 virtual HRESULT STDMETHODCALLTYPE
GetDllEntry(MEMBERID memid
,
394 WORD
*pwOrdinal
) override
;
395 virtual HRESULT STDMETHODCALLTYPE
GetRefTypeInfo(HREFTYPE hRefType
,
396 ITypeInfo
**ppTInfo
) override
;
397 virtual HRESULT STDMETHODCALLTYPE
AddressOfMember(MEMBERID memid
,
399 PVOID
*ppv
) override
;
400 virtual HRESULT STDMETHODCALLTYPE
CreateInstance(IUnknown
*pUnkOuter
,
402 PVOID
*ppvObj
) override
;
403 virtual HRESULT STDMETHODCALLTYPE
GetMops(MEMBERID memid
,
404 BSTR
*pBstrMops
) override
;
405 virtual HRESULT STDMETHODCALLTYPE
GetContainingTypeLib(ITypeLib
**ppTLib
,
406 UINT
*pIndex
) override
;
407 virtual void STDMETHODCALLTYPE
ReleaseTypeAttr(TYPEATTR
*pTypeAttr
) override
;
408 virtual void STDMETHODCALLTYPE
ReleaseFuncDesc(FUNCDESC
*pFuncDesc
) override
;
409 virtual void STDMETHODCALLTYPE
ReleaseVarDesc(VARDESC
*pVarDesc
) override
;
413 Reference
<XInterface
> mxOrigin
;
414 OUString msImplementationName
;
415 OUString msInterfaceName
;
417 Reference
<XMultiServiceFactory
> mxMSF
;
421 class CXTypeLib
: public ITypeLib
,
422 public CComObjectRoot
425 #if defined __clang__
426 #pragma clang diagnostic push
427 #pragma clang diagnostic ignored "-Wunused-function"
429 BEGIN_COM_MAP(CXTypeLib
)
430 #if defined __clang__
431 #pragma clang diagnostic pop
433 COM_INTERFACE_ENTRY(ITypeLib
)
434 #if defined __clang__
435 #pragma clang diagnostic push
436 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
437 #pragma clang diagnostic ignored "-Wunused-function"
440 #if defined __clang__
441 #pragma clang diagnostic pop
444 DECLARE_NOT_AGGREGATABLE(CXTypeLib
)
446 virtual ~CXTypeLib() {}
448 void Init(Reference
<XInterface
> xOrigin
,
449 const OUString
& sImplementationName
,
450 Reference
<XMultiServiceFactory
> xMSF
)
452 SAL_INFO("extensions.olebridge", this << "@CXTypeLib::Init for " << sImplementationName
);
454 msImplementationName
= sImplementationName
;
458 virtual UINT STDMETHODCALLTYPE
GetTypeInfoCount() override
460 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoCount");
464 virtual HRESULT STDMETHODCALLTYPE
GetTypeInfo(UINT
,
465 ITypeInfo
**) override
467 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfo: E_NOTIMPL");
471 virtual HRESULT STDMETHODCALLTYPE
GetTypeInfoType(UINT
,
474 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoType: E_NOTIMPL");
478 virtual HRESULT STDMETHODCALLTYPE
GetTypeInfoOfGuid(REFGUID guid
,
479 ITypeInfo
**ppTInfo
) override
481 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
483 SAL_INFO("extensions.olebridge", this << "@CXTypeLib::GetTypeInfoOfGuid(" << guid
<< ")");
487 Reference
<ooo::vba::XConnectable
> xConnectable(mxOrigin
, UNO_QUERY
);
488 if (!xConnectable
.is())
489 return TYPE_E_ELEMENTNOTFOUND
;
492 if (SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(xConnectable
->getIID().pData
->buffer
), &aIID
)))
494 if (IsEqualIID(guid
, aIID
))
498 CComObject
<CXTypeInfo
>* pTypeInfo
;
500 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
506 pTypeInfo
->InitForCoclass(mxOrigin
, msImplementationName
, aIID
, mxMSF
);
508 *ppTInfo
= pTypeInfo
;
515 ooo::vba::TypeAndIID aTypeAndIID
= xConnectable
->GetConnectionPoint();
518 if (SUCCEEDED(IIDFromString((LPOLESTR
)aTypeAndIID
.IID
.pData
->buffer
, &aIID
)))
522 CComObject
<CXTypeInfo
>* pTypeInfo
;
524 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
530 pTypeInfo
->InitForOutgoing(mxOrigin
, msImplementationName
, aIID
, mxMSF
);
532 *ppTInfo
= pTypeInfo
;
537 SAL_WARN("extensions.olebridge", "Not implemented: GetTypeInfoOfGuid(" << guid
<< ")");
540 return TYPE_E_ELEMENTNOTFOUND
;
544 virtual HRESULT STDMETHODCALLTYPE
GetLibAttr(TLIBATTR
**) override
546 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetLibAttr: E_NOTIMPL");
550 virtual HRESULT STDMETHODCALLTYPE
GetTypeComp(ITypeComp
**) override
552 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetTypeComp: E_NOTIMPL");
556 virtual HRESULT STDMETHODCALLTYPE
GetDocumentation(INT
,
562 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::GetDocumentation: E_NOTIMPL");
566 virtual HRESULT STDMETHODCALLTYPE
IsName(LPOLESTR
,
570 SAL_WARN("extensions.olebridge", this << "@CXTypeLib:IsName: E_NOTIMPL");
574 virtual HRESULT STDMETHODCALLTYPE
FindName(LPOLESTR
,
580 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::FindName: E_NOTIMPL");
584 virtual void STDMETHODCALLTYPE
ReleaseTLibAttr(TLIBATTR
*) override
586 SAL_WARN("extensions.olebridge", this << "@CXTypeLib::ReleaseTLibAttr: E_NOTIMPL");
590 Reference
<XInterface
> mxOrigin
;
591 OUString msImplementationName
;
592 Reference
<XMultiServiceFactory
> mxMSF
;
595 void CXTypeInfo::InitForCoclass(Reference
<XInterface
> xOrigin
,
596 const OUString
& sImplementationName
,
598 Reference
<XMultiServiceFactory
> xMSF
)
600 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForCoclass(" << sImplementationName
<< "," << rIID
<< ")");
601 meKind
= Kind::COCLASS
;
603 msImplementationName
= sImplementationName
;
608 void CXTypeInfo::InitForClassItself(Reference
<XInterface
> xOrigin
,
609 const OUString
& sImplementationName
,
611 Reference
<XMultiServiceFactory
> xMSF
)
613 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForClassItself(" << sImplementationName
<< "," << rIID
<< ")");
616 msImplementationName
= sImplementationName
;
621 void CXTypeInfo::InitForOutgoing(Reference
<XInterface
> xOrigin
,
622 const OUString
& sInterfaceName
,
624 Reference
<XMultiServiceFactory
> xMSF
,
627 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::InitForOutgoing(" << sInterfaceName
<< "," << rIID
<< ")");
628 meKind
= Kind::OUTGOING
;
630 msInterfaceName
= sInterfaceName
;
636 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetTypeAttr(TYPEATTR
**ppTypeAttr
)
638 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
640 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetTypeAttr");
645 assert(!IsEqualIID(maIID
, IID_NULL
));
647 TYPEATTR
*pTypeAttr
= new TYPEATTR
;
648 memset(pTypeAttr
, 0, sizeof(*pTypeAttr
));
650 pTypeAttr
->guid
= maIID
;
652 if (meKind
== Kind::COCLASS
)
654 pTypeAttr
->typekind
= TKIND_COCLASS
;
655 pTypeAttr
->cFuncs
= 0;
656 pTypeAttr
->cVars
= 0;
657 pTypeAttr
->cImplTypes
= 3;
658 pTypeAttr
->cbSizeVft
= 0;
659 pTypeAttr
->cbAlignment
= 8;
660 pTypeAttr
->wTypeFlags
= TYPEFLAG_FCANCREATE
;
662 else if (meKind
== Kind::MAIN
)
664 pTypeAttr
->typekind
= TKIND_DISPATCH
;
665 pTypeAttr
->cFuncs
= 10; // FIXME, dummy
666 pTypeAttr
->cVars
= 0;
667 pTypeAttr
->cImplTypes
= 1;
668 // FIXME: I think this is always supposed to be as if just for the seven methods in
670 pTypeAttr
->cbSizeVft
= 7 * sizeof(void*);
671 pTypeAttr
->cbAlignment
= 8;
672 pTypeAttr
->wTypeFlags
= TYPEFLAG_FHIDDEN
|TYPEFLAG_FDISPATCHABLE
;
674 else if (meKind
== Kind::OUTGOING
)
676 pTypeAttr
->typekind
= TKIND_DISPATCH
;
678 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
681 Reference
<XIdlClass
> xClass
= xRefl
->forName(maType
.getTypeName());
684 auto aMethods
= xClass
->getMethods();
685 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
686 aMethods
.getLength() > 0);
688 // Drop the three XInterface methods, add the three corresponding IUnknown ones plus the
689 // four IDispatch ones on top of that.
690 pTypeAttr
->cFuncs
= aMethods
.getLength() - 3 + 3 + 4;
691 pTypeAttr
->cVars
= 0;
692 pTypeAttr
->cImplTypes
= 1;
693 // FIXME: I think this, too, is always supposed to be as if just for the seven methods in
695 pTypeAttr
->cbSizeVft
= 7 * sizeof(void*);
696 pTypeAttr
->cbAlignment
= 8;
697 pTypeAttr
->wTypeFlags
= TYPEFLAG_FHIDDEN
|TYPEFLAG_FNONEXTENSIBLE
|TYPEFLAG_FDISPATCHABLE
;
702 pTypeAttr
->lcid
= LOCALE_USER_DEFAULT
;
703 pTypeAttr
->memidConstructor
= MEMBERID_NIL
;
704 pTypeAttr
->memidDestructor
= MEMBERID_NIL
;
705 // FIXME: Is this correct, just the vtable pointer, right?
706 pTypeAttr
->cbSizeInstance
= sizeof(void*);
707 pTypeAttr
->wMajorVerNum
= 0;
708 pTypeAttr
->wMinorVerNum
= 0;
709 pTypeAttr
->idldescType
.wIDLFlags
= IDLFLAG_NONE
;
711 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetTypeAttr: " << pTypeAttr
);
713 *ppTypeAttr
= pTypeAttr
;
718 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetTypeComp(ITypeComp
**)
720 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetTypeComp: E_NOTIMPL");
724 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetFuncDesc(UINT index
,
725 FUNCDESC
**ppFuncDesc
)
727 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
732 if (meKind
!= Kind::OUTGOING
)
737 *ppFuncDesc
= new FUNCDESC
;
738 (*ppFuncDesc
)->memid
= 0x60000000 + index
;
739 (*ppFuncDesc
)->lprgscode
= nullptr;
740 (*ppFuncDesc
)->lprgelemdescParam
= nullptr;
741 (*ppFuncDesc
)->funckind
= FUNC_DISPATCH
;
742 (*ppFuncDesc
)->invkind
= INVOKE_FUNC
;
743 (*ppFuncDesc
)->callconv
= CC_STDCALL
;
746 case 0: // QueryInterface
747 (*ppFuncDesc
)->cParams
= 2;
748 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
749 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
752 (*ppFuncDesc
)->cParams
= 0;
753 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
754 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_UI4
;
757 (*ppFuncDesc
)->cParams
= 1;
758 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
759 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_UI4
;
761 case 3: // GetTypeInfoCount
762 (*ppFuncDesc
)->cParams
= 1;
763 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
764 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
766 case 4: // GetTypeInfo
767 (*ppFuncDesc
)->cParams
= 3;
768 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
769 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
771 case 5: // GetIDsOfNames
772 (*ppFuncDesc
)->cParams
= 5;
773 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
774 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
777 (*ppFuncDesc
)->cParams
= 8;
778 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr;
779 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
;
782 (*ppFuncDesc
)->cParamsOpt
= 0;
783 (*ppFuncDesc
)->oVft
= index
* sizeof(void*);
784 (*ppFuncDesc
)->cScodes
= 0;
785 (*ppFuncDesc
)->wFuncFlags
= FUNCFLAG_FRESTRICTED
;
787 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetFuncDesc(" << index
<< "): S_OK: " << *ppFuncDesc
);
792 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
795 Reference
<XIdlClass
> xClass
= xRefl
->forName(maType
.getTypeName());
798 auto aMethods
= xClass
->getMethods();
799 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
800 aMethods
.getLength() > 0);
802 if (index
> static_cast<UINT
>(aMethods
.getLength() - 3 + 3 + 4))
805 *ppFuncDesc
= new FUNCDESC
;
807 (*ppFuncDesc
)->memid
= index
- 6;
808 (*ppFuncDesc
)->lprgscode
= nullptr;
809 (*ppFuncDesc
)->lprgelemdescParam
= nullptr;
810 (*ppFuncDesc
)->funckind
= FUNC_DISPATCH
;
811 (*ppFuncDesc
)->invkind
= INVOKE_FUNC
;
812 (*ppFuncDesc
)->callconv
= CC_STDCALL
;
813 (*ppFuncDesc
)->cParams
= aMethods
[index
- 4]->getParameterInfos().getLength();
814 (*ppFuncDesc
)->cParamsOpt
= 0;
815 (*ppFuncDesc
)->oVft
= index
* sizeof(void*);
816 (*ppFuncDesc
)->cScodes
= 0;
817 (*ppFuncDesc
)->elemdescFunc
.tdesc
.lptdesc
= nullptr; // ???
818 (*ppFuncDesc
)->elemdescFunc
.tdesc
.vt
= VT_VOID
; // ???
819 (*ppFuncDesc
)->wFuncFlags
= 0;
821 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetFuncDesc(" << index
<< "): S_OK: " << *ppFuncDesc
);
826 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetVarDesc(UINT
,
829 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetVarDesc: E_NOTIMPL");
833 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetNames(MEMBERID memid
,
838 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
840 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetNames(" << memid
<< ")");
841 assert(meKind
!= Kind::COCLASS
);
855 if (meKind
== Kind::MAIN
)
857 SAL_WARN("extensions.olebridge", "GetNames() for MAIN not implemented");
861 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
864 Reference
<XIdlClass
> xClass
= xRefl
->forName(maType
.getTypeName());
867 auto aMethods
= xClass
->getMethods();
868 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
869 aMethods
.getLength() > 0);
871 // Subtract the three XInterface methods. Memid for the first following method is 1.
872 if (memid
> aMethods
.getLength() - 3)
875 SAL_INFO("extensions.olebridge", "..." << this << "@CXTypeInfo::GetNames(" << memid
<< "): " << aMethods
[memid
+ 2]->getName());
876 rgBstrNames
[0] = SysAllocString(reinterpret_cast<LPOLESTR
>(aMethods
[memid
+ 2]->getName().pData
->buffer
));
882 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetRefTypeOfImplType(UINT index
,
885 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetRefTypeOfImplType(" << index
<< ")");
890 assert(index
== 0 || index
== 1);
892 *pRefType
= 1000+index
;
897 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetImplTypeFlags(UINT index
,
900 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
902 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetImplTypeFlags(" << index
<< ")");
907 assert(meKind
== Kind::COCLASS
);
908 assert(index
== 0 || index
== 1);
911 *pImplTypeFlags
= IMPLTYPEFLAG_FDEFAULT
;
913 *pImplTypeFlags
= IMPLTYPEFLAG_FDEFAULT
|IMPLTYPEFLAG_FSOURCE
;
918 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetIDsOfNames(LPOLESTR
*,
922 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetIDsOfNames: E_NOTIMPL");
926 HRESULT STDMETHODCALLTYPE
CXTypeInfo::Invoke(PVOID
,
934 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::Invoke: E_NOTIMPL");
938 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetDocumentation(MEMBERID memid
,
940 BSTR
*pBstrDocString
,
941 DWORD
*pdwHelpContext
,
944 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
946 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetDocumentation(" << memid
<< ")");
950 if (memid
== MEMBERID_NIL
)
952 *pBstrName
= SysAllocString(o3tl::toW(msImplementationName
.getStr()));
954 else if (memid
== DISPID_VALUE
)
956 // MEMBERIDs are the same as DISPIDs, apparently?
957 *pBstrName
= SysAllocString(L
"Value");
961 // FIXME: Shouldn't we be able to know the names of the members of UNO interfaces?
962 *pBstrName
= SysAllocString(o3tl::toW(OUString("UnknownNameOfMember#" + OUString::number(memid
)).getStr()));
966 *pBstrDocString
= SysAllocString(L
"");
970 *pBstrHelpFile
= nullptr;
975 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetDllEntry(MEMBERID
,
981 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetDllEntry: E_NOTIMPL");
985 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetRefTypeInfo(HREFTYPE hRefType
,
988 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
990 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetRefTypeInfo(" << hRefType
<< ")");
995 // FIXME: Is it correct to assume that the only interfaces on which GetRefTypeInfo() would be
996 // called are those that implement ooo::vba::XConnectable?
998 Reference
<ooo::vba::XConnectable
> xConnectable(mxOrigin
, UNO_QUERY
);
999 if (!xConnectable
.is())
1002 ooo::vba::TypeAndIID aTypeAndIID
= xConnectable
->GetConnectionPoint();
1005 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(aTypeAndIID
.IID
.pData
->buffer
), &aIID
)))
1010 CComObject
<CXTypeInfo
>* pTypeInfo
;
1012 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
1016 pTypeInfo
->AddRef();
1018 pTypeInfo
->InitForOutgoing(mxOrigin
, aTypeAndIID
.Type
.getTypeName(), aIID
, mxMSF
, aTypeAndIID
.Type
);
1020 *ppTInfo
= pTypeInfo
;
1025 HRESULT STDMETHODCALLTYPE
CXTypeInfo::AddressOfMember(MEMBERID
,
1029 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::AddressOfMember: E_NOTIMPL");
1033 HRESULT STDMETHODCALLTYPE
CXTypeInfo::CreateInstance(IUnknown
*,
1037 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::CreateInstance: E_NOTIMPL");
1041 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetMops(MEMBERID
,
1044 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::GetMops: E_NOTIMPL");
1048 // This is not actually called any more by my vbscript test after I added the IProvideClassInfo
1049 // thing... so all the CXTypeLib stuff is dead code at the moment.
1051 HRESULT STDMETHODCALLTYPE
CXTypeInfo::GetContainingTypeLib(ITypeLib
**ppTLib
,
1054 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
1056 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::GetContainingTypeLib");
1058 if (!ppTLib
|| !pIndex
)
1063 CComObject
<CXTypeLib
>* pTypeLib
;
1065 ret
= CComObject
<CXTypeLib
>::CreateInstance(&pTypeLib
);
1071 pTypeLib
->Init(mxOrigin
, msImplementationName
, mxMSF
);
1078 void STDMETHODCALLTYPE
CXTypeInfo::ReleaseTypeAttr(TYPEATTR
*pTypeAttr
)
1080 SAL_INFO("extensions.olebridge", this << "@CXTypeInfo::ReleaseTypeAttr(" << pTypeAttr
<< ")");
1085 void STDMETHODCALLTYPE
CXTypeInfo::ReleaseFuncDesc(FUNCDESC
*pFuncDesc
)
1087 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::ReleaseFuncDesc(" << pFuncDesc
<< ")");
1092 void STDMETHODCALLTYPE
CXTypeInfo::ReleaseVarDesc(VARDESC
*)
1094 SAL_WARN("extensions.olebridge", this << "@CXTypeInfo::ReleaseVarDesc: E_NOTIMPL");
1097 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::GetTypeInfo(UINT iTInfo
, LCID
, ITypeInfo
** ppTInfo
)
1099 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
1101 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetTypeInfo(" << iTInfo
<< ")");
1109 // FIXME: This is surely incorrect. Why is being able to handle GetTypeInfo() here coupled to
1110 // being a source for outgoing events, i.e. implementing XConnectable? What would break if we
1111 // would use XInterfaceWithIID and its getIID instead?
1113 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
1114 if (!xConnectable
.is())
1117 OUString sIID
= xConnectable
->GetIIDForClassItselfNotCoclass();
1119 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(sIID
.pData
->buffer
), &aIID
)))
1124 CComObject
<CXTypeInfo
>* pTypeInfo
;
1126 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
1130 pTypeInfo
->AddRef();
1132 pTypeInfo
->InitForClassItself(m_xOrigin
, m_sImplementationName
, aIID
, m_smgr
);
1134 *ppTInfo
= pTypeInfo
;
1139 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::GetIDsOfNames(REFIID
/*riid*/,
1140 LPOLESTR
* rgszNames
,
1145 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
1150 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetIDsOfNames:");
1151 for (unsigned int i
= 0; i
< cNames
; ++i
)
1153 // Initialise returned rgdispid values.
1154 rgdispid
[i
] = DISPID_UNKNOWN
;
1156 SAL_INFO("extensions.olebridge", " " << o3tl::toU(rgszNames
[i
]));
1159 HRESULT ret
= DISP_E_UNKNOWNNAME
;
1162 MutexGuard
guard( getBridgeMutex());
1164 // FIXME: Handle the cNames > 1 case? Note that the rest of the names mean the names of *arguments*.
1166 if( ! _wcsicmp( *rgszNames
, JSCRIPT_VALUE_FUNC
) ||
1167 ! _wcsicmp( *rgszNames
, BRIDGE_VALUE_FUNC
))
1169 *rgdispid
= DISPID_JSCRIPT_VALUE_FUNC
;
1172 else if( ! _wcsicmp( *rgszNames
, GET_STRUCT_FUNC
) ||
1173 ! _wcsicmp( *rgszNames
, BRIDGE_GET_STRUCT_FUNC
))
1175 *rgdispid
= DISPID_GET_STRUCT_FUNC
;
1178 else if( ! _wcsicmp( *rgszNames
, BRIDGE_CREATE_TYPE_FUNC
))
1180 *rgdispid
= DISPID_CREATE_TYPE_FUNC
;
1184 if (m_xInvocation
.is() && (cNames
> 0))
1186 OUString
name(o3tl::toU(rgszNames
[0]));
1187 NameToIdMap::iterator iter
= m_nameToDispIdMap
.find(name
);
1189 bool bIsMethod
= false;
1191 OUString exactName
= name
;
1193 if (iter
== m_nameToDispIdMap
.end())
1195 if (m_xExactName
.is())
1197 exactName
= m_xExactName
->getExactName(name
);
1198 if (exactName
.isEmpty())
1202 MemberInfo
d(0, exactName
);
1204 if (m_xInvocation
->hasProperty(exactName
))
1206 d
.flags
|= DISPATCH_PROPERTYGET
;
1207 d
.flags
|= DISPATCH_PROPERTYPUT
;
1208 d
.flags
|= DISPATCH_PROPERTYPUTREF
;
1211 if (m_xInvocation
->hasMethod(exactName
))
1213 d
.flags
|= DISPATCH_METHOD
;
1219 m_MemberInfos
.push_back(d
);
1220 iter
= m_nameToDispIdMap
.emplace(exactName
, static_cast<DISPID
>(m_MemberInfos
.size())).first
;
1222 if (exactName
!= name
)
1224 iter
= m_nameToDispIdMap
.emplace(name
, static_cast<DISPID
>(m_MemberInfos
.size())).first
;
1229 if (iter
== m_nameToDispIdMap
.end())
1231 ret
= DISP_E_UNKNOWNNAME
;
1232 SAL_INFO("extensions.olebridge", " " << name
<< ": UNKNOWN");
1236 rgdispid
[0] = (*iter
).second
;
1237 SAL_INFO("extensions.olebridge", " " << name
<< ": " << rgdispid
[0]);
1239 if (bIsMethod
&& cNames
> 1)
1241 Reference
<XIdlMethod
> xIdlMethod
;
1242 Reference
<XIntrospectionAccess
> xIntrospectionAccess
= m_xInvocation
->getIntrospection();
1245 if (xIntrospectionAccess
.is())
1246 xIdlMethod
= xIntrospectionAccess
->getMethod(exactName
, MethodConcept::ALL
);
1248 catch (const NoSuchMethodException
&)
1251 if (xIdlMethod
.is())
1253 auto aParamInfos
= xIdlMethod
->getParameterInfos();
1254 for (unsigned int i
= 1; i
< cNames
; ++i
)
1256 bool bFound
= false;
1257 for (int j
= 0; j
< aParamInfos
.getLength(); ++j
)
1259 if (aParamInfos
[j
].aName
.equalsIgnoreAsciiCase(OUString(o3tl::toU(rgszNames
[i
]))))
1263 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames
[i
])) << ": " << rgdispid
[i
]);
1268 SAL_INFO("extensions.olebridge", " " << OUString(o3tl::toU(rgszNames
[i
])) << ": NOT FOUND");
1273 // Return value should be S_OK only if *all* the names were found.
1275 for (i
= 0; i
< cNames
; ++i
)
1276 if (rgdispid
[i
] == DISPID_UNKNOWN
)
1283 catch(const BridgeRuntimeError
&)
1287 catch(const Exception
&)
1299 // Note: What the comments here say about JScript possibly holds for Automation clients in general,
1300 // like VBScript ones, too. Or not. Hard to say. What is the relevance of JScript nowadays anyway,
1301 // and can LO really be used from JScript code on web pages any longer?
1303 // "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts
1304 // The parameters "id", "wFlags" and "pdispparams" equal those as used in
1305 // IDispatch::Invoke. The function handles special JavaScript
1306 // cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent
1307 // an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object)
1308 // parameter (JavaScript Array object)
1309 // Because all those VT_DISPATCH objects need a different conversion
1310 // we have to find out what the object is supposed to be. The function does this
1311 // by either using type information or by help of a specialized ValueObject object.
1313 // A. Type Information
1315 // With the help of type information the kind of parameter can be exactly determined
1316 // and an appropriate conversion can be chosen. A problem arises if a method expects
1317 // an Any. Then the type info does not tell what the type of the value, that is kept
1318 // by the any, should be. In this situation the decision whether the param is a
1319 // sequence or an object is made upon the fact if the object has a property "0"
1320 // ( see function "isJScriptArray"). Since this is unsafe it is recommended to use
1321 // the JScript value objects within a JScript script on such an occasion.
1323 // B. JavaScript Value Object ( class JScriptValue )
1325 // A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the
1326 // IJScriptValue object interface. Such objects are provided by all UNO wrapper
1327 // objects used within a JScript script. To obtain an instance one has to call
1328 // "_GetValueObject() or Bridge_GetValueObject()" on a UNO wrapper object (class InterfaceOleWrapper).
1329 // A value object is appropriately initialized within the script and passed as
1330 // parameter to a UNO object method or property. The convertDispparamsArgs function
1331 // can easily find out that a param is such an object by querying for the
1332 // IJScriptValue interface. By this interface one the type and kind ( out, in/out)
1333 // can be determined and the right conversion can be applied.
1334 // Using ValueObjects we spare us the effort of acquiring and examining type information
1335 // in order to figure out what the an IDispatch parameter is meant for.
1337 // Normal JScript object parameter can be mixed with JScriptValue object. If an
1338 // VARIANT contains a VT_DISPATCH that is no JScriptValue than the type information
1339 // is used to find out about the required type.
1340 void InterfaceOleWrapper::convertDispparamsArgs(DISPID id
,
1341 unsigned short /*wFlags*/, DISPPARAMS
* pdispparams
, Sequence
<Any
>& rSeq
)
1343 // Parameters come in in reverse order in pdispparams. There might be less parameters than
1344 // expected. In that case, assume they are "optional" (but can't be marked as such in UNO IDL),
1345 // and fill in the rest with empty Anys. There might also be more than expected. In that case,
1346 // assume the oovbaapi UNO IDL hasn't kept up with added optional parameters in MSO, and just
1347 // ignore the extra ones, as long as they are empty.
1349 // An example: incoming parameters: <12, 13, "foo/bar.tem">
1351 // Expected parameters: (string filename, int something, int somethingElse, Any whatever, Any
1354 // Here the existing incoming parameters are placed in reverse order in the first three outgoing
1355 // parameters, and the rest of the outgoing parameters are kept as empty Anys.
1357 // Another example: incoming parameters: <EMPTY, TRUE>
1359 // Expected parameters: (bool flag)
1361 // Here the TRUE is passed as the sole outgoing parameter, and the incoming EMPTY is ignored.
1363 // Still an example: incoming parameters: <"foo.doc", TRUE>
1365 // Expected parameters: (bool flag)
1367 // This throws an error as the incoming string parameter presumably should do something important,
1368 // but there is no corresponding outgoing parameter.
1371 const int countIncomingArgs
= pdispparams
->cArgs
;
1373 //Get type information for the current call
1374 InvocationInfo info
;
1375 if( ! getInvocationInfoForCall( id
, info
))
1376 throw BridgeRuntimeError(
1377 "[automation bridge]InterfaceOleWrapper::convertDispparamsArgs \n"
1378 "Could not obtain type information for current call.");
1380 // Size rSeq according to the number of expected parameters.
1381 const int expectedArgs
= info
.aParamTypes
.getLength() + (info
.eMemberType
== MemberType_PROPERTY
? 1 : 0);
1382 rSeq
.realloc( expectedArgs
);
1383 Any
* pParams
= rSeq
.getArray();
1387 int outgoingArgIndex
= 0;
1389 // Go through incoming parameters in reverse order, i.e. in the order as declared in IDL
1390 for (int i
= std::max(countIncomingArgs
, expectedArgs
) - 1; i
>= 0; i
--)
1392 // Ignore too many parameters if they are VT_EMPTY anyway
1393 if ( outgoingArgIndex
>= expectedArgs
&& pdispparams
->rgvarg
[i
].vt
== VT_EMPTY
)
1396 // But otherwise too many parameters is an error
1397 if ( outgoingArgIndex
>= expectedArgs
)
1398 throw BridgeRuntimeError( "[automation bridge] Too many parameters" );
1400 if (info
.eMemberType
== MemberType_METHOD
&&
1401 info
.aParamModes
[ outgoingArgIndex
] == ParamMode_OUT
)
1407 if (i
< countIncomingArgs
)
1409 // A missing (and hopefully optional) arg (in the middle of the argument list) is passed
1411 if (pdispparams
->rgvarg
[i
].vt
== VT_ERROR
&& pdispparams
->rgvarg
[i
].scode
== DISP_E_PARAMNOTFOUND
)
1414 pParams
[ outgoingArgIndex
] = aEmpty
;
1419 if(convertValueObject( & pdispparams
->rgvarg
[i
], anyParam
))
1420 { //a param is a ValueObject and could be converted
1421 pParams
[ outgoingArgIndex
] = anyParam
;
1428 // A missing arg. Let's hope it is de facto optional (there is no way in UNO IDL to mark
1429 // a parameter as optional). The corresponding slot in pParams is already a void Any.
1430 // Here we don't increase outgoingArgIndex!
1434 // If the param is an out, in/out parameter in
1435 // JScript (Array object, with value at index 0) then we
1436 // extract Array[0] and put the value into varParam. At the end of the loop varParam
1437 // is converted if it contains a value otherwise the VARIANT from
1438 // DISPPARAMS is converted.
1439 CComVariant varParam
;
1441 // Check for JScript out and in/out paramsobjects (VT_DISPATCH).
1442 // To find them out we use typeinformation of the function being called.
1444 // No idea how this stuff, originally written for JScript, works for other Automation
1447 if( pdispparams
->rgvarg
[i
].vt
== VT_DISPATCH
)
1449 if( info
.eMemberType
== MemberType_METHOD
&& info
.aParamModes
[ outgoingArgIndex
] == ParamMode_INOUT
)
1452 // Index ( property) "0" contains the actual IN-param. The object is a JScript
1454 // Get the IN-param at index "0"
1455 IDispatch
* pdisp
= pdispparams
->rgvarg
[i
].pdispVal
;
1457 OLECHAR
const * sindex
= L
"0";
1459 DISPPARAMS noParams
= {nullptr,nullptr,0,0};
1460 if(SUCCEEDED( hr
= pdisp
->GetIDsOfNames( IID_NULL
, const_cast<OLECHAR
**>(&sindex
), 1, LOCALE_USER_DEFAULT
, &id2
)))
1461 hr
= pdisp
->Invoke( id2
, IID_NULL
, LOCALE_USER_DEFAULT
, DISPATCH_PROPERTYGET
,
1462 & noParams
, & varParam
, nullptr, nullptr);
1465 throw BridgeRuntimeError(
1466 "[automation bridge] Could not determine "
1467 "if the object has a member \"0\". Error: " +
1468 OUString::number(hr
));
1473 if( varParam
.vt
== VT_EMPTY
) // then it was no in/out parameter
1474 varParam
= pdispparams
->rgvarg
[i
];
1476 if(info
.eMemberType
== MemberType_METHOD
)
1477 variantToAny( & varParam
, anyParam
,
1478 info
.aParamTypes
[ outgoingArgIndex
]);
1479 else if(info
.eMemberType
== MemberType_PROPERTY
)
1480 variantToAny( & varParam
, anyParam
, info
.aType
);
1484 if (outgoingArgIndex
< expectedArgs
)
1485 pParams
[ outgoingArgIndex
]= anyParam
;
1487 }// end for / iterating over all parameters
1490 bool InterfaceOleWrapper::getInvocationInfoForCall( DISPID id
, InvocationInfo
& info
)
1492 bool bTypesAvailable
= false;
1494 if( !m_xInvocation
.is() )return false;
1495 Reference
<XInvocation2
> inv2( m_xInvocation
, UNO_QUERY
);
1498 // We need the name of the property or method to get its type information.
1499 // The name can be identified through the param "id"
1500 // that is kept as value in the map m_nameToDispIdMap.
1501 // Problem: the Windows JScript engine sometimes changes small letters to capital
1502 // letters as happens in xidlclass_obj.createObject( var) // in JScript.
1503 // IDispatch::GetIdsOfNames is then called with "CreateObject" !!!
1504 // m_nameToDispIdMap can contain several names for one DISPID but only one is
1505 // the exact one. If there's no m_xExactName and therefore no exact name then
1506 // there's only one entry in the map.
1507 OUString sMemberName
;
1509 auto ci1
= std::find_if(m_nameToDispIdMap
.cbegin(), m_nameToDispIdMap
.cend(),
1510 [&id
](const NameToIdMap::value_type
& nameToDispId
) { return nameToDispId
.second
== id
; }); // item is a pair<OUString, DISPID>
1511 if (ci1
!= m_nameToDispIdMap
.cend())
1512 sMemberName
= (*ci1
).first
;
1513 // Get information for the current call ( property or method).
1514 // There could be similar names which only differ in the cases
1515 // of letters. First we assume that the name which was passed into
1516 // GetIDsOfNames is correct. If we won't get information with that
1517 // name then we have the invocation service use the XExactName interface.
1518 bool validInfo
= true;
1519 InvocationInfo invInfo
;
1521 invInfo
= inv2
->getInfoForName( sMemberName
, false);
1523 catch(const IllegalArgumentException
&)
1530 invInfo
= inv2
->getInfoForName( sMemberName
, true);
1532 if( invInfo
.aName
.pData
)
1534 bTypesAvailable
= true;
1538 return bTypesAvailable
;
1541 // XBridgeSupplier2 ---------------------------------------------------
1542 // only bridges itself ( this instance of InterfaceOleWrapper)from UNO to IDispatch
1543 // If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper
1544 // can bridged to IDispatch ( if destModelType == OLE). The IDispatch is
1545 // implemented by this class.
1546 Any SAL_CALL
InterfaceOleWrapper::createBridge(const Any
& modelDepObject
,
1547 const Sequence
<sal_Int8
>& /*ProcessId*/,
1548 sal_Int16 sourceModelType
,
1549 sal_Int16 destModelType
)
1553 if( sourceModelType
== UNO
&& destModelType
== OLE
&&
1554 modelDepObject
.getValueTypeClass() == TypeClass_INTERFACE
)
1556 Reference
<XInterface
> xInt
;
1557 if( modelDepObject
>>= xInt
)
1559 if( xInt
== Reference
<XInterface
>( static_cast<XWeak
*>( this), UNO_QUERY
))
1561 VARIANT
*pVar
= static_cast<VARIANT
*>(CoTaskMemAlloc( sizeof( VARIANT
)));
1564 pVar
->vt
= VT_DISPATCH
;
1565 pVar
->pdispVal
= static_cast<IDispatch
*>( this);
1568 retAny
<<= reinterpret_cast< sal_uIntPtr
>( pVar
);
1577 // XInitialization --------------------------------------------------
1578 void SAL_CALL
InterfaceOleWrapper::initialize( const Sequence
< Any
>& aArguments
)
1580 switch( aArguments
.getLength() )
1582 case 2: // the object wraps a UNO struct
1583 aArguments
[0] >>= m_xInvocation
;
1584 aArguments
[1] >>= m_defaultValueType
;
1586 case 3: // the object wraps a UNO interface
1587 aArguments
[0] >>= m_xInvocation
;
1588 aArguments
[1] >>= m_xOrigin
;
1589 aArguments
[2] >>= m_defaultValueType
;
1591 Reference
<XServiceInfo
> xServiceInfo(m_xOrigin
, UNO_QUERY
);
1592 if (xServiceInfo
.is())
1593 m_sImplementationName
= xServiceInfo
->getImplementationName();
1595 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::initialize for "
1596 << (m_sImplementationName
.isEmpty()?"an unknown implementation":m_sImplementationName
));
1600 m_xExactName
.set( m_xInvocation
, UNO_QUERY
);
1603 Reference
< XInterface
> InterfaceOleWrapper::createUnoWrapperInstance()
1605 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper(
1606 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1607 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1610 Reference
<XInterface
> InterfaceOleWrapper::createComWrapperInstance()
1612 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper(
1613 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1614 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1617 // "getType" is used in convertValueObject to map the string denoting the type
1618 // to an actual Type object.
1619 bool getType( const BSTR name
, Type
& type
)
1622 typelib_TypeDescription
* pDesc
= nullptr;
1623 OUString
str(o3tl::toU(name
));
1624 typelib_typedescription_getByName( &pDesc
, str
.pData
);
1627 type
= Type( pDesc
->pWeakRef
);
1628 typelib_typedescription_release( pDesc
);
1634 static bool writeBackOutParameter2( VARIANTARG
* pDest
, VARIANT
* pSource
)
1639 // Handle JScriptValue objects and JScript out params ( Array object )
1640 CComVariant
varDest( *pDest
);
1642 if( SUCCEEDED( varDest
.ChangeType(VT_DISPATCH
)))
1644 CComPtr
<IDispatch
> spDispDest(varDest
.pdispVal
);
1646 // special Handling for a JScriptValue object
1647 CComQIPtr
<IJScriptValueObject
> spValueDest(spDispDest
);
1650 VARIANT_BOOL varBool
= VARIANT_FALSE
;
1651 if ((SUCCEEDED(hr
= spValueDest
->IsOutParam(&varBool
))
1652 && varBool
== VARIANT_TRUE
)
1653 || (SUCCEEDED(hr
= spValueDest
->IsInOutParam(&varBool
))
1654 && varBool
== VARIANT_TRUE
))
1656 if( SUCCEEDED( spValueDest
->Set( CComVariant(), *pSource
)))
1660 else if (pDest
->vt
== VT_DISPATCH
)// VT_DISPATCH -> JScript out param
1662 // We use IDispatchEx because its GetDispID function causes the creation
1663 // of a property if it does not exist already. This is convenient for
1664 // out parameters in JScript. Then the user must not specify property "0"
1666 CComQIPtr
<IDispatchEx
> spDispEx( spDispDest
);
1669 CComBSTR
nullProp(L
"0");
1671 if( SUCCEEDED( spDispEx
->GetDispID( nullProp
, fdexNameEnsure
, &dwDispID
)))
1673 DISPPARAMS dispparams
= {nullptr, nullptr, 1, 1};
1674 dispparams
.rgvarg
= pSource
;
1675 DISPID dispidPut
= DISPID_PROPERTYPUT
;
1676 dispparams
.rgdispidNamedArgs
= &dispidPut
;
1678 if (pSource
->vt
== VT_UNKNOWN
|| pSource
->vt
== VT_DISPATCH
||
1679 (pSource
->vt
& VT_ARRAY
) || (pSource
->vt
& VT_BYREF
))
1680 hr
= spDispEx
->InvokeEx(dwDispID
, LOCALE_USER_DEFAULT
, DISPATCH_PROPERTYPUTREF
,
1681 &dispparams
, nullptr, nullptr, nullptr);
1683 hr
= spDispEx
->InvokeEx(dwDispID
, LOCALE_USER_DEFAULT
, DISPATCH_PROPERTYPUT
,
1684 &dispparams
, nullptr, nullptr, nullptr);
1691 ret
= writeBackOutParameter( pDest
, pSource
);
1693 else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript
1694 { // param. The function checks itself for correct VBScript params
1695 ret
= writeBackOutParameter( pDest
, pSource
);
1700 // VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter.
1701 // Thus we are in charge of freeing an eventual value contained by the inner VARIANT
1702 // Please note: VariantCopy doesn't free a VT_BYREF value
1703 // The out parameters are expected to have always a valid type
1704 static bool writeBackOutParameter(VARIANTARG
* pDest
, VARIANT
* pSource
)
1708 // Out parameter must be VT_BYREF
1709 if ((V_VT(pDest
) & VT_BYREF
) != 0 )
1711 VARTYPE oleTypeFlags
= V_VT(pSource
);
1713 // if caller accept VARIANT as out parameter, any value must be converted
1714 if (V_VT(pDest
) == (VT_VARIANT
| VT_BYREF
))
1716 // When the user provides a VARIANT rather than a concrete type
1717 // we just copy the source to the out, in/out parameter
1718 // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that
1719 // is contained in pDest are released by VariantCopy
1720 VariantCopy(V_VARIANTREF(pDest
), pSource
);
1725 // variantarg and variant must have same type
1726 if ((V_VT(pDest
) & oleTypeFlags
) == oleTypeFlags
)
1728 if ((oleTypeFlags
& VT_ARRAY
) != 0)
1731 if( *V_ARRAYREF(pDest
) != nullptr)
1732 hr
= SafeArrayCopyData( V_ARRAY(pSource
), *V_ARRAYREF(pDest
));
1735 hr
= SafeArrayCopy(V_ARRAY(pSource
), V_ARRAYREF(pDest
));
1742 switch (V_VT(pSource
))
1746 *V_I2REF(pDest
) = V_I2(pSource
);
1751 *V_I4REF(pDest
) = V_I4(pSource
);
1755 *V_R4REF(pDest
) = V_R4(pSource
);
1759 *V_R8REF(pDest
) = V_R8(pSource
);
1763 *V_CYREF(pDest
) = V_CY(pSource
);
1767 *V_DATEREF(pDest
) = V_DATE(pSource
);
1771 SysFreeString( *pDest
->pbstrVal
);
1773 *V_BSTRREF(pDest
) = SysAllocString(V_BSTR(pSource
));
1777 if (*V_DISPATCHREF(pDest
) != nullptr)
1778 (*V_DISPATCHREF(pDest
))->Release();
1780 *V_DISPATCHREF(pDest
) = V_DISPATCH(pSource
);
1782 if (*V_DISPATCHREF(pDest
) != nullptr)
1783 (*V_DISPATCHREF(pDest
))->AddRef();
1788 *V_ERRORREF(pDest
) = V_ERROR(pSource
);
1792 *V_BOOLREF(pDest
) = V_BOOL(pSource
);
1796 if (*V_UNKNOWNREF(pDest
) != nullptr)
1797 (*V_UNKNOWNREF(pDest
))->Release();
1799 *V_UNKNOWNREF(pDest
) = V_UNKNOWN(pSource
);
1801 if (*V_UNKNOWNREF(pDest
) != nullptr)
1802 (*V_UNKNOWNREF(pDest
))->AddRef();
1807 *V_I1REF(pDest
) = V_I1(pSource
);
1811 *V_UI1REF(pDest
) = V_UI1(pSource
);
1815 *V_UI2REF(pDest
) = V_UI2(pSource
);
1819 *V_UI4REF(pDest
) = V_UI4(pSource
);
1823 *V_INTREF(pDest
) = V_INT(pSource
);
1827 *V_UINTREF(pDest
) = V_UINT(pSource
);
1831 memcpy(pDest
->pdecVal
, pSource
, sizeof(DECIMAL
));
1841 // Handling of special cases
1842 // Destination and source types are different
1843 if( pDest
->vt
== (VT_BSTR
| VT_BYREF
)
1844 && pSource
->vt
== VT_I2
)
1846 // When the user provides a String as out our in/out parameter
1847 // and the type is char (TypeClass_CHAR) then we convert to a BSTR
1848 // instead of VT_I2 as is done otherwise
1849 OLECHAR buff
[]= {0,0};
1850 buff
[0]= pSource
->iVal
;
1852 SysFreeString( *pDest
->pbstrVal
);
1853 *pDest
->pbstrVal
= SysAllocString( buff
);
1862 COM_DECLSPEC_NOTHROW STDMETHODIMP
InterfaceOleWrapper::Invoke(DISPID dispidMember
,
1866 DISPPARAMS
* pdispparams
,
1867 VARIANT
* pvarResult
,
1868 EXCEPINFO
* pexcepinfo
,
1871 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
1874 #if defined SAL_LOG_INFO
1876 for (unsigned int i
= 0; i
< pdispparams
->cArgs
; ++i
)
1880 std::stringstream aStringStream
;
1881 aStringStream
<< pdispparams
->rgvarg
[i
];
1882 sParams
+= OUString::createFromAscii(aStringStream
.str().c_str());
1886 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::Invoke(" << dispidMember
<< "," << sParams
<< ")");
1888 comphelper::ProfileZone
aZone("COM Bridge");
1893 bool bHandled
= false;
1894 ret
= InvokeGeneral( dispidMember
, wFlags
, pdispparams
, pvarResult
, pexcepinfo
,
1895 puArgErr
, bHandled
);
1899 if ((dispidMember
> 0) && (static_cast<size_t>(dispidMember
) <= m_MemberInfos
.size()) && m_xInvocation
.is())
1901 MemberInfo d
= m_MemberInfos
[dispidMember
- 1];
1902 DWORD flags
= wFlags
& d
.flags
;
1906 if ((flags
& DISPATCH_METHOD
) != 0)
1908 std::unique_ptr
<DISPPARAMS
> pNewDispParams
;
1909 std::vector
<VARIANTARG
> vNewArgs
;
1911 if (pdispparams
->cNamedArgs
> 0)
1913 // Convert named arguments to positional ones.
1917 // Function declaration (in pseudo-code):
1918 // int foo(int A, int B, optional int C, optional int D, optional int E, optional int F, optional int G)
1920 // Corresponding parameter numbers (DISPIDs):
1924 // foo(10, 20, E:=50, D:=40, F:=60)
1926 // That is, A and B are passed positionally, D, E, and F as named arguments,
1927 // and the optional C and G parameters are left out.
1929 // Incoming DISPPARAMS:
1930 // cArgs=5, cNamedArgs=3
1931 // rgvarg: [60, 40, 50, 20, 10]
1932 // rgdispidNamedArgs: [5, 3, 4]
1934 // We calculate nLowestNamedArgDispid = 3 and nHighestNamedArgDispid = 5.
1936 // Result of conversion, no named args:
1937 // cArgs=6, cNamedArgs=0
1938 // rgvarg: [60, 50, 40, DISP_E_PARAMNOTFOUND, 20, 10]
1940 // First find the lowest and highest DISPID of the named arguments.
1941 DISPID nLowestNamedArgDispid
= 1000000;
1942 DISPID nHighestNamedArgDispid
= -1;
1943 for (unsigned int i
= 0; i
< pdispparams
->cNamedArgs
; ++i
)
1945 if (pdispparams
->rgdispidNamedArgs
[i
] < nLowestNamedArgDispid
)
1946 nLowestNamedArgDispid
= pdispparams
->rgdispidNamedArgs
[i
];
1947 if (pdispparams
->rgdispidNamedArgs
[i
] > nHighestNamedArgDispid
)
1948 nHighestNamedArgDispid
= pdispparams
->rgdispidNamedArgs
[i
];
1951 // Make sure named arguments don't overlap with positional ones. The lowest
1952 // DISPID of the named arguments should be >= the number of positional
1954 if (nLowestNamedArgDispid
< static_cast<DISPID
>(pdispparams
->cArgs
- pdispparams
->cNamedArgs
))
1955 return DISP_E_NONAMEDARGS
;
1957 // Do the actual conversion.
1958 pNewDispParams
.reset(new DISPPARAMS
);
1959 vNewArgs
.resize(nHighestNamedArgDispid
+ 1);
1960 pNewDispParams
->rgvarg
= vNewArgs
.data();
1961 pNewDispParams
->rgdispidNamedArgs
= nullptr;
1962 pNewDispParams
->cArgs
= nHighestNamedArgDispid
+ 1;
1963 pNewDispParams
->cNamedArgs
= 0;
1965 // Initialise all parameter slots as missing
1966 for (int i
= 0; i
< nHighestNamedArgDispid
; ++i
)
1968 pNewDispParams
->rgvarg
[i
].vt
= VT_ERROR
;
1969 pNewDispParams
->rgvarg
[i
].scode
= DISP_E_PARAMNOTFOUND
;
1972 // Then set the value of those actually present.
1973 for (unsigned int i
= 0; i
< pdispparams
->cNamedArgs
; ++i
)
1974 pNewDispParams
->rgvarg
[nHighestNamedArgDispid
- pdispparams
->rgdispidNamedArgs
[i
]] = pdispparams
->rgvarg
[i
];
1976 const int nFirstUnnamedArg
= pdispparams
->cNamedArgs
+ (nLowestNamedArgDispid
-(pdispparams
->cArgs
- pdispparams
->cNamedArgs
));
1978 for (unsigned int i
= pdispparams
->cNamedArgs
; i
< pdispparams
->cArgs
; ++i
)
1979 pNewDispParams
->rgvarg
[nFirstUnnamedArg
+ (i
-pdispparams
->cNamedArgs
)] = pdispparams
->rgvarg
[i
];
1981 pdispparams
= pNewDispParams
.get();
1984 Sequence
<Any
> params
;
1986 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
1988 ret
= doInvoke(pdispparams
, pvarResult
,
1989 pexcepinfo
, puArgErr
, d
.name
, params
);
1991 else if ((flags
& DISPATCH_PROPERTYGET
) != 0)
1993 ret
= doGetProperty( pdispparams
, pvarResult
,
1994 pexcepinfo
, d
.name
);
1996 else if ((flags
& DISPATCH_PROPERTYPUT
) != 0 || (flags
& DISPATCH_PROPERTYPUTREF
) != 0)
1998 if (pdispparams
->cArgs
!= 1)
1999 ret
= DISP_E_BADPARAMCOUNT
;
2002 Sequence
<Any
> params
;
2003 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
2004 if(params
.getLength() > 0)
2005 ret
= doSetProperty( pdispparams
, pvarResult
, pexcepinfo
, puArgErr
, d
.name
, params
);
2007 ret
= DISP_E_BADVARTYPE
;
2012 ret
= DISP_E_MEMBERNOTFOUND
;
2015 ret
= DISP_E_MEMBERNOTFOUND
;
2017 catch(const BridgeRuntimeError
& e
)
2019 writeExcepinfo(pexcepinfo
, e
.message
);
2020 ret
= DISP_E_EXCEPTION
;
2022 catch(const Exception
& e
)
2024 OUString message
= "InterfaceOleWrapper::Invoke : \n" +
2026 writeExcepinfo(pexcepinfo
, message
);
2027 ret
= DISP_E_EXCEPTION
;
2031 OUString message
= "InterfaceOleWrapper::Invoke : \n"
2032 "Unexpected exception";
2033 writeExcepinfo(pexcepinfo
, message
);
2034 ret
= DISP_E_EXCEPTION
;
2040 HRESULT
InterfaceOleWrapper::doInvoke( DISPPARAMS
* pdispparams
, VARIANT
* pvarResult
,
2041 EXCEPINFO
* pexcepinfo
, unsigned int * puArgErr
, OUString
& name
, Sequence
<Any
>& params
)
2048 Sequence
<sal_Int16
> outIndex
;
2049 Sequence
<Any
> outParams
;
2052 if (pdispparams
->cNamedArgs
> 0)
2053 return DISP_E_NONAMEDARGS
;
2055 // invoke method and take care of exceptions
2056 returnValue
= m_xInvocation
->invoke(name
,
2061 // try to write back out parameter
2062 if (outIndex
.getLength() > 0)
2064 const sal_Int16
* pOutIndex
= outIndex
.getConstArray();
2065 const Any
* pOutParams
= outParams
.getConstArray();
2067 for (sal_Int32 i
= 0; i
< outIndex
.getLength(); i
++)
2069 CComVariant variant
;
2070 // Currently a Sequence is converted to an SafeArray of VARIANTs.
2071 anyToVariant( &variant
, pOutParams
[i
]);
2073 // out parameter need special handling if they are VT_DISPATCH
2074 // and used in JScript
2075 int outindex
= pOutIndex
[i
];
2076 writeBackOutParameter2(&(pdispparams
->rgvarg
[pdispparams
->cArgs
- 1 - outindex
]),
2081 // write back return value
2082 if (pvarResult
!= nullptr)
2083 anyToVariant(pvarResult
, returnValue
);
2085 catch(const IllegalArgumentException
& e
) //XInvocation::invoke
2087 writeExcepinfo(pexcepinfo
, e
.Message
);
2088 ret
= DISP_E_TYPEMISMATCH
;
2090 catch(const CannotConvertException
& e
) //XInvocation::invoke
2092 writeExcepinfo(pexcepinfo
, e
.Message
);
2093 ret
= mapCannotConvertException( e
, puArgErr
);
2095 catch(const InvocationTargetException
& e
) //XInvocation::invoke
2097 const Any
& org
= e
.TargetException
;
2098 Exception excTarget
;
2101 org
.getValueType().getTypeName() + ": " + excTarget
.Message
;
2102 writeExcepinfo(pexcepinfo
, message
);
2103 ret
= DISP_E_EXCEPTION
;
2105 catch(const NoSuchMethodException
& e
) //XInvocation::invoke
2107 writeExcepinfo(pexcepinfo
, e
.Message
);
2108 ret
= DISP_E_MEMBERNOTFOUND
;
2110 catch(const BridgeRuntimeError
& e
)
2112 writeExcepinfo(pexcepinfo
, e
.message
);
2113 ret
= DISP_E_EXCEPTION
;
2115 catch(const Exception
& e
)
2117 OUString message
= "InterfaceOleWrapper::doInvoke : \n" +
2119 writeExcepinfo(pexcepinfo
, message
);
2120 ret
= DISP_E_EXCEPTION
;
2124 OUString message
= "InterfaceOleWrapper::doInvoke : \n"
2125 "Unexpected exception";
2126 writeExcepinfo(pexcepinfo
, message
);
2127 ret
= DISP_E_EXCEPTION
;
2132 HRESULT
InterfaceOleWrapper::doGetProperty( DISPPARAMS
* /*pdispparams*/, VARIANT
* pvarResult
,
2133 EXCEPINFO
* pexcepinfo
, OUString
& name
)
2139 Any returnValue
= m_xInvocation
->getValue( name
);
2140 // write back return value
2142 anyToVariant(pvarResult
, returnValue
);
2144 catch(const UnknownPropertyException
& e
) //XInvocation::getValue
2146 writeExcepinfo(pexcepinfo
, e
.Message
);
2147 ret
= DISP_E_MEMBERNOTFOUND
;
2149 catch(const BridgeRuntimeError
& e
)
2151 writeExcepinfo(pexcepinfo
, e
.message
);
2152 ret
= DISP_E_EXCEPTION
;
2154 catch(const Exception
& e
)
2156 OUString message
= "InterfaceOleWrapper::doGetProperty : \n" +
2158 writeExcepinfo(pexcepinfo
, message
);
2162 OUString message
= "InterfaceOleWrapper::doInvoke : \n"
2163 "Unexpected exception";
2164 writeExcepinfo(pexcepinfo
, message
);
2165 ret
= DISP_E_EXCEPTION
;
2170 HRESULT
InterfaceOleWrapper::doSetProperty( DISPPARAMS
* /*pdispparams*/, VARIANT
* /*pvarResult*/,
2171 EXCEPINFO
* pexcepinfo
, unsigned int * puArgErr
, OUString
& name
, Sequence
<Any
> const & params
)
2177 m_xInvocation
->setValue( name
, params
.getConstArray()[0]);
2179 catch(const UnknownPropertyException
&)
2181 ret
= DISP_E_MEMBERNOTFOUND
;
2183 catch(const CannotConvertException
&e
)
2185 ret
= mapCannotConvertException( e
, puArgErr
);
2187 catch(const InvocationTargetException
&e
)
2189 if (pexcepinfo
!= nullptr)
2191 Any org
= e
.TargetException
;
2193 pexcepinfo
->wCode
= UNO_2_OLE_EXCEPTIONCODE
;
2194 pexcepinfo
->bstrSource
= SysAllocString(L
"any ONE component");
2195 pexcepinfo
->bstrDescription
= SysAllocString(
2196 o3tl::toW(org
.getValueType().getTypeName().getStr()));
2198 ret
= DISP_E_EXCEPTION
;
2202 ret
= DISP_E_EXCEPTION
;
2207 class CXEnumVariant
: public IEnumVARIANT
,
2208 public CComObjectRoot
2212 : mnIndex(1) // ooo::vba::XCollection index starts at one
2216 virtual ~CXEnumVariant()
2220 #if defined __clang__
2221 #pragma clang diagnostic push
2222 #pragma clang diagnostic ignored "-Wunused-function"
2224 BEGIN_COM_MAP(CXEnumVariant
)
2225 #if defined __clang__
2226 #pragma clang diagnostic pop
2228 COM_INTERFACE_ENTRY(IEnumVARIANT
)
2229 #if defined __clang__
2230 #pragma clang diagnostic push
2231 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
2232 #pragma clang diagnostic ignored "-Wunused-function"
2235 #if defined __clang__
2236 #pragma clang diagnostic pop
2239 DECLARE_NOT_AGGREGATABLE(CXEnumVariant
)
2241 // Creates and initializes the enumerator
2242 void Init(InterfaceOleWrapper
* pInterfaceOleWrapper
,
2243 const Reference
<ooo::vba::XCollection
> xCollection
)
2245 mpInterfaceOleWrapper
= pInterfaceOleWrapper
;
2246 mxCollection
= xCollection
;
2250 virtual HRESULT STDMETHODCALLTYPE
Clone(IEnumVARIANT
**) override
2252 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Clone: E_NOTIMPL");
2256 virtual HRESULT STDMETHODCALLTYPE
Next(ULONG
const celt
,
2258 ULONG
*pCeltFetched
) override
2260 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2267 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): E_INVALIDARG");
2268 return E_INVALIDARG
;
2271 if (rgVar
== nullptr || (celt
!= 1 && pCeltFetched
== nullptr))
2273 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): E_FAIL");
2277 for (ULONG i
= 0; i
< celt
; i
++)
2278 VariantInit(&rgVar
[i
]);
2281 ULONG nReturned
= 0;
2284 if (mnIndex
> mxCollection
->getCount())
2286 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): got " << nReturned
<< ": S_FALSE");
2291 Any aElement
= mxCollection
->Item(aIndex
, Any());
2292 mpInterfaceOleWrapper
->anyToVariant(rgVar
, aElement
);
2293 // rgVar->pdispVal->AddRef(); ??
2301 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Next(" << celt
<< "): S_OK");
2305 virtual HRESULT STDMETHODCALLTYPE
Reset() override
2307 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Reset: S_OK");
2312 virtual HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE
Skip(ULONG
const celt
) override
2314 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2320 if (mnIndex
> mxCollection
->getCount())
2322 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Skip(" << celt
<< "): skipped " << nSkipped
<< ": S_FALSE");
2328 SAL_INFO("extensions.olebridge", this << "@CXEnumVariant::Skip(" << celt
<< "): S_OK");
2333 InterfaceOleWrapper
* mpInterfaceOleWrapper
;
2334 Reference
<ooo::vba::XCollection
> mxCollection
;
2338 class Sink
: public cppu::WeakImplHelper
<ooo::vba::XSink
>
2341 Sink(IUnknown
* pUnkSink
,
2342 Reference
<XMultiServiceFactory
> xMSF
,
2343 ooo::vba::TypeAndIID aTypeAndIID
,
2344 InterfaceOleWrapper
* pInterfaceOleWrapper
);
2347 void SAL_CALL
Call( const OUString
& Method
, Sequence
< Any
>& Arguments
) override
;
2350 IUnknown
* mpUnkSink
;
2351 Reference
<XMultiServiceFactory
> mxMSF
;
2352 ooo::vba::TypeAndIID maTypeAndIID
;
2353 InterfaceOleWrapper
* mpInterfaceOleWrapper
;
2356 Sink::Sink(IUnknown
* pUnkSink
,
2357 Reference
<XMultiServiceFactory
> xMSF
,
2358 ooo::vba::TypeAndIID aTypeAndIID
,
2359 InterfaceOleWrapper
* pInterfaceOleWrapper
) :
2360 mpUnkSink(pUnkSink
),
2362 maTypeAndIID(aTypeAndIID
),
2363 mpInterfaceOleWrapper(pInterfaceOleWrapper
)
2365 mpUnkSink
->AddRef();
2369 Sink::Call( const OUString
& Method
, Sequence
< Any
>& Arguments
)
2371 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method
<< ", " << Arguments
.getLength() << " arguments)");
2373 IDispatch
* pDispatch
;
2374 HRESULT nResult
= mpUnkSink
->QueryInterface(IID_IDispatch
, reinterpret_cast<void **>(&pDispatch
));
2375 if (!SUCCEEDED(nResult
))
2377 SAL_WARN("extensions.olebridge", "Sink::Call: Not IDispatch: " << WindowsErrorStringFromHRESULT(nResult
));
2381 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(mxMSF
));
2384 Reference
<XIdlClass
> xClass
= xRefl
->forName(maTypeAndIID
.Type
.getTypeName());
2385 assert(xClass
.is());
2387 auto aMethods
= xClass
->getMethods();
2388 assert(xClass
->getTypeClass() == TypeClass_INTERFACE
&&
2389 aMethods
.getLength() > 0);
2392 // Skip the three XInterface methods
2393 for (int i
= 3; i
< aMethods
.getLength(); i
++)
2395 if (aMethods
[i
]->getName() == Method
)
2397 // FIXME: Handle mismatch in type of actual argument and parameter of the method.
2399 // FIXME: Handle mismatch in number of arguments passed and actual number of parameters
2402 auto aParamInfos
= aMethods
[i
]->getParameterInfos();
2404 assert(Arguments
.getLength() == aParamInfos
.getLength());
2406 DISPPARAMS aDispParams
;
2407 aDispParams
.rgdispidNamedArgs
= nullptr;
2408 aDispParams
.cArgs
= Arguments
.getLength();
2409 aDispParams
.cNamedArgs
= 0;
2410 aDispParams
.rgvarg
= new VARIANT
[aDispParams
.cArgs
];
2411 for (unsigned j
= 0; j
< aDispParams
.cArgs
; j
++)
2413 VariantInit(aDispParams
.rgvarg
+j
);
2414 // Note: Reverse order of arguments in Arguments and aDispParams.rgvarg!
2415 const unsigned nIncomingArgIndex
= aDispParams
.cArgs
- j
- 1;
2416 mpInterfaceOleWrapper
->anyToVariant(aDispParams
.rgvarg
+j
, Arguments
[nIncomingArgIndex
]);
2418 // Handle OUT and INOUT arguments. For instance, the second ('Cancel') parameter to
2419 // DocumentBeforeClose() should be a VT_BYREF|VT_BOOL parameter. Need to handle that
2422 if (aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_OUT
||
2423 aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_INOUT
)
2425 switch (aDispParams
.rgvarg
[j
].vt
)
2428 aDispParams
.rgvarg
[j
].byref
= new SHORT(aDispParams
.rgvarg
[j
].iVal
);
2429 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2432 aDispParams
.rgvarg
[j
].byref
= new LONG(aDispParams
.rgvarg
[j
].lVal
);
2433 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2436 aDispParams
.rgvarg
[j
].byref
= new BSTR(aDispParams
.rgvarg
[j
].bstrVal
);
2437 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2440 // SAL_ DEBUG("===> VT_BOOL is initially " << (int)aDispParams.rgvarg[j].boolVal);
2441 aDispParams
.rgvarg
[j
].byref
= new VARIANT_BOOL(aDispParams
.rgvarg
[j
].boolVal
);
2442 // SAL_ DEBUG(" byref=" << aDispParams.rgvarg[j].byref);
2443 aDispParams
.rgvarg
[j
].vt
|= VT_BYREF
;
2446 assert(false && "Not handled yet");
2453 VariantInit(&aVarResult
);
2456 // In the case of a VBScript client, which uses "late binding", calling Invoke on the
2457 // sink it provides will cause a callback to our CXTypeInfo::GetNames for the given
2458 // member id, and in that we will tell it the name of the corresponding method, and the
2459 // client will know what event handler to invoke based on that name.
2461 // As the outgoing interfaces used (ooo::vba::word::XApplicationOutgoing and others) are
2462 // totally not stable and not published in any way, there can be no client that would
2463 // have done "compile-time binding" and where the sink would actually be an object with
2464 // a vtbl corresponding to the outgoing interface. Late binding clients that work like
2465 // VBScript is all we support.
2466 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method
<< "): Calling Invoke(" << nMemId
<< ")");
2468 nResult
= pDispatch
->Invoke(nMemId
, IID_NULL
, LOCALE_USER_DEFAULT
, DISPATCH_METHOD
, &aDispParams
, &aVarResult
, nullptr, &uArgErr
);
2469 SAL_INFO("extensions.olebridge", "Sink::Call(" << Method
<< "): Invoke() returned");
2471 SAL_WARN_IF(!SUCCEEDED(nResult
), "extensions.olebridge", "Call to " << Method
<< " failed: " << WindowsErrorStringFromHRESULT(nResult
));
2473 // Undo VT_BYREF magic done above. Copy out parameters back to the Anys in Arguments
2474 for (unsigned j
= 0; j
< aDispParams
.cArgs
; j
++)
2476 const unsigned nIncomingArgIndex
= aDispParams
.cArgs
- j
- 1;
2477 if (aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_OUT
||
2478 aParamInfos
[nIncomingArgIndex
].aMode
== ParamMode_INOUT
)
2480 switch (aDispParams
.rgvarg
[j
].vt
)
2482 case VT_BYREF
|VT_I2
:
2484 SHORT
*pI
= static_cast<SHORT
*>(aDispParams
.rgvarg
[j
].byref
);
2485 Arguments
[nIncomingArgIndex
] <<= static_cast<sal_Int16
>(*pI
);
2489 case VT_BYREF
|VT_I4
:
2491 LONG
*pL
= static_cast<LONG
*>(aDispParams
.rgvarg
[j
].byref
);
2492 Arguments
[nIncomingArgIndex
] <<= static_cast<sal_Int32
>(*pL
);
2496 case VT_BYREF
|VT_BSTR
:
2498 BSTR
*pBstr
= static_cast<BSTR
*>(aDispParams
.rgvarg
[j
].byref
);
2499 Arguments
[nIncomingArgIndex
] <<= OUString(o3tl::toU(*pBstr
));
2500 // Undo SysAllocString() done in anyToVariant()
2501 SysFreeString(*pBstr
);
2505 case VT_BYREF
|VT_BOOL
:
2507 VARIANT_BOOL
*pBool
= static_cast<VARIANT_BOOL
*>(aDispParams
.rgvarg
[j
].byref
);
2508 // SAL_ DEBUG("===> VT_BOOL: byref is now " << aDispParams.rgvarg[j].byref << ", " << (int)*pBool);
2509 Arguments
[nIncomingArgIndex
] <<= (*pBool
!= VARIANT_FALSE
);
2514 assert(false && "Not handled yet");
2520 switch (aDispParams
.rgvarg
[j
].vt
)
2523 // Undo SysAllocString() done in anyToVariant()
2524 SysFreeString(aDispParams
.rgvarg
[j
].bstrVal
);
2530 delete[] aDispParams
.rgvarg
;
2535 SAL_WARN("extensions.olebridge", "Sink::Call: Unknown method '" << Method
<< "'");
2538 class CXEnumConnections
: public IEnumConnections
,
2539 public CComObjectRoot
2546 virtual ~CXEnumConnections()
2550 #if defined __clang__
2551 #pragma clang diagnostic push
2552 #pragma clang diagnostic ignored "-Wunused-function"
2554 BEGIN_COM_MAP(CXEnumConnections
)
2555 #if defined __clang__
2556 #pragma clang diagnostic pop
2558 COM_INTERFACE_ENTRY(IEnumConnections
)
2559 #if defined __clang__
2560 #pragma clang diagnostic push
2561 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
2562 #pragma clang diagnostic ignored "-Wunused-function"
2565 #if defined __clang__
2566 #pragma clang diagnostic pop
2569 DECLARE_NOT_AGGREGATABLE(CXEnumConnections
)
2571 void Init(std::vector
<IUnknown
*>& rUnknowns
, std::vector
<DWORD
>& rCookies
)
2573 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Init");
2574 SAL_WARN_IF(rUnknowns
.size() != rCookies
.size(), "extensions.olebridge", "Vectors of different size");
2575 mvUnknowns
= rUnknowns
;
2576 mvCookies
= rCookies
;
2580 virtual HRESULT STDMETHODCALLTYPE
Next(ULONG cConnections
,
2582 ULONG
*pcFetched
) override
2584 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2588 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): E_POINTER");
2592 if (pcFetched
&& cConnections
!= 1)
2594 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): E_INVALIDARG");
2595 return E_INVALIDARG
;
2599 while (nFetched
< cConnections
&& mnIndex
< mvUnknowns
.size())
2601 rgcd
[nFetched
].pUnk
= mvUnknowns
[mnIndex
];
2602 rgcd
[nFetched
].pUnk
->AddRef();
2603 rgcd
[nFetched
].dwCookie
= mvCookies
[mnIndex
];
2607 if (nFetched
!= cConnections
)
2609 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): S_FALSE");
2611 *pcFetched
= nFetched
;
2614 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections
<< "): S_OK");
2616 *pcFetched
= nFetched
;
2621 virtual HRESULT STDMETHODCALLTYPE
Skip(ULONG cConnections
) override
2623 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Skip(" << cConnections
<< "): E_NOTIMPL");
2628 virtual HRESULT STDMETHODCALLTYPE
Reset() override
2630 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Reset: E_NOTIMPL");
2635 virtual HRESULT STDMETHODCALLTYPE
Clone(IEnumConnections
** /* ppEnum */) override
2637 SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Clone: E_NOTIMPL");
2643 std::vector
<IUnknown
*> mvUnknowns
;
2644 std::vector
<DWORD
> mvCookies
;
2648 class CXConnectionPoint
: public IConnectionPoint
,
2649 public CComObjectRoot
2652 #if defined __clang__
2653 #pragma clang diagnostic push
2654 #pragma clang diagnostic ignored "-Wunused-function"
2656 BEGIN_COM_MAP(CXConnectionPoint
)
2657 #if defined __clang__
2658 #pragma clang diagnostic pop
2660 COM_INTERFACE_ENTRY(IConnectionPoint
)
2661 #if defined __clang__
2662 #pragma clang diagnostic push
2663 #pragma clang diagnostic ignored "-Winconsistent-missing-override"
2664 #pragma clang diagnostic ignored "-Wunused-function"
2667 #if defined __clang__
2668 #pragma clang diagnostic pop
2671 DECLARE_NOT_AGGREGATABLE(CXConnectionPoint
)
2673 virtual ~CXConnectionPoint() {}
2675 void Init(InterfaceOleWrapper
* pInterfaceOleWrapper
,
2676 Reference
<ooo::vba::XConnectionPoint
>& xCP
,
2677 Reference
<XMultiServiceFactory
>& xMSF
,
2678 ooo::vba::TypeAndIID aTypeAndIID
)
2680 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Init for " << pInterfaceOleWrapper
->getImplementationName());
2683 if (SUCCEEDED(QueryInterface(IID_IUnknown
, reinterpret_cast<void **>(&pUnknown
))))
2685 // In case QI for IUnknown returns a different pointer, but nah, it doesn't
2686 SAL_INFO("extensions.olebridge", " (IUnknown@" << pUnknown
<< ")");
2689 mpInterfaceOleWrapper
= pInterfaceOleWrapper
;
2692 maTypeAndIID
= aTypeAndIID
;
2695 virtual HRESULT STDMETHODCALLTYPE
GetConnectionInterface(IID
*pIID
) override
2697 SAL_WARN("extensions.olebridge", this << "@CXConnectionPoint::GetConnectionInterface(" << *pIID
<< "): E_NOTIMPL");
2704 virtual HRESULT STDMETHODCALLTYPE
GetConnectionPointContainer(IConnectionPointContainer
**) override
2706 SAL_WARN("extensions.olebridge", this << "@CXConnectionPoint::GetConnectionInterface: E_NOTIMPL");
2713 virtual HRESULT STDMETHODCALLTYPE
Advise(IUnknown
*pUnkSink
,
2714 DWORD
*pdwCookie
) override
2716 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2718 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Advise(" << pUnkSink
<< ")");
2723 Reference
<ooo::vba::XSink
> xSink(new Sink(pUnkSink
, mxMSF
, maTypeAndIID
, mpInterfaceOleWrapper
));
2725 mvISinks
.push_back(pUnkSink
);
2726 *pdwCookie
= mvISinks
.size();
2728 mvCookies
.push_back(mxCP
->Advise(xSink
));
2730 mvXSinks
.push_back(xSink
);
2732 SAL_INFO("extensions.olebridge", " *pdwCookie: " << *pdwCookie
);
2737 virtual HRESULT STDMETHODCALLTYPE
Unadvise(DWORD dwCookie
) override
2739 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2741 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::Unadvise(" << dwCookie
<< ")");
2743 if (dwCookie
== 0 || dwCookie
> mvISinks
.size())
2746 mvISinks
[dwCookie
-1] = nullptr;
2748 mxCP
->Unadvise(mvCookies
[dwCookie
-1]);
2750 mvXSinks
[dwCookie
-1] = Reference
<ooo::vba::XSink
>();
2755 virtual HRESULT STDMETHODCALLTYPE
EnumConnections(IEnumConnections
**ppEnum
) override
2757 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
2761 SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::EnumConnections...");
2765 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: E_POINTER");
2769 CComObject
<CXEnumConnections
>* pEnumConnections
;
2771 nResult
= CComObject
<CXEnumConnections
>::CreateInstance(&pEnumConnections
);
2772 if (FAILED(nResult
))
2774 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: " << WindowsErrorStringFromHRESULT(nResult
));
2778 pEnumConnections
->AddRef();
2780 pEnumConnections
->Init(mvISinks
, mvCookies
);
2781 *ppEnum
= pEnumConnections
;
2783 SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: S_OK");
2788 InterfaceOleWrapper
* mpInterfaceOleWrapper
;
2789 std::vector
<IUnknown
*> mvISinks
;
2790 std::vector
<Reference
<ooo::vba::XSink
>> mvXSinks
;
2791 std::vector
<DWORD
> mvCookies
;
2792 Reference
<XMultiServiceFactory
> mxMSF
;
2793 Reference
<ooo::vba::XConnectionPoint
> mxCP
;
2794 ooo::vba::TypeAndIID maTypeAndIID
;
2797 HRESULT
InterfaceOleWrapper::InvokeGeneral( DISPID dispidMember
, unsigned short wFlags
,
2798 DISPPARAMS
* pdispparams
, VARIANT
* pvarResult
, EXCEPINFO
* pexcepinfo
,
2799 unsigned int * /*puArgErr*/, bool& bHandled
)
2804 // DISPID_VALUE | The DEFAULT Value is required in JScript when the situation
2805 // is that we put an object into an Array object ( out parameter). We have to return
2806 // IDispatch otherwise the object cannot be accessed from the Script.
2807 if( dispidMember
== DISPID_VALUE
&& (wFlags
& DISPATCH_PROPERTYGET
) != 0
2808 && m_defaultValueType
!= VT_EMPTY
&& pvarResult
!= nullptr)
2810 // Special case hack: If it is a ScVbaCheckBox, return the boolean value
2811 Reference
<ooo::vba::msforms::XCheckBox
> xCheckBox(m_xOrigin
, UNO_QUERY
);
2815 Any aValue
= xCheckBox
->getValue();
2816 anyToVariant(pvarResult
, aValue
);
2821 if( m_defaultValueType
== VT_DISPATCH
)
2823 pvarResult
->vt
= VT_DISPATCH
;
2824 pvarResult
->pdispVal
= static_cast<IDispatch
*>( this);
2830 // function: _GetValueObject
2831 else if( dispidMember
== DISPID_JSCRIPT_VALUE_FUNC
)
2836 CComObject
< JScriptValue
>* pValue
;
2837 if( SUCCEEDED( CComObject
<JScriptValue
>::CreateInstance( &pValue
)))
2840 pvarResult
->vt
= VT_DISPATCH
;
2841 pvarResult
->pdispVal
= CComQIPtr
<IDispatch
>(pValue
->GetUnknown());
2845 ret
= DISP_E_EXCEPTION
;
2847 else if( dispidMember
== DISPID_GET_STRUCT_FUNC
)
2850 bool bStruct
= false;
2853 Reference
<XIdlReflection
> xRefl
= theCoreReflection::get(comphelper::getComponentContext(m_smgr
));
2854 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
2856 if( pdispparams
->cArgs
== 1 && SUCCEEDED( arg
.ChangeType( VT_BSTR
, &pdispparams
->rgvarg
[0])) )
2858 Reference
<XIdlClass
> classStruct
= xRefl
->forName(o3tl::toU(arg
.bstrVal
));
2859 if( classStruct
.is())
2862 classStruct
->createObject( anyStruct
);
2864 anyToVariant( &var
, anyStruct
);
2866 if( var
.vt
== VT_DISPATCH
)
2868 VariantCopy( pvarResult
, & var
);
2873 ret
= bStruct
? S_OK
: DISP_E_EXCEPTION
;
2875 else if (dispidMember
== DISPID_CREATE_TYPE_FUNC
)
2880 // the first parameter is in DISPPARAMS rgvargs contains the name of the struct.
2882 if( pdispparams
->cArgs
!= 1)
2883 return DISP_E_BADPARAMCOUNT
;
2884 if (FAILED( arg
.ChangeType( VT_BSTR
, &pdispparams
->rgvarg
[0])))
2885 return DISP_E_BADVARTYPE
;
2887 //check if the provided name represents a valid type
2889 if (!getType(arg
.bstrVal
, type
))
2891 writeExcepinfo(pexcepinfo
, OUStringLiteral("[automation bridge] A UNO type with the name ") +
2892 o3tl::toU(arg
.bstrVal
) + " does not exist!");
2893 return DISP_E_EXCEPTION
;
2896 if (!createUnoTypeWrapper(arg
.bstrVal
, pvarResult
))
2898 writeExcepinfo(pexcepinfo
, "[automation bridge] InterfaceOleWrapper::InvokeGeneral\n"
2899 "Could not initialize UnoTypeWrapper object!");
2900 return DISP_E_EXCEPTION
;
2903 else if (dispidMember
== DISPID_NEWENUM
)
2909 Reference
< ooo::vba::XCollection
> xCollection(m_xOrigin
, UNO_QUERY
);
2910 if (!xCollection
.is())
2911 return DISP_E_MEMBERNOTFOUND
;
2913 CComObject
<CXEnumVariant
>* pEnumVar
;
2915 ret
= CComObject
<CXEnumVariant
>::CreateInstance(&pEnumVar
);
2921 pEnumVar
->Init(this, xCollection
);
2923 pvarResult
->vt
= VT_UNKNOWN
;
2924 pvarResult
->punkVal
= nullptr;
2926 ret
= pEnumVar
->QueryInterface(IID_IUnknown
, reinterpret_cast<void**>(&pvarResult
->punkVal
));
2929 pEnumVar
->Release();
2934 catch(const BridgeRuntimeError
& e
)
2936 writeExcepinfo(pexcepinfo
, e
.message
);
2937 ret
= DISP_E_EXCEPTION
;
2939 catch(const Exception
& e
)
2941 OUString message
= "InterfaceOleWrapper::InvokeGeneral : \n" +
2943 writeExcepinfo(pexcepinfo
, message
);
2944 ret
= DISP_E_EXCEPTION
;
2948 OUString message
= "InterfaceOleWrapper::InvokeGeneral : \n"
2949 "Unexpected exception";
2950 writeExcepinfo(pexcepinfo
, message
);
2951 ret
= DISP_E_EXCEPTION
;
2956 STDMETHODIMP
InterfaceOleWrapper::GetDispID(BSTR
/*bstrName*/, DWORD
/*grfdex*/, DISPID __RPC_FAR
* /*pid*/)
2958 return ResultFromScode(E_NOTIMPL
);
2961 STDMETHODIMP
InterfaceOleWrapper::InvokeEx(
2962 /* [in] */ DISPID
/*id*/,
2963 /* [in] */ LCID
/*lcid*/,
2964 /* [in] */ WORD
/*wFlags*/,
2965 /* [in] */ DISPPARAMS __RPC_FAR
* /*pdp*/,
2966 /* [out] */ VARIANT __RPC_FAR
* /*pvarRes*/,
2967 /* [out] */ EXCEPINFO __RPC_FAR
* /*pei*/,
2968 /* [unique][in] */ IServiceProvider __RPC_FAR
* /*pspCaller*/)
2970 return ResultFromScode(E_NOTIMPL
);
2973 STDMETHODIMP
InterfaceOleWrapper::DeleteMemberByName(
2974 /* [in] */ BSTR
/*bstr*/,
2975 /* [in] */ DWORD
/*grfdex*/)
2977 return ResultFromScode(E_NOTIMPL
);
2980 STDMETHODIMP
InterfaceOleWrapper::DeleteMemberByDispID(DISPID
/*id*/)
2982 return ResultFromScode(E_NOTIMPL
);
2985 STDMETHODIMP
InterfaceOleWrapper::GetMemberProperties(
2986 /* [in] */ DISPID
/*id*/,
2987 /* [in] */ DWORD
/*grfdexFetch*/,
2988 /* [out] */ DWORD __RPC_FAR
* /*pgrfdex*/)
2990 return ResultFromScode(E_NOTIMPL
);
2993 STDMETHODIMP
InterfaceOleWrapper::GetMemberName(
2994 /* [in] */ DISPID
/*id*/,
2995 /* [out] */ BSTR __RPC_FAR
* /*pbstrName*/)
2997 return ResultFromScode(E_NOTIMPL
);
3000 STDMETHODIMP
InterfaceOleWrapper::GetNextDispID(
3001 /* [in] */ DWORD
/*grfdex*/,
3002 /* [in] */ DISPID
/*id*/,
3003 /* [out] */ DISPID __RPC_FAR
* /*pid*/)
3005 return ResultFromScode(E_NOTIMPL
);
3008 STDMETHODIMP
InterfaceOleWrapper::GetNameSpaceParent(
3009 /* [out] */ IUnknown __RPC_FAR
*__RPC_FAR
* /*ppunk*/)
3011 return ResultFromScode(E_NOTIMPL
);
3014 // IProvideClassInfo
3015 HRESULT STDMETHODCALLTYPE
InterfaceOleWrapper::GetClassInfo (
3016 /* [out] */ ITypeInfo
**ppTI
)
3018 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
3020 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::GetClassInfo");
3025 Reference
<ooo::vba::XInterfaceWithIID
> xIID(m_xOrigin
, UNO_QUERY
);
3029 OUString sIID
= xIID
->getIID();
3031 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(sIID
.pData
->buffer
), &aIID
)))
3036 CComObject
<CXTypeInfo
>* pTypeInfo
;
3038 ret
= CComObject
<CXTypeInfo
>::CreateInstance(&pTypeInfo
);
3042 pTypeInfo
->AddRef();
3044 pTypeInfo
->InitForCoclass(m_xOrigin
, m_sImplementationName
, aIID
, m_smgr
);
3051 // IConnectionPointContainer
3052 HRESULT STDMETHODCALLTYPE
InterfaceOleWrapper::EnumConnectionPoints(
3053 /* [out] */ IEnumConnectionPoints
**)
3055 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::EnumConnectionPoints");
3056 return ResultFromScode(E_NOTIMPL
);
3059 HRESULT STDMETHODCALLTYPE
InterfaceOleWrapper::FindConnectionPoint(
3060 /* [in] */ REFIID riid
,
3061 /* [out] */ IConnectionPoint
**ppCP
)
3063 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
3065 SAL_INFO("extensions.olebridge", this << "@InterfaceOleWrapper::FindConnectionPoint(" << riid
<< ")");
3070 Reference
<ooo::vba::XConnectable
> xConnectable(m_xOrigin
, UNO_QUERY
);
3072 // We checked already
3073 assert(xConnectable
.is());
3074 if (!xConnectable
.is())
3077 ooo::vba::TypeAndIID aTypeAndIID
= xConnectable
->GetConnectionPoint();
3080 if (!SUCCEEDED(IIDFromString(reinterpret_cast<LPOLESTR
>(aTypeAndIID
.IID
.pData
->buffer
), &aIID
)))
3081 return E_INVALIDARG
;
3083 if (!IsEqualIID(riid
, aIID
))
3084 return E_INVALIDARG
;
3086 Reference
<ooo::vba::XConnectionPoint
> xCP
= xConnectable
->FindConnectionPoint();
3088 return E_INVALIDARG
;
3092 CComObject
<CXConnectionPoint
>* pConnectionPoint
;
3094 ret
= CComObject
<CXConnectionPoint
>::CreateInstance(&pConnectionPoint
);
3098 pConnectionPoint
->AddRef();
3100 pConnectionPoint
->Init(this, xCP
, m_smgr
, aTypeAndIID
);
3102 *ppCP
= pConnectionPoint
;
3107 // UnoObjectWrapperRemoteOpt ---------------------------------------------------
3109 UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference
<XMultiServiceFactory
> const & aFactory
,
3110 sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
3111 InterfaceOleWrapper( aFactory
, unoWrapperClass
, comWrapperClass
),
3116 UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt()
3120 // UnoConversionUtilities
3121 Reference
< XInterface
> UnoObjectWrapperRemoteOpt::createUnoWrapperInstance()
3123 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
3124 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
3125 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
3128 COM_DECLSPEC_NOTHROW STDMETHODIMP
UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID
/*riid*/, LPOLESTR
* rgszNames
, UINT cNames
,
3129 LCID
/*lcid*/, DISPID
* rgdispid
)
3131 MutexGuard
guard( getBridgeMutex());
3135 HRESULT ret
= E_UNEXPECTED
;
3138 if( ! wcscmp( *rgszNames
, JSCRIPT_VALUE_FUNC
))
3140 *rgdispid
= DISPID_JSCRIPT_VALUE_FUNC
;
3143 else if( ! wcscmp( *rgszNames
, GET_STRUCT_FUNC
))
3145 *rgdispid
= DISPID_GET_STRUCT_FUNC
;
3149 if (m_xInvocation
.is() && (cNames
> 0))
3151 OUString
name(o3tl::toU(rgszNames
[0]));
3152 // has this name been determined as "bad"
3153 BadNameMap::iterator badIter
= m_badNameMap
.find( name
);
3154 if( badIter
== m_badNameMap
.end() )
3156 // name has not been bad before( member exists
3157 typedef NameToIdMap::iterator ITnames
;
3158 pair
< ITnames
, bool > pair_id
= m_nameToDispIdMap
.emplace(name
, m_currentId
++);
3159 // new ID inserted ?
3160 if( pair_id
.second
)
3161 {// yes, now create MemberInfo and ad to IdToMemberInfoMap
3162 MemberInfo
d(0, name
);
3163 m_idToMemberInfoMap
.emplace(m_currentId
- 1, d
);
3166 *rgdispid
= pair_id
.first
->second
;
3170 ret
= DISP_E_UNKNOWNNAME
;
3175 COM_DECLSPEC_NOTHROW STDMETHODIMP
UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember
, REFIID
/*riid*/, LCID
/*lcid*/, WORD wFlags
,
3176 DISPPARAMS
* pdispparams
, VARIANT
* pvarResult
, EXCEPINFO
* pexcepinfo
,
3179 comphelper::Automation::AutomationInvokedZone aAutomationActive
;
3184 bool bHandled
= false;
3185 ret
= InvokeGeneral( dispidMember
, wFlags
, pdispparams
, pvarResult
, pexcepinfo
,
3186 puArgErr
, bHandled
);
3190 if ( dispidMember
> 0 && m_xInvocation
.is())
3193 IdToMemberInfoMap::iterator it_MemberInfo
= m_idToMemberInfoMap
.find( dispidMember
);
3194 if( it_MemberInfo
!= m_idToMemberInfoMap
.end() )
3196 MemberInfo
& info
= it_MemberInfo
->second
;
3198 Sequence
<Any
> params
; // holds converted any s
3200 { // DISPID called for the first time
3201 if( wFlags
== DISPATCH_METHOD
)
3203 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3205 if( FAILED( ret
= doInvoke( pdispparams
, pvarResult
,
3206 pexcepinfo
, puArgErr
, info
.name
, params
))
3207 && ret
== DISP_E_MEMBERNOTFOUND
)
3209 // try to get the exact name
3211 if (m_xExactName
.is())
3213 exactName
= m_xExactName
->getExactName( info
.name
);
3215 if( !exactName
.isEmpty() )
3217 if( SUCCEEDED( ret
= doInvoke( pdispparams
, pvarResult
,
3218 pexcepinfo
, puArgErr
, exactName
, params
)))
3219 info
.name
= exactName
;
3223 if( SUCCEEDED( ret
) )
3224 info
.flags
= DISPATCH_METHOD
;
3226 else if( wFlags
== DISPATCH_PROPERTYPUT
|| wFlags
== DISPATCH_PROPERTYPUTREF
)
3228 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3229 if( FAILED( ret
= doSetProperty( pdispparams
, pvarResult
,
3230 pexcepinfo
, puArgErr
, info
.name
, params
))
3231 && ret
== DISP_E_MEMBERNOTFOUND
)
3233 // try to get the exact name
3235 if (m_xExactName
.is())
3237 exactName
= m_xExactName
->getExactName( info
.name
);
3239 if( !exactName
.isEmpty() )
3241 if( SUCCEEDED( ret
= doSetProperty( pdispparams
, pvarResult
,
3242 pexcepinfo
, puArgErr
, exactName
, params
)))
3243 info
.name
= exactName
;
3247 if( SUCCEEDED( ret
) )
3248 info
.flags
= DISPATCH_PROPERTYPUT
| DISPATCH_PROPERTYGET
;
3250 else if( wFlags
== DISPATCH_PROPERTYGET
)
3252 if( FAILED( ret
= doGetProperty( pdispparams
, pvarResult
,
3253 pexcepinfo
, info
.name
))
3254 && ret
== DISP_E_MEMBERNOTFOUND
)
3256 // try to get the exact name
3258 if (m_xExactName
.is())
3260 exactName
= m_xExactName
->getExactName( info
.name
);
3262 if( !exactName
.isEmpty() )
3264 if( SUCCEEDED( ret
= doGetProperty( pdispparams
, pvarResult
,
3265 pexcepinfo
, exactName
)))
3266 info
.name
= exactName
;
3270 if( SUCCEEDED( ret
) )
3271 info
.flags
= DISPATCH_PROPERTYGET
| DISPATCH_PROPERTYPUT
;
3273 else if( wFlags
& DISPATCH_METHOD
&&
3274 (wFlags
& DISPATCH_PROPERTYPUT
|| wFlags
& DISPATCH_PROPERTYPUTREF
))
3278 // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT
3279 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3280 // try first as method
3281 if( FAILED( ret
= doInvoke( pdispparams
, pvarResult
,
3282 pexcepinfo
, puArgErr
, info
.name
, params
))
3283 && ret
== DISP_E_MEMBERNOTFOUND
)
3285 // try to get the exact name
3286 if (m_xExactName
.is())
3288 exactName
= m_xExactName
->getExactName( info
.name
);
3290 if( !exactName
.isEmpty() )
3292 if( SUCCEEDED( ret
= doInvoke( pdispparams
, pvarResult
,
3293 pexcepinfo
, puArgErr
, exactName
, params
)))
3294 info
.name
= exactName
;
3298 if( SUCCEEDED( ret
) )
3299 info
.flags
= DISPATCH_METHOD
;
3302 if( FAILED( ret
) && pdispparams
->cArgs
== 1)
3304 if( FAILED( ret
= doSetProperty( pdispparams
, pvarResult
,
3305 pexcepinfo
, puArgErr
, info
.name
, params
))
3306 && ret
== DISP_E_MEMBERNOTFOUND
)
3308 // try to get the exact name
3309 if( !exactName
.isEmpty() )
3311 if( SUCCEEDED( ret
= doSetProperty( pdispparams
, pvarResult
,
3312 pexcepinfo
, puArgErr
, exactName
, params
)))
3313 info
.name
= exactName
;
3316 if( SUCCEEDED( ret
) )
3317 info
.flags
= DISPATCH_PROPERTYPUT
| DISPATCH_PROPERTYGET
;
3320 else if( wFlags
& DISPATCH_METHOD
&& wFlags
& DISPATCH_PROPERTYGET
)
3323 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3325 if( FAILED( ret
= doInvoke( pdispparams
, pvarResult
,
3326 pexcepinfo
, puArgErr
, info
.name
, params
))
3327 && ret
== DISP_E_MEMBERNOTFOUND
)
3329 // try to get the exact name
3330 if (m_xExactName
.is())
3332 exactName
= m_xExactName
->getExactName( info
.name
);
3334 if( !exactName
.isEmpty() )
3336 if( SUCCEEDED( ret
= doInvoke( pdispparams
, pvarResult
,
3337 pexcepinfo
, puArgErr
, exactName
, params
)))
3338 info
.name
= exactName
;
3342 if( SUCCEEDED( ret
) )
3343 info
.flags
= DISPATCH_METHOD
;
3346 if( FAILED( ret
) && pdispparams
->cArgs
== 1)
3348 if( FAILED( ret
= doGetProperty( pdispparams
, pvarResult
,
3349 pexcepinfo
, info
.name
))
3350 && ret
== DISP_E_MEMBERNOTFOUND
)
3352 if( !exactName
.isEmpty() )
3354 if( SUCCEEDED( ret
= doSetProperty( pdispparams
, pvarResult
,
3355 pexcepinfo
, puArgErr
, exactName
, params
)))
3356 info
.name
= exactName
;
3359 if( SUCCEEDED( ret
) )
3360 info
.flags
= DISPATCH_PROPERTYGET
;
3364 // update information about this member
3365 if( ret
== DISP_E_MEMBERNOTFOUND
)
3367 // Remember the name as not existing
3368 // and remove the MemberInfo
3369 m_badNameMap
[info
.name
]= false;
3370 m_idToMemberInfoMap
.erase( it_MemberInfo
);
3372 } // if( ! info.flags )
3373 else // IdToMemberInfoMap contains a MemberInfo
3375 if( wFlags
& DISPATCH_METHOD
&& info
.flags
== DISPATCH_METHOD
)
3377 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3378 ret
= doInvoke( pdispparams
, pvarResult
,
3379 pexcepinfo
, puArgErr
, info
.name
, params
);
3381 else if( (wFlags
& DISPATCH_PROPERTYPUT
|| wFlags
& DISPATCH_PROPERTYPUTREF
) &&
3382 info
.flags
& DISPATCH_PROPERTYPUT
)
3384 convertDispparamsArgs(dispidMember
, wFlags
, pdispparams
, params
);
3385 ret
= doSetProperty( pdispparams
, pvarResult
,
3386 pexcepinfo
, puArgErr
, info
.name
, params
);
3388 else if( (wFlags
& DISPATCH_PROPERTYGET
) && ( info
.flags
& DISPATCH_PROPERTYGET
))
3390 ret
= doGetProperty( pdispparams
, pvarResult
,
3391 pexcepinfo
, info
.name
);
3395 ret
= DISP_E_MEMBERNOTFOUND
;
3398 }// if( it_MemberInfo != m_idToMemberInfoMap.end() )
3400 ret
= DISP_E_MEMBERNOTFOUND
;
3403 catch(const BridgeRuntimeError
& e
)
3405 writeExcepinfo(pexcepinfo
, e
.message
);
3406 ret
= DISP_E_EXCEPTION
;
3408 catch(const Exception
& e
)
3410 OUString message
= "UnoObjectWrapperRemoteOpt::Invoke : \n" +
3412 writeExcepinfo(pexcepinfo
, message
);
3413 ret
= DISP_E_EXCEPTION
;
3417 OUString message
= "UnoObjectWrapperRemoteOpt::Invoke : \n"
3418 "Unexpected exception";
3419 writeExcepinfo(pexcepinfo
, message
);
3420 ret
= DISP_E_EXCEPTION
;
3426 HRESULT
UnoObjectWrapperRemoteOpt::methodInvoke( DISPID
/*dispidMember*/, DISPPARAMS
* /*pdispparams*/, VARIANT
* /*pvarResult*/,
3427 EXCEPINFO
* /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence
<Any
> const &)
3432 // The returned HRESULT is only appropriate for IDispatch::Invoke
3433 static HRESULT
mapCannotConvertException(const CannotConvertException
&e
, unsigned int * puArgErr
)
3436 bool bWriteIndex
= true;
3440 case FailReason::OUT_OF_RANGE
:
3441 ret
= DISP_E_OVERFLOW
;
3443 case FailReason::IS_NOT_NUMBER
:
3444 ret
= DISP_E_TYPEMISMATCH
;
3446 case FailReason::IS_NOT_ENUM
:
3447 ret
= DISP_E_TYPEMISMATCH
;
3449 case FailReason::IS_NOT_BOOL
:
3450 ret
= DISP_E_TYPEMISMATCH
;
3452 case FailReason::NO_SUCH_INTERFACE
:
3453 ret
= DISP_E_TYPEMISMATCH
;
3455 case FailReason::SOURCE_IS_NO_DERIVED_TYPE
:
3456 ret
= DISP_E_TYPEMISMATCH
;
3458 case FailReason::TYPE_NOT_SUPPORTED
:
3459 ret
= DISP_E_TYPEMISMATCH
;
3461 case FailReason::INVALID
:
3462 ret
= DISP_E_TYPEMISMATCH
;
3464 case FailReason::NO_DEFAULT_AVAILABLE
:
3465 ret
= DISP_E_BADPARAMCOUNT
;
3467 case FailReason::UNKNOWN
:
3476 if( bWriteIndex
&& puArgErr
!= nullptr)
3477 *puArgErr
= e
.ArgumentIndex
;
3481 // The function maps the TypeClass of the any to VARTYPE: If
3482 // the Any contains STRUCT or INTERFACE then the return value
3483 // is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper
3484 // and the result is put into the constructor of the uno - wrapper
3485 // object. If a client asks the object for DISPID_VALUE and this
3486 // function returned VT_DISPATCH then the IDispatch of the same
3487 // object is being returned.
3488 // See InterfaceOleWrapper::Invoke, InterfaceOleWrapper::m_defaultValueType
3489 VARTYPE
getVarType( const Any
& value
)
3491 VARTYPE ret
= VT_EMPTY
;
3493 switch ( value
.getValueTypeClass())
3495 case TypeClass_STRUCT
: ret
= VT_DISPATCH
; break;
3496 case TypeClass_INTERFACE
: ret
= VT_DISPATCH
; break;
3502 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */