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"
28 #include "boost/scoped_array.hpp"
29 #include <com/sun/star/script/FailReason.hpp>
30 #include <com/sun/star/beans/XMaterialHolder.hpp>
31 #include <com/sun/star/script/XTypeConverter.hpp>
32 #include <com/sun/star/script/FinishEngineEvent.hpp>
33 #include <com/sun/star/script/InterruptReason.hpp>
34 #include <com/sun/star/script/XEngineListener.hpp>
35 #include <com/sun/star/script/XDebugging.hpp>
36 #include <com/sun/star/script/XInvocation.hpp>
37 #include <com/sun/star/script/ContextInformation.hpp>
38 #include <com/sun/star/script/FinishReason.hpp>
39 #include <com/sun/star/script/XEngine.hpp>
40 #include <com/sun/star/script/InterruptEngineEvent.hpp>
41 #include <com/sun/star/script/XLibraryAccess.hpp>
42 #include <com/sun/star/bridge/ModelDependent.hpp>
44 #include "com/sun/star/bridge/oleautomation/NamedArgument.hpp"
45 #include "com/sun/star/bridge/oleautomation/PropertyPutArgument.hpp"
47 #include <typelib/typedescription.hxx>
49 #include <rtl/ustring.hxx>
51 #include "jscriptclasses.hxx"
53 #include "oleobjw.hxx"
54 #include "unoobjw.hxx"
57 using namespace boost
;
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_uInt32
, sal_uInt32
> 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 AdapterToWrappperMap 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_uInt32
,sal_uInt32
> WrapperToAdapterMap
;
91 std::unordered_map
<sal_uInt32
, 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( NULL
), 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
= (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_uInt32
, sal_uInt32
>::iterator _IT
;
119 _IT it
= WrapperToAdapterMap
.find( (sal_uInt32
) xIntRoot
);
120 if( it
!= WrapperToAdapterMap
.end())
122 sal_uInt32 adapter
= it
->second
;
124 AdapterToWrapperMap
.erase( adapter
);
125 WrapperToAdapterMap
.erase( it
);
128 IT_Com it_c
= ComPtrToWrapperMap
.find( (sal_uInt32
) m_spUnknown
.p
);
129 if(it_c
!= ComPtrToWrapperMap
.end())
130 ComPtrToWrapperMap
.erase(it_c
);
132 #if OSL_DEBUG_LEVEL > 0
133 fprintf(stderr
,"[automation bridge] ComPtrToWrapperMap contains: %i \n",
134 ComPtrToWrapperMap
.size());
138 Any
IUnknownWrapper_Impl::queryInterface(const Type
& t
)
139 throw (RuntimeException
)
141 if (t
== cppu::UnoType
<XDefaultMethod
>::get() && !m_bHasDfltMethod
)
143 if (t
== cppu::UnoType
<XDefaultProperty
>::get() && !m_bHasDfltProperty
)
145 if ( ( t
== cppu::UnoType
<XInvocation
>::get() || t
== cppu::UnoType
<XAutomationInvocation
>::get() ) && !m_spDispatch
)
147 // XDirectInvocation seems to be an oracle replacement for XAutomationInvocation, however it is flawed esecially wrt. assumptions about whether to invoke a
148 // 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.
149 // XAutomationInvocation provides separate calls for put& get
150 // 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.
151 // For the moment for ease of merging we will let the XDirectInvoke and XAuthomationInvocation interfaces stay side by side ( and for the momemnt at least I would prefer the basic
152 // runtime to call XAutomationInvocation instead of XDirectInvoke
153 return WeakImplHelper7
<XBridgeSupplier2
,
154 XInitialization
, XAutomationObject
, XDefaultProperty
, XDefaultMethod
, XDirectInvocation
, XAutomationInvocation
>::queryInterface(t
);
157 Reference
<XIntrospectionAccess
> SAL_CALL
IUnknownWrapper_Impl::getIntrospection()
158 throw (RuntimeException
)
160 Reference
<XIntrospectionAccess
> ret
;
165 Any SAL_CALL
IUnknownWrapper_Impl::invokeGetProperty( const OUString
& aPropertyName
, const Sequence
< Any
>& aParams
, Sequence
< sal_Int16
>& aOutParamIndex
, Sequence
< Any
>& aOutParam
)
170 o2u_attachCurrentThread();
171 ITypeInfo
* pInfo
= getTypeInfo();
172 FuncDesc
aDescGet(pInfo
);
173 FuncDesc
aDescPut(pInfo
);
174 VarDesc
aVarDesc(pInfo
);
175 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
178 OUString
msg("[automation bridge]Property \"" + aPropertyName
+
179 "\" is not supported");
180 throw UnknownPropertyException(msg
);
182 aResult
= invokeWithDispIdComTlb( aDescGet
, aPropertyName
, aParams
, aOutParamIndex
, aOutParam
);
184 catch ( const Exception
& e
)
186 throw RuntimeException("[automation bridge] unexpected exception in "
187 "IUnknownWrapper_Impl::invokeGetProperty ! Message : \n" +
193 Any SAL_CALL
IUnknownWrapper_Impl::invokePutProperty( const OUString
& aPropertyName
, const Sequence
< Any
>& aParams
, Sequence
< sal_Int16
>& aOutParamIndex
, Sequence
< Any
>& aOutParam
)
198 o2u_attachCurrentThread();
199 ITypeInfo
* pInfo
= getTypeInfo();
200 FuncDesc
aDescGet(pInfo
);
201 FuncDesc
aDescPut(pInfo
);
202 VarDesc
aVarDesc(pInfo
);
203 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
206 OUString
msg("[automation bridge]Property \"" + aPropertyName
+
207 "\" is not supported");
208 throw UnknownPropertyException(msg
);
210 aResult
= invokeWithDispIdComTlb( aDescPut
, aPropertyName
, aParams
, aOutParamIndex
, aOutParam
);
212 catch ( const Exception
& e
)
214 throw RuntimeException("[automation bridge] unexpected exception in "
215 "IUnknownWrapper_Impl::invokePutProperty ! Message : \n" +
222 Any SAL_CALL
IUnknownWrapper_Impl::invoke( const OUString
& aFunctionName
,
223 const Sequence
< Any
>& aParams
, Sequence
< sal_Int16
>& aOutParamIndex
,
224 Sequence
< Any
>& aOutParam
)
225 throw(IllegalArgumentException
, CannotConvertException
, InvocationTargetException
,
228 if ( ! m_spDispatch
)
230 throw RuntimeException(
231 "[automation bridge] The object does not have an IDispatch interface");
238 o2u_attachCurrentThread();
240 TypeDescription methodDesc
;
241 getMethodInfo(aFunctionName
, methodDesc
);
244 ret
= invokeWithDispIdUnoTlb(aFunctionName
,
251 ret
= invokeWithDispIdComTlb( aFunctionName
,
257 catch (const IllegalArgumentException
&)
261 catch (const CannotConvertException
&)
265 catch (const BridgeRuntimeError
& e
)
267 throw RuntimeException(e
.message
);
269 catch (const Exception
& e
)
271 throw RuntimeException("[automation bridge] unexpected exception in "
272 "IUnknownWrapper_Impl::invoke ! Message : \n" +
278 throw RuntimeException("[automation bridge] unexpected exception in "
279 "IUnknownWrapper_Impl::Invoke !");
284 void SAL_CALL
IUnknownWrapper_Impl::setValue( const OUString
& aPropertyName
,
286 throw(UnknownPropertyException
, CannotConvertException
, InvocationTargetException
,
289 if ( ! m_spDispatch
)
291 throw RuntimeException(
292 "[automation bridge] The object does not have an IDispatch interface");
296 o2u_attachCurrentThread();
298 ITypeInfo
* pInfo
= getTypeInfo();
299 FuncDesc
aDescGet(pInfo
);
300 FuncDesc
aDescPut(pInfo
);
301 VarDesc
aVarDesc(pInfo
);
302 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
303 //check if there is such a property at all or if it is read only
304 if ( ! aDescPut
&& ! aDescGet
&& ! aVarDesc
)
306 OUString
msg("[automation bridge]Property \"" + aPropertyName
+
307 "\" is not supported");
308 throw UnknownPropertyException(msg
);
311 if ( (! aDescPut
&& aDescGet
) || aVarDesc
312 && aVarDesc
->wVarFlags
== VARFLAG_FREADONLY
)
315 OUString
msg("[automation bridge] Property " + aPropertyName
+
317 OString sMsg
= OUStringToOString(msg
, osl_getThreadTextEncoding());
318 OSL_FAIL(sMsg
.getStr());
324 DISPPARAMS dispparams
;
326 CComVariant varRefArg
;
327 CComVariant varResult
;
329 unsigned int uArgErr
;
331 // converting UNO value to OLE variant
332 DISPID dispidPut
= DISPID_PROPERTYPUT
;
333 dispparams
.rgdispidNamedArgs
= &dispidPut
;
334 dispparams
.cArgs
= 1;
335 dispparams
.cNamedArgs
= 1;
336 dispparams
.rgvarg
= & varArg
;
338 OSL_ASSERT(aDescPut
|| aVarDesc
);
342 INVOKEKIND invkind
= INVOKE_PROPERTYPUT
;
343 //determine the expected type, dispid, invoke kind (DISPATCH_PROPERTYPUT,
344 //DISPATCH_PROPERTYPUTREF)
347 vt
= getElementTypeDesc(& aDescPut
->lprgelemdescParam
[0].tdesc
);
348 dispid
= aDescPut
->memid
;
349 invkind
= aDescPut
->invkind
;
353 vt
= getElementTypeDesc( & aVarDesc
->elemdescVar
.tdesc
);
354 dispid
= aVarDesc
->memid
;
355 if (vt
== VT_UNKNOWN
|| vt
== VT_DISPATCH
||
356 (vt
& VT_ARRAY
) || (vt
& VT_BYREF
))
358 invkind
= INVOKE_PROPERTYPUTREF
;
362 // convert the uno argument
365 anyToVariant( & varRefArg
, aValue
, ::sal::static_int_cast
< VARTYPE
, int >( vt
^ VT_BYREF
) );
367 if( (vt
& VT_TYPEMASK
) == VT_VARIANT
)
368 varArg
.byref
= & varRefArg
;
369 else if ((vt
& VT_TYPEMASK
) == VT_DECIMAL
)
370 varArg
.byref
= & varRefArg
.decVal
;
372 varArg
.byref
= & varRefArg
.byref
;
376 anyToVariant(& varArg
, aValue
, vt
);
379 hr
= m_spDispatch
->Invoke(dispid
, IID_NULL
, LOCALE_USER_DEFAULT
, ::sal::static_int_cast
< WORD
, INVOKEKIND
>( invkind
),
380 &dispparams
, & varResult
, & excepinfo
, &uArgErr
);
387 case DISP_E_BADPARAMCOUNT
:
388 throw RuntimeException();
390 case DISP_E_BADVARTYPE
:
391 throw RuntimeException();
393 case DISP_E_EXCEPTION
:
394 throw InvocationTargetException();
396 case DISP_E_MEMBERNOTFOUND
:
397 throw UnknownPropertyException();
399 case DISP_E_NONAMEDARGS
:
400 throw RuntimeException();
402 case DISP_E_OVERFLOW
:
403 throw CannotConvertException("call to OLE object failed", static_cast<XInterface
*>(
404 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
406 case DISP_E_PARAMNOTFOUND
:
407 throw IllegalArgumentException("call to OLE object failed", static_cast<XInterface
*>(
408 static_cast<XWeak
*>(this)), ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
)) ;
410 case DISP_E_TYPEMISMATCH
:
411 throw CannotConvertException("call to OLE object failed", static_cast<XInterface
*>(
412 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::UNKNOWN
, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
414 case DISP_E_UNKNOWNINTERFACE
:
415 throw RuntimeException();
417 case DISP_E_UNKNOWNLCID
:
418 throw RuntimeException();
420 case DISP_E_PARAMNOTOPTIONAL
:
421 throw CannotConvertException("call to OLE object failed",static_cast<XInterface
*>(
422 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
425 throw RuntimeException();
429 catch (const CannotConvertException
&)
433 catch (const UnknownPropertyException
&)
437 catch (const BridgeRuntimeError
& e
)
439 throw RuntimeException(e
.message
);
441 catch (const Exception
& e
)
443 throw RuntimeException("[automation bridge] unexpected exception in "
444 "IUnknownWrapper_Impl::setValue ! Message : \n" +
450 throw RuntimeException(
451 "[automation bridge] unexpected exception in "
452 "IUnknownWrapper_Impl::setValue !");
456 Any SAL_CALL
IUnknownWrapper_Impl::getValue( const OUString
& aPropertyName
)
457 throw(UnknownPropertyException
, RuntimeException
)
459 if ( ! m_spDispatch
)
461 throw RuntimeException(
462 "[automation bridge] The object does not have an IDispatch interface");
467 o2u_attachCurrentThread();
468 ITypeInfo
* pInfo
= getTypeInfo();
469 // I was going to implement an XServiceInfo interface to allow the type
470 // of the automation object to be exposed.. but it seems
471 // from looking at comments in the code that it is possible for
472 // this object to actually wrap an UNO object ( I guess if automation is
473 // used from MSO to create Openoffice objects ) Therefore, those objects
474 // will more than likely already have their own XServiceInfo interface.
475 // Instead here I chose a name that should be illegal both in COM and
476 // UNO ( from an IDL point of view ) therefore I think this is a safe
478 if ( aPropertyName
== "$GetTypeName" )
480 if ( pInfo
&& m_sTypeName
.getLength() == 0 )
482 m_sTypeName
= "IDispatch";
485 if ( SUCCEEDED( pInfo
->GetDocumentation( -1, &sName
, NULL
, NULL
, NULL
) ) )
487 OUString
sTmp( reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(sName
)));
488 if ( sTmp
.startsWith("_") )
490 // do we own the memory for pTypeLib, msdn doco is vague
492 CComPtr
< ITypeLib
> pTypeLib
;
494 if ( SUCCEEDED( pInfo
->GetContainingTypeLib( &pTypeLib
.p
, &index
)) )
496 if ( SUCCEEDED( pTypeLib
->GetDocumentation( -1, &sName
, NULL
, NULL
, NULL
) ) )
498 OUString
sLibName( reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(sName
)));
499 m_sTypeName
= sLibName
.concat( OUString(".") ).concat( sTmp
);
509 FuncDesc
aDescGet(pInfo
);
510 FuncDesc
aDescPut(pInfo
);
511 VarDesc
aVarDesc(pInfo
);
512 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
513 if ( ! aDescGet
&& ! aDescPut
&& ! aVarDesc
)
516 OUString
msg("[automation bridge]Property \"" + aPropertyName
+
517 "\" is not supported");
518 throw UnknownPropertyException(msg
);
520 // write-only should not be possible
521 OSL_ASSERT( aDescGet
|| ! aDescPut
);
524 DISPPARAMS dispparams
= {0, 0, 0, 0};
525 CComVariant varResult
;
527 unsigned int uArgErr
;
530 dispid
= aDescGet
->memid
;
532 dispid
= aVarDesc
->memid
;
534 dispid
= aDescPut
->memid
;
536 hr
= m_spDispatch
->Invoke(dispid
,
539 DISPATCH_PROPERTYGET
,
545 // converting return value and out parameter back to UNO
548 // If the com object implements uno interfaces then we have
549 // to convert the attribute into the expected type.
550 TypeDescription attrInfo
;
551 getAttributeInfo(aPropertyName
, attrInfo
);
553 variantToAny( &varResult
, ret
, Type( attrInfo
.get()->pWeakRef
));
555 variantToAny(&varResult
, ret
);
563 case DISP_E_BADPARAMCOUNT
:
564 case DISP_E_BADVARTYPE
:
565 case DISP_E_EXCEPTION
:
566 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)));
568 case DISP_E_MEMBERNOTFOUND
:
569 throw UnknownPropertyException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)));
572 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)));
576 catch ( const UnknownPropertyException
& )
580 catch (const BridgeRuntimeError
& e
)
582 throw RuntimeException(e
.message
);
584 catch (const Exception
& e
)
586 throw RuntimeException("[automation bridge] unexpected exception in "
587 "IUnknownWrapper_Impl::getValue ! Message : \n" +
592 throw RuntimeException(
593 "[automation bridge] unexpected exception in "
594 "IUnknownWrapper_Impl::getValue !");
599 sal_Bool SAL_CALL
IUnknownWrapper_Impl::hasMethod( const OUString
& aName
)
600 throw(RuntimeException
)
602 if ( ! m_spDispatch
)
604 throw RuntimeException(
605 "[automation bridge] The object does not have an IDispatch interface");
607 sal_Bool ret
= sal_False
;
611 o2u_attachCurrentThread();
612 ITypeInfo
* pInfo
= getTypeInfo();
613 FuncDesc
aDesc(pInfo
);
614 getFuncDesc(aName
, & aDesc
);
615 // Automation properties can have arguments. Those are treated as methods and
616 //are called through XInvocation::invoke.
619 FuncDesc
aDescGet(pInfo
);
620 FuncDesc
aDescPut(pInfo
);
621 VarDesc
aVarDesc(pInfo
);
622 getPropDesc( aName
, & aDescGet
, & aDescPut
, & aVarDesc
);
623 if (aDescGet
&& aDescGet
->cParams
> 0
624 || aDescPut
&& aDescPut
->cParams
> 0)
630 catch (const BridgeRuntimeError
& e
)
632 throw RuntimeException(e
.message
);
634 catch (const Exception
& e
)
636 throw RuntimeException("[automation bridge] unexpected exception in "
637 "IUnknownWrapper_Impl::hasMethod ! Message : \n" +
642 throw RuntimeException("[automation bridge] unexpected exception in "
643 "IUnknownWrapper_Impl::hasMethod !");
648 sal_Bool SAL_CALL
IUnknownWrapper_Impl::hasProperty( const OUString
& aName
)
649 throw(RuntimeException
)
651 if ( ! m_spDispatch
)
653 throw RuntimeException("[automation bridge] The object does not have an "
654 "IDispatch interface");
656 sal_Bool ret
= sal_False
;
659 o2u_attachCurrentThread();
661 ITypeInfo
* pInfo
= getTypeInfo();
662 FuncDesc
aDescGet(pInfo
);
663 FuncDesc
aDescPut(pInfo
);
664 VarDesc
aVarDesc(pInfo
);
665 getPropDesc(aName
, & aDescGet
, & aDescPut
, & aVarDesc
);
667 // we should probably just check the funckind
668 // basic has been modified to handle properties ( 'get' ) props at
669 // least with parameters
670 // additionally you can call invoke(Get|Set)Property on the bridge
671 // you can determine if a property has parameter is hasMethod
672 // returns true for the name
680 catch (const BridgeRuntimeError
& e
)
682 throw RuntimeException(e
.message
);
684 catch (const Exception
& e
)
686 throw RuntimeException("[automation bridge] unexpected exception in "
687 "IUnknownWrapper_Impl::hasProperty ! Message : \n" +
693 throw RuntimeException("[automation bridge] unexpected exception in "
694 "IUnknownWrapper_Impl::hasProperty !");
699 Any SAL_CALL
IUnknownWrapper_Impl::createBridge( const Any
& modelDepObject
,
700 const Sequence
< sal_Int8
>& /*aProcessId*/, sal_Int16 sourceModelType
,
701 sal_Int16 destModelType
)
702 throw( IllegalArgumentException
, RuntimeException
)
705 o2u_attachCurrentThread();
708 (sourceModelType
== UNO
) &&
709 (destModelType
== OLE
) &&
710 (modelDepObject
.getValueTypeClass() == TypeClass_INTERFACE
)
713 Reference
<XInterface
> xInt( *(XInterface
**) modelDepObject
.getValue());
714 Reference
<XInterface
> xSelf( (OWeakObject
*)this);
718 VARIANT
* pVariant
= (VARIANT
*) CoTaskMemAlloc(sizeof(VARIANT
));
720 VariantInit(pVariant
);
721 if (m_bOriginalDispatch
== sal_True
)
723 pVariant
->vt
= VT_DISPATCH
;
724 pVariant
->pdispVal
= m_spDispatch
;
725 pVariant
->pdispVal
->AddRef();
729 pVariant
->vt
= VT_UNKNOWN
;
730 pVariant
->punkVal
= m_spUnknown
;
731 pVariant
->punkVal
->AddRef();
734 ret
.setValue((void*)&pVariant
, cppu::UnoType
<sal_uInt32
>::get());
741 @exception IllegalArgumentException
742 @exception CannotConvertException
743 @exception InvocationTargetException
746 Any
IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString
& sFunctionName
,
747 const Sequence
< Any
>& Params
,
748 Sequence
< sal_Int16
>& OutParamIndex
,
749 Sequence
< Any
>& OutParam
)
754 sal_Int32 parameterCount
= Params
.getLength();
755 sal_Int32 outParameterCount
= 0;
756 typelib_InterfaceMethodTypeDescription
* pMethod
= NULL
;
757 TypeDescription methodDesc
;
758 getMethodInfo(sFunctionName
, methodDesc
);
760 // We need to know whether the IDispatch is from a JScript object.
761 // Then out and in/out parameters have to be treated differently than
762 // with common COM objects.
763 sal_Bool bJScriptObject
= isJScriptObject();
764 scoped_array
<CComVariant
> sarParams
;
765 scoped_array
<CComVariant
> sarParamsRef
;
766 CComVariant
*pVarParams
= NULL
;
767 CComVariant
*pVarParamsRef
= NULL
;
768 sal_Bool bConvRet
= sal_True
;
772 pMethod
= (typelib_InterfaceMethodTypeDescription
* )methodDesc
.get();
773 parameterCount
= pMethod
->nParams
;
774 // Create the Array for the array being passed in DISPPARAMS
775 // the array also contains the outparameter (but not the values)
776 if( pMethod
->nParams
> 0)
778 sarParams
.reset(new CComVariant
[ parameterCount
]);
779 pVarParams
= sarParams
.get();
782 // Create the Array for the out an in/out parameter. These values
783 // are referenced by the VT_BYREF VARIANTs in DISPPARAMS.
784 // We need to find out the number of out and in/out parameter.
785 for( sal_Int32 i
=0; i
< parameterCount
; i
++)
787 if( pMethod
->pParams
[i
].bOut
)
793 sarParamsRef
.reset(new CComVariant
[outParameterCount
]);
794 pVarParamsRef
= sarParamsRef
.get();
795 // build up the parameters for IDispatch::Invoke
796 sal_Int32 outParamIndex
=0;
800 for( i
= 0; i
< parameterCount
; i
++)
803 if( pMethod
->pParams
[i
].bIn
== sal_True
&& ! pMethod
->pParams
[i
].bOut
)
805 anyToVariant( &pVarParams
[parameterCount
- i
-1], Params
.getConstArray()[i
]);
807 // Out parameter + in/out parameter
808 else if( pMethod
->pParams
[i
].bOut
== sal_True
)
811 if(pMethod
->pParams
[i
].bIn
)
813 anyToVariant( & var
,Params
[i
]);
814 pVarParamsRef
[outParamIndex
] = var
;
817 switch( pMethod
->pParams
[i
].pTypeRef
->eTypeClass
)
819 case TypeClass_INTERFACE
:
820 case TypeClass_STRUCT
:
821 if( ! pMethod
->pParams
[i
].bIn
)
823 pVarParamsRef
[ outParamIndex
].vt
= VT_DISPATCH
;
824 pVarParamsRef
[ outParamIndex
].pdispVal
= 0;
826 pVarParams
[parameterCount
- i
-1].vt
= VT_DISPATCH
| VT_BYREF
;
827 pVarParams
[parameterCount
- i
-1].ppdispVal
= &pVarParamsRef
[outParamIndex
].pdispVal
;
831 case TypeClass_UNSIGNED_LONG
:
832 if( ! pMethod
->pParams
[i
].bIn
)
834 pVarParamsRef
[ outParamIndex
].vt
= VT_I4
;
835 pVarParamsRef
[ outParamIndex
].lVal
= 0;
837 pVarParams
[parameterCount
- i
-1].vt
= VT_I4
| VT_BYREF
;
838 pVarParams
[parameterCount
- i
-1].plVal
= &pVarParamsRef
[outParamIndex
].lVal
;
840 case TypeClass_SEQUENCE
:
841 if( ! pMethod
->pParams
[i
].bIn
)
843 pVarParamsRef
[ outParamIndex
].vt
= VT_ARRAY
| VT_VARIANT
;
844 pVarParamsRef
[ outParamIndex
].parray
= NULL
;
846 pVarParams
[parameterCount
- i
-1].vt
= VT_ARRAY
| VT_BYREF
| VT_VARIANT
;
847 pVarParams
[parameterCount
- i
-1].pparray
= &pVarParamsRef
[outParamIndex
].parray
;
850 if( ! pMethod
->pParams
[i
].bIn
)
852 pVarParamsRef
[ outParamIndex
].vt
= VT_EMPTY
;
853 pVarParamsRef
[ outParamIndex
].lVal
= 0;
855 pVarParams
[parameterCount
- i
-1].vt
= VT_VARIANT
| VT_BYREF
;
856 pVarParams
[parameterCount
- i
-1].pvarVal
= &pVarParamsRef
[outParamIndex
];
858 case TypeClass_BOOLEAN
:
859 if( ! pMethod
->pParams
[i
].bIn
)
861 pVarParamsRef
[ outParamIndex
].vt
= VT_BOOL
;
862 pVarParamsRef
[ outParamIndex
].boolVal
= 0;
864 pVarParams
[parameterCount
- i
-1].vt
= VT_BOOL
| VT_BYREF
;
865 pVarParams
[parameterCount
- i
-1].pboolVal
=
866 & pVarParamsRef
[outParamIndex
].boolVal
;
869 case TypeClass_STRING
:
870 if( ! pMethod
->pParams
[i
].bIn
)
872 pVarParamsRef
[ outParamIndex
].vt
= VT_BSTR
;
873 pVarParamsRef
[ outParamIndex
].bstrVal
= 0;
875 pVarParams
[parameterCount
- i
-1].vt
= VT_BSTR
| VT_BYREF
;
876 pVarParams
[parameterCount
- i
-1].pbstrVal
=
877 & pVarParamsRef
[outParamIndex
].bstrVal
;
880 case TypeClass_FLOAT
:
881 if( ! pMethod
->pParams
[i
].bIn
)
883 pVarParamsRef
[ outParamIndex
].vt
= VT_R4
;
884 pVarParamsRef
[ outParamIndex
].fltVal
= 0;
886 pVarParams
[parameterCount
- i
-1].vt
= VT_R4
| VT_BYREF
;
887 pVarParams
[parameterCount
- i
-1].pfltVal
=
888 & pVarParamsRef
[outParamIndex
].fltVal
;
890 case TypeClass_DOUBLE
:
891 if( ! pMethod
->pParams
[i
].bIn
)
893 pVarParamsRef
[ outParamIndex
].vt
= VT_R8
;
894 pVarParamsRef
[ outParamIndex
].dblVal
= 0;
896 pVarParams
[parameterCount
- i
-1].vt
= VT_R8
| VT_BYREF
;
897 pVarParams
[parameterCount
- i
-1].pdblVal
=
898 & pVarParamsRef
[outParamIndex
].dblVal
;
901 if( ! pMethod
->pParams
[i
].bIn
)
903 pVarParamsRef
[ outParamIndex
].vt
= VT_UI1
;
904 pVarParamsRef
[ outParamIndex
].bVal
= 0;
906 pVarParams
[parameterCount
- i
-1].vt
= VT_UI1
| VT_BYREF
;
907 pVarParams
[parameterCount
- i
-1].pbVal
=
908 & pVarParamsRef
[outParamIndex
].bVal
;
911 case TypeClass_SHORT
:
912 case TypeClass_UNSIGNED_SHORT
:
913 if( ! pMethod
->pParams
[i
].bIn
)
915 pVarParamsRef
[ outParamIndex
].vt
= VT_I2
;
916 pVarParamsRef
[ outParamIndex
].iVal
= 0;
918 pVarParams
[parameterCount
- i
-1].vt
= VT_I2
| VT_BYREF
;
919 pVarParams
[parameterCount
- i
-1].piVal
=
920 & pVarParamsRef
[outParamIndex
].iVal
;
924 if( ! pMethod
->pParams
[i
].bIn
)
926 pVarParamsRef
[ outParamIndex
].vt
= VT_EMPTY
;
927 pVarParamsRef
[ outParamIndex
].lVal
= 0;
929 pVarParams
[parameterCount
- i
-1].vt
= VT_VARIANT
| VT_BYREF
;
930 pVarParams
[parameterCount
- i
-1].pvarVal
=
931 & pVarParamsRef
[outParamIndex
];
937 catch (IllegalArgumentException
& e
)
939 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
942 catch (CannotConvertException
& e
)
948 else // it is an JScriptObject
953 for( ; i
< parameterCount
; i
++)
956 if( pMethod
->pParams
[i
].bIn
== sal_True
&& ! pMethod
->pParams
[i
].bOut
)
958 anyToVariant( &pVarParams
[parameterCount
- i
-1], Params
.getConstArray()[i
]);
960 // Out parameter + in/out parameter
961 else if( pMethod
->pParams
[i
].bOut
== sal_True
)
963 CComObject
<JScriptOutParam
>* pParamObject
;
964 if( SUCCEEDED( CComObject
<JScriptOutParam
>::CreateInstance( &pParamObject
)))
966 CComPtr
<IUnknown
> pUnk(pParamObject
->GetUnknown());
968 CComQIPtr
<IDispatch
, &__uuidof(IDispatch
)> pDisp( pUnk
);
970 CComQIPtr
<IDispatch
> pDisp( pUnk
);
973 pVarParams
[ parameterCount
- i
-1].vt
= VT_DISPATCH
;
974 pVarParams
[ parameterCount
- i
-1].pdispVal
= pDisp
;
975 pVarParams
[ parameterCount
- i
-1].pdispVal
->AddRef();
976 // if the param is in/out then put the parameter on index 0
977 if( pMethod
->pParams
[i
].bIn
== sal_True
) // in / out
979 CComVariant varParam
;
980 anyToVariant( &varParam
, Params
.getConstArray()[i
]);
981 CComDispatchDriver
dispDriver( pDisp
);
982 if(FAILED( dispDriver
.PutPropertyByName( L
"0", &varParam
)))
983 throw BridgeRuntimeError(
984 "[automation bridge]IUnknownWrapper_Impl::"
985 "invokeWithDispIdUnoTlb\n"
986 "Could not set property \"0\" for the in/out "
993 throw BridgeRuntimeError(
994 "[automation bridge]IUnknownWrapper_Impl::"
995 "invokeWithDispIdUnoTlb\n"
996 "Could not create out parameter at index: " +
997 OUString::number((sal_Int32
) i
));
1003 catch (IllegalArgumentException
& e
)
1005 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
1008 catch (CannotConvertException
& e
)
1010 e
.ArgumentIndex
= i
;
1015 // No type description Available, that is we have to deal with a COM component,
1016 // that does not implements UNO interfaces ( IDispatch based)
1019 //We should not run into this block, because invokeWithDispIdComTlb should
1020 //have been called instead.
1025 CComVariant varResult
;
1026 ExcepInfo excepinfo
;
1027 unsigned int uArgErr
;
1028 DISPPARAMS dispparams
= { pVarParams
, NULL
, parameterCount
, 0};
1030 FuncDesc
aDesc(getTypeInfo());
1031 getFuncDesc(sFunctionName
, & aDesc
);
1032 // invoking OLE method
1033 hr
= m_spDispatch
->Invoke(aDesc
->memid
,
1035 LOCALE_USER_DEFAULT
,
1042 // converting return value and out parameter back to UNO
1045 if( outParameterCount
&& pMethod
)
1047 OutParamIndex
.realloc( outParameterCount
);
1048 OutParam
.realloc( outParameterCount
);
1049 sal_Int32 outIndex
=0;
1053 for( ; i
< parameterCount
; i
++)
1055 if( pMethod
->pParams
[i
].bOut
)
1057 OutParamIndex
[outIndex
]= (sal_Int16
) i
;
1059 if( !bJScriptObject
)
1061 variantToAny( &pVarParamsRef
[outIndex
], outAny
,
1062 Type(pMethod
->pParams
[i
].pTypeRef
), sal_False
);
1063 OutParam
[outIndex
++]= outAny
;
1065 else //JScriptObject
1067 if( pVarParams
[i
].vt
== VT_DISPATCH
)
1069 CComDispatchDriver
pDisp( pVarParams
[i
].pdispVal
);
1073 if( SUCCEEDED( pDisp
.GetPropertyByName( L
"0", &varOut
)))
1075 variantToAny( &varOut
, outAny
,
1076 Type(pMethod
->pParams
[parameterCount
- 1 - i
].pTypeRef
), sal_False
);
1077 OutParam
[outParameterCount
- 1 - outIndex
++]= outAny
;
1080 bConvRet
= sal_False
;
1083 bConvRet
= sal_False
;
1086 bConvRet
= sal_False
;
1089 if( !bConvRet
) break;
1092 catch(IllegalArgumentException
& e
)
1094 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
1097 catch(CannotConvertException
& e
)
1099 e
.ArgumentIndex
= i
;
1103 // return value, no type information available
1109 variantToAny(&varResult
, ret
, Type( pMethod
->pReturnTypeRef
), sal_False
);
1111 variantToAny(&varResult
, ret
, sal_False
);
1113 catch (IllegalArgumentException
& e
)
1116 "[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1117 "Could not convert return value! \n Message: \n" + e
.Message
;
1120 catch (CannotConvertException
& e
)
1123 "[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1124 "Could not convert return value! \n Message: \n" + e
.Message
;
1130 if( !bConvRet
) // conversion of return or out parameter failed
1131 throw CannotConvertException("Call to COM object failed. Conversion of return or out value failed",
1132 Reference
<XInterface
>( static_cast<XWeak
*>(this), UNO_QUERY
), TypeClass_UNKNOWN
,
1133 FailReason::UNKNOWN
, 0);// lookup error code
1134 // conversion of return or out parameter failed
1139 case DISP_E_BADPARAMCOUNT
:
1140 throw IllegalArgumentException();
1142 case DISP_E_BADVARTYPE
:
1143 throw RuntimeException();
1145 case DISP_E_EXCEPTION
:
1146 throw InvocationTargetException();
1148 case DISP_E_MEMBERNOTFOUND
:
1149 throw IllegalArgumentException();
1151 case DISP_E_NONAMEDARGS
:
1152 throw IllegalArgumentException();
1154 case DISP_E_OVERFLOW
:
1155 throw CannotConvertException("call to OLE object failed", static_cast<XInterface
*>(
1156 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
1158 case DISP_E_PARAMNOTFOUND
:
1159 throw IllegalArgumentException("call to OLE object failed", static_cast<XInterface
*>(
1160 static_cast<XWeak
*>(this)), ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1162 case DISP_E_TYPEMISMATCH
:
1163 throw CannotConvertException("call to OLE object failed",static_cast<XInterface
*>(
1164 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::UNKNOWN
, uArgErr
);
1166 case DISP_E_UNKNOWNINTERFACE
:
1167 throw RuntimeException() ;
1169 case DISP_E_UNKNOWNLCID
:
1170 throw RuntimeException() ;
1172 case DISP_E_PARAMNOTOPTIONAL
:
1173 throw CannotConvertException("call to OLE object failed", static_cast<XInterface
*>(
1174 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
1177 throw RuntimeException();
1188 void SAL_CALL
IUnknownWrapper_Impl::initialize( const Sequence
< Any
>& aArguments
) throw(Exception
, RuntimeException
)
1190 // 1.parameter is IUnknown
1191 // 2.parameter is a boolean which indicates if the COM pointer was a IUnknown or IDispatch
1192 // 3.parameter is a Sequence<Type>
1193 o2u_attachCurrentThread();
1194 OSL_ASSERT(aArguments
.getLength() == 3);
1196 m_spUnknown
= *(IUnknown
**) aArguments
[0].getValue();
1198 m_spUnknown
->QueryInterface(IID_IDispatch
, reinterpret_cast<LPVOID
*>( & m_spDispatch
.p
));
1200 m_spUnknown
.QueryInterface( & m_spDispatch
.p
);
1203 aArguments
[1] >>= m_bOriginalDispatch
;
1204 aArguments
[2] >>= m_seqTypes
;
1206 ITypeInfo
* pType
= NULL
;
1209 // a COM object implementation that has no TypeInfo is still a legal COM object;
1210 // such objects can at least be transported through UNO using the bridge
1211 // so we should allow to create wrappers for them as well
1212 pType
= getTypeInfo();
1214 catch( const BridgeRuntimeError
& )
1216 catch( const Exception
& )
1223 // Get Default member
1224 CComBSTR defaultMemberName
;
1225 if ( SUCCEEDED( pType
->GetDocumentation(0, &defaultMemberName
, 0, 0, 0 ) ) )
1227 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(defaultMemberName
)));
1228 FuncDesc
aDescGet(pType
);
1229 FuncDesc
aDescPut(pType
);
1230 VarDesc
aVarDesc(pType
);
1231 // see if this is a property first ( more likely to be a property then a method )
1232 getPropDesc( usName
, & aDescGet
, & aDescPut
, & aVarDesc
);
1234 if ( !aDescGet
&& !aDescPut
)
1236 getFuncDesc( usName
, &aDescGet
);
1238 throw BridgeRuntimeError( "[automation bridge]IUnknownWrapper_Impl::initialize() Failed to get Function or Property desc. for " + usName
);
1240 // now for some funny heuristics to make basic understand what to do
1241 // a single aDescGet ( that doesn't take any params ) would be
1242 // a read only ( defaultmember ) property e.g. this object
1243 // should implement XDefaultProperty
1244 // a single aDescGet ( that *does* ) take params is basically a
1245 // default method e.g. implement XDefaultMethod
1247 // 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 )
1248 if ( aDescPut
|| ( aDescGet
&& aDescGet
->cParams
== 0 ) )
1249 m_bHasDfltProperty
= true;
1250 if ( aDescGet
->cParams
> 0 )
1251 m_bHasDfltMethod
= true;
1252 if ( m_bHasDfltProperty
|| m_bHasDfltMethod
)
1253 m_sDefaultMember
= usName
;
1256 catch ( const BridgeRuntimeError
& e
)
1258 throw RuntimeException( e
.message
);
1260 catch( const Exception
& e
)
1262 throw RuntimeException(
1263 "[automation bridge] unexpected exception in IUnknownWrapper_Impl::initialiase() error message: \n" + e
.Message
);
1269 // XDirectInvocation
1270 uno::Any SAL_CALL
IUnknownWrapper_Impl::directInvoke( const OUString
& aName
, const uno::Sequence
< uno::Any
>& aParams
)
1271 throw (lang::IllegalArgumentException
, script::CannotConvertException
, reflection::InvocationTargetException
, uno::RuntimeException
)
1275 if ( !m_spDispatch
)
1277 throw RuntimeException(
1278 "[automation bridge] The object does not have an IDispatch interface");
1281 o2u_attachCurrentThread();
1283 if ( !getDispid( aName
, &dispid
) )
1284 throw IllegalArgumentException(
1285 "[automation bridge] The object does not have a function or property "
1286 + aName
, Reference
<XInterface
>(), 0);
1288 CComVariant varResult
;
1289 ExcepInfo excepinfo
;
1290 unsigned int uArgErr
= 0;
1291 INVOKEKIND pInvkinds
[2];
1292 pInvkinds
[0] = INVOKE_FUNC
;
1293 pInvkinds
[1] = aParams
.getLength() ? INVOKE_PROPERTYPUT
: INVOKE_PROPERTYGET
;
1294 HRESULT hInvRes
= E_FAIL
;
1296 // try Invoke first, if it does not work, try put/get property
1297 for ( sal_Int32 nStep
= 0; FAILED( hInvRes
) && nStep
< 2; nStep
++ )
1299 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
1301 scoped_array
<DISPID
> arDispidNamedArgs
;
1302 scoped_array
<CComVariant
> ptrArgs
;
1303 scoped_array
<CComVariant
> ptrRefArgs
; // referenced arguments
1304 CComVariant
* arArgs
= NULL
;
1305 CComVariant
* arRefArgs
= NULL
;
1307 dispparams
.cArgs
= aParams
.getLength();
1309 // Determine the number of named arguments
1310 for ( sal_Int32 nInd
= 0; nInd
< aParams
.getLength(); nInd
++ )
1311 if ( aParams
[nInd
].getValueType() == cppu::UnoType
<NamedArgument
>::get() )
1312 dispparams
.cNamedArgs
++;
1314 // fill the named arguments
1315 if ( dispparams
.cNamedArgs
> 0
1316 && !( dispparams
.cNamedArgs
== 1 && pInvkinds
[nStep
] == INVOKE_PROPERTYPUT
) )
1318 int nSizeAr
= dispparams
.cNamedArgs
+ 1;
1319 if ( pInvkinds
[nStep
] == INVOKE_PROPERTYPUT
)
1320 nSizeAr
= dispparams
.cNamedArgs
;
1322 scoped_array
<OLECHAR
*> saNames(new OLECHAR
*[nSizeAr
]);
1323 OLECHAR
** pNames
= saNames
.get();
1324 pNames
[0] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(aName
.getStr()));
1327 for ( size_t nInd
= 0; nInd
< dispparams
.cArgs
; nInd
++ )
1329 if ( aParams
[nInd
].getValueType() == cppu::UnoType
<NamedArgument
>::get())
1331 const NamedArgument
& arg
= *(NamedArgument
const*)aParams
[nInd
].getValue();
1333 //We put the parameter names in reverse order into the array,
1334 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1335 //The first name in the array is the method name
1336 pNames
[nSizeAr
- 1 - cNamedArg
++] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(arg
.Name
.getStr()));
1340 arDispidNamedArgs
.reset( new DISPID
[nSizeAr
] );
1341 HRESULT hr
= getTypeInfo()->GetIDsOfNames( pNames
, nSizeAr
, arDispidNamedArgs
.get() );
1342 if ( hr
== E_NOTIMPL
)
1343 hr
= m_spDispatch
->GetIDsOfNames(IID_NULL
, pNames
, nSizeAr
, LOCALE_USER_DEFAULT
, arDispidNamedArgs
.get() );
1345 if ( SUCCEEDED( hr
) )
1347 if ( pInvkinds
[nStep
] == DISPATCH_PROPERTYPUT
)
1349 DISPID
* arIDs
= arDispidNamedArgs
.get();
1350 arIDs
[0] = DISPID_PROPERTYPUT
;
1351 dispparams
.rgdispidNamedArgs
= arIDs
;
1355 DISPID
* arIDs
= arDispidNamedArgs
.get();
1356 dispparams
.rgdispidNamedArgs
= & arIDs
[1];
1359 else if (hr
== DISP_E_UNKNOWNNAME
)
1361 throw IllegalArgumentException(
1362 "[automation bridge]One of the named arguments is wrong!",
1363 Reference
<XInterface
>(), 0);
1367 throw InvocationTargetException(
1368 "[automation bridge] ITypeInfo::GetIDsOfNames returned error "
1369 + OUString::number((sal_Int32
) hr
, 16), Reference
<XInterface
>(), Any());
1374 ptrArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1375 ptrRefArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1376 arArgs
= ptrArgs
.get();
1377 arRefArgs
= ptrRefArgs
.get();
1382 sal_Int32 revIndex
= 0;
1383 for ( nInd
= 0; nInd
< sal_Int32(dispparams
.cArgs
); nInd
++)
1385 revIndex
= dispparams
.cArgs
- nInd
- 1;
1386 arRefArgs
[revIndex
].byref
= 0;
1388 if ( nInd
< aParams
.getLength() )
1389 anyArg
= aParams
.getConstArray()[nInd
];
1391 // Property Put arguments
1392 if ( anyArg
.getValueType() == cppu::UnoType
<PropertyPutArgument
>::get() )
1394 PropertyPutArgument arg
;
1396 anyArg
<<= arg
.Value
;
1399 if (anyArg
.getValueType() == cppu::UnoType
<NamedArgument
>::get())
1401 NamedArgument aNamedArgument
;
1402 anyArg
>>= aNamedArgument
;
1403 anyArg
<<= aNamedArgument
.Value
;
1406 if ( nInd
< aParams
.getLength() && anyArg
.getValueTypeClass() != TypeClass_VOID
)
1408 anyToVariant( &arArgs
[revIndex
], anyArg
, VT_VARIANT
);
1412 arArgs
[revIndex
].vt
= VT_ERROR
;
1413 arArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1417 catch (IllegalArgumentException
& e
)
1419 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, sal_Int32
>( nInd
);
1422 catch (CannotConvertException
& e
)
1424 e
.ArgumentIndex
= nInd
;
1428 dispparams
.rgvarg
= arArgs
;
1429 // invoking OLE method
1430 DWORD localeId
= LOCALE_USER_DEFAULT
;
1431 hInvRes
= m_spDispatch
->Invoke( dispid
,
1434 ::sal::static_int_cast
< WORD
, INVOKEKIND
>( pInvkinds
[nStep
] ),
1441 // converting return value and out parameter back to UNO
1442 if ( SUCCEEDED( hInvRes
) )
1443 variantToAny( &varResult
, aResult
, sal_False
);
1446 // map error codes to exceptions
1452 case DISP_E_BADPARAMCOUNT
:
1453 throw IllegalArgumentException("[automation bridge] Wrong "
1454 "number of arguments. Object returned DISP_E_BADPARAMCOUNT.",
1457 case DISP_E_BADVARTYPE
:
1458 throw RuntimeException("[automation bridge] One or more "
1459 "arguments have the wrong type. Object returned "
1460 "DISP_E_BADVARTYPE.", 0);
1462 case DISP_E_EXCEPTION
:
1463 message
= "[automation bridge]: ";
1464 message
+= OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
),
1465 ::SysStringLen(excepinfo
.bstrDescription
));
1466 throw InvocationTargetException(message
, Reference
<XInterface
>(), Any());
1468 case DISP_E_MEMBERNOTFOUND
:
1469 message
= "[automation bridge]: A function with the name \""
1470 + aName
+ "\" is not supported. Object returned "
1471 "DISP_E_MEMBERNOTFOUND.";
1472 throw IllegalArgumentException(message
, 0, 0);
1474 case DISP_E_NONAMEDARGS
:
1475 throw IllegalArgumentException("[automation bridge] Object "
1476 "returned DISP_E_NONAMEDARGS",0, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1478 case DISP_E_OVERFLOW
:
1479 throw CannotConvertException("[automation bridge] Call failed.",
1480 static_cast<XInterface
*>(
1481 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
1483 case DISP_E_PARAMNOTFOUND
:
1484 throw IllegalArgumentException("[automation bridge]Call failed."
1485 "Object returned DISP_E_PARAMNOTFOUND.",
1486 0, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1488 case DISP_E_TYPEMISMATCH
:
1489 throw CannotConvertException("[automation bridge] Call failed. "
1490 "Object returned DISP_E_TYPEMISMATCH",
1491 static_cast<XInterface
*>(
1492 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::UNKNOWN
, uArgErr
);
1494 case DISP_E_UNKNOWNINTERFACE
:
1495 throw RuntimeException("[automation bridge] Call failed. "
1496 "Object returned DISP_E_UNKNOWNINTERFACE.",0);
1498 case DISP_E_UNKNOWNLCID
:
1499 throw RuntimeException("[automation bridge] Call failed. "
1500 "Object returned DISP_E_UNKNOWNLCID.",0);
1502 case DISP_E_PARAMNOTOPTIONAL
:
1503 throw CannotConvertException("[automation bridge] Call failed."
1504 "Object returned DISP_E_PARAMNOTOPTIONAL",
1505 static_cast<XInterface
*>(static_cast<XWeak
*>(this)),
1506 TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
1509 throw RuntimeException();
1517 sal_Bool SAL_CALL
IUnknownWrapper_Impl::hasMember( const OUString
& aName
)
1518 throw (uno::RuntimeException
)
1520 if ( ! m_spDispatch
)
1522 throw RuntimeException(
1523 "[automation bridge] The object does not have an IDispatch interface");
1526 o2u_attachCurrentThread();
1528 return getDispid( aName
, &dispid
);
1532 // UnoConversionUtilities --------------------------------------------------------------------------------
1533 Reference
< XInterface
> IUnknownWrapper_Impl::createUnoWrapperInstance()
1535 if( m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
)
1537 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper_Impl(
1538 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1539 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1541 else if( m_nUnoWrapperClass
== UNO_OBJECT_WRAPPER_REMOTE_OPT
)
1543 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
1544 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1545 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1548 return Reference
<XInterface
>();
1550 Reference
<XInterface
> IUnknownWrapper_Impl::createComWrapperInstance()
1552 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper_Impl(
1553 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1554 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1559 void IUnknownWrapper_Impl::getMethodInfo(const OUString
& sName
, TypeDescription
& methodInfo
)
1561 TypeDescription desc
= getInterfaceMemberDescOfCurrentCall(sName
);
1564 typelib_TypeDescription
* pMember
= desc
.get();
1565 if( pMember
->eTypeClass
== TypeClass_INTERFACE_METHOD
)
1566 methodInfo
= pMember
;
1570 void IUnknownWrapper_Impl::getAttributeInfo(const OUString
& sName
, TypeDescription
& attributeInfo
)
1572 TypeDescription desc
= getInterfaceMemberDescOfCurrentCall(sName
);
1575 typelib_TypeDescription
* pMember
= desc
.get();
1576 if( pMember
->eTypeClass
== TypeClass_INTERFACE_ATTRIBUTE
)
1578 attributeInfo
= ((typelib_InterfaceAttributeTypeDescription
*)pMember
)->pAttributeTypeRef
;
1582 TypeDescription
IUnknownWrapper_Impl::getInterfaceMemberDescOfCurrentCall(const OUString
& sName
)
1584 TypeDescription ret
;
1586 for( sal_Int32 i
=0; i
< m_seqTypes
.getLength(); i
++)
1588 TypeDescription
_curDesc( m_seqTypes
[i
]);
1589 _curDesc
.makeComplete();
1590 typelib_InterfaceTypeDescription
* pInterface
= (typelib_InterfaceTypeDescription
*) _curDesc
.get();
1593 typelib_InterfaceMemberTypeDescription
* pMember
= NULL
;
1594 //find the member description of the current call
1595 for( int i
=0; i
< pInterface
->nAllMembers
; i
++)
1597 typelib_TypeDescriptionReference
* pTypeRefMember
= pInterface
->ppAllMembers
[i
];
1598 typelib_TypeDescription
* pDescMember
= NULL
;
1599 TYPELIB_DANGER_GET( &pDescMember
, pTypeRefMember
);
1601 typelib_InterfaceMemberTypeDescription
* pInterfaceMember
=
1602 (typelib_InterfaceMemberTypeDescription
*) pDescMember
;
1603 if( OUString( pInterfaceMember
->pMemberName
) == sName
)
1605 pMember
= pInterfaceMember
;
1608 TYPELIB_DANGER_RELEASE( pDescMember
);
1613 ret
= (typelib_TypeDescription
*)pMember
;
1614 TYPELIB_DANGER_RELEASE( (typelib_TypeDescription
*)pMember
);
1623 sal_Bool
IUnknownWrapper_Impl::isJScriptObject()
1625 if( m_eJScript
== JScriptUndefined
)
1627 CComDispatchDriver
disp( m_spDispatch
);
1631 if( SUCCEEDED( disp
.GetPropertyByName( JSCRIPT_ID_PROPERTY
, &result
)))
1633 if(result
.vt
== VT_BSTR
)
1635 CComBSTR
name( result
.bstrVal
);
1637 if( name
== CComBSTR(JSCRIPT_ID
))
1638 m_eJScript
= IsJScript
;
1642 if( m_eJScript
== JScriptUndefined
)
1643 m_eJScript
= NoJScript
;
1646 return m_eJScript
== NoJScript
? sal_False
: sal_True
;
1652 The function ultimately calls IDispatch::Invoke on the wrapped COM object.
1653 The COM object does not implement UNO Interfaces ( via IDispatch). This
1654 is the case when the OleObjectFactory service has been used to create a
1656 @exception IllegalArgumentException
1657 @exception CannotConvertException
1658 @InvocationTargetException
1662 Any
IUnknownWrapper_Impl::invokeWithDispIdComTlb(const OUString
& sFuncName
,
1663 const Sequence
< Any
>& Params
,
1664 Sequence
< sal_Int16
>& OutParamIndex
,
1665 Sequence
< Any
>& OutParam
)
1667 // Get type info for the call. It can be a method call or property put or
1668 // property get operation.
1669 FuncDesc
aFuncDesc(getTypeInfo());
1670 getFuncDescForInvoke(sFuncName
, Params
, & aFuncDesc
);
1671 return invokeWithDispIdComTlb( aFuncDesc
, sFuncName
, Params
, OutParamIndex
, OutParam
);
1674 Any
IUnknownWrapper_Impl::invokeWithDispIdComTlb(FuncDesc
& aFuncDesc
,
1675 const OUString
& sFuncName
,
1676 const Sequence
< Any
>& Params
,
1677 Sequence
< sal_Int16
>& OutParamIndex
,
1678 Sequence
< Any
>& OutParam
)
1683 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
1684 CComVariant varResult
;
1685 ExcepInfo excepinfo
;
1686 unsigned int uArgErr
;
1688 sal_Int32 nUnoArgs
= Params
.getLength();
1689 DISPID idPropertyPut
= DISPID_PROPERTYPUT
;
1690 scoped_array
<DISPID
> arDispidNamedArgs
;
1691 scoped_array
<CComVariant
> ptrArgs
;
1692 scoped_array
<CComVariant
> ptrRefArgs
; // referenced arguments
1693 CComVariant
* arArgs
= NULL
;
1694 CComVariant
* arRefArgs
= NULL
;
1695 sal_Int32 revIndex
= 0;
1697 //Set the array of DISPIDs for named args if it is a property put operation.
1698 //If there are other named arguments another array is set later on.
1699 if (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
1700 || aFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
1701 dispparams
.rgdispidNamedArgs
= & idPropertyPut
;
1703 //Determine the number of named arguments
1704 for (int iParam
= 0; iParam
< nUnoArgs
; iParam
++)
1706 const Any
& curArg
= Params
[iParam
];
1707 if (curArg
.getValueType() == cppu::UnoType
<NamedArgument
>::get())
1708 dispparams
.cNamedArgs
++;
1710 //In a property put operation a property value is a named argument (DISPID_PROPERTYPUT).
1711 //Therefore the number of named arguments is increased by one.
1712 //Although named, the argument is not named in an actual language, such as Basic,
1713 //therefore it is never a com.sun.star.bridge.oleautomation.NamedArgument
1714 if (aFuncDesc
->invkind
== DISPATCH_PROPERTYPUT
1715 || aFuncDesc
->invkind
== DISPATCH_PROPERTYPUTREF
)
1716 dispparams
.cNamedArgs
++;
1718 //Determine the number of all arguments and named arguments
1719 if (aFuncDesc
->cParamsOpt
== -1)
1721 //Attribute vararg is set on this method. "Unlimited" number of args
1722 //supported. There can be no optional or defaultvalue on any of the arguments.
1723 dispparams
.cArgs
= nUnoArgs
;
1727 //If there are namesd arguments, then the dispparams.cArgs
1728 //is the number of supplied args, otherwise it is the expected number.
1729 if (dispparams
.cNamedArgs
)
1730 dispparams
.cArgs
= nUnoArgs
;
1732 dispparams
.cArgs
= aFuncDesc
->cParams
;
1735 //check if there are not to many arguments supplied
1736 if (::sal::static_int_cast
< sal_uInt32
, int >( nUnoArgs
) > dispparams
.cArgs
)
1738 OUStringBuffer
buf(256);
1739 buf
.appendAscii("[automation bridge] There are too many arguments for this method");
1740 throw IllegalArgumentException( buf
.makeStringAndClear(),
1741 Reference
<XInterface
>(), (sal_Int16
) dispparams
.cArgs
);
1744 //Set up the array of DISPIDs (DISPPARAMS::rgdispidNamedArgs)
1745 //for the named arguments.
1746 //If there is only one named arg and if it is because of a property put
1747 //operation, then we need not set up the DISPID array.
1748 if (dispparams
.cNamedArgs
> 0 &&
1749 ! (dispparams
.cNamedArgs
== 1 &&
1750 (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
||
1751 aFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)))
1753 //set up an array containing the member and parameter names
1754 //which is then used in ITypeInfo::GetIDsOfNames
1755 //First determine the size of the array of names which is passed to
1756 //ITypeInfo::GetIDsOfNames. It must hold the method names + the named
1758 int nSizeAr
= dispparams
.cNamedArgs
+ 1;
1759 if (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
1760 || aFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
1762 nSizeAr
= dispparams
.cNamedArgs
; //counts the DISID_PROPERTYPUT
1765 scoped_array
<OLECHAR
*> saNames(new OLECHAR
*[nSizeAr
]);
1766 OLECHAR
** arNames
= saNames
.get();
1767 arNames
[0] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(sFuncName
.getStr()));
1770 for (size_t iParams
= 0; iParams
< dispparams
.cArgs
; iParams
++)
1772 const Any
& curArg
= Params
[iParams
];
1773 if (curArg
.getValueType() == cppu::UnoType
<NamedArgument
>::get())
1775 const NamedArgument
& arg
= *(NamedArgument
const*) curArg
.getValue();
1776 //We put the parameter names in reverse order into the array,
1777 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1778 //The first name in the array is the method name
1779 arNames
[nSizeAr
- 1 - cNamedArg
++] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(arg
.Name
.getStr()));
1783 //Prepare the array of DISPIDs for ITypeInfo::GetIDsOfNames
1784 //it must be big enough to contain the DISPIDs of the member + parameters
1785 arDispidNamedArgs
.reset(new DISPID
[nSizeAr
]);
1786 HRESULT hr
= getTypeInfo()->GetIDsOfNames(arNames
, nSizeAr
,
1787 arDispidNamedArgs
.get());
1788 if ( hr
== E_NOTIMPL
)
1789 hr
= m_spDispatch
->GetIDsOfNames(IID_NULL
, arNames
, nSizeAr
, LOCALE_USER_DEFAULT
, arDispidNamedArgs
.get() );
1793 // In a "property put" operation, the property value is a named param with the
1794 //special DISPID DISPID_PROPERTYPUT
1795 if (aFuncDesc
->invkind
== DISPATCH_PROPERTYPUT
1796 || aFuncDesc
->invkind
== DISPATCH_PROPERTYPUTREF
)
1798 //Element at index 0 in the DISPID array must be DISPID_PROPERTYPUT
1799 //The first item in the array arDispidNamedArgs is the DISPID for
1800 //the method. We replace it with DISPID_PROPERTYPUT.
1801 DISPID
* arIDs
= arDispidNamedArgs
.get();
1802 arIDs
[0] = DISPID_PROPERTYPUT
;
1803 dispparams
.rgdispidNamedArgs
= arIDs
;
1807 //The first item in the array arDispidNamedArgs is the DISPID for
1808 //the method. It must be removed
1809 DISPID
* arIDs
= arDispidNamedArgs
.get();
1810 dispparams
.rgdispidNamedArgs
= & arIDs
[1];
1813 else if (hr
== DISP_E_UNKNOWNNAME
)
1815 throw IllegalArgumentException(
1816 "[automation bridge]One of the named arguments is wrong!",
1817 Reference
<XInterface
>(), 0);
1821 throw InvocationTargetException(
1822 "[automation bridge] ITypeInfo::GetIDsOfNames returned error "
1823 + OUString::number((sal_Int32
) hr
, 16), Reference
<XInterface
>(), Any());
1828 ptrArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1829 ptrRefArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1830 arArgs
= ptrArgs
.get();
1831 arRefArgs
= ptrRefArgs
.get();
1834 for (i
= 0; i
< (sal_Int32
) dispparams
.cArgs
; i
++)
1836 revIndex
= dispparams
.cArgs
- i
-1;
1837 arRefArgs
[revIndex
].byref
=0;
1840 anyArg
= Params
.getConstArray()[i
];
1842 unsigned short paramFlags
= PARAMFLAG_FOPT
| PARAMFLAG_FIN
;
1843 VARTYPE varType
= VT_VARIANT
;
1844 if (aFuncDesc
->cParamsOpt
!= -1 || aFuncDesc
->cParams
!= (i
+ 1))
1846 paramFlags
= aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
1847 varType
= getElementTypeDesc(&aFuncDesc
->lprgelemdescParam
[i
].tdesc
);
1850 // Make sure that there is a UNO parameter for every
1851 // expected parameter. If there is no UNO parameter where the
1852 // called function expects one, then it must be optional. Otherwise
1853 // it's a UNO programming error.
1854 if (i
>= nUnoArgs
&& !(paramFlags
& PARAMFLAG_FOPT
))
1856 OUStringBuffer
buf(256);
1857 buf
.appendAscii("ole automation bridge: The called function expects an argument at"
1858 "position: "); //a different number of arguments")),
1859 buf
.append(OUString::number((sal_Int32
) i
));
1860 buf
.appendAscii(" (index starting at 0).");
1861 throw IllegalArgumentException( buf
.makeStringAndClear(),
1862 Reference
<XInterface
>(), (sal_Int16
) i
);
1865 // Property Put arguments
1866 if (anyArg
.getValueType() == cppu::UnoType
<PropertyPutArgument
>::get())
1868 PropertyPutArgument arg
;
1870 anyArg
<<= arg
.Value
;
1873 if (anyArg
.getValueType() == cppu::UnoType
<NamedArgument
>::get())
1875 NamedArgument aNamedArgument
;
1876 anyArg
>>= aNamedArgument
;
1877 anyArg
<<= aNamedArgument
.Value
;
1880 if (paramFlags
& PARAMFLAG_FOUT
&&
1881 ! (paramFlags
& PARAMFLAG_FIN
) )
1883 VARTYPE type
= ::sal::static_int_cast
< VARTYPE
, int >( varType
^ VT_BYREF
);
1886 arRefArgs
[revIndex
].vt
= type
;
1891 arRefArgs
[revIndex
].vt
= VT_ERROR
;
1892 arRefArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1894 if( type
== VT_VARIANT
)
1896 arArgs
[revIndex
].vt
= VT_VARIANT
| VT_BYREF
;
1897 arArgs
[revIndex
].byref
= &arRefArgs
[revIndex
];
1901 arArgs
[revIndex
].vt
= varType
;
1902 if (type
== VT_DECIMAL
)
1903 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].decVal
;
1905 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].byref
;
1908 // in/out + in byref params
1909 else if (varType
& VT_BYREF
)
1911 VARTYPE type
= ::sal::static_int_cast
< VARTYPE
, int >( varType
^ VT_BYREF
);
1914 if (i
< nUnoArgs
&& anyArg
.getValueTypeClass() != TypeClass_VOID
)
1916 anyToVariant( & arRefArgs
[revIndex
], anyArg
, type
);
1918 else if (paramFlags
& PARAMFLAG_FHASDEFAULT
)
1920 //optional arg with default
1921 VariantCopy( & arRefArgs
[revIndex
],
1922 & aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.
1923 pparamdescex
->varDefaultValue
);
1928 //e.g: call func(x) in basic : func() ' no arg supplied
1929 OSL_ASSERT(paramFlags
& PARAMFLAG_FOPT
);
1930 arRefArgs
[revIndex
].vt
= VT_ERROR
;
1931 arRefArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1934 // Set the converted arguments in the array which will be
1935 // DISPPARAMS::rgvarg
1936 // byref arg VT_XXX |VT_BYREF
1937 arArgs
[revIndex
].vt
= varType
;
1938 if (revIndex
== 0 && aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
)
1940 arArgs
[revIndex
] = arRefArgs
[revIndex
];
1942 else if (type
== VT_DECIMAL
)
1944 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].decVal
;
1946 else if (type
== VT_VARIANT
)
1948 if ( ! (paramFlags
& PARAMFLAG_FOUT
))
1949 arArgs
[revIndex
] = arRefArgs
[revIndex
];
1951 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
];
1955 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].byref
;
1956 arArgs
[revIndex
].vt
= ::sal::static_int_cast
< VARTYPE
, int >( arRefArgs
[revIndex
].vt
| VT_BYREF
);
1960 // in parameter no VT_BYREF except for array, interfaces
1962 { // void any stands for optional param
1963 if (i
< nUnoArgs
&& anyArg
.getValueTypeClass() != TypeClass_VOID
)
1965 anyToVariant( & arArgs
[revIndex
], anyArg
, varType
);
1967 //optional arg but no void any supplied
1968 //Basic: obj.func() ' first parameter left out because it is optional
1969 else if (paramFlags
& PARAMFLAG_FHASDEFAULT
)
1971 //optional arg with defaulteithter as direct arg : VT_XXX or
1972 VariantCopy( & arArgs
[revIndex
],
1973 & aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.
1974 pparamdescex
->varDefaultValue
);
1976 else if (paramFlags
& PARAMFLAG_FOPT
)
1978 arArgs
[revIndex
].vt
= VT_ERROR
;
1979 arArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1983 arArgs
[revIndex
].vt
= VT_EMPTY
;
1984 arArgs
[revIndex
].lVal
= 0;
1989 catch (IllegalArgumentException
& e
)
1991 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, sal_Int32
>( i
);
1994 catch (CannotConvertException
& e
)
1996 e
.ArgumentIndex
= i
;
1999 dispparams
.rgvarg
= arArgs
;
2000 // invoking OLE method
2001 DWORD localeId
= LOCALE_USER_DEFAULT
;
2002 result
= m_spDispatch
->Invoke(aFuncDesc
->memid
,
2005 ::sal::static_int_cast
< WORD
, INVOKEKIND
>( aFuncDesc
->invkind
),
2011 // converting return value and out parameter back to UNO
2015 // allocate space for the out param Sequence and indices Sequence
2016 int outParamsCount
= 0; // includes in/out parameter
2017 for (int i
= 0; i
< aFuncDesc
->cParams
; i
++)
2019 if (aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
&
2024 OutParamIndex
.realloc(outParamsCount
);
2025 OutParam
.realloc(outParamsCount
);
2026 // Convert out params
2029 int outParamIndex
=0;
2030 for (int paramIndex
= 0; paramIndex
< nUnoArgs
; paramIndex
++)
2032 //Determine the index within the method sinature
2033 int realParamIndex
= paramIndex
;
2034 int revParamIndex
= dispparams
.cArgs
- paramIndex
- 1;
2035 if (Params
[paramIndex
].getValueType()
2036 == cppu::UnoType
<NamedArgument
>::get())
2038 //dispparams.rgdispidNamedArgs contains the mapping from index
2039 //of named args list to index of parameter list
2040 realParamIndex
= dispparams
.rgdispidNamedArgs
[revParamIndex
];
2043 // no named arg, always come before named args
2044 if (! (aFuncDesc
->lprgelemdescParam
[realParamIndex
].paramdesc
.wParamFlags
2048 // variantToAny is called with the "reduce range" parameter set to sal_False.
2049 // That causes VT_I4 values not to be converted down to a "lower" type. That
2050 // feature exist for JScript only because it only uses VT_I4 for integer types.
2053 variantToAny( & arRefArgs
[revParamIndex
], outAny
, sal_False
);
2055 catch (IllegalArgumentException
& e
)
2057 e
.ArgumentPosition
= (sal_Int16
)paramIndex
;
2060 catch (CannotConvertException
& e
)
2062 e
.ArgumentIndex
= paramIndex
;
2065 OutParam
[outParamIndex
] = outAny
;
2066 OutParamIndex
[outParamIndex
] = ::sal::static_int_cast
< sal_Int16
, int >( paramIndex
);
2069 OutParam
.realloc(outParamIndex
);
2070 OutParamIndex
.realloc(outParamIndex
);
2073 variantToAny(&varResult
, ret
, sal_False
);
2076 // map error codes to exceptions
2082 case DISP_E_BADPARAMCOUNT
:
2083 throw IllegalArgumentException("[automation bridge] Wrong "
2084 "number of arguments. Object returned DISP_E_BADPARAMCOUNT.",
2087 case DISP_E_BADVARTYPE
:
2088 throw RuntimeException("[automation bridge] One or more "
2089 "arguments have the wrong type. Object returned "
2090 "DISP_E_BADVARTYPE.", 0);
2092 case DISP_E_EXCEPTION
:
2093 message
= "[automation bridge]: ";
2094 message
+= OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
),
2095 ::SysStringLen(excepinfo
.bstrDescription
));
2097 throw InvocationTargetException(message
, Reference
<XInterface
>(), Any());
2099 case DISP_E_MEMBERNOTFOUND
:
2100 message
= "[automation bridge]: A function with the name \""
2101 + sFuncName
+ "\" is not supported. Object returned "
2102 "DISP_E_MEMBERNOTFOUND.";
2103 throw IllegalArgumentException(message
, 0, 0);
2105 case DISP_E_NONAMEDARGS
:
2106 throw IllegalArgumentException("[automation bridge] Object "
2107 "returned DISP_E_NONAMEDARGS",0, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
2109 case DISP_E_OVERFLOW
:
2110 throw CannotConvertException("[automation bridge] Call failed.",
2111 static_cast<XInterface
*>(
2112 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
2114 case DISP_E_PARAMNOTFOUND
:
2115 throw IllegalArgumentException("[automation bridge]Call failed."
2116 "Object returned DISP_E_PARAMNOTFOUND.",
2117 0, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
2119 case DISP_E_TYPEMISMATCH
:
2120 throw CannotConvertException("[automation bridge] Call failed. "
2121 "Object returned DISP_E_TYPEMISMATCH",
2122 static_cast<XInterface
*>(
2123 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::UNKNOWN
, uArgErr
);
2125 case DISP_E_UNKNOWNINTERFACE
:
2126 throw RuntimeException("[automation bridge] Call failed. "
2127 "Object returned DISP_E_UNKNOWNINTERFACE.",0);
2129 case DISP_E_UNKNOWNLCID
:
2130 throw RuntimeException("[automation bridge] Call failed. "
2131 "Object returned DISP_E_UNKNOWNLCID.",0);
2133 case DISP_E_PARAMNOTOPTIONAL
:
2134 throw CannotConvertException("[automation bridge] Call failed."
2135 "Object returned DISP_E_PARAMNOTOPTIONAL",
2136 static_cast<XInterface
*>(static_cast<XWeak
*>(this)),
2137 TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
2140 throw RuntimeException();
2147 void IUnknownWrapper_Impl::getFuncDescForInvoke(const OUString
& sFuncName
,
2148 const Sequence
<Any
> & seqArgs
,
2149 FUNCDESC
** pFuncDesc
)
2151 int nUnoArgs
= seqArgs
.getLength();
2152 const Any
* arArgs
= seqArgs
.getConstArray();
2153 ITypeInfo
* pInfo
= getTypeInfo();
2155 //If the last of the positional arguments is a PropertyPutArgument
2156 //then obtain the type info for the property put operation.
2158 //The property value is always the last argument, in a positional argument list
2159 //or in a list of named arguments. A PropertyPutArgument is actually a named argument
2160 //hence it must not be put in an extra NamedArgument structure
2162 arArgs
[nUnoArgs
- 1].getValueType() == cppu::UnoType
<PropertyPutArgument
>::get())
2164 // DISPATCH_PROPERTYPUT
2165 FuncDesc
aDescGet(pInfo
);
2166 FuncDesc
aDescPut(pInfo
);
2167 VarDesc
aVarDesc(pInfo
);
2168 getPropDesc(sFuncName
, & aDescGet
, & aDescPut
, & aVarDesc
);
2171 throw IllegalArgumentException(
2172 "[automation bridge] The object does not have a writeable property: "
2173 + sFuncName
, Reference
<XInterface
>(), 0);
2175 *pFuncDesc
= aDescPut
.Detach();
2178 { // DISPATCH_METHOD
2179 FuncDesc
aFuncDesc(pInfo
);
2180 getFuncDesc(sFuncName
, & aFuncDesc
);
2183 // Fallback: DISPATCH_PROPERTYGET can mostly be called as
2185 ITypeInfo
* pInfo
= getTypeInfo();
2186 FuncDesc
aDescPut(pInfo
);
2187 VarDesc
aVarDesc(pInfo
);
2188 getPropDesc(sFuncName
, & aFuncDesc
, & aDescPut
, & aVarDesc
);
2191 throw IllegalArgumentException(
2192 "[automation bridge] The object does not have a function"
2193 "or readable property \""
2194 + sFuncName
, Reference
<XInterface
>(), 0);
2197 *pFuncDesc
= aFuncDesc
.Detach();
2200 bool IUnknownWrapper_Impl::getDispid(const OUString
& sFuncName
, DISPID
* id
)
2202 OSL_ASSERT(m_spDispatch
);
2203 LPOLESTR lpsz
= const_cast<LPOLESTR
> (reinterpret_cast<LPCOLESTR
>(sFuncName
.getStr()));
2204 HRESULT hr
= m_spDispatch
->GetIDsOfNames(IID_NULL
, &lpsz
, 1, LOCALE_USER_DEFAULT
, id
);
2207 void IUnknownWrapper_Impl::getFuncDesc(const OUString
& sFuncName
, FUNCDESC
** pFuncDesc
)
2210 OSL_ASSERT( * pFuncDesc
== 0);
2212 typedef TLBFuncIndexMap::const_iterator cit
;
2213 typedef TLBFuncIndexMap::iterator it
;
2214 //We assume there is only one entry with the function name. A property
2215 //would have two entries.
2216 cit itIndex
= m_mapComFunc
.find(sFuncName
);
2217 if (itIndex
== m_mapComFunc
.end())
2219 //try case insensive with IDispatch::GetIDsOfNames
2221 if (getDispid(sFuncName
, &id
))
2223 CComBSTR memberName
;
2224 unsigned int pcNames
=0;
2225 // get the case sensitive name
2226 if( SUCCEEDED(getTypeInfo()->GetNames( id
, & memberName
, 1, &pcNames
)))
2228 //get the associated index and add an entry to the map
2229 //with the name sFuncName which differs in the casing of the letters to
2230 //the actual name as obtained from ITypeInfo
2231 OUString
sRealName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
)));
2232 cit itOrg
= m_mapComFunc
.find(sRealName
);
2233 OSL_ASSERT(itOrg
!= m_mapComFunc
.end());
2234 // maybe this is a property, if so we need
2235 // to store either both id's ( put/get ) or
2236 // just the get. Storing both is more consistent
2237 pair
<cit
, cit
> pItems
= m_mapComFunc
.equal_range( sRealName
);
2238 for ( ;pItems
.first
!= pItems
.second
; ++pItems
.first
)
2239 m_mapComFunc
.insert( TLBFuncIndexMap::value_type ( make_pair(sFuncName
, pItems
.first
->second
) ));
2241 m_mapComFunc
.find( sFuncName
);
2246 #if OSL_DEBUG_LEVEL >= 1
2247 // There must only be one entry if sFuncName represents a function or two
2248 // if it is a property
2249 pair
<cit
, cit
> p
= m_mapComFunc
.equal_range(sFuncName
.toAsciiLowerCase());
2251 for ( ;p
.first
!= p
.second
; p
.first
++, numEntries
++);
2252 OSL_ASSERT( ! (numEntries
> 3) );
2254 if( itIndex
!= m_mapComFunc
.end())
2256 ITypeInfo
* pType
= getTypeInfo();
2257 FUNCDESC
* pDesc
= NULL
;
2258 if (SUCCEEDED(pType
->GetFuncDesc(itIndex
->second
, & pDesc
)))
2260 if (pDesc
->invkind
== INVOKE_FUNC
)
2262 (*pFuncDesc
) = pDesc
;
2266 pType
->ReleaseFuncDesc(pDesc
);
2271 throw BridgeRuntimeError("[automation bridge] Could not get "
2272 "FUNCDESC for " + sFuncName
);
2275 //else no entry found for sFuncName, pFuncDesc will not be filled in
2278 void IUnknownWrapper_Impl::getPropDesc(const OUString
& sFuncName
, FUNCDESC
** pFuncDescGet
,
2279 FUNCDESC
** pFuncDescPut
, VARDESC
** pVarDesc
)
2281 OSL_ASSERT( * pFuncDescGet
== 0 && * pFuncDescPut
== 0);
2283 typedef TLBFuncIndexMap::const_iterator cit
;
2284 pair
<cit
, cit
> p
= m_mapComFunc
.equal_range(sFuncName
);
2285 if (p
.first
== m_mapComFunc
.end())
2287 //try case insensive with IDispatch::GetIDsOfNames
2289 if (getDispid(sFuncName
, &id
))
2291 CComBSTR memberName
;
2292 unsigned int pcNames
=0;
2293 // get the case sensitive name
2294 if( SUCCEEDED(getTypeInfo()->GetNames( id
, & memberName
, 1, &pcNames
)))
2296 //As opposed to getFuncDesc, we do not add the value because we would
2297 // need to find the get and set description for the property. This would
2298 //mean to iterate over all FUNCDESCs again.
2299 p
= m_mapComFunc
.equal_range(OUString(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
))));
2304 for ( int i
= 0 ;p
.first
!= p
.second
; p
.first
++, i
++)
2306 // There are a maximum of two entries, property put and property get
2307 OSL_ASSERT( ! (i
> 2) );
2308 ITypeInfo
* pType
= getTypeInfo();
2309 FUNCDESC
* pFuncDesc
= NULL
;
2310 if (SUCCEEDED( pType
->GetFuncDesc(p
.first
->second
, & pFuncDesc
)))
2312 if (pFuncDesc
->invkind
== INVOKE_PROPERTYGET
)
2314 (*pFuncDescGet
) = pFuncDesc
;
2316 else if (pFuncDesc
->invkind
== INVOKE_PROPERTYPUT
||
2317 pFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
2319 //a property can have 3 entries, put, put ref, get
2320 // If INVOKE_PROPERTYPUTREF or INVOKE_PROPERTYPUT is used
2321 //depends on what is found first.
2322 if ( * pFuncDescPut
)
2324 //we already have found one
2325 pType
->ReleaseFuncDesc(pFuncDesc
);
2329 (*pFuncDescPut
) = pFuncDesc
;
2334 pType
->ReleaseFuncDesc(pFuncDesc
);
2337 //ITypeInfo::GetFuncDesc may even provide a funcdesc for a VARDESC
2338 // with invkind = INVOKE_FUNC. Since this function should only return
2339 //a value for a real property (XInvokation::hasMethod, ..::hasProperty
2340 //we need to make sure that sFuncName represents a real property.
2341 VARDESC
* pVD
= NULL
;
2342 if (SUCCEEDED(pType
->GetVarDesc(p
.first
->second
, & pVD
)))
2345 //else no entry for sFuncName, pFuncDesc will not be filled in
2348 VARTYPE
IUnknownWrapper_Impl::getUserDefinedElementType( ITypeInfo
* pTypeInfo
, const DWORD nHrefType
)
2350 VARTYPE
_type( VT_NULL
);
2353 CComPtr
<ITypeInfo
> spRefInfo
;
2354 pTypeInfo
->GetRefTypeInfo( nHrefType
, &spRefInfo
.p
);
2357 TypeAttr
attr( spRefInfo
);
2358 spRefInfo
->GetTypeAttr( &attr
);
2359 if ( attr
->typekind
== TKIND_ENUM
)
2361 // We use the type of the first enum value.
2362 if ( attr
->cVars
== 0 )
2364 throw BridgeRuntimeError("[automation bridge] Could not obtain type description");
2366 VarDesc
var( spRefInfo
);
2367 spRefInfo
->GetVarDesc( 0, &var
);
2368 _type
= var
->lpvarValue
->vt
;
2370 else if ( attr
->typekind
== TKIND_INTERFACE
)
2374 else if ( attr
->typekind
== TKIND_DISPATCH
)
2376 _type
= VT_DISPATCH
;
2378 else if ( attr
->typekind
== TKIND_ALIAS
)
2380 // TKIND_ALIAS is a type that is an alias for another type. So get that alias type.
2381 _type
= getUserDefinedElementType( pTypeInfo
, attr
->tdescAlias
.hreftype
);
2385 throw BridgeRuntimeError( "[automation bridge] Unhandled user defined type." );
2392 VARTYPE
IUnknownWrapper_Impl::getElementTypeDesc(const TYPEDESC
*desc
)
2394 VARTYPE
_type( VT_NULL
);
2396 if (desc
->vt
== VT_PTR
)
2398 _type
= getElementTypeDesc(desc
->lptdesc
);
2401 else if (desc
->vt
== VT_SAFEARRAY
)
2403 _type
= getElementTypeDesc(desc
->lptdesc
);
2406 else if (desc
->vt
== VT_USERDEFINED
)
2408 ITypeInfo
* thisInfo
= getTypeInfo(); //kept by this instance
2409 _type
= getUserDefinedElementType( thisInfo
, desc
->hreftype
);
2418 void IUnknownWrapper_Impl::buildComTlbIndex()
2420 if ( ! m_bComTlbIndexInit
)
2422 MutexGuard
guard(getBridgeMutex());
2424 if ( ! m_bComTlbIndexInit
)
2427 ITypeInfo
* pType
= getTypeInfo();
2428 TypeAttr
typeAttr(pType
);
2429 if( SUCCEEDED( pType
->GetTypeAttr( &typeAttr
)))
2431 for( long i
= 0; i
< typeAttr
->cFuncs
; i
++)
2433 FuncDesc
funcDesc(pType
);
2434 if( SUCCEEDED( pType
->GetFuncDesc( i
, &funcDesc
)))
2436 CComBSTR memberName
;
2437 unsigned int pcNames
=0;
2438 if( SUCCEEDED(pType
->GetNames( funcDesc
->memid
, & memberName
, 1, &pcNames
)))
2440 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
)));
2441 m_mapComFunc
.insert( TLBFuncIndexMap::value_type( usName
, i
));
2445 sError
= "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2446 "ITypeInfo::GetNames failed.";
2450 sError
= "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2451 "ITypeInfo::GetFuncDesc failed.";
2454 //If we create an Object in JScript and a property then it
2455 //has VARDESC instead of FUNCDESC
2456 for (long i
= 0; i
< typeAttr
->cVars
; i
++)
2458 VarDesc
varDesc(pType
);
2459 if (SUCCEEDED(pType
->GetVarDesc(i
, & varDesc
)))
2461 CComBSTR memberName
;
2462 unsigned int pcNames
= 0;
2463 if (SUCCEEDED(pType
->GetNames(varDesc
->memid
, & memberName
, 1, &pcNames
)))
2465 if (varDesc
->varkind
== VAR_DISPATCH
)
2467 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
)));
2468 m_mapComFunc
.insert(TLBFuncIndexMap::value_type(
2474 sError
= "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2475 "ITypeInfo::GetNames failed.";
2479 sError
= "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2480 "ITypeInfo::GetVarDesc failed.";
2485 sError
= "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2486 "ITypeInfo::GetTypeAttr failed.";
2488 if (sError
.getLength())
2490 throw BridgeRuntimeError(sError
);
2493 m_bComTlbIndexInit
= true;
2499 ITypeInfo
* IUnknownWrapper_Impl::getTypeInfo()
2503 throw BridgeRuntimeError("The object has no IDispatch interface!");
2508 MutexGuard
guard(getBridgeMutex());
2511 CComPtr
< ITypeInfo
> spType
;
2512 if( SUCCEEDED( m_spDispatch
->GetTypeInfo( 0, LOCALE_USER_DEFAULT
, &spType
.p
)))
2515 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
2517 //If this is a dual interface then TYPEATTR::typekind is usually TKIND_INTERFACE
2518 //We need to get the type description for TKIND_DISPATCH
2519 TypeAttr
typeAttr(spType
.p
);
2520 if( SUCCEEDED(spType
->GetTypeAttr( &typeAttr
)))
2522 if (typeAttr
->typekind
== TKIND_INTERFACE
&&
2523 typeAttr
->wTypeFlags
& TYPEFLAG_FDUAL
)
2525 HREFTYPE refDispatch
;
2526 if (SUCCEEDED(spType
->GetRefTypeOfImplType(::sal::static_int_cast
< UINT
, int >( -1 ), &refDispatch
)))
2528 CComPtr
<ITypeInfo
> spTypeDisp
;
2529 if (SUCCEEDED(spType
->GetRefTypeInfo(refDispatch
, & spTypeDisp
)))
2530 m_spTypeInfo
= spTypeDisp
;
2534 throw BridgeRuntimeError(
2535 "[automation bridge] Could not obtain type information "
2536 "for dispatch interface." );
2539 else if (typeAttr
->typekind
== TKIND_DISPATCH
)
2541 m_spTypeInfo
= spType
;
2545 throw BridgeRuntimeError(
2546 "[automation bridge] Automation object does not "
2547 "provide type information.");
2553 throw BridgeRuntimeError("[automation bridge]The dispatch object does not "
2554 "support ITypeInfo!");
2558 return m_spTypeInfo
;
2563 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */