1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 #include "ole2uno.hxx"
21 #include "rtl/ustrbuf.hxx"
24 #include "osl/diagnose.h"
25 #include "osl/doublecheckedlocking.h"
26 #include "osl/thread.h"
29 #include <com/sun/star/script/CannotConvertException.hpp>
30 #include <com/sun/star/script/FailReason.hpp>
31 #include <com/sun/star/beans/XMaterialHolder.hpp>
32 #include <com/sun/star/script/XTypeConverter.hpp>
33 #include <com/sun/star/script/FinishEngineEvent.hpp>
34 #include <com/sun/star/script/InterruptReason.hpp>
35 #include <com/sun/star/script/XEngineListener.hpp>
36 #include <com/sun/star/script/XDebugging.hpp>
37 #include <com/sun/star/script/XInvocation.hpp>
38 #include <com/sun/star/script/ContextInformation.hpp>
39 #include <com/sun/star/script/FinishReason.hpp>
40 #include <com/sun/star/script/XEngine.hpp>
41 #include <com/sun/star/script/InterruptEngineEvent.hpp>
42 #include <com/sun/star/script/XLibraryAccess.hpp>
43 #include <com/sun/star/bridge/ModelDependent.hpp>
45 #include "com/sun/star/bridge/oleautomation/NamedArgument.hpp"
46 #include "com/sun/star/bridge/oleautomation/PropertyPutArgument.hpp"
48 #include <typelib/typedescription.hxx>
50 #include <rtl/ustring.hxx>
52 #include "jscriptclasses.hxx"
54 #include "oleobjw.hxx"
55 #include "unoobjw.hxx"
60 using namespace com::sun::star::script
;
61 using namespace com::sun::star::lang
;
62 using namespace com::sun::star::bridge
;
63 using namespace com::sun::star::bridge::oleautomation
;
64 using namespace com::sun::star::bridge::ModelDependent
;
65 using namespace ::com::sun::star
;
68 #define JSCRIPT_ID_PROPERTY L"_environment"
69 #define JSCRIPT_ID L"jscript"
74 // key: XInterface pointer created by Invocation Adapter Factory
75 // value: XInterface pointer to the wrapper class.
76 // Entries to the map are made within
77 // Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType);
78 // Entries are being deleted if the wrapper class's destructor has been
80 // Before UNO object is wrapped to COM object this map is checked
81 // to see if the UNO object is already a wrapper.
82 std::unordered_map
<sal_uIntPtr
, sal_uIntPtr
> AdapterToWrapperMap
;
83 // key: XInterface of the wrapper object.
84 // value: XInterface of the Interface created by the Invocation Adapter Factory.
85 // A COM wrapper is responsible for removing the corresponding entry
86 // in AdapterToWrapperMap if it is being destroyed. Because the wrapper does not
87 // know about its adapted interface it uses WrapperToAdapterMap to get the
88 // adapted interface which is then used to locate the entry in AdapterToWrapperMap.
89 std::unordered_map
<sal_uIntPtr
,sal_uIntPtr
> WrapperToAdapterMap
;
91 std::unordered_map
<sal_uIntPtr
, WeakReference
<XInterface
> > ComPtrToWrapperMap
;
92 /*****************************************************************************
94 class implementation IUnknownWrapper_Impl
96 *****************************************************************************/
98 IUnknownWrapper_Impl::IUnknownWrapper_Impl( Reference
<XMultiServiceFactory
>& xFactory
,
99 sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
100 UnoConversionUtilities
<IUnknownWrapper_Impl
>( xFactory
, unoWrapperClass
, comWrapperClass
),
101 m_pxIdlClass( nullptr), m_eJScript( JScriptUndefined
),
102 m_bComTlbIndexInit(false), m_bHasDfltMethod(false), m_bHasDfltProperty(false)
107 IUnknownWrapper_Impl::~IUnknownWrapper_Impl()
109 o2u_attachCurrentThread();
110 MutexGuard
guard(getBridgeMutex());
111 XInterface
* xIntRoot
= static_cast<OWeakObject
*>(this);
112 #if OSL_DEBUG_LEVEL > 0
113 acquire(); // make sure we don't delete us twice because of Reference
114 OSL_ASSERT( Reference
<XInterface
>( static_cast<XWeak
*>(this), UNO_QUERY
).get() == xIntRoot
);
117 // remove entries in global maps
118 typedef std::unordered_map
<sal_uIntPtr
, sal_uIntPtr
>::iterator IT
;
119 IT it
= WrapperToAdapterMap
.find( reinterpret_cast<sal_uIntPtr
>(xIntRoot
));
120 if( it
!= WrapperToAdapterMap
.end())
122 sal_uIntPtr adapter
= it
->second
;
124 AdapterToWrapperMap
.erase( adapter
);
125 WrapperToAdapterMap
.erase( it
);
128 IT_Com it_c
= ComPtrToWrapperMap
.find( reinterpret_cast<sal_uIntPtr
>(m_spUnknown
.p
));
129 if(it_c
!= ComPtrToWrapperMap
.end())
130 ComPtrToWrapperMap
.erase(it_c
);
133 Any
IUnknownWrapper_Impl::queryInterface(const Type
& t
)
135 if (t
== cppu::UnoType
<XDefaultMethod
>::get() && !m_bHasDfltMethod
)
137 if (t
== cppu::UnoType
<XDefaultProperty
>::get() && !m_bHasDfltProperty
)
139 if ( ( t
== cppu::UnoType
<XInvocation
>::get() || t
== cppu::UnoType
<XAutomationInvocation
>::get() ) && !m_spDispatch
)
141 // XDirectInvocation seems to be an oracle replacement for XAutomationInvocation, however it is flawed especially wrt. assumptions about whether to invoke a
142 // Put or Get property, the implementation code has no business guessing that, it's up to the caller to decide that. Worse XDirectInvocation duplicates lots of code.
143 // XAutomationInvocation provides separate calls for put& get
144 // properties. Note: Currently the basic runtime doesn't call put properties directly, it should... after all the basic runtime should know whether it is calling a put or get property.
145 // For the moment for ease of merging we will let the XDirectInvoke and XAuthomationInvocation interfaces stay side by side (and for the moment at least I would prefer the basic
146 // runtime to call XAutomationInvocation instead of XDirectInvoke
147 return WeakImplHelper
<XBridgeSupplier2
,
148 XInitialization
, XAutomationObject
, XDefaultProperty
, XDefaultMethod
, XDirectInvocation
, XAutomationInvocation
>::queryInterface(t
);
151 Reference
<XIntrospectionAccess
> SAL_CALL
IUnknownWrapper_Impl::getIntrospection()
153 Reference
<XIntrospectionAccess
> ret
;
158 Any SAL_CALL
IUnknownWrapper_Impl::invokeGetProperty( const OUString
& aPropertyName
, const Sequence
< Any
>& aParams
, Sequence
< sal_Int16
>& aOutParamIndex
, Sequence
< Any
>& aOutParam
)
163 o2u_attachCurrentThread();
164 ITypeInfo
* pInfo
= getTypeInfo();
165 FuncDesc
aDescGet(pInfo
);
166 FuncDesc
aDescPut(pInfo
);
167 VarDesc
aVarDesc(pInfo
);
168 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
171 OUString
msg("[automation bridge]Property \"" + aPropertyName
+
172 "\" is not supported");
173 throw UnknownPropertyException(msg
);
175 aResult
= invokeWithDispIdComTlb( aDescGet
, aPropertyName
, aParams
, aOutParamIndex
, aOutParam
);
177 catch ( const Exception
& e
)
179 throw RuntimeException("[automation bridge] unexpected exception in "
180 "IUnknownWrapper_Impl::invokeGetProperty ! Message : \n" +
186 Any SAL_CALL
IUnknownWrapper_Impl::invokePutProperty( const OUString
& aPropertyName
, const Sequence
< Any
>& aParams
, Sequence
< sal_Int16
>& aOutParamIndex
, Sequence
< Any
>& aOutParam
)
191 o2u_attachCurrentThread();
192 ITypeInfo
* pInfo
= getTypeInfo();
193 FuncDesc
aDescGet(pInfo
);
194 FuncDesc
aDescPut(pInfo
);
195 VarDesc
aVarDesc(pInfo
);
196 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
199 OUString
msg("[automation bridge]Property \"" + aPropertyName
+
200 "\" is not supported");
201 throw UnknownPropertyException(msg
);
203 aResult
= invokeWithDispIdComTlb( aDescPut
, aPropertyName
, aParams
, aOutParamIndex
, aOutParam
);
205 catch ( const Exception
& e
)
207 throw RuntimeException("[automation bridge] unexpected exception in "
208 "IUnknownWrapper_Impl::invokePutProperty ! Message : \n" +
215 Any SAL_CALL
IUnknownWrapper_Impl::invoke( const OUString
& aFunctionName
,
216 const Sequence
< Any
>& aParams
, Sequence
< sal_Int16
>& aOutParamIndex
,
217 Sequence
< Any
>& aOutParam
)
219 if ( ! m_spDispatch
)
221 throw RuntimeException(
222 "[automation bridge] The object does not have an IDispatch interface");
229 o2u_attachCurrentThread();
231 TypeDescription methodDesc
;
232 getMethodInfo(aFunctionName
, methodDesc
);
235 ret
= invokeWithDispIdUnoTlb(aFunctionName
,
242 ret
= invokeWithDispIdComTlb( aFunctionName
,
248 catch (const IllegalArgumentException
&)
252 catch (const CannotConvertException
&)
256 catch (const BridgeRuntimeError
& e
)
258 throw RuntimeException(e
.message
);
260 catch (const Exception
& e
)
262 throw RuntimeException("[automation bridge] unexpected exception in "
263 "IUnknownWrapper_Impl::invoke ! Message : \n" +
269 throw RuntimeException("[automation bridge] unexpected exception in "
270 "IUnknownWrapper_Impl::Invoke !");
275 void SAL_CALL
IUnknownWrapper_Impl::setValue( const OUString
& aPropertyName
,
278 if ( ! m_spDispatch
)
280 throw RuntimeException(
281 "[automation bridge] The object does not have an IDispatch interface");
285 o2u_attachCurrentThread();
287 ITypeInfo
* pInfo
= getTypeInfo();
288 FuncDesc
aDescGet(pInfo
);
289 FuncDesc
aDescPut(pInfo
);
290 VarDesc
aVarDesc(pInfo
);
291 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
292 //check if there is such a property at all or if it is read only
293 if ( ! aDescPut
&& ! aDescGet
&& ! aVarDesc
)
295 OUString
msg("[automation bridge]Property \"" + aPropertyName
+
296 "\" is not supported");
297 throw UnknownPropertyException(msg
);
300 if ( (! aDescPut
&& aDescGet
)
301 || (aVarDesc
&& aVarDesc
->wVarFlags
== VARFLAG_FREADONLY
) )
304 OUString
msg("[automation bridge] Property " + aPropertyName
+
306 OString sMsg
= OUStringToOString(msg
, osl_getThreadTextEncoding());
307 OSL_FAIL(sMsg
.getStr());
313 DISPPARAMS dispparams
;
315 CComVariant varRefArg
;
316 CComVariant varResult
;
318 unsigned int uArgErr
;
320 // converting UNO value to OLE variant
321 DISPID dispidPut
= DISPID_PROPERTYPUT
;
322 dispparams
.rgdispidNamedArgs
= &dispidPut
;
323 dispparams
.cArgs
= 1;
324 dispparams
.cNamedArgs
= 1;
325 dispparams
.rgvarg
= & varArg
;
327 OSL_ASSERT(aDescPut
|| aVarDesc
);
331 INVOKEKIND invkind
= INVOKE_PROPERTYPUT
;
332 //determine the expected type, dispid, invoke kind (DISPATCH_PROPERTYPUT,
333 //DISPATCH_PROPERTYPUTREF)
336 vt
= getElementTypeDesc(& aDescPut
->lprgelemdescParam
[0].tdesc
);
337 dispid
= aDescPut
->memid
;
338 invkind
= aDescPut
->invkind
;
342 vt
= getElementTypeDesc( & aVarDesc
->elemdescVar
.tdesc
);
343 dispid
= aVarDesc
->memid
;
344 if (vt
== VT_UNKNOWN
|| vt
== VT_DISPATCH
||
345 (vt
& VT_ARRAY
) || (vt
& VT_BYREF
))
347 invkind
= INVOKE_PROPERTYPUTREF
;
351 // convert the uno argument
354 anyToVariant( & varRefArg
, aValue
, ::sal::static_int_cast
< VARTYPE
, int >( vt
^ VT_BYREF
) );
356 if( (vt
& VT_TYPEMASK
) == VT_VARIANT
)
357 varArg
.byref
= & varRefArg
;
358 else if ((vt
& VT_TYPEMASK
) == VT_DECIMAL
)
359 varArg
.byref
= & varRefArg
.decVal
;
361 varArg
.byref
= & varRefArg
.byref
;
365 anyToVariant(& varArg
, aValue
, vt
);
368 hr
= m_spDispatch
->Invoke(dispid
, IID_NULL
, LOCALE_USER_DEFAULT
, ::sal::static_int_cast
< WORD
, INVOKEKIND
>( invkind
),
369 &dispparams
, & varResult
, & excepinfo
, &uArgErr
);
376 case DISP_E_BADPARAMCOUNT
:
377 throw RuntimeException();
379 case DISP_E_BADVARTYPE
:
380 throw RuntimeException();
382 case DISP_E_EXCEPTION
:
383 throw InvocationTargetException();
385 case DISP_E_MEMBERNOTFOUND
:
386 throw UnknownPropertyException();
388 case DISP_E_NONAMEDARGS
:
389 throw RuntimeException();
391 case DISP_E_OVERFLOW
:
392 throw CannotConvertException("call to OLE object failed", static_cast<XInterface
*>(
393 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
395 case DISP_E_PARAMNOTFOUND
:
396 throw IllegalArgumentException("call to OLE object failed", static_cast<XInterface
*>(
397 static_cast<XWeak
*>(this)), ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
)) ;
399 case DISP_E_TYPEMISMATCH
:
400 throw CannotConvertException("call to OLE object failed", static_cast<XInterface
*>(
401 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::UNKNOWN
, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
403 case DISP_E_UNKNOWNINTERFACE
:
404 throw RuntimeException();
406 case DISP_E_UNKNOWNLCID
:
407 throw RuntimeException();
409 case DISP_E_PARAMNOTOPTIONAL
:
410 throw CannotConvertException("call to OLE object failed",static_cast<XInterface
*>(
411 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
414 throw RuntimeException();
418 catch (const CannotConvertException
&)
422 catch (const UnknownPropertyException
&)
426 catch (const BridgeRuntimeError
& e
)
428 throw RuntimeException(e
.message
);
430 catch (const Exception
& e
)
432 throw RuntimeException("[automation bridge] unexpected exception in "
433 "IUnknownWrapper_Impl::setValue ! Message : \n" +
439 throw RuntimeException(
440 "[automation bridge] unexpected exception in "
441 "IUnknownWrapper_Impl::setValue !");
445 Any SAL_CALL
IUnknownWrapper_Impl::getValue( const OUString
& aPropertyName
)
447 if ( ! m_spDispatch
)
449 throw RuntimeException(
450 "[automation bridge] The object does not have an IDispatch interface");
455 o2u_attachCurrentThread();
456 ITypeInfo
* pInfo
= getTypeInfo();
457 // I was going to implement an XServiceInfo interface to allow the type
458 // of the automation object to be exposed.. but it seems
459 // from looking at comments in the code that it is possible for
460 // this object to actually wrap an UNO object ( I guess if automation is
461 // used from MSO to create Openoffice objects ) Therefore, those objects
462 // will more than likely already have their own XServiceInfo interface.
463 // Instead here I chose a name that should be illegal both in COM and
464 // UNO ( from an IDL point of view ) therefore I think this is a safe
466 if ( aPropertyName
== "$GetTypeName" )
468 if ( pInfo
&& m_sTypeName
.getLength() == 0 )
470 m_sTypeName
= "IDispatch";
473 if ( SUCCEEDED( pInfo
->GetDocumentation( -1, &sName
, nullptr, nullptr, nullptr ) ) )
475 OUString
sTmp( reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(sName
)));
476 if ( sTmp
.startsWith("_") )
478 // do we own the memory for pTypeLib, msdn doc is vague
480 CComPtr
< ITypeLib
> pTypeLib
;
482 if ( SUCCEEDED( pInfo
->GetContainingTypeLib( &pTypeLib
.p
, &index
)) )
484 if ( SUCCEEDED( pTypeLib
->GetDocumentation( -1, &sName
, nullptr, nullptr, nullptr ) ) )
486 OUString
sLibName( reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(sName
)));
487 m_sTypeName
= sLibName
.concat( "." ).concat( sTmp
);
497 FuncDesc
aDescGet(pInfo
);
498 FuncDesc
aDescPut(pInfo
);
499 VarDesc
aVarDesc(pInfo
);
500 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
501 if ( ! aDescGet
&& ! aDescPut
&& ! aVarDesc
)
504 OUString
msg("[automation bridge]Property \"" + aPropertyName
+
505 "\" is not supported");
506 throw UnknownPropertyException(msg
);
508 // write-only should not be possible
509 OSL_ASSERT( aDescGet
|| ! aDescPut
);
512 DISPPARAMS dispparams
= {nullptr, nullptr, 0, 0};
513 CComVariant varResult
;
515 unsigned int uArgErr
;
518 dispid
= aDescGet
->memid
;
520 dispid
= aVarDesc
->memid
;
522 dispid
= aDescPut
->memid
;
524 hr
= m_spDispatch
->Invoke(dispid
,
527 DISPATCH_PROPERTYGET
,
533 // converting return value and out parameter back to UNO
536 // If the com object implements uno interfaces then we have
537 // to convert the attribute into the expected type.
538 TypeDescription attrInfo
;
539 getAttributeInfo(aPropertyName
, attrInfo
);
541 variantToAny( &varResult
, ret
, Type( attrInfo
.get()->pWeakRef
));
543 variantToAny(&varResult
, ret
);
551 case DISP_E_BADPARAMCOUNT
:
552 case DISP_E_BADVARTYPE
:
553 case DISP_E_EXCEPTION
:
554 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)));
556 case DISP_E_MEMBERNOTFOUND
:
557 throw UnknownPropertyException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)));
560 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)));
564 catch ( const UnknownPropertyException
& )
568 catch (const BridgeRuntimeError
& e
)
570 throw RuntimeException(e
.message
);
572 catch (const Exception
& e
)
574 throw RuntimeException("[automation bridge] unexpected exception in "
575 "IUnknownWrapper_Impl::getValue ! Message : \n" +
580 throw RuntimeException(
581 "[automation bridge] unexpected exception in "
582 "IUnknownWrapper_Impl::getValue !");
587 sal_Bool SAL_CALL
IUnknownWrapper_Impl::hasMethod( const OUString
& aName
)
589 if ( ! m_spDispatch
)
591 throw RuntimeException(
592 "[automation bridge] The object does not have an IDispatch interface");
598 o2u_attachCurrentThread();
599 ITypeInfo
* pInfo
= getTypeInfo();
600 FuncDesc
aDesc(pInfo
);
601 getFuncDesc(aName
, & aDesc
);
602 // Automation properties can have arguments. Those are treated as methods and
603 //are called through XInvocation::invoke.
606 FuncDesc
aDescGet(pInfo
);
607 FuncDesc
aDescPut(pInfo
);
608 VarDesc
aVarDesc(pInfo
);
609 getPropDesc( aName
, & aDescGet
, & aDescPut
, & aVarDesc
);
610 if ((aDescGet
&& aDescGet
->cParams
> 0)
611 || (aDescPut
&& aDescPut
->cParams
> 0))
617 catch (const BridgeRuntimeError
& e
)
619 throw RuntimeException(e
.message
);
621 catch (const Exception
& e
)
623 throw RuntimeException("[automation bridge] unexpected exception in "
624 "IUnknownWrapper_Impl::hasMethod ! Message : \n" +
629 throw RuntimeException("[automation bridge] unexpected exception in "
630 "IUnknownWrapper_Impl::hasMethod !");
635 sal_Bool SAL_CALL
IUnknownWrapper_Impl::hasProperty( const OUString
& aName
)
637 if ( ! m_spDispatch
)
639 throw RuntimeException("[automation bridge] The object does not have an "
640 "IDispatch interface");
645 o2u_attachCurrentThread();
647 ITypeInfo
* pInfo
= getTypeInfo();
648 FuncDesc
aDescGet(pInfo
);
649 FuncDesc
aDescPut(pInfo
);
650 VarDesc
aVarDesc(pInfo
);
651 getPropDesc(aName
, & aDescGet
, & aDescPut
, & aVarDesc
);
653 // we should probably just check the func kind
654 // basic has been modified to handle properties ( 'get' ) props at
655 // least with parameters
656 // additionally you can call invoke(Get|Set)Property on the bridge
657 // you can determine if a property has parameter is hasMethod
658 // returns true for the name
666 catch (const BridgeRuntimeError
& e
)
668 throw RuntimeException(e
.message
);
670 catch (const Exception
& e
)
672 throw RuntimeException("[automation bridge] unexpected exception in "
673 "IUnknownWrapper_Impl::hasProperty ! Message : \n" +
679 throw RuntimeException("[automation bridge] unexpected exception in "
680 "IUnknownWrapper_Impl::hasProperty !");
685 Any SAL_CALL
IUnknownWrapper_Impl::createBridge( const Any
& modelDepObject
,
686 const Sequence
< sal_Int8
>& /*aProcessId*/, sal_Int16 sourceModelType
,
687 sal_Int16 destModelType
)
690 o2u_attachCurrentThread();
693 (sourceModelType
== UNO
) &&
694 (destModelType
== OLE
) &&
695 (modelDepObject
.getValueTypeClass() == TypeClass_INTERFACE
)
698 Reference
<XInterface
> xInt( *static_cast<XInterface
* const *>(modelDepObject
.getValue()));
699 Reference
<XInterface
> xSelf( static_cast<OWeakObject
*>(this));
703 VARIANT
* pVariant
= static_cast<VARIANT
*>(CoTaskMemAlloc(sizeof(VARIANT
)));
705 VariantInit(pVariant
);
706 if (m_bOriginalDispatch
)
708 pVariant
->vt
= VT_DISPATCH
;
709 pVariant
->pdispVal
= m_spDispatch
;
710 pVariant
->pdispVal
->AddRef();
714 pVariant
->vt
= VT_UNKNOWN
;
715 pVariant
->punkVal
= m_spUnknown
;
716 pVariant
->punkVal
->AddRef();
719 ret
.setValue(static_cast<void*>(&pVariant
), cppu::UnoType
<sal_uIntPtr
>::get());
726 @exception IllegalArgumentException
727 @exception CannotConvertException
728 @exception InvocationTargetException
731 Any
IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString
& sFunctionName
,
732 const Sequence
< Any
>& Params
,
733 Sequence
< sal_Int16
>& OutParamIndex
,
734 Sequence
< Any
>& OutParam
)
739 sal_Int32 parameterCount
= Params
.getLength();
740 sal_Int32 outParameterCount
= 0;
741 typelib_InterfaceMethodTypeDescription
* pMethod
= nullptr;
742 TypeDescription methodDesc
;
743 getMethodInfo(sFunctionName
, methodDesc
);
745 // We need to know whether the IDispatch is from a JScript object.
746 // Then out and in/out parameters have to be treated differently than
747 // with common COM objects.
748 bool bJScriptObject
= isJScriptObject();
749 std::unique_ptr
<CComVariant
[]> sarParams
;
750 std::unique_ptr
<CComVariant
[]> sarParamsRef
;
751 CComVariant
*pVarParams
= nullptr;
752 CComVariant
*pVarParamsRef
= nullptr;
757 pMethod
= reinterpret_cast<typelib_InterfaceMethodTypeDescription
*>(methodDesc
.get());
758 parameterCount
= pMethod
->nParams
;
759 // Create the Array for the array being passed in DISPPARAMS
760 // the array also contains the outparameter (but not the values)
761 if( pMethod
->nParams
> 0)
763 sarParams
.reset(new CComVariant
[ parameterCount
]);
764 pVarParams
= sarParams
.get();
767 // Create the Array for the out an in/out parameter. These values
768 // are referenced by the VT_BYREF VARIANTs in DISPPARAMS.
769 // We need to find out the number of out and in/out parameter.
770 for( sal_Int32 i
=0; i
< parameterCount
; i
++)
772 if( pMethod
->pParams
[i
].bOut
)
778 sarParamsRef
.reset(new CComVariant
[outParameterCount
]);
779 pVarParamsRef
= sarParamsRef
.get();
780 // build up the parameters for IDispatch::Invoke
781 sal_Int32 outParamIndex
=0;
785 for( i
= 0; i
< parameterCount
; i
++)
788 if( pMethod
->pParams
[i
].bIn
&& ! pMethod
->pParams
[i
].bOut
)
790 anyToVariant( &pVarParams
[parameterCount
- i
-1], Params
.getConstArray()[i
]);
792 // Out parameter + in/out parameter
793 else if( pMethod
->pParams
[i
].bOut
)
796 if(pMethod
->pParams
[i
].bIn
)
798 anyToVariant( & var
,Params
[i
]);
799 pVarParamsRef
[outParamIndex
] = var
;
802 switch( pMethod
->pParams
[i
].pTypeRef
->eTypeClass
)
804 case typelib_TypeClass_INTERFACE
:
805 case typelib_TypeClass_STRUCT
:
806 if( ! pMethod
->pParams
[i
].bIn
)
808 pVarParamsRef
[ outParamIndex
].vt
= VT_DISPATCH
;
809 pVarParamsRef
[ outParamIndex
].pdispVal
= nullptr;
811 pVarParams
[parameterCount
- i
-1].vt
= VT_DISPATCH
| VT_BYREF
;
812 pVarParams
[parameterCount
- i
-1].ppdispVal
= &pVarParamsRef
[outParamIndex
].pdispVal
;
814 case typelib_TypeClass_ENUM
:
815 case typelib_TypeClass_LONG
:
816 case typelib_TypeClass_UNSIGNED_LONG
:
817 if( ! pMethod
->pParams
[i
].bIn
)
819 pVarParamsRef
[ outParamIndex
].vt
= VT_I4
;
820 pVarParamsRef
[ outParamIndex
].lVal
= 0;
822 pVarParams
[parameterCount
- i
-1].vt
= VT_I4
| VT_BYREF
;
823 pVarParams
[parameterCount
- i
-1].plVal
= &pVarParamsRef
[outParamIndex
].lVal
;
825 case typelib_TypeClass_SEQUENCE
:
826 if( ! pMethod
->pParams
[i
].bIn
)
828 pVarParamsRef
[ outParamIndex
].vt
= VT_ARRAY
| VT_VARIANT
;
829 pVarParamsRef
[ outParamIndex
].parray
= nullptr;
831 pVarParams
[parameterCount
- i
-1].vt
= VT_ARRAY
| VT_BYREF
| VT_VARIANT
;
832 pVarParams
[parameterCount
- i
-1].pparray
= &pVarParamsRef
[outParamIndex
].parray
;
834 case typelib_TypeClass_ANY
:
835 if( ! pMethod
->pParams
[i
].bIn
)
837 pVarParamsRef
[ outParamIndex
].vt
= VT_EMPTY
;
838 pVarParamsRef
[ outParamIndex
].lVal
= 0;
840 pVarParams
[parameterCount
- i
-1].vt
= VT_VARIANT
| VT_BYREF
;
841 pVarParams
[parameterCount
- i
-1].pvarVal
= &pVarParamsRef
[outParamIndex
];
843 case typelib_TypeClass_BOOLEAN
:
844 if( ! pMethod
->pParams
[i
].bIn
)
846 pVarParamsRef
[ outParamIndex
].vt
= VT_BOOL
;
847 pVarParamsRef
[ outParamIndex
].boolVal
= 0;
849 pVarParams
[parameterCount
- i
-1].vt
= VT_BOOL
| VT_BYREF
;
850 pVarParams
[parameterCount
- i
-1].pboolVal
=
851 & pVarParamsRef
[outParamIndex
].boolVal
;
854 case typelib_TypeClass_STRING
:
855 if( ! pMethod
->pParams
[i
].bIn
)
857 pVarParamsRef
[ outParamIndex
].vt
= VT_BSTR
;
858 pVarParamsRef
[ outParamIndex
].bstrVal
= nullptr;
860 pVarParams
[parameterCount
- i
-1].vt
= VT_BSTR
| VT_BYREF
;
861 pVarParams
[parameterCount
- i
-1].pbstrVal
=
862 & pVarParamsRef
[outParamIndex
].bstrVal
;
865 case typelib_TypeClass_FLOAT
:
866 if( ! pMethod
->pParams
[i
].bIn
)
868 pVarParamsRef
[ outParamIndex
].vt
= VT_R4
;
869 pVarParamsRef
[ outParamIndex
].fltVal
= 0;
871 pVarParams
[parameterCount
- i
-1].vt
= VT_R4
| VT_BYREF
;
872 pVarParams
[parameterCount
- i
-1].pfltVal
=
873 & pVarParamsRef
[outParamIndex
].fltVal
;
875 case typelib_TypeClass_DOUBLE
:
876 if( ! pMethod
->pParams
[i
].bIn
)
878 pVarParamsRef
[ outParamIndex
].vt
= VT_R8
;
879 pVarParamsRef
[ outParamIndex
].dblVal
= 0;
881 pVarParams
[parameterCount
- i
-1].vt
= VT_R8
| VT_BYREF
;
882 pVarParams
[parameterCount
- i
-1].pdblVal
=
883 & pVarParamsRef
[outParamIndex
].dblVal
;
885 case typelib_TypeClass_BYTE
:
886 if( ! pMethod
->pParams
[i
].bIn
)
888 pVarParamsRef
[ outParamIndex
].vt
= VT_UI1
;
889 pVarParamsRef
[ outParamIndex
].bVal
= 0;
891 pVarParams
[parameterCount
- i
-1].vt
= VT_UI1
| VT_BYREF
;
892 pVarParams
[parameterCount
- i
-1].pbVal
=
893 & pVarParamsRef
[outParamIndex
].bVal
;
895 case typelib_TypeClass_CHAR
:
896 case typelib_TypeClass_SHORT
:
897 case typelib_TypeClass_UNSIGNED_SHORT
:
898 if( ! pMethod
->pParams
[i
].bIn
)
900 pVarParamsRef
[ outParamIndex
].vt
= VT_I2
;
901 pVarParamsRef
[ outParamIndex
].iVal
= 0;
903 pVarParams
[parameterCount
- i
-1].vt
= VT_I2
| VT_BYREF
;
904 pVarParams
[parameterCount
- i
-1].piVal
=
905 & pVarParamsRef
[outParamIndex
].iVal
;
909 if( ! pMethod
->pParams
[i
].bIn
)
911 pVarParamsRef
[ outParamIndex
].vt
= VT_EMPTY
;
912 pVarParamsRef
[ outParamIndex
].lVal
= 0;
914 pVarParams
[parameterCount
- i
-1].vt
= VT_VARIANT
| VT_BYREF
;
915 pVarParams
[parameterCount
- i
-1].pvarVal
=
916 & pVarParamsRef
[outParamIndex
];
922 catch (IllegalArgumentException
& e
)
924 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
927 catch (CannotConvertException
& e
)
933 else // it is an JScriptObject
938 for( ; i
< parameterCount
; i
++)
941 if( pMethod
->pParams
[i
].bIn
&& ! pMethod
->pParams
[i
].bOut
)
943 anyToVariant( &pVarParams
[parameterCount
- i
-1], Params
.getConstArray()[i
]);
945 // Out parameter + in/out parameter
946 else if( pMethod
->pParams
[i
].bOut
)
948 CComObject
<JScriptOutParam
>* pParamObject
;
949 if( SUCCEEDED( CComObject
<JScriptOutParam
>::CreateInstance( &pParamObject
)))
951 CComPtr
<IUnknown
> pUnk(pParamObject
->GetUnknown());
952 CComQIPtr
<IDispatch
> pDisp( pUnk
);
954 pVarParams
[ parameterCount
- i
-1].vt
= VT_DISPATCH
;
955 pVarParams
[ parameterCount
- i
-1].pdispVal
= pDisp
;
956 pVarParams
[ parameterCount
- i
-1].pdispVal
->AddRef();
957 // if the param is in/out then put the parameter on index 0
958 if( pMethod
->pParams
[i
].bIn
) // in / out
960 CComVariant varParam
;
961 anyToVariant( &varParam
, Params
.getConstArray()[i
]);
962 CComDispatchDriver
dispDriver( pDisp
);
963 if(FAILED( dispDriver
.PutPropertyByName( L
"0", &varParam
)))
964 throw BridgeRuntimeError(
965 "[automation bridge]IUnknownWrapper_Impl::"
966 "invokeWithDispIdUnoTlb\n"
967 "Could not set property \"0\" for the in/out "
974 throw BridgeRuntimeError(
975 "[automation bridge]IUnknownWrapper_Impl::"
976 "invokeWithDispIdUnoTlb\n"
977 "Could not create out parameter at index: " +
978 OUString::number((sal_Int32
) i
));
984 catch (IllegalArgumentException
& e
)
986 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
989 catch (CannotConvertException
& e
)
996 // No type description Available, that is we have to deal with a COM component,
997 // that does not implements UNO interfaces ( IDispatch based)
1000 //We should not run into this block, because invokeWithDispIdComTlb should
1001 //have been called instead.
1006 CComVariant varResult
;
1007 ExcepInfo excepinfo
;
1008 unsigned int uArgErr
;
1009 DISPPARAMS dispparams
= { pVarParams
, nullptr, static_cast<UINT
>(parameterCount
), 0};
1012 FuncDesc
aDesc(getTypeInfo());
1013 getFuncDesc(sFunctionName
, & aDesc
);
1014 // invoking OLE method
1015 hr
= m_spDispatch
->Invoke(aDesc
->memid
,
1017 LOCALE_USER_DEFAULT
,
1024 // converting return value and out parameter back to UNO
1027 if( outParameterCount
&& pMethod
)
1029 OutParamIndex
.realloc( outParameterCount
);
1030 OutParam
.realloc( outParameterCount
);
1031 sal_Int32 outIndex
=0;
1035 for( ; i
< parameterCount
; i
++)
1037 if( pMethod
->pParams
[i
].bOut
)
1039 OutParamIndex
[outIndex
]= (sal_Int16
) i
;
1041 if( !bJScriptObject
)
1043 variantToAny( &pVarParamsRef
[outIndex
], outAny
,
1044 Type(pMethod
->pParams
[i
].pTypeRef
), false);
1045 OutParam
[outIndex
++]= outAny
;
1047 else //JScriptObject
1049 if( pVarParams
[i
].vt
== VT_DISPATCH
)
1051 CComDispatchDriver
pDisp( pVarParams
[i
].pdispVal
);
1055 if( SUCCEEDED( pDisp
.GetPropertyByName( L
"0", &varOut
)))
1057 variantToAny( &varOut
, outAny
,
1058 Type(pMethod
->pParams
[parameterCount
- 1 - i
].pTypeRef
), false);
1059 OutParam
[outParameterCount
- 1 - outIndex
++]= outAny
;
1071 if( !bConvRet
) break;
1074 catch(IllegalArgumentException
& e
)
1076 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
1079 catch(CannotConvertException
& e
)
1081 e
.ArgumentIndex
= i
;
1085 // return value, no type information available
1091 variantToAny(&varResult
, ret
, Type( pMethod
->pReturnTypeRef
), false);
1093 variantToAny(&varResult
, ret
, false);
1095 catch (IllegalArgumentException
& e
)
1098 "[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1099 "Could not convert return value! \n Message: \n" + e
.Message
;
1102 catch (CannotConvertException
& e
)
1105 "[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1106 "Could not convert return value! \n Message: \n" + e
.Message
;
1112 if( !bConvRet
) // conversion of return or out parameter failed
1113 throw CannotConvertException("Call to COM object failed. Conversion of return or out value failed",
1114 Reference
<XInterface
>( static_cast<XWeak
*>(this), UNO_QUERY
), TypeClass_UNKNOWN
,
1115 FailReason::UNKNOWN
, 0);// lookup error code
1116 // conversion of return or out parameter failed
1121 case DISP_E_BADPARAMCOUNT
:
1122 throw IllegalArgumentException();
1124 case DISP_E_BADVARTYPE
:
1125 throw RuntimeException();
1127 case DISP_E_EXCEPTION
:
1128 throw InvocationTargetException();
1130 case DISP_E_MEMBERNOTFOUND
:
1131 throw IllegalArgumentException();
1133 case DISP_E_NONAMEDARGS
:
1134 throw IllegalArgumentException();
1136 case DISP_E_OVERFLOW
:
1137 throw CannotConvertException("call to OLE object failed", static_cast<XInterface
*>(
1138 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
1140 case DISP_E_PARAMNOTFOUND
:
1141 throw IllegalArgumentException("call to OLE object failed", static_cast<XInterface
*>(
1142 static_cast<XWeak
*>(this)), ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1144 case DISP_E_TYPEMISMATCH
:
1145 throw CannotConvertException("call to OLE object failed",static_cast<XInterface
*>(
1146 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::UNKNOWN
, uArgErr
);
1148 case DISP_E_UNKNOWNINTERFACE
:
1149 throw RuntimeException() ;
1151 case DISP_E_UNKNOWNLCID
:
1152 throw RuntimeException() ;
1154 case DISP_E_PARAMNOTOPTIONAL
:
1155 throw CannotConvertException("call to OLE object failed", static_cast<XInterface
*>(
1156 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
1159 throw RuntimeException();
1168 void SAL_CALL
IUnknownWrapper_Impl::initialize( const Sequence
< Any
>& aArguments
)
1170 // 1.parameter is IUnknown
1171 // 2.parameter is a boolean which indicates if the COM pointer was a IUnknown or IDispatch
1172 // 3.parameter is a Sequence<Type>
1173 o2u_attachCurrentThread();
1174 OSL_ASSERT(aArguments
.getLength() == 3);
1176 m_spUnknown
= *static_cast<IUnknown
* const *>(aArguments
[0].getValue());
1177 m_spUnknown
.QueryInterface( & m_spDispatch
.p
);
1179 aArguments
[1] >>= m_bOriginalDispatch
;
1180 aArguments
[2] >>= m_seqTypes
;
1182 ITypeInfo
* pType
= nullptr;
1185 // a COM object implementation that has no TypeInfo is still a legal COM object;
1186 // such objects can at least be transported through UNO using the bridge
1187 // so we should allow to create wrappers for them as well
1188 pType
= getTypeInfo();
1190 catch( const BridgeRuntimeError
& )
1192 catch( const Exception
& )
1199 // Get Default member
1200 CComBSTR defaultMemberName
;
1201 if ( SUCCEEDED( pType
->GetDocumentation(0, &defaultMemberName
, nullptr, nullptr, nullptr ) ) )
1203 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(defaultMemberName
)));
1204 FuncDesc
aDescGet(pType
);
1205 FuncDesc
aDescPut(pType
);
1206 VarDesc
aVarDesc(pType
);
1207 // see if this is a property first ( more likely to be a property then a method )
1208 getPropDesc( usName
, & aDescGet
, & aDescPut
, & aVarDesc
);
1210 if ( !aDescGet
&& !aDescPut
)
1212 getFuncDesc( usName
, &aDescGet
);
1214 throw BridgeRuntimeError( "[automation bridge]IUnknownWrapper_Impl::initialize() Failed to get Function or Property desc. for " + usName
);
1216 // now for some funny heuristics to make basic understand what to do
1217 // a single aDescGet ( that doesn't take any params ) would be
1218 // a read only ( defaultmember ) property e.g. this object
1219 // should implement XDefaultProperty
1220 // a single aDescGet ( that *does* ) take params is basically a
1221 // default method e.g. implement XDefaultMethod
1223 // a DescPut ( I guess we only really support a default param with '1' param ) as a setValue ( but I guess we can leave it through, the object will fail if we don't get it right anyway )
1224 if ( aDescPut
|| ( aDescGet
&& aDescGet
->cParams
== 0 ) )
1225 m_bHasDfltProperty
= true;
1226 if ( aDescGet
->cParams
> 0 )
1227 m_bHasDfltMethod
= true;
1228 if ( m_bHasDfltProperty
|| m_bHasDfltMethod
)
1229 m_sDefaultMember
= usName
;
1232 catch ( const BridgeRuntimeError
& e
)
1234 throw RuntimeException( e
.message
);
1236 catch( const Exception
& e
)
1238 throw RuntimeException(
1239 "[automation bridge] unexpected exception in IUnknownWrapper_Impl::initialize() error message: \n" + e
.Message
);
1245 // XDirectInvocation
1246 uno::Any SAL_CALL
IUnknownWrapper_Impl::directInvoke( const OUString
& aName
, const uno::Sequence
< uno::Any
>& aParams
)
1250 if ( !m_spDispatch
)
1252 throw RuntimeException(
1253 "[automation bridge] The object does not have an IDispatch interface");
1256 o2u_attachCurrentThread();
1258 if ( !getDispid( aName
, &dispid
) )
1259 throw IllegalArgumentException(
1260 "[automation bridge] The object does not have a function or property "
1261 + aName
, Reference
<XInterface
>(), 0);
1263 CComVariant varResult
;
1264 ExcepInfo excepinfo
;
1265 unsigned int uArgErr
= 0;
1266 INVOKEKIND pInvkinds
[2];
1267 pInvkinds
[0] = INVOKE_FUNC
;
1268 pInvkinds
[1] = aParams
.getLength() ? INVOKE_PROPERTYPUT
: INVOKE_PROPERTYGET
;
1269 HRESULT hInvRes
= E_FAIL
;
1271 // try Invoke first, if it does not work, try put/get property
1272 for ( sal_Int32 nStep
= 0; FAILED( hInvRes
) && nStep
< 2; nStep
++ )
1274 DISPPARAMS dispparams
= {nullptr, nullptr, 0, 0};
1276 std::unique_ptr
<DISPID
[]> arDispidNamedArgs
;
1277 std::unique_ptr
<CComVariant
[]> ptrArgs
;
1278 std::unique_ptr
<CComVariant
[]> ptrRefArgs
; // referenced arguments
1279 CComVariant
* arArgs
= nullptr;
1280 CComVariant
* arRefArgs
= nullptr;
1282 dispparams
.cArgs
= aParams
.getLength();
1284 // Determine the number of named arguments
1285 for ( sal_Int32 nInd
= 0; nInd
< aParams
.getLength(); nInd
++ )
1286 if ( aParams
[nInd
].getValueType() == cppu::UnoType
<NamedArgument
>::get() )
1287 dispparams
.cNamedArgs
++;
1289 // fill the named arguments
1290 if ( dispparams
.cNamedArgs
> 0
1291 && !( dispparams
.cNamedArgs
== 1 && pInvkinds
[nStep
] == INVOKE_PROPERTYPUT
) )
1293 int nSizeAr
= dispparams
.cNamedArgs
+ 1;
1294 if ( pInvkinds
[nStep
] == INVOKE_PROPERTYPUT
)
1295 nSizeAr
= dispparams
.cNamedArgs
;
1297 std::unique_ptr
<OLECHAR
*[]> saNames(new OLECHAR
*[nSizeAr
]);
1298 OLECHAR
** pNames
= saNames
.get();
1299 pNames
[0] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(aName
.getStr()));
1302 for ( size_t nInd
= 0; nInd
< dispparams
.cArgs
; nInd
++ )
1304 if (auto v
= o3tl::tryAccess
<NamedArgument
>(aParams
[nInd
]))
1306 const NamedArgument
& arg
= *v
;
1308 //We put the parameter names in reverse order into the array,
1309 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1310 //The first name in the array is the method name
1311 pNames
[nSizeAr
- 1 - cNamedArg
++] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(arg
.Name
.getStr()));
1315 arDispidNamedArgs
.reset( new DISPID
[nSizeAr
] );
1316 HRESULT hr
= getTypeInfo()->GetIDsOfNames( pNames
, nSizeAr
, arDispidNamedArgs
.get() );
1317 if ( hr
== E_NOTIMPL
)
1318 hr
= m_spDispatch
->GetIDsOfNames(IID_NULL
, pNames
, nSizeAr
, LOCALE_USER_DEFAULT
, arDispidNamedArgs
.get() );
1320 if ( SUCCEEDED( hr
) )
1322 if ( pInvkinds
[nStep
] == DISPATCH_PROPERTYPUT
)
1324 DISPID
* arIDs
= arDispidNamedArgs
.get();
1325 arIDs
[0] = DISPID_PROPERTYPUT
;
1326 dispparams
.rgdispidNamedArgs
= arIDs
;
1330 DISPID
* arIDs
= arDispidNamedArgs
.get();
1331 dispparams
.rgdispidNamedArgs
= & arIDs
[1];
1334 else if (hr
== DISP_E_UNKNOWNNAME
)
1336 throw IllegalArgumentException(
1337 "[automation bridge]One of the named arguments is wrong!",
1338 Reference
<XInterface
>(), 0);
1342 throw InvocationTargetException(
1343 "[automation bridge] ITypeInfo::GetIDsOfNames returned error "
1344 + OUString::number((sal_Int32
) hr
, 16), Reference
<XInterface
>(), Any());
1349 ptrArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1350 ptrRefArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1351 arArgs
= ptrArgs
.get();
1352 arRefArgs
= ptrRefArgs
.get();
1357 sal_Int32 revIndex
= 0;
1358 for ( nInd
= 0; nInd
< sal_Int32(dispparams
.cArgs
); nInd
++)
1360 revIndex
= dispparams
.cArgs
- nInd
- 1;
1361 arRefArgs
[revIndex
].byref
= nullptr;
1363 if ( nInd
< aParams
.getLength() )
1364 anyArg
= aParams
.getConstArray()[nInd
];
1366 // Property Put arguments
1367 if ( anyArg
.getValueType() == cppu::UnoType
<PropertyPutArgument
>::get() )
1369 PropertyPutArgument arg
;
1374 if (anyArg
.getValueType() == cppu::UnoType
<NamedArgument
>::get())
1376 NamedArgument aNamedArgument
;
1377 anyArg
>>= aNamedArgument
;
1378 anyArg
= aNamedArgument
.Value
;
1381 if ( nInd
< aParams
.getLength() && anyArg
.getValueTypeClass() != TypeClass_VOID
)
1383 anyToVariant( &arArgs
[revIndex
], anyArg
, VT_VARIANT
);
1387 arArgs
[revIndex
].vt
= VT_ERROR
;
1388 arArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1392 catch (IllegalArgumentException
& e
)
1394 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, sal_Int32
>( nInd
);
1397 catch (CannotConvertException
& e
)
1399 e
.ArgumentIndex
= nInd
;
1403 dispparams
.rgvarg
= arArgs
;
1404 // invoking OLE method
1405 DWORD localeId
= LOCALE_USER_DEFAULT
;
1406 hInvRes
= m_spDispatch
->Invoke( dispid
,
1409 ::sal::static_int_cast
< WORD
, INVOKEKIND
>( pInvkinds
[nStep
] ),
1416 // converting return value and out parameter back to UNO
1417 if ( SUCCEEDED( hInvRes
) )
1418 variantToAny( &varResult
, aResult
, false );
1421 // map error codes to exceptions
1427 case DISP_E_BADPARAMCOUNT
:
1428 throw IllegalArgumentException("[automation bridge] Wrong "
1429 "number of arguments. Object returned DISP_E_BADPARAMCOUNT.",
1432 case DISP_E_BADVARTYPE
:
1433 throw RuntimeException("[automation bridge] One or more "
1434 "arguments have the wrong type. Object returned "
1435 "DISP_E_BADVARTYPE.", nullptr);
1437 case DISP_E_EXCEPTION
:
1438 message
= "[automation bridge]: ";
1439 message
+= OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
),
1440 ::SysStringLen(excepinfo
.bstrDescription
));
1441 throw InvocationTargetException(message
, Reference
<XInterface
>(), Any());
1443 case DISP_E_MEMBERNOTFOUND
:
1444 message
= "[automation bridge]: A function with the name \""
1445 + aName
+ "\" is not supported. Object returned "
1446 "DISP_E_MEMBERNOTFOUND.";
1447 throw IllegalArgumentException(message
, nullptr, 0);
1449 case DISP_E_NONAMEDARGS
:
1450 throw IllegalArgumentException("[automation bridge] Object "
1451 "returned DISP_E_NONAMEDARGS",nullptr, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1453 case DISP_E_OVERFLOW
:
1454 throw CannotConvertException("[automation bridge] Call failed.",
1455 static_cast<XInterface
*>(
1456 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
1458 case DISP_E_PARAMNOTFOUND
:
1459 throw IllegalArgumentException("[automation bridge]Call failed."
1460 "Object returned DISP_E_PARAMNOTFOUND.",
1461 nullptr, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1463 case DISP_E_TYPEMISMATCH
:
1464 throw CannotConvertException("[automation bridge] Call failed. "
1465 "Object returned DISP_E_TYPEMISMATCH",
1466 static_cast<XInterface
*>(
1467 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::UNKNOWN
, uArgErr
);
1469 case DISP_E_UNKNOWNINTERFACE
:
1470 throw RuntimeException("[automation bridge] Call failed. "
1471 "Object returned DISP_E_UNKNOWNINTERFACE.",nullptr);
1473 case DISP_E_UNKNOWNLCID
:
1474 throw RuntimeException("[automation bridge] Call failed. "
1475 "Object returned DISP_E_UNKNOWNLCID.",nullptr);
1477 case DISP_E_PARAMNOTOPTIONAL
:
1478 throw CannotConvertException("[automation bridge] Call failed."
1479 "Object returned DISP_E_PARAMNOTOPTIONAL",
1480 static_cast<XInterface
*>(static_cast<XWeak
*>(this)),
1481 TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
1484 throw RuntimeException();
1492 sal_Bool SAL_CALL
IUnknownWrapper_Impl::hasMember( const OUString
& aName
)
1494 if ( ! m_spDispatch
)
1496 throw RuntimeException(
1497 "[automation bridge] The object does not have an IDispatch interface");
1500 o2u_attachCurrentThread();
1502 return getDispid( aName
, &dispid
);
1506 // UnoConversionUtilities --------------------------------------------------------------------------------
1507 Reference
< XInterface
> IUnknownWrapper_Impl::createUnoWrapperInstance()
1509 if( m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
)
1511 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper_Impl(
1512 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1513 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1515 else if( m_nUnoWrapperClass
== UNO_OBJECT_WRAPPER_REMOTE_OPT
)
1517 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
1518 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1519 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1522 return Reference
<XInterface
>();
1524 Reference
<XInterface
> IUnknownWrapper_Impl::createComWrapperInstance()
1526 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper_Impl(
1527 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1528 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1532 void IUnknownWrapper_Impl::getMethodInfo(const OUString
& sName
, TypeDescription
& methodInfo
)
1534 TypeDescription desc
= getInterfaceMemberDescOfCurrentCall(sName
);
1537 typelib_TypeDescription
* pMember
= desc
.get();
1538 if( pMember
->eTypeClass
== typelib_TypeClass_INTERFACE_METHOD
)
1539 methodInfo
= pMember
;
1543 void IUnknownWrapper_Impl::getAttributeInfo(const OUString
& sName
, TypeDescription
& attributeInfo
)
1545 TypeDescription desc
= getInterfaceMemberDescOfCurrentCall(sName
);
1548 typelib_TypeDescription
* pMember
= desc
.get();
1549 if( pMember
->eTypeClass
== typelib_TypeClass_INTERFACE_ATTRIBUTE
)
1551 attributeInfo
= reinterpret_cast<typelib_InterfaceAttributeTypeDescription
*>(pMember
)->pAttributeTypeRef
;
1555 TypeDescription
IUnknownWrapper_Impl::getInterfaceMemberDescOfCurrentCall(const OUString
& sName
)
1557 TypeDescription ret
;
1559 for( sal_Int32 i
=0; i
< m_seqTypes
.getLength(); i
++)
1561 TypeDescription
_curDesc( m_seqTypes
[i
]);
1562 _curDesc
.makeComplete();
1563 typelib_InterfaceTypeDescription
* pInterface
= reinterpret_cast<typelib_InterfaceTypeDescription
*>(_curDesc
.get());
1566 typelib_InterfaceMemberTypeDescription
* pMember
= nullptr;
1567 //find the member description of the current call
1568 for( int j
=0; j
< pInterface
->nAllMembers
; j
++)
1570 typelib_TypeDescriptionReference
* pTypeRefMember
= pInterface
->ppAllMembers
[j
];
1571 typelib_TypeDescription
* pDescMember
= nullptr;
1572 TYPELIB_DANGER_GET( &pDescMember
, pTypeRefMember
);
1574 typelib_InterfaceMemberTypeDescription
* pInterfaceMember
=
1575 reinterpret_cast<typelib_InterfaceMemberTypeDescription
*>(pDescMember
);
1576 if( OUString( pInterfaceMember
->pMemberName
) == sName
)
1578 pMember
= pInterfaceMember
;
1581 TYPELIB_DANGER_RELEASE( pDescMember
);
1586 ret
= &pMember
->aBase
;
1587 TYPELIB_DANGER_RELEASE( &pMember
->aBase
);
1596 bool IUnknownWrapper_Impl::isJScriptObject()
1598 if( m_eJScript
== JScriptUndefined
)
1600 CComDispatchDriver
disp( m_spDispatch
);
1604 if( SUCCEEDED( disp
.GetPropertyByName( JSCRIPT_ID_PROPERTY
, &result
)))
1606 if(result
.vt
== VT_BSTR
)
1608 CComBSTR
name( result
.bstrVal
);
1610 if( name
== CComBSTR(JSCRIPT_ID
))
1611 m_eJScript
= IsJScript
;
1615 if( m_eJScript
== JScriptUndefined
)
1616 m_eJScript
= NoJScript
;
1619 return m_eJScript
!= NoJScript
;
1624 The function ultimately calls IDispatch::Invoke on the wrapped COM object.
1625 The COM object does not implement UNO Interfaces ( via IDispatch). This
1626 is the case when the OleObjectFactory service has been used to create a
1628 @exception IllegalArgumentException
1629 @exception CannotConvertException
1630 @InvocationTargetException
1634 Any
IUnknownWrapper_Impl::invokeWithDispIdComTlb(const OUString
& sFuncName
,
1635 const Sequence
< Any
>& Params
,
1636 Sequence
< sal_Int16
>& OutParamIndex
,
1637 Sequence
< Any
>& OutParam
)
1639 // Get type info for the call. It can be a method call or property put or
1640 // property get operation.
1641 FuncDesc
aFuncDesc(getTypeInfo());
1642 getFuncDescForInvoke(sFuncName
, Params
, & aFuncDesc
);
1643 return invokeWithDispIdComTlb( aFuncDesc
, sFuncName
, Params
, OutParamIndex
, OutParam
);
1646 Any
IUnknownWrapper_Impl::invokeWithDispIdComTlb(FuncDesc
& aFuncDesc
,
1647 const OUString
& sFuncName
,
1648 const Sequence
< Any
>& Params
,
1649 Sequence
< sal_Int16
>& OutParamIndex
,
1650 Sequence
< Any
>& OutParam
)
1655 DISPPARAMS dispparams
= {nullptr, nullptr, 0, 0};
1656 CComVariant varResult
;
1657 ExcepInfo excepinfo
;
1658 unsigned int uArgErr
;
1660 sal_Int32 nUnoArgs
= Params
.getLength();
1661 DISPID idPropertyPut
= DISPID_PROPERTYPUT
;
1662 std::unique_ptr
<DISPID
[]> arDispidNamedArgs
;
1663 std::unique_ptr
<CComVariant
[]> ptrArgs
;
1664 std::unique_ptr
<CComVariant
[]> ptrRefArgs
; // referenced arguments
1665 CComVariant
* arArgs
= nullptr;
1666 CComVariant
* arRefArgs
= nullptr;
1667 sal_Int32 revIndex
= 0;
1669 //Set the array of DISPIDs for named args if it is a property put operation.
1670 //If there are other named arguments another array is set later on.
1671 if (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
1672 || aFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
1673 dispparams
.rgdispidNamedArgs
= & idPropertyPut
;
1675 //Determine the number of named arguments
1676 for (int iParam
= 0; iParam
< nUnoArgs
; iParam
++)
1678 const Any
& curArg
= Params
[iParam
];
1679 if (curArg
.getValueType() == cppu::UnoType
<NamedArgument
>::get())
1680 dispparams
.cNamedArgs
++;
1682 //In a property put operation a property value is a named argument (DISPID_PROPERTYPUT).
1683 //Therefore the number of named arguments is increased by one.
1684 //Although named, the argument is not named in an actual language, such as Basic,
1685 //therefore it is never a com.sun.star.bridge.oleautomation.NamedArgument
1686 if (aFuncDesc
->invkind
== DISPATCH_PROPERTYPUT
1687 || aFuncDesc
->invkind
== DISPATCH_PROPERTYPUTREF
)
1688 dispparams
.cNamedArgs
++;
1690 //Determine the number of all arguments and named arguments
1691 if (aFuncDesc
->cParamsOpt
== -1)
1693 //Attribute vararg is set on this method. "Unlimited" number of args
1694 //supported. There can be no optional or defaultvalue on any of the arguments.
1695 dispparams
.cArgs
= nUnoArgs
;
1699 //If there are named arguments, then the dispparams.cArgs
1700 //is the number of supplied args, otherwise it is the expected number.
1701 if (dispparams
.cNamedArgs
)
1702 dispparams
.cArgs
= nUnoArgs
;
1704 dispparams
.cArgs
= aFuncDesc
->cParams
;
1707 //check if there are not to many arguments supplied
1708 if (::sal::static_int_cast
< sal_uInt32
, int >( nUnoArgs
) > dispparams
.cArgs
)
1710 OUStringBuffer
buf(256);
1711 buf
.append("[automation bridge] There are too many arguments for this method");
1712 throw IllegalArgumentException( buf
.makeStringAndClear(),
1713 Reference
<XInterface
>(), (sal_Int16
) dispparams
.cArgs
);
1716 //Set up the array of DISPIDs (DISPPARAMS::rgdispidNamedArgs)
1717 //for the named arguments.
1718 //If there is only one named arg and if it is because of a property put
1719 //operation, then we need not set up the DISPID array.
1720 if (dispparams
.cNamedArgs
> 0 &&
1721 ! (dispparams
.cNamedArgs
== 1 &&
1722 (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
||
1723 aFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)))
1725 //set up an array containing the member and parameter names
1726 //which is then used in ITypeInfo::GetIDsOfNames
1727 //First determine the size of the array of names which is passed to
1728 //ITypeInfo::GetIDsOfNames. It must hold the method names + the named
1730 int nSizeAr
= dispparams
.cNamedArgs
+ 1;
1731 if (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
1732 || aFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
1734 nSizeAr
= dispparams
.cNamedArgs
; //counts the DISID_PROPERTYPUT
1737 std::unique_ptr
<OLECHAR
*[]> saNames(new OLECHAR
*[nSizeAr
]);
1738 OLECHAR
** arNames
= saNames
.get();
1739 arNames
[0] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(sFuncName
.getStr()));
1742 for (size_t iParams
= 0; iParams
< dispparams
.cArgs
; iParams
++)
1744 const Any
& curArg
= Params
[iParams
];
1745 if (auto v
= o3tl::tryAccess
<NamedArgument
>(curArg
))
1747 const NamedArgument
& arg
= *v
;
1748 //We put the parameter names in reverse order into the array,
1749 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1750 //The first name in the array is the method name
1751 arNames
[nSizeAr
- 1 - cNamedArg
++] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(arg
.Name
.getStr()));
1755 //Prepare the array of DISPIDs for ITypeInfo::GetIDsOfNames
1756 //it must be big enough to contain the DISPIDs of the member + parameters
1757 arDispidNamedArgs
.reset(new DISPID
[nSizeAr
]);
1758 HRESULT hr
= getTypeInfo()->GetIDsOfNames(arNames
, nSizeAr
,
1759 arDispidNamedArgs
.get());
1760 if ( hr
== E_NOTIMPL
)
1761 hr
= m_spDispatch
->GetIDsOfNames(IID_NULL
, arNames
, nSizeAr
, LOCALE_USER_DEFAULT
, arDispidNamedArgs
.get() );
1765 // In a "property put" operation, the property value is a named param with the
1766 //special DISPID DISPID_PROPERTYPUT
1767 if (aFuncDesc
->invkind
== DISPATCH_PROPERTYPUT
1768 || aFuncDesc
->invkind
== DISPATCH_PROPERTYPUTREF
)
1770 //Element at index 0 in the DISPID array must be DISPID_PROPERTYPUT
1771 //The first item in the array arDispidNamedArgs is the DISPID for
1772 //the method. We replace it with DISPID_PROPERTYPUT.
1773 DISPID
* arIDs
= arDispidNamedArgs
.get();
1774 arIDs
[0] = DISPID_PROPERTYPUT
;
1775 dispparams
.rgdispidNamedArgs
= arIDs
;
1779 //The first item in the array arDispidNamedArgs is the DISPID for
1780 //the method. It must be removed
1781 DISPID
* arIDs
= arDispidNamedArgs
.get();
1782 dispparams
.rgdispidNamedArgs
= & arIDs
[1];
1785 else if (hr
== DISP_E_UNKNOWNNAME
)
1787 throw IllegalArgumentException(
1788 "[automation bridge]One of the named arguments is wrong!",
1789 Reference
<XInterface
>(), 0);
1793 throw InvocationTargetException(
1794 "[automation bridge] ITypeInfo::GetIDsOfNames returned error "
1795 + OUString::number((sal_Int32
) hr
, 16), Reference
<XInterface
>(), Any());
1800 ptrArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1801 ptrRefArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1802 arArgs
= ptrArgs
.get();
1803 arRefArgs
= ptrRefArgs
.get();
1806 for (i
= 0; i
< (sal_Int32
) dispparams
.cArgs
; i
++)
1808 revIndex
= dispparams
.cArgs
- i
-1;
1809 arRefArgs
[revIndex
].byref
=nullptr;
1812 anyArg
= Params
.getConstArray()[i
];
1814 unsigned short paramFlags
= PARAMFLAG_FOPT
| PARAMFLAG_FIN
;
1815 VARTYPE varType
= VT_VARIANT
;
1816 if (aFuncDesc
->cParamsOpt
!= -1 || aFuncDesc
->cParams
!= (i
+ 1))
1818 paramFlags
= aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
1819 varType
= getElementTypeDesc(&aFuncDesc
->lprgelemdescParam
[i
].tdesc
);
1822 // Make sure that there is a UNO parameter for every
1823 // expected parameter. If there is no UNO parameter where the
1824 // called function expects one, then it must be optional. Otherwise
1825 // it's a UNO programming error.
1826 if (i
>= nUnoArgs
&& !(paramFlags
& PARAMFLAG_FOPT
))
1828 OUStringBuffer
buf(256);
1829 buf
.append("ole automation bridge: The called function expects an argument at"
1830 "position: "); //a different number of arguments")),
1831 buf
.append(OUString::number(i
));
1832 buf
.append(" (index starting at 0).");
1833 throw IllegalArgumentException( buf
.makeStringAndClear(),
1834 Reference
<XInterface
>(), (sal_Int16
) i
);
1837 // Property Put arguments
1838 if (anyArg
.getValueType() == cppu::UnoType
<PropertyPutArgument
>::get())
1840 PropertyPutArgument arg
;
1845 if (anyArg
.getValueType() == cppu::UnoType
<NamedArgument
>::get())
1847 NamedArgument aNamedArgument
;
1848 anyArg
>>= aNamedArgument
;
1849 anyArg
= aNamedArgument
.Value
;
1852 if (paramFlags
& PARAMFLAG_FOUT
&&
1853 ! (paramFlags
& PARAMFLAG_FIN
) )
1855 VARTYPE type
= ::sal::static_int_cast
< VARTYPE
, int >( varType
^ VT_BYREF
);
1858 arRefArgs
[revIndex
].vt
= type
;
1863 arRefArgs
[revIndex
].vt
= VT_ERROR
;
1864 arRefArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1866 if( type
== VT_VARIANT
)
1868 arArgs
[revIndex
].vt
= VT_VARIANT
| VT_BYREF
;
1869 arArgs
[revIndex
].byref
= &arRefArgs
[revIndex
];
1873 arArgs
[revIndex
].vt
= varType
;
1874 if (type
== VT_DECIMAL
)
1875 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].decVal
;
1877 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].byref
;
1880 // in/out + in byref params
1881 else if (varType
& VT_BYREF
)
1883 VARTYPE type
= ::sal::static_int_cast
< VARTYPE
, int >( varType
^ VT_BYREF
);
1886 if (i
< nUnoArgs
&& anyArg
.getValueTypeClass() != TypeClass_VOID
)
1888 anyToVariant( & arRefArgs
[revIndex
], anyArg
, type
);
1890 else if (paramFlags
& PARAMFLAG_FHASDEFAULT
)
1892 //optional arg with default
1893 VariantCopy( & arRefArgs
[revIndex
],
1894 & aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.
1895 pparamdescex
->varDefaultValue
);
1900 //e.g: call func(x) in basic : func() ' no arg supplied
1901 OSL_ASSERT(paramFlags
& PARAMFLAG_FOPT
);
1902 arRefArgs
[revIndex
].vt
= VT_ERROR
;
1903 arRefArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1906 // Set the converted arguments in the array which will be
1907 // DISPPARAMS::rgvarg
1908 // byref arg VT_XXX |VT_BYREF
1909 arArgs
[revIndex
].vt
= varType
;
1910 if (revIndex
== 0 && aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
)
1912 arArgs
[revIndex
] = arRefArgs
[revIndex
];
1914 else if (type
== VT_DECIMAL
)
1916 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].decVal
;
1918 else if (type
== VT_VARIANT
)
1920 if ( ! (paramFlags
& PARAMFLAG_FOUT
))
1921 arArgs
[revIndex
] = arRefArgs
[revIndex
];
1923 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
];
1927 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].byref
;
1928 arArgs
[revIndex
].vt
= ::sal::static_int_cast
< VARTYPE
, int >( arRefArgs
[revIndex
].vt
| VT_BYREF
);
1932 // in parameter no VT_BYREF except for array, interfaces
1934 { // void any stands for optional param
1935 if (i
< nUnoArgs
&& anyArg
.getValueTypeClass() != TypeClass_VOID
)
1937 anyToVariant( & arArgs
[revIndex
], anyArg
, varType
);
1939 //optional arg but no void any supplied
1940 //Basic: obj.func() ' first parameter left out because it is optional
1941 else if (paramFlags
& PARAMFLAG_FHASDEFAULT
)
1943 //optional arg with default either as direct arg : VT_XXX or
1944 VariantCopy( & arArgs
[revIndex
],
1945 & aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.
1946 pparamdescex
->varDefaultValue
);
1948 else if (paramFlags
& PARAMFLAG_FOPT
)
1950 arArgs
[revIndex
].vt
= VT_ERROR
;
1951 arArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1955 arArgs
[revIndex
].vt
= VT_EMPTY
;
1956 arArgs
[revIndex
].lVal
= 0;
1961 catch (IllegalArgumentException
& e
)
1963 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, sal_Int32
>( i
);
1966 catch (CannotConvertException
& e
)
1968 e
.ArgumentIndex
= i
;
1971 dispparams
.rgvarg
= arArgs
;
1972 // invoking OLE method
1973 DWORD localeId
= LOCALE_USER_DEFAULT
;
1974 result
= m_spDispatch
->Invoke(aFuncDesc
->memid
,
1977 ::sal::static_int_cast
< WORD
, INVOKEKIND
>( aFuncDesc
->invkind
),
1983 // converting return value and out parameter back to UNO
1987 // allocate space for the out param Sequence and indices Sequence
1988 int outParamsCount
= 0; // includes in/out parameter
1989 for (int j
= 0; j
< aFuncDesc
->cParams
; j
++)
1991 if (aFuncDesc
->lprgelemdescParam
[j
].paramdesc
.wParamFlags
&
1996 OutParamIndex
.realloc(outParamsCount
);
1997 OutParam
.realloc(outParamsCount
);
1998 // Convert out params
2001 int outParamIndex
=0;
2002 for (int paramIndex
= 0; paramIndex
< nUnoArgs
; paramIndex
++)
2004 //Determine the index within the method signature
2005 int realParamIndex
= paramIndex
;
2006 int revParamIndex
= dispparams
.cArgs
- paramIndex
- 1;
2007 if (Params
[paramIndex
].getValueType()
2008 == cppu::UnoType
<NamedArgument
>::get())
2010 //dispparams.rgdispidNamedArgs contains the mapping from index
2011 //of named args list to index of parameter list
2012 realParamIndex
= dispparams
.rgdispidNamedArgs
[revParamIndex
];
2015 // no named arg, always come before named args
2016 if (! (aFuncDesc
->lprgelemdescParam
[realParamIndex
].paramdesc
.wParamFlags
2020 // variantToAny is called with the "reduce range" parameter set to sal_False.
2021 // That causes VT_I4 values not to be converted down to a "lower" type. That
2022 // feature exist for JScript only because it only uses VT_I4 for integer types.
2025 variantToAny( & arRefArgs
[revParamIndex
], outAny
, false );
2027 catch (IllegalArgumentException
& e
)
2029 e
.ArgumentPosition
= (sal_Int16
)paramIndex
;
2032 catch (CannotConvertException
& e
)
2034 e
.ArgumentIndex
= paramIndex
;
2037 OutParam
[outParamIndex
] = outAny
;
2038 OutParamIndex
[outParamIndex
] = ::sal::static_int_cast
< sal_Int16
, int >( paramIndex
);
2041 OutParam
.realloc(outParamIndex
);
2042 OutParamIndex
.realloc(outParamIndex
);
2045 variantToAny(&varResult
, ret
, false);
2048 // map error codes to exceptions
2054 case DISP_E_BADPARAMCOUNT
:
2055 throw IllegalArgumentException("[automation bridge] Wrong "
2056 "number of arguments. Object returned DISP_E_BADPARAMCOUNT.",
2059 case DISP_E_BADVARTYPE
:
2060 throw RuntimeException("[automation bridge] One or more "
2061 "arguments have the wrong type. Object returned "
2062 "DISP_E_BADVARTYPE.", nullptr);
2064 case DISP_E_EXCEPTION
:
2065 message
= "[automation bridge]: ";
2066 message
+= OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
),
2067 ::SysStringLen(excepinfo
.bstrDescription
));
2069 throw InvocationTargetException(message
, Reference
<XInterface
>(), Any());
2071 case DISP_E_MEMBERNOTFOUND
:
2072 message
= "[automation bridge]: A function with the name \""
2073 + sFuncName
+ "\" is not supported. Object returned "
2074 "DISP_E_MEMBERNOTFOUND.";
2075 throw IllegalArgumentException(message
, nullptr, 0);
2077 case DISP_E_NONAMEDARGS
:
2078 throw IllegalArgumentException("[automation bridge] Object "
2079 "returned DISP_E_NONAMEDARGS",nullptr, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
2081 case DISP_E_OVERFLOW
:
2082 throw CannotConvertException("[automation bridge] Call failed.",
2083 static_cast<XInterface
*>(
2084 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
2086 case DISP_E_PARAMNOTFOUND
:
2087 throw IllegalArgumentException("[automation bridge]Call failed."
2088 "Object returned DISP_E_PARAMNOTFOUND.",
2089 nullptr, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
2091 case DISP_E_TYPEMISMATCH
:
2092 throw CannotConvertException("[automation bridge] Call failed. "
2093 "Object returned DISP_E_TYPEMISMATCH",
2094 static_cast<XInterface
*>(
2095 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::UNKNOWN
, uArgErr
);
2097 case DISP_E_UNKNOWNINTERFACE
:
2098 throw RuntimeException("[automation bridge] Call failed. "
2099 "Object returned DISP_E_UNKNOWNINTERFACE.",nullptr);
2101 case DISP_E_UNKNOWNLCID
:
2102 throw RuntimeException("[automation bridge] Call failed. "
2103 "Object returned DISP_E_UNKNOWNLCID.",nullptr);
2105 case DISP_E_PARAMNOTOPTIONAL
:
2106 throw CannotConvertException("[automation bridge] Call failed."
2107 "Object returned DISP_E_PARAMNOTOPTIONAL",
2108 static_cast<XInterface
*>(static_cast<XWeak
*>(this)),
2109 TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
2112 throw RuntimeException();
2119 void IUnknownWrapper_Impl::getFuncDescForInvoke(const OUString
& sFuncName
,
2120 const Sequence
<Any
> & seqArgs
,
2121 FUNCDESC
** pFuncDesc
)
2123 int nUnoArgs
= seqArgs
.getLength();
2124 const Any
* arArgs
= seqArgs
.getConstArray();
2125 ITypeInfo
* pInfo
= getTypeInfo();
2127 //If the last of the positional arguments is a PropertyPutArgument
2128 //then obtain the type info for the property put operation.
2130 //The property value is always the last argument, in a positional argument list
2131 //or in a list of named arguments. A PropertyPutArgument is actually a named argument
2132 //hence it must not be put in an extra NamedArgument structure
2134 arArgs
[nUnoArgs
- 1].getValueType() == cppu::UnoType
<PropertyPutArgument
>::get())
2136 // DISPATCH_PROPERTYPUT
2137 FuncDesc
aDescGet(pInfo
);
2138 FuncDesc
aDescPut(pInfo
);
2139 VarDesc
aVarDesc(pInfo
);
2140 getPropDesc(sFuncName
, & aDescGet
, & aDescPut
, & aVarDesc
);
2143 throw IllegalArgumentException(
2144 "[automation bridge] The object does not have a writeable property: "
2145 + sFuncName
, Reference
<XInterface
>(), 0);
2147 *pFuncDesc
= aDescPut
.Detach();
2150 { // DISPATCH_METHOD
2151 FuncDesc
aFuncDesc(pInfo
);
2152 getFuncDesc(sFuncName
, & aFuncDesc
);
2155 // Fallback: DISPATCH_PROPERTYGET can mostly be called as
2157 ITypeInfo
* pTypeInfo
= getTypeInfo();
2158 FuncDesc
aDescPut(pTypeInfo
);
2159 VarDesc
aVarDesc(pTypeInfo
);
2160 getPropDesc(sFuncName
, & aFuncDesc
, & aDescPut
, & aVarDesc
);
2163 throw IllegalArgumentException(
2164 "[automation bridge] The object does not have a function"
2165 "or readable property \""
2166 + sFuncName
, Reference
<XInterface
>(), 0);
2169 *pFuncDesc
= aFuncDesc
.Detach();
2172 bool IUnknownWrapper_Impl::getDispid(const OUString
& sFuncName
, DISPID
* id
)
2174 OSL_ASSERT(m_spDispatch
);
2175 LPOLESTR lpsz
= const_cast<LPOLESTR
> (reinterpret_cast<LPCOLESTR
>(sFuncName
.getStr()));
2176 HRESULT hr
= m_spDispatch
->GetIDsOfNames(IID_NULL
, &lpsz
, 1, LOCALE_USER_DEFAULT
, id
);
2179 void IUnknownWrapper_Impl::getFuncDesc(const OUString
& sFuncName
, FUNCDESC
** pFuncDesc
)
2182 OSL_ASSERT( * pFuncDesc
== nullptr);
2184 typedef TLBFuncIndexMap::const_iterator cit
;
2185 //We assume there is only one entry with the function name. A property
2186 //would have two entries.
2187 cit itIndex
= m_mapComFunc
.find(sFuncName
);
2188 if (itIndex
== m_mapComFunc
.end())
2190 //try case insensitive with IDispatch::GetIDsOfNames
2192 if (getDispid(sFuncName
, &id
))
2194 CComBSTR memberName
;
2195 unsigned int pcNames
=0;
2196 // get the case sensitive name
2197 if( SUCCEEDED(getTypeInfo()->GetNames( id
, & memberName
, 1, &pcNames
)))
2199 //get the associated index and add an entry to the map
2200 //with the name sFuncName which differs in the casing of the letters to
2201 //the actual name as obtained from ITypeInfo
2202 OUString
sRealName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
)));
2203 cit itOrg
= m_mapComFunc
.find(sRealName
);
2204 OSL_ASSERT(itOrg
!= m_mapComFunc
.end());
2205 // maybe this is a property, if so we need
2206 // to store either both id's ( put/get ) or
2207 // just the get. Storing both is more consistent
2208 pair
<cit
, cit
> pItems
= m_mapComFunc
.equal_range( sRealName
);
2209 for ( ;pItems
.first
!= pItems
.second
; ++pItems
.first
)
2210 m_mapComFunc
.insert( TLBFuncIndexMap::value_type ( make_pair(sFuncName
, pItems
.first
->second
) ));
2212 m_mapComFunc
.find( sFuncName
);
2217 #if OSL_DEBUG_LEVEL >= 1
2218 // There must only be one entry if sFuncName represents a function or two
2219 // if it is a property
2220 pair
<cit
, cit
> p
= m_mapComFunc
.equal_range(sFuncName
.toAsciiLowerCase());
2222 for ( ;p
.first
!= p
.second
; p
.first
++, numEntries
++);
2223 OSL_ASSERT( ! (numEntries
> 3) );
2225 if( itIndex
!= m_mapComFunc
.end())
2227 ITypeInfo
* pType
= getTypeInfo();
2228 FUNCDESC
* pDesc
= nullptr;
2229 if (SUCCEEDED(pType
->GetFuncDesc(itIndex
->second
, & pDesc
)))
2231 if (pDesc
->invkind
== INVOKE_FUNC
)
2233 (*pFuncDesc
) = pDesc
;
2237 pType
->ReleaseFuncDesc(pDesc
);
2242 throw BridgeRuntimeError("[automation bridge] Could not get "
2243 "FUNCDESC for " + sFuncName
);
2246 //else no entry found for sFuncName, pFuncDesc will not be filled in
2249 void IUnknownWrapper_Impl::getPropDesc(const OUString
& sFuncName
, FUNCDESC
** pFuncDescGet
,
2250 FUNCDESC
** pFuncDescPut
, VARDESC
** pVarDesc
)
2252 OSL_ASSERT( * pFuncDescGet
== nullptr && * pFuncDescPut
== nullptr);
2254 typedef TLBFuncIndexMap::const_iterator cit
;
2255 pair
<cit
, cit
> p
= m_mapComFunc
.equal_range(sFuncName
);
2256 if (p
.first
== m_mapComFunc
.end())
2258 //try case insensitive with IDispatch::GetIDsOfNames
2260 if (getDispid(sFuncName
, &id
))
2262 CComBSTR memberName
;
2263 unsigned int pcNames
=0;
2264 // get the case sensitive name
2265 if( SUCCEEDED(getTypeInfo()->GetNames( id
, & memberName
, 1, &pcNames
)))
2267 //As opposed to getFuncDesc, we do not add the value because we would
2268 // need to find the get and set description for the property. This would
2269 //mean to iterate over all FUNCDESCs again.
2270 p
= m_mapComFunc
.equal_range(OUString(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
))));
2275 for ( int i
= 0 ;p
.first
!= p
.second
; p
.first
++, i
++)
2277 // There are a maximum of two entries, property put and property get
2278 OSL_ASSERT( ! (i
> 2) );
2279 ITypeInfo
* pType
= getTypeInfo();
2280 FUNCDESC
* pFuncDesc
= nullptr;
2281 if (SUCCEEDED( pType
->GetFuncDesc(p
.first
->second
, & pFuncDesc
)))
2283 if (pFuncDesc
->invkind
== INVOKE_PROPERTYGET
)
2285 (*pFuncDescGet
) = pFuncDesc
;
2287 else if (pFuncDesc
->invkind
== INVOKE_PROPERTYPUT
||
2288 pFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
2290 //a property can have 3 entries, put, put ref, get
2291 // If INVOKE_PROPERTYPUTREF or INVOKE_PROPERTYPUT is used
2292 //depends on what is found first.
2293 if ( * pFuncDescPut
)
2295 //we already have found one
2296 pType
->ReleaseFuncDesc(pFuncDesc
);
2300 (*pFuncDescPut
) = pFuncDesc
;
2305 pType
->ReleaseFuncDesc(pFuncDesc
);
2308 //ITypeInfo::GetFuncDesc may even provide a funcdesc for a VARDESC
2309 // with invkind = INVOKE_FUNC. Since this function should only return
2310 //a value for a real property (XInvokation::hasMethod, ..::hasProperty
2311 //we need to make sure that sFuncName represents a real property.
2312 VARDESC
* pVD
= nullptr;
2313 if (SUCCEEDED(pType
->GetVarDesc(p
.first
->second
, & pVD
)))
2316 //else no entry for sFuncName, pFuncDesc will not be filled in
2319 VARTYPE
IUnknownWrapper_Impl::getUserDefinedElementType( ITypeInfo
* pTypeInfo
, const DWORD nHrefType
)
2321 VARTYPE
_type( VT_NULL
);
2324 CComPtr
<ITypeInfo
> spRefInfo
;
2325 pTypeInfo
->GetRefTypeInfo( nHrefType
, &spRefInfo
.p
);
2328 TypeAttr
attr( spRefInfo
);
2329 spRefInfo
->GetTypeAttr( &attr
);
2330 if ( attr
->typekind
== TKIND_ENUM
)
2332 // We use the type of the first enum value.
2333 if ( attr
->cVars
== 0 )
2335 throw BridgeRuntimeError("[automation bridge] Could not obtain type description");
2337 VarDesc
var( spRefInfo
);
2338 spRefInfo
->GetVarDesc( 0, &var
);
2339 _type
= var
->lpvarValue
->vt
;
2341 else if ( attr
->typekind
== TKIND_INTERFACE
)
2345 else if ( attr
->typekind
== TKIND_DISPATCH
)
2347 _type
= VT_DISPATCH
;
2349 else if ( attr
->typekind
== TKIND_ALIAS
)
2351 // TKIND_ALIAS is a type that is an alias for another type. So get that alias type.
2352 _type
= getUserDefinedElementType( pTypeInfo
, attr
->tdescAlias
.hreftype
);
2356 throw BridgeRuntimeError( "[automation bridge] Unhandled user defined type." );
2363 VARTYPE
IUnknownWrapper_Impl::getElementTypeDesc(const TYPEDESC
*desc
)
2365 VARTYPE
_type( VT_NULL
);
2367 if (desc
->vt
== VT_PTR
)
2369 _type
= getElementTypeDesc(desc
->lptdesc
);
2372 else if (desc
->vt
== VT_SAFEARRAY
)
2374 _type
= getElementTypeDesc(desc
->lptdesc
);
2377 else if (desc
->vt
== VT_USERDEFINED
)
2379 ITypeInfo
* thisInfo
= getTypeInfo(); //kept by this instance
2380 _type
= getUserDefinedElementType( thisInfo
, desc
->hreftype
);
2389 void IUnknownWrapper_Impl::buildComTlbIndex()
2391 if ( ! m_bComTlbIndexInit
)
2393 MutexGuard
guard(getBridgeMutex());
2395 if ( ! m_bComTlbIndexInit
)
2398 ITypeInfo
* pType
= getTypeInfo();
2399 TypeAttr
typeAttr(pType
);
2400 if( SUCCEEDED( pType
->GetTypeAttr( &typeAttr
)))
2402 for( long i
= 0; i
< typeAttr
->cFuncs
; i
++)
2404 FuncDesc
funcDesc(pType
);
2405 if( SUCCEEDED( pType
->GetFuncDesc( i
, &funcDesc
)))
2407 CComBSTR memberName
;
2408 unsigned int pcNames
=0;
2409 if( SUCCEEDED(pType
->GetNames( funcDesc
->memid
, & memberName
, 1, &pcNames
)))
2411 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
)));
2412 m_mapComFunc
.insert( TLBFuncIndexMap::value_type( usName
, i
));
2416 sError
= "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2417 "ITypeInfo::GetNames failed.";
2421 sError
= "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2422 "ITypeInfo::GetFuncDesc failed.";
2425 //If we create an Object in JScript and a property then it
2426 //has VARDESC instead of FUNCDESC
2427 for (long i
= 0; i
< typeAttr
->cVars
; i
++)
2429 VarDesc
varDesc(pType
);
2430 if (SUCCEEDED(pType
->GetVarDesc(i
, & varDesc
)))
2432 CComBSTR memberName
;
2433 unsigned int pcNames
= 0;
2434 if (SUCCEEDED(pType
->GetNames(varDesc
->memid
, & memberName
, 1, &pcNames
)))
2436 if (varDesc
->varkind
== VAR_DISPATCH
)
2438 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
)));
2439 m_mapComFunc
.insert(TLBFuncIndexMap::value_type(
2445 sError
= "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2446 "ITypeInfo::GetNames failed.";
2450 sError
= "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2451 "ITypeInfo::GetVarDesc failed.";
2456 sError
= "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2457 "ITypeInfo::GetTypeAttr failed.";
2459 if (sError
.getLength())
2461 throw BridgeRuntimeError(sError
);
2464 m_bComTlbIndexInit
= true;
2470 ITypeInfo
* IUnknownWrapper_Impl::getTypeInfo()
2474 throw BridgeRuntimeError("The object has no IDispatch interface!");
2479 MutexGuard
guard(getBridgeMutex());
2482 CComPtr
< ITypeInfo
> spType
;
2483 if( SUCCEEDED( m_spDispatch
->GetTypeInfo( 0, LOCALE_USER_DEFAULT
, &spType
.p
)))
2486 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
2488 //If this is a dual interface then TYPEATTR::typekind is usually TKIND_INTERFACE
2489 //We need to get the type description for TKIND_DISPATCH
2490 TypeAttr
typeAttr(spType
.p
);
2491 if( SUCCEEDED(spType
->GetTypeAttr( &typeAttr
)))
2493 if (typeAttr
->typekind
== TKIND_INTERFACE
&&
2494 typeAttr
->wTypeFlags
& TYPEFLAG_FDUAL
)
2496 HREFTYPE refDispatch
;
2497 if (SUCCEEDED(spType
->GetRefTypeOfImplType(::sal::static_int_cast
< UINT
, int >( -1 ), &refDispatch
)))
2499 CComPtr
<ITypeInfo
> spTypeDisp
;
2500 if (SUCCEEDED(spType
->GetRefTypeInfo(refDispatch
, & spTypeDisp
)))
2501 m_spTypeInfo
= spTypeDisp
;
2505 throw BridgeRuntimeError(
2506 "[automation bridge] Could not obtain type information "
2507 "for dispatch interface." );
2510 else if (typeAttr
->typekind
== TKIND_DISPATCH
)
2512 m_spTypeInfo
= spType
;
2516 throw BridgeRuntimeError(
2517 "[automation bridge] Automation object does not "
2518 "provide type information.");
2524 throw BridgeRuntimeError("[automation bridge]The dispatch object does not "
2525 "support ITypeInfo!");
2529 return m_spTypeInfo
;
2534 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */