1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: oleobjw.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
33 #include "ole2uno.hxx"
34 #include "rtl/ustrbuf.hxx"
37 #include "osl/diagnose.h"
38 #include "osl/doublecheckedlocking.h"
39 #include "osl/thread.h"
41 #include "boost/scoped_array.hpp"
42 #include <com/sun/star/script/FailReason.hpp>
43 #include <com/sun/star/beans/XMaterialHolder.hpp>
44 #include <com/sun/star/script/XTypeConverter.hpp>
45 #include <com/sun/star/script/FinishEngineEvent.hpp>
46 #include <com/sun/star/script/InterruptReason.hpp>
47 #include <com/sun/star/script/XEngineListener.hpp>
48 #include <com/sun/star/script/XDebugging.hpp>
49 #include <com/sun/star/script/XInvocation.hpp>
50 #include <com/sun/star/script/ContextInformation.hpp>
51 #include <com/sun/star/script/FinishReason.hpp>
52 #include <com/sun/star/script/XEngine.hpp>
53 #include <com/sun/star/script/InterruptEngineEvent.hpp>
54 #include <com/sun/star/script/XLibraryAccess.hpp>
55 #include <com/sun/star/bridge/ModelDependent.hpp>
57 #include "com/sun/star/bridge/oleautomation/NamedArgument.hpp"
58 #include "com/sun/star/bridge/oleautomation/PropertyPutArgument.hpp"
60 #include <typelib/typedescription.hxx>
62 #include <rtl/memory.h>
63 #include <rtl/ustring.hxx>
65 #include "jscriptclasses.hxx"
67 #include "oleobjw.hxx"
68 #include "unoobjw.hxx"
71 using namespace boost
;
75 using namespace com::sun::star::script
;
76 using namespace com::sun::star::lang
;
77 using namespace com::sun::star::bridge
;
78 using namespace com::sun::star::bridge::oleautomation
;
79 using namespace com::sun::star::bridge::ModelDependent
;
81 #define JSCRIPT_ID_PROPERTY L"_environment"
82 #define JSCRIPT_ID L"jscript"
87 // key: XInterface pointer created by Invocation Adapter Factory
88 // value: XInterface pointer to the wrapper class.
89 // Entries to the map are made within
90 // Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType);
91 // Entries are being deleted if the wrapper class's destructor has been
93 // Before UNO object is wrapped to COM object this map is checked
94 // to see if the UNO object is already a wrapper.
95 hash_map
<sal_uInt32
, sal_uInt32
> AdapterToWrapperMap
;
96 // key: XInterface of the wrapper object.
97 // value: XInterface of the Interface created by the Invocation Adapter Factory.
98 // A COM wrapper is responsible for removing the corresponding entry
99 // in AdapterToWrappperMap if it is being destroyed. Because the wrapper does not
100 // know about its adapted interface it uses WrapperToAdapterMap to get the
101 // adapted interface which is then used to locate the entry in AdapterToWrapperMap.
102 hash_map
<sal_uInt32
,sal_uInt32
> WrapperToAdapterMap
;
104 hash_map
<sal_uInt32
, WeakReference
<XInterface
> > ComPtrToWrapperMap
;
105 /*****************************************************************************
107 class implementation IUnknownWrapper_Impl
109 *****************************************************************************/
111 IUnknownWrapper_Impl::IUnknownWrapper_Impl( Reference
<XMultiServiceFactory
>& xFactory
,
112 sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
113 UnoConversionUtilities
<IUnknownWrapper_Impl
>( xFactory
, unoWrapperClass
, comWrapperClass
),
114 m_pxIdlClass( NULL
), m_eJScript( JScriptUndefined
),
115 m_bComTlbIndexInit(false), m_bHasDfltMethod(false), m_bHasDfltProperty(false)
120 IUnknownWrapper_Impl::~IUnknownWrapper_Impl()
122 o2u_attachCurrentThread();
123 MutexGuard
guard(getBridgeMutex());
124 XInterface
* xIntRoot
= (OWeakObject
*)this;
125 #if OSL_DEBUG_LEVEL > 0
126 acquire(); // make sure we don't delete us twice because of Reference
127 OSL_ASSERT( Reference
<XInterface
>( static_cast<XWeak
*>(this), UNO_QUERY
).get() == xIntRoot
);
130 // remove entries in global maps
131 typedef hash_map
<sal_uInt32
, sal_uInt32
>::iterator _IT
;
132 _IT it
= WrapperToAdapterMap
.find( (sal_uInt32
) xIntRoot
);
133 if( it
!= WrapperToAdapterMap
.end())
135 sal_uInt32 adapter
= it
->second
;
137 AdapterToWrapperMap
.erase( adapter
);
138 WrapperToAdapterMap
.erase( it
);
141 IT_Com it_c
= ComPtrToWrapperMap
.find( (sal_uInt32
) m_spUnknown
.p
);
142 if(it_c
!= ComPtrToWrapperMap
.end())
143 ComPtrToWrapperMap
.erase(it_c
);
145 #if OSL_DEBUG_LEVEL > 0
146 fprintf(stderr
,"[automation bridge] ComPtrToWrapperMap contains: %i \n",
147 ComPtrToWrapperMap
.size());
151 Any
IUnknownWrapper_Impl::queryInterface(const Type
& t
)
152 throw (RuntimeException
)
154 if (t
== getCppuType(static_cast<Reference
<XDefaultMethod
>*>( 0)) && !m_bHasDfltMethod
)
156 if (t
== getCppuType(static_cast<Reference
<XDefaultProperty
>*>( 0)) && !m_bHasDfltProperty
)
158 if (t
== getCppuType(static_cast<Reference
<XInvocation
>*>( 0)) && !m_spDispatch
)
161 return WeakImplHelper6
<XInvocation
, XBridgeSupplier2
,
162 XInitialization
, XAutomationObject
, XDefaultProperty
, XDefaultMethod
>::queryInterface(t
);
165 Reference
<XIntrospectionAccess
> SAL_CALL
IUnknownWrapper_Impl::getIntrospection(void)
166 throw (RuntimeException
)
168 Reference
<XIntrospectionAccess
> ret
;
175 Any SAL_CALL
IUnknownWrapper_Impl::invoke( const OUString
& aFunctionName
,
176 const Sequence
< Any
>& aParams
, Sequence
< sal_Int16
>& aOutParamIndex
,
177 Sequence
< Any
>& aOutParam
)
178 throw(IllegalArgumentException
, CannotConvertException
, InvocationTargetException
,
181 if ( ! m_spDispatch
)
183 throw RuntimeException(
184 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
185 Reference
<XInterface
>());
192 o2u_attachCurrentThread();
194 TypeDescription methodDesc
;
195 getMethodInfo(aFunctionName
, methodDesc
);
198 ret
= invokeWithDispIdUnoTlb(aFunctionName
,
205 ret
= invokeWithDispIdComTlb( aFunctionName
,
211 catch (IllegalArgumentException
&)
215 catch (CannotConvertException
&)
219 catch (BridgeRuntimeError
& e
)
221 throw RuntimeException(e
.message
, Reference
<XInterface
>());
223 catch (Exception
& e
)
225 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
226 "IUnknownWrapper_Impl::invoke ! Message : \n") +
227 e
.Message
, Reference
<XInterface
>());
232 throw RuntimeException(
233 OUSTR("[automation bridge] unexpected exception in "
234 "IUnknownWrapper_Impl::Invoke !"), Reference
<XInterface
>());
239 void SAL_CALL
IUnknownWrapper_Impl::setValue( const OUString
& aPropertyName
,
241 throw(UnknownPropertyException
, CannotConvertException
, InvocationTargetException
,
244 if ( ! m_spDispatch
)
246 throw RuntimeException(
247 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
248 Reference
<XInterface
>());
252 o2u_attachCurrentThread();
254 ITypeInfo
* pInfo
= getTypeInfo();
255 FuncDesc
aDescGet(pInfo
);
256 FuncDesc
aDescPut(pInfo
);
257 VarDesc
aVarDesc(pInfo
);
258 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
259 //check if there is such a property at all or if it is read only
260 if ( ! aDescPut
&& ! aDescGet
&& ! aVarDesc
)
262 OUString
msg(OUSTR("[automation bridge]Property \"") + aPropertyName
+
263 OUSTR("\" is not supported"));
264 throw UnknownPropertyException(msg
, Reference
<XInterface
>());
267 if ( (! aDescPut
&& aDescGet
) || aVarDesc
268 && aVarDesc
->wVarFlags
== VARFLAG_FREADONLY
)
271 OUString
msg(OUSTR("[automation bridge] Property ") + aPropertyName
+
272 OUSTR(" is read-only"));
273 OString sMsg
= OUStringToOString(msg
, osl_getThreadTextEncoding());
274 OSL_ENSURE(0, sMsg
.getStr());
280 DISPPARAMS dispparams
;
282 CComVariant varRefArg
;
283 CComVariant varResult
;
285 unsigned int uArgErr
;
287 // converting UNO value to OLE variant
288 DISPID dispidPut
= DISPID_PROPERTYPUT
;
289 dispparams
.rgdispidNamedArgs
= &dispidPut
;
290 dispparams
.cArgs
= 1;
291 dispparams
.cNamedArgs
= 1;
292 dispparams
.rgvarg
= & varArg
;
294 OSL_ASSERT(aDescPut
|| aVarDesc
);
298 INVOKEKIND invkind
= INVOKE_PROPERTYPUT
;
299 //determine the expected type, dispid, invoke kind (DISPATCH_PROPERTYPUT,
300 //DISPATCH_PROPERTYPUTREF)
303 vt
= getElementTypeDesc(& aDescPut
->lprgelemdescParam
[0].tdesc
);
304 dispid
= aDescPut
->memid
;
305 invkind
= aDescPut
->invkind
;
309 vt
= getElementTypeDesc( & aVarDesc
->elemdescVar
.tdesc
);
310 dispid
= aVarDesc
->memid
;
311 if (vt
== VT_UNKNOWN
|| vt
== VT_DISPATCH
||
312 (vt
& VT_ARRAY
) || (vt
& VT_BYREF
))
314 invkind
= INVOKE_PROPERTYPUTREF
;
318 // convert the uno argument
321 anyToVariant( & varRefArg
, aValue
, ::sal::static_int_cast
< VARTYPE
, int >( vt
^ VT_BYREF
) );
323 if( (vt
& VT_TYPEMASK
) == VT_VARIANT
)
324 varArg
.byref
= & varRefArg
;
325 else if ((vt
& VT_TYPEMASK
) == VT_DECIMAL
)
326 varArg
.byref
= & varRefArg
.decVal
;
328 varArg
.byref
= & varRefArg
.byref
;
332 anyToVariant(& varArg
, aValue
, vt
);
335 hr
= m_spDispatch
->Invoke(dispid
, IID_NULL
, LOCALE_USER_DEFAULT
, ::sal::static_int_cast
< WORD
, INVOKEKIND
>( invkind
),
336 &dispparams
, & varResult
, & excepinfo
, &uArgErr
);
343 case DISP_E_BADPARAMCOUNT
:
344 throw RuntimeException();
346 case DISP_E_BADVARTYPE
:
347 throw RuntimeException();
349 case DISP_E_EXCEPTION
:
350 throw InvocationTargetException();
352 case DISP_E_MEMBERNOTFOUND
:
353 throw UnknownPropertyException();
355 case DISP_E_NONAMEDARGS
:
356 throw RuntimeException();
358 case DISP_E_OVERFLOW
:
359 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
360 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
362 case DISP_E_PARAMNOTFOUND
:
363 throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
364 static_cast<XWeak
*>(this)), ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
)) ;
366 case DISP_E_TYPEMISMATCH
:
367 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
368 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::UNKNOWN
, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
370 case DISP_E_UNKNOWNINTERFACE
:
371 throw RuntimeException();
373 case DISP_E_UNKNOWNLCID
:
374 throw RuntimeException();
376 case DISP_E_PARAMNOTOPTIONAL
:
377 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface
*>(
378 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
381 throw RuntimeException();
385 catch (CannotConvertException
&)
389 catch (UnknownPropertyException
&)
393 catch (BridgeRuntimeError
& e
)
395 throw RuntimeException(
396 e
.message
, Reference
<XInterface
>());
398 catch (Exception
& e
)
400 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
401 "IUnknownWrapper_Impl::setValue ! Message : \n") +
402 e
.Message
, Reference
<XInterface
>());
407 throw RuntimeException(
408 OUSTR("[automation bridge] unexpected exception in "
409 "IUnknownWrapper_Impl::setValue !"), Reference
<XInterface
>());
413 Any SAL_CALL
IUnknownWrapper_Impl::getValue( const OUString
& aPropertyName
)
414 throw(UnknownPropertyException
, RuntimeException
)
416 if ( ! m_spDispatch
)
418 throw RuntimeException(
419 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
420 Reference
<XInterface
>());
425 o2u_attachCurrentThread();
426 ITypeInfo
* pInfo
= getTypeInfo();
427 // I was going to implement an XServiceInfo interface to allow the type
428 // of the automation object to be exposed.. but it seems
429 // from looking at comments in the code that it is possible for a
430 // this object to actually wrap an UNO object ( I guess if automation is
431 // used from MSO to create Openoffice objects ) Therefore, those objects
432 // will more than likely already have an XServiceInfo interface.
433 // Instead here I chose a name that should be illegal both in COM and
434 // UNO ( from an IDL point of view ) therefore I think this is a safe
436 if ( aPropertyName
.equals( rtl::OUString::createFromAscii("$GetTypeName") ))
438 if ( pInfo
&& m_sTypeName
.getLength() == 0 )
440 m_sTypeName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IDispatch") );
443 if ( SUCCEEDED( pInfo
->GetDocumentation( -1, &sName
, NULL
, NULL
, NULL
) ) )
445 rtl::OUString
sTmp( reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(sName
)));
446 if ( sTmp
.indexOf('_') == 0 )
448 // do we own the memory for pTypeLib, msdn doco is vague
450 CComPtr
< ITypeLib
> pTypeLib
;
452 if ( SUCCEEDED( pInfo
->GetContainingTypeLib( &pTypeLib
.p
, &index
)) )
454 if ( SUCCEEDED( pTypeLib
->GetDocumentation( -1, &sName
, NULL
, NULL
, NULL
) ) )
456 rtl::OUString
sLibName( reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(sName
)));
457 m_sTypeName
= sLibName
.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".") ) ).concat( sTmp
);
467 FuncDesc
aDescGet(pInfo
);
468 FuncDesc
aDescPut(pInfo
);
469 VarDesc
aVarDesc(pInfo
);
470 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
471 if ( ! aDescGet
&& ! aDescPut
&& ! aVarDesc
)
474 OUString
msg(OUSTR("[automation bridge]Property \"") + aPropertyName
+
475 OUSTR("\" is not supported"));
476 throw UnknownPropertyException(msg
, Reference
<XInterface
>());
478 // write-only should not be possible
479 OSL_ASSERT( aDescGet
|| ! aDescPut
);
482 DISPPARAMS dispparams
= {0, 0, 0, 0};
483 CComVariant varResult
;
485 unsigned int uArgErr
;
488 dispid
= aDescGet
->memid
;
490 dispid
= aVarDesc
->memid
;
492 dispid
= aDescPut
->memid
;
494 hr
= m_spDispatch
->Invoke(dispid
,
497 DISPATCH_PROPERTYGET
,
503 // converting return value and out parameter back to UNO
506 // If the com object implements uno interfaces then we have
507 // to convert the attribute into the expected type.
508 TypeDescription attrInfo
;
509 getAttributeInfo(aPropertyName
, attrInfo
);
511 variantToAny( &varResult
, ret
, Type( attrInfo
.get()->pWeakRef
));
513 variantToAny(&varResult
, ret
);
521 case DISP_E_BADPARAMCOUNT
:
522 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
523 Reference
<XInterface
>());
525 case DISP_E_BADVARTYPE
:
526 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
527 Reference
<XInterface
>());
529 case DISP_E_EXCEPTION
:
530 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
531 Reference
<XInterface
>());
533 case DISP_E_MEMBERNOTFOUND
:
534 throw UnknownPropertyException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
535 Reference
<XInterface
>());
537 case DISP_E_NONAMEDARGS
:
538 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
539 Reference
<XInterface
>());
541 case DISP_E_OVERFLOW
:
542 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
543 Reference
<XInterface
>());
545 case DISP_E_PARAMNOTFOUND
:
546 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
547 Reference
<XInterface
>());
549 case DISP_E_TYPEMISMATCH
:
550 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
551 Reference
<XInterface
>());
553 case DISP_E_UNKNOWNINTERFACE
:
554 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
555 Reference
<XInterface
>());
557 case DISP_E_UNKNOWNLCID
:
558 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
559 Reference
<XInterface
>());
561 case DISP_E_PARAMNOTOPTIONAL
:
562 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
563 Reference
<XInterface
>());
566 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
567 Reference
<XInterface
>());
571 catch (UnknownPropertyException
& )
575 catch (BridgeRuntimeError
& e
)
577 throw RuntimeException(
578 e
.message
, Reference
<XInterface
>());
580 catch (Exception
& e
)
582 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
583 "IUnknownWrapper_Impl::getValue ! Message : \n") +
584 e
.Message
, Reference
<XInterface
>());
588 throw RuntimeException(
589 OUSTR("[automation bridge] unexpected exception in "
590 "IUnknownWrapper_Impl::getValue !"), Reference
<XInterface
>());
595 sal_Bool SAL_CALL
IUnknownWrapper_Impl::hasMethod( const OUString
& aName
)
596 throw(RuntimeException
)
598 if ( ! m_spDispatch
)
600 throw RuntimeException(
601 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
602 Reference
<XInterface
>());
604 sal_Bool ret
= sal_False
;
608 o2u_attachCurrentThread();
609 ITypeInfo
* pInfo
= getTypeInfo();
610 FuncDesc
aDesc(pInfo
);
611 getFuncDesc(aName
, & aDesc
);
612 // Automation properties can have arguments. Those are treated as methods and
613 //are called through XInvocation::invoke.
616 FuncDesc
aDescGet(pInfo
);
617 FuncDesc
aDescPut(pInfo
);
618 VarDesc
aVarDesc(pInfo
);
619 getPropDesc( aName
, & aDescGet
, & aDescPut
, & aVarDesc
);
620 if (aDescGet
&& aDescGet
->cParams
> 0
621 || aDescPut
&& aDescPut
->cParams
> 0)
627 catch (BridgeRuntimeError
& e
)
629 throw RuntimeException(e
.message
, Reference
<XInterface
>());
631 catch (Exception
& e
)
633 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
634 "IUnknownWrapper_Impl::hasMethod ! Message : \n") +
635 e
.Message
, Reference
<XInterface
>());
639 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
640 "IUnknownWrapper_Impl::hasMethod !"), Reference
<XInterface
>());;
645 sal_Bool SAL_CALL
IUnknownWrapper_Impl::hasProperty( const OUString
& aName
)
646 throw(RuntimeException
)
648 if ( ! m_spDispatch
)
650 throw RuntimeException(OUSTR("[automation bridge] The object does not have an "
651 "IDispatch interface"), Reference
<XInterface
>());
654 sal_Bool ret
= sal_False
;
657 o2u_attachCurrentThread();
659 ITypeInfo
* pInfo
= getTypeInfo();
660 FuncDesc
aDescGet(pInfo
);
661 FuncDesc
aDescPut(pInfo
);
662 VarDesc
aVarDesc(pInfo
);
663 getPropDesc(aName
, & aDescGet
, & aDescPut
, & aVarDesc
);
664 // Automation properties can have parameters. If so, we access them through
665 // XInvocation::invoke. Thas is, hasProperty must return false for such a
668 || aDescPut
&& aDescPut
->cParams
== 0
669 || aDescGet
&& aDescGet
->cParams
== 0)
674 catch (BridgeRuntimeError
& e
)
676 throw RuntimeException(e
.message
, Reference
<XInterface
>());
678 catch (Exception
& e
)
680 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
681 "IUnknownWrapper_Impl::hasProperty ! Message : \n") +
682 e
.Message
, Reference
<XInterface
>());
687 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
688 "IUnknownWrapper_Impl::hasProperty !"), Reference
<XInterface
>());
693 Any SAL_CALL
IUnknownWrapper_Impl::createBridge( const Any
& modelDepObject
,
694 const Sequence
< sal_Int8
>& /*aProcessId*/, sal_Int16 sourceModelType
,
695 sal_Int16 destModelType
)
696 throw( IllegalArgumentException
, RuntimeException
)
699 o2u_attachCurrentThread();
702 (sourceModelType
== UNO
) &&
703 (destModelType
== OLE
) &&
704 (modelDepObject
.getValueTypeClass() == TypeClass_INTERFACE
)
707 Reference
<XInterface
> xInt( *(XInterface
**) modelDepObject
.getValue());
708 Reference
<XInterface
> xSelf( (OWeakObject
*)this);
712 VARIANT
* pVariant
= (VARIANT
*) CoTaskMemAlloc(sizeof(VARIANT
));
714 VariantInit(pVariant
);
715 if (m_bOriginalDispatch
== sal_True
)
717 pVariant
->vt
= VT_DISPATCH
;
718 pVariant
->pdispVal
= m_spDispatch
;
719 pVariant
->pdispVal
->AddRef();
723 pVariant
->vt
= VT_UNKNOWN
;
724 pVariant
->punkVal
= m_spUnknown
;
725 pVariant
->punkVal
->AddRef();
728 ret
.setValue((void*)&pVariant
, getCppuType( (sal_uInt32
*) 0));
735 @exception IllegalArgumentException
736 @exception CannotConvertException
737 @exception InvocationTargetException
740 Any
IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString
& sFunctionName
,
741 const Sequence
< Any
>& Params
,
742 Sequence
< sal_Int16
>& OutParamIndex
,
743 Sequence
< Any
>& OutParam
)
748 sal_Int32 parameterCount
= Params
.getLength();
749 sal_Int32 outParameterCount
= 0;
750 typelib_InterfaceMethodTypeDescription
* pMethod
= NULL
;
751 TypeDescription methodDesc
;
752 getMethodInfo(sFunctionName
, methodDesc
);
754 // We need to know whether the IDispatch is from a JScript object.
755 // Then out and in/out parameters have to be treated differently than
756 // with common COM objects.
757 sal_Bool bJScriptObject
= isJScriptObject();
758 scoped_array
<CComVariant
> sarParams
;
759 scoped_array
<CComVariant
> sarParamsRef
;
760 CComVariant
*pVarParams
= NULL
;
761 CComVariant
*pVarParamsRef
= NULL
;
762 sal_Bool bConvRet
= sal_True
;
766 pMethod
= (typelib_InterfaceMethodTypeDescription
* )methodDesc
.get();
767 parameterCount
= pMethod
->nParams
;
768 // Create the Array for the array being passed in DISPPARAMS
769 // the array also contains the outparameter (but not the values)
770 if( pMethod
->nParams
> 0)
772 sarParams
.reset(new CComVariant
[ parameterCount
]);
773 pVarParams
= sarParams
.get();
776 // Create the Array for the out an in/out parameter. These values
777 // are referenced by the VT_BYREF VARIANTs in DISPPARAMS.
778 // We need to find out the number of out and in/out parameter.
779 for( sal_Int32 i
=0; i
< parameterCount
; i
++)
781 if( pMethod
->pParams
[i
].bOut
)
787 sarParamsRef
.reset(new CComVariant
[outParameterCount
]);
788 pVarParamsRef
= sarParamsRef
.get();
789 // build up the parameters for IDispatch::Invoke
790 sal_Int32 outParamIndex
=0;
794 for( i
= 0; i
< parameterCount
; i
++)
797 if( pMethod
->pParams
[i
].bIn
== sal_True
&& ! pMethod
->pParams
[i
].bOut
)
799 anyToVariant( &pVarParams
[parameterCount
- i
-1], Params
.getConstArray()[i
]);
801 // Out parameter + in/out parameter
802 else if( pMethod
->pParams
[i
].bOut
== sal_True
)
805 if(pMethod
->pParams
[i
].bIn
)
807 anyToVariant( & var
,Params
[i
]);
808 pVarParamsRef
[outParamIndex
] = var
;
811 switch( pMethod
->pParams
[i
].pTypeRef
->eTypeClass
)
813 case TypeClass_INTERFACE
:
814 case TypeClass_STRUCT
:
815 if( ! pMethod
->pParams
[i
].bIn
)
817 pVarParamsRef
[ outParamIndex
].vt
= VT_DISPATCH
;
818 pVarParamsRef
[ outParamIndex
].pdispVal
= 0;
820 pVarParams
[parameterCount
- i
-1].vt
= VT_DISPATCH
| VT_BYREF
;
821 pVarParams
[parameterCount
- i
-1].ppdispVal
= &pVarParamsRef
[outParamIndex
].pdispVal
;
825 case TypeClass_UNSIGNED_LONG
:
826 if( ! pMethod
->pParams
[i
].bIn
)
828 pVarParamsRef
[ outParamIndex
].vt
= VT_I4
;
829 pVarParamsRef
[ outParamIndex
].lVal
= 0;
831 pVarParams
[parameterCount
- i
-1].vt
= VT_I4
| VT_BYREF
;
832 pVarParams
[parameterCount
- i
-1].plVal
= &pVarParamsRef
[outParamIndex
].lVal
;
834 case TypeClass_SEQUENCE
:
835 if( ! pMethod
->pParams
[i
].bIn
)
837 pVarParamsRef
[ outParamIndex
].vt
= VT_ARRAY
| VT_VARIANT
;
838 pVarParamsRef
[ outParamIndex
].parray
= NULL
;
840 pVarParams
[parameterCount
- i
-1].vt
= VT_ARRAY
| VT_BYREF
| VT_VARIANT
;
841 pVarParams
[parameterCount
- i
-1].pparray
= &pVarParamsRef
[outParamIndex
].parray
;
844 if( ! pMethod
->pParams
[i
].bIn
)
846 pVarParamsRef
[ outParamIndex
].vt
= VT_EMPTY
;
847 pVarParamsRef
[ outParamIndex
].lVal
= 0;
849 pVarParams
[parameterCount
- i
-1].vt
= VT_VARIANT
| VT_BYREF
;
850 pVarParams
[parameterCount
- i
-1].pvarVal
= &pVarParamsRef
[outParamIndex
];
852 case TypeClass_BOOLEAN
:
853 if( ! pMethod
->pParams
[i
].bIn
)
855 pVarParamsRef
[ outParamIndex
].vt
= VT_BOOL
;
856 pVarParamsRef
[ outParamIndex
].boolVal
= 0;
858 pVarParams
[parameterCount
- i
-1].vt
= VT_BOOL
| VT_BYREF
;
859 pVarParams
[parameterCount
- i
-1].pboolVal
=
860 & pVarParamsRef
[outParamIndex
].boolVal
;
863 case TypeClass_STRING
:
864 if( ! pMethod
->pParams
[i
].bIn
)
866 pVarParamsRef
[ outParamIndex
].vt
= VT_BSTR
;
867 pVarParamsRef
[ outParamIndex
].bstrVal
= 0;
869 pVarParams
[parameterCount
- i
-1].vt
= VT_BSTR
| VT_BYREF
;
870 pVarParams
[parameterCount
- i
-1].pbstrVal
=
871 & pVarParamsRef
[outParamIndex
].bstrVal
;
874 case TypeClass_FLOAT
:
875 if( ! pMethod
->pParams
[i
].bIn
)
877 pVarParamsRef
[ outParamIndex
].vt
= VT_R4
;
878 pVarParamsRef
[ outParamIndex
].fltVal
= 0;
880 pVarParams
[parameterCount
- i
-1].vt
= VT_R4
| VT_BYREF
;
881 pVarParams
[parameterCount
- i
-1].pfltVal
=
882 & pVarParamsRef
[outParamIndex
].fltVal
;
884 case TypeClass_DOUBLE
:
885 if( ! pMethod
->pParams
[i
].bIn
)
887 pVarParamsRef
[ outParamIndex
].vt
= VT_R8
;
888 pVarParamsRef
[ outParamIndex
].dblVal
= 0;
890 pVarParams
[parameterCount
- i
-1].vt
= VT_R8
| VT_BYREF
;
891 pVarParams
[parameterCount
- i
-1].pdblVal
=
892 & pVarParamsRef
[outParamIndex
].dblVal
;
895 if( ! pMethod
->pParams
[i
].bIn
)
897 pVarParamsRef
[ outParamIndex
].vt
= VT_UI1
;
898 pVarParamsRef
[ outParamIndex
].bVal
= 0;
900 pVarParams
[parameterCount
- i
-1].vt
= VT_UI1
| VT_BYREF
;
901 pVarParams
[parameterCount
- i
-1].pbVal
=
902 & pVarParamsRef
[outParamIndex
].bVal
;
905 case TypeClass_SHORT
:
906 case TypeClass_UNSIGNED_SHORT
:
907 if( ! pMethod
->pParams
[i
].bIn
)
909 pVarParamsRef
[ outParamIndex
].vt
= VT_I2
;
910 pVarParamsRef
[ outParamIndex
].iVal
= 0;
912 pVarParams
[parameterCount
- i
-1].vt
= VT_I2
| VT_BYREF
;
913 pVarParams
[parameterCount
- i
-1].piVal
=
914 & pVarParamsRef
[outParamIndex
].iVal
;
918 if( ! pMethod
->pParams
[i
].bIn
)
920 pVarParamsRef
[ outParamIndex
].vt
= VT_EMPTY
;
921 pVarParamsRef
[ outParamIndex
].lVal
= 0;
923 pVarParams
[parameterCount
- i
-1].vt
= VT_VARIANT
| VT_BYREF
;
924 pVarParams
[parameterCount
- i
-1].pvarVal
=
925 & pVarParamsRef
[outParamIndex
];
931 catch (IllegalArgumentException
& e
)
933 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
936 catch (CannotConvertException
& e
)
942 else // it is an JScriptObject
947 for( ; i
< parameterCount
; i
++)
950 if( pMethod
->pParams
[i
].bIn
== sal_True
&& ! pMethod
->pParams
[i
].bOut
)
952 anyToVariant( &pVarParams
[parameterCount
- i
-1], Params
.getConstArray()[i
]);
954 // Out parameter + in/out parameter
955 else if( pMethod
->pParams
[i
].bOut
== sal_True
)
957 CComObject
<JScriptOutParam
>* pParamObject
;
958 if( SUCCEEDED( CComObject
<JScriptOutParam
>::CreateInstance( &pParamObject
)))
960 CComPtr
<IUnknown
> pUnk(pParamObject
->GetUnknown());
962 CComQIPtr
<IDispatch
, &__uuidof(IDispatch
)> pDisp( pUnk
);
964 CComQIPtr
<IDispatch
> pDisp( pUnk
);
967 pVarParams
[ parameterCount
- i
-1].vt
= VT_DISPATCH
;
968 pVarParams
[ parameterCount
- i
-1].pdispVal
= pDisp
;
969 pVarParams
[ parameterCount
- i
-1].pdispVal
->AddRef();
970 // if the param is in/out then put the parameter on index 0
971 if( pMethod
->pParams
[i
].bIn
== sal_True
) // in / out
973 CComVariant varParam
;
974 anyToVariant( &varParam
, Params
.getConstArray()[i
]);
975 CComDispatchDriver
dispDriver( pDisp
);
976 if(FAILED( dispDriver
.PutPropertyByName( L
"0", &varParam
)))
977 throw BridgeRuntimeError(
978 OUSTR("[automation bridge]IUnknownWrapper_Impl::"
979 "invokeWithDispIdUnoTlb\n"
980 "Could not set property \"0\" for the in/out "
987 throw BridgeRuntimeError(
988 OUSTR("[automation bridge]IUnknownWrapper_Impl::"
989 "invokeWithDispIdUnoTlb\n"
990 "Could not create out parameter at index: ") +
991 OUString::valueOf((sal_Int32
) i
));
997 catch (IllegalArgumentException
& e
)
999 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
1002 catch (CannotConvertException
& e
)
1004 e
.ArgumentIndex
= i
;
1009 // No type description Available, that is we have to deal with a COM component,
1010 // that does not implements UNO interfaces ( IDispatch based)
1013 //We should not run into this block, because invokeWithDispIdComTlb should
1014 //have been called instead.
1019 CComVariant varResult
;
1020 ExcepInfo excepinfo
;
1021 unsigned int uArgErr
;
1022 DISPPARAMS dispparams
= { pVarParams
, NULL
, parameterCount
, 0};
1024 FuncDesc
aDesc(getTypeInfo());
1025 getFuncDesc(sFunctionName
, & aDesc
);
1026 // invoking OLE method
1027 hr
= m_spDispatch
->Invoke(aDesc
->memid
,
1029 LOCALE_USER_DEFAULT
,
1036 // converting return value and out parameter back to UNO
1039 if( outParameterCount
&& pMethod
)
1041 OutParamIndex
.realloc( outParameterCount
);
1042 OutParam
.realloc( outParameterCount
);
1043 sal_Int32 outIndex
=0;
1047 for( ; i
< parameterCount
; i
++)
1049 if( pMethod
->pParams
[i
].bOut
)
1051 OutParamIndex
[outIndex
]= (sal_Int16
) i
;
1053 if( !bJScriptObject
)
1055 variantToAny( &pVarParamsRef
[outIndex
], outAny
,
1056 Type(pMethod
->pParams
[i
].pTypeRef
), sal_False
);
1057 OutParam
[outIndex
++]= outAny
;
1059 else //JScriptObject
1061 if( pVarParams
[i
].vt
== VT_DISPATCH
)
1063 CComDispatchDriver
pDisp( pVarParams
[i
].pdispVal
);
1067 if( SUCCEEDED( pDisp
.GetPropertyByName( L
"0", &varOut
)))
1069 variantToAny( &varOut
, outAny
,
1070 Type(pMethod
->pParams
[parameterCount
- 1 - i
].pTypeRef
), sal_False
);
1071 OutParam
[outParameterCount
- 1 - outIndex
++]= outAny
;
1074 bConvRet
= sal_False
;
1077 bConvRet
= sal_False
;
1080 bConvRet
= sal_False
;
1083 if( !bConvRet
) break;
1086 catch(IllegalArgumentException
& e
)
1088 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
1091 catch(CannotConvertException
& e
)
1093 e
.ArgumentIndex
= i
;
1097 // return value, no type information available
1103 variantToAny(&varResult
, ret
, Type( pMethod
->pReturnTypeRef
), sal_False
);
1105 variantToAny(&varResult
, ret
, sal_False
);
1107 catch (IllegalArgumentException
& e
)
1110 OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1111 "Could not convert return value! \n Message: \n") + e
.Message
;
1114 catch (CannotConvertException
& e
)
1117 OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1118 "Could not convert return value! \n Message: \n") + e
.Message
;
1124 if( !bConvRet
) // conversion of return or out parameter failed
1125 throw CannotConvertException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Call to COM object failed. Conversion of return or out value failed")),
1126 Reference
<XInterface
>( static_cast<XWeak
*>(this), UNO_QUERY
), TypeClass_UNKNOWN
,
1127 FailReason::UNKNOWN
, 0);// lookup error code
1128 // conversion of return or out parameter failed
1133 case DISP_E_BADPARAMCOUNT
:
1134 throw IllegalArgumentException();
1136 case DISP_E_BADVARTYPE
:
1137 throw RuntimeException();
1139 case DISP_E_EXCEPTION
:
1140 throw InvocationTargetException();
1142 case DISP_E_MEMBERNOTFOUND
:
1143 throw IllegalArgumentException();
1145 case DISP_E_NONAMEDARGS
:
1146 throw IllegalArgumentException();
1148 case DISP_E_OVERFLOW
:
1149 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
1150 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
1152 case DISP_E_PARAMNOTFOUND
:
1153 throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
1154 static_cast<XWeak
*>(this)), ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1156 case DISP_E_TYPEMISMATCH
:
1157 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface
*>(
1158 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::UNKNOWN
, uArgErr
);
1160 case DISP_E_UNKNOWNINTERFACE
:
1161 throw RuntimeException() ;
1163 case DISP_E_UNKNOWNLCID
:
1164 throw RuntimeException() ;
1166 case DISP_E_PARAMNOTOPTIONAL
:
1167 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
1168 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
1171 throw RuntimeException();
1180 // --------------------------
1182 void SAL_CALL
IUnknownWrapper_Impl::initialize( const Sequence
< Any
>& aArguments
) throw(Exception
, RuntimeException
)
1184 // 1.parameter is IUnknown
1185 // 2.parameter is a boolean which indicates if the the COM pointer was a IUnknown or IDispatch
1186 // 3.parameter is a Sequence<Type>
1187 o2u_attachCurrentThread();
1188 OSL_ASSERT(aArguments
.getLength() == 3);
1190 m_spUnknown
= *(IUnknown
**) aArguments
[0].getValue();
1192 m_spUnknown
->QueryInterface(IID_IDispatch
, reinterpret_cast<LPVOID
*>( & m_spDispatch
.p
));
1194 m_spUnknown
.QueryInterface( & m_spDispatch
.p
);
1197 aArguments
[1] >>= m_bOriginalDispatch
;
1198 aArguments
[2] >>= m_seqTypes
;
1201 ITypeInfo
* pType
= getTypeInfo();
1202 // Get Default member
1203 CComBSTR defaultMemberName
;
1204 if ( SUCCEEDED( pType
->GetDocumentation(0, &defaultMemberName
, 0, 0, 0 ) ) )
1206 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(defaultMemberName
)));
1207 FuncDesc
aDescGet(pType
);
1208 FuncDesc
aDescPut(pType
);
1209 VarDesc
aVarDesc(pType
);
1210 // see if this is a property first ( more likely to be a property then a method )
1211 getPropDesc( usName
, & aDescGet
, & aDescPut
, & aVarDesc
);
1213 if ( !aDescGet
&& !aDescPut
)
1215 getFuncDesc( usName
, &aDescGet
);
1218 throw RuntimeException();
1221 // now for some funny heuristics to make basic understand what to do
1222 // a single aDescGet ( that doesn't take any params ) would be
1223 // a read only ( defaultmember ) property e.g. this object
1224 // should implement XDefaultProperty
1225 // a single aDescGet ( that *does* ) take params is basically a
1226 // default method e.g. implement XDefaultMethod
1228 // 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 )
1229 if ( aDescPut
|| ( aDescGet
&& aDescGet
->cParams
== 0 ) )
1230 m_bHasDfltProperty
= true;
1231 if ( aDescGet
->cParams
> 0 )
1232 m_bHasDfltMethod
= true;
1233 if ( m_bHasDfltProperty
|| m_bHasDfltMethod
)
1234 m_sDefaultMember
= usName
;
1242 // UnoConversionUtilities --------------------------------------------------------------------------------
1243 Reference
< XInterface
> IUnknownWrapper_Impl::createUnoWrapperInstance()
1245 if( m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
)
1247 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper_Impl(
1248 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1249 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1251 else if( m_nUnoWrapperClass
== UNO_OBJECT_WRAPPER_REMOTE_OPT
)
1253 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
1254 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1255 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1258 return Reference
<XInterface
>();
1260 Reference
<XInterface
> IUnknownWrapper_Impl::createComWrapperInstance()
1262 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper_Impl(
1263 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1264 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1269 void IUnknownWrapper_Impl::getMethodInfo(const OUString
& sName
, TypeDescription
& methodInfo
)
1271 TypeDescription desc
= getInterfaceMemberDescOfCurrentCall(sName
);
1274 typelib_TypeDescription
* pMember
= desc
.get();
1275 if( pMember
->eTypeClass
== TypeClass_INTERFACE_METHOD
)
1276 methodInfo
= pMember
;
1280 void IUnknownWrapper_Impl::getAttributeInfo(const OUString
& sName
, TypeDescription
& attributeInfo
)
1282 TypeDescription desc
= getInterfaceMemberDescOfCurrentCall(sName
);
1285 typelib_TypeDescription
* pMember
= desc
.get();
1286 if( pMember
->eTypeClass
== TypeClass_INTERFACE_ATTRIBUTE
)
1288 attributeInfo
= ((typelib_InterfaceAttributeTypeDescription
*)pMember
)->pAttributeTypeRef
;
1292 TypeDescription
IUnknownWrapper_Impl::getInterfaceMemberDescOfCurrentCall(const OUString
& sName
)
1294 TypeDescription ret
;
1296 for( sal_Int32 i
=0; i
< m_seqTypes
.getLength(); i
++)
1298 TypeDescription
_curDesc( m_seqTypes
[i
]);
1299 _curDesc
.makeComplete();
1300 typelib_InterfaceTypeDescription
* pInterface
= (typelib_InterfaceTypeDescription
*) _curDesc
.get();
1303 typelib_InterfaceMemberTypeDescription
* pMember
= NULL
;
1304 //find the member description of the current call
1305 for( int i
=0; i
< pInterface
->nAllMembers
; i
++)
1307 typelib_TypeDescriptionReference
* pTypeRefMember
= pInterface
->ppAllMembers
[i
];
1308 typelib_TypeDescription
* pDescMember
= NULL
;
1309 TYPELIB_DANGER_GET( &pDescMember
, pTypeRefMember
)
1311 typelib_InterfaceMemberTypeDescription
* pInterfaceMember
=
1312 (typelib_InterfaceMemberTypeDescription
*) pDescMember
;
1313 if( OUString( pInterfaceMember
->pMemberName
) == sName
)
1315 pMember
= pInterfaceMember
;
1318 TYPELIB_DANGER_RELEASE( pDescMember
)
1323 ret
= (typelib_TypeDescription
*)pMember
;
1324 TYPELIB_DANGER_RELEASE( (typelib_TypeDescription
*)pMember
);
1333 sal_Bool
IUnknownWrapper_Impl::isJScriptObject()
1335 if( m_eJScript
== JScriptUndefined
)
1337 CComDispatchDriver
disp( m_spDispatch
);
1341 if( SUCCEEDED( disp
.GetPropertyByName( JSCRIPT_ID_PROPERTY
, &result
)))
1343 if(result
.vt
== VT_BSTR
)
1345 CComBSTR
name( result
.bstrVal
);
1347 if( name
== CComBSTR(JSCRIPT_ID
))
1348 m_eJScript
= IsJScript
;
1352 if( m_eJScript
== JScriptUndefined
)
1353 m_eJScript
= NoJScript
;
1356 return m_eJScript
== NoJScript
? sal_False
: sal_True
;
1362 The function ultimately calls IDispatch::Invoke on the wrapped COM object.
1363 The COM object does not implement UNO Interfaces ( via IDispatch). This
1364 is the case when the OleObjectFactory service has been used to create a
1366 @exception IllegalArgumentException
1367 @exception CannotConvertException
1368 @InvocationTargetException
1372 Any
IUnknownWrapper_Impl::invokeWithDispIdComTlb(const OUString
& sFuncName
,
1373 const Sequence
< Any
>& Params
,
1374 Sequence
< sal_Int16
>& OutParamIndex
,
1375 Sequence
< Any
>& OutParam
)
1380 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
1381 CComVariant varResult
;
1382 ExcepInfo excepinfo
;
1383 unsigned int uArgErr
;
1385 sal_Int32 nUnoArgs
= Params
.getLength();
1386 DISPID idPropertyPut
= DISPID_PROPERTYPUT
;
1387 scoped_array
<DISPID
> arDispidNamedArgs
;
1388 scoped_array
<CComVariant
> ptrArgs
;
1389 scoped_array
<CComVariant
> ptrRefArgs
; // referenced arguments
1390 CComVariant
* arArgs
= NULL
;
1391 CComVariant
* arRefArgs
= NULL
;
1392 sal_Int32 revIndex
= 0;
1393 bool bVarargParam
= false;
1395 // Get type info for the call. It can be a method call or property put or
1396 // property get operation.
1397 FuncDesc
aFuncDesc(getTypeInfo());
1398 getFuncDescForInvoke(sFuncName
, Params
, & aFuncDesc
);
1400 //Set the array of DISPIDs for named args if it is a property put operation.
1401 //If there are other named arguments another array is set later on.
1402 if (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
1403 || aFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
1404 dispparams
.rgdispidNamedArgs
= & idPropertyPut
;
1406 //Determine the number of named arguments
1407 for (int iParam
= 0; iParam
< nUnoArgs
; iParam
++)
1409 const Any
& curArg
= Params
[iParam
];
1410 if (curArg
.getValueType() == getCppuType((NamedArgument
*) 0))
1411 dispparams
.cNamedArgs
++;
1413 //In a property put operation a property value is a named argument (DISPID_PROPERTYPUT).
1414 //Therefore the number of named arguments is increased by one.
1415 //Although named, the argument is not named in a actual language, such as Basic,
1416 //therefore it is never a com.sun.star.bridge.oleautomation.NamedArgument
1417 if (aFuncDesc
->invkind
== DISPATCH_PROPERTYPUT
1418 || aFuncDesc
->invkind
== DISPATCH_PROPERTYPUTREF
)
1419 dispparams
.cNamedArgs
++;
1421 //Determine the number of all arguments and named arguments
1422 if (aFuncDesc
->cParamsOpt
== -1)
1424 //Attribute vararg is set on this method. "Unlimited" number of args
1425 //supported. There can be no optional or defaultvalue on any of the arguments.
1426 dispparams
.cArgs
= nUnoArgs
;
1430 //If there are namesd arguments, then the dispparams.cArgs
1431 //is the number of supplied args, otherwise it is the expected number.
1432 if (dispparams
.cNamedArgs
)
1433 dispparams
.cArgs
= nUnoArgs
;
1435 dispparams
.cArgs
= aFuncDesc
->cParams
;
1438 //check if there are not to many arguments supplied
1439 if (::sal::static_int_cast
< sal_uInt32
, int >( nUnoArgs
) > dispparams
.cArgs
)
1441 OUStringBuffer
buf(256);
1442 buf
.appendAscii("[automation bridge] There are too many arguments for this method");
1443 throw IllegalArgumentException( buf
.makeStringAndClear(),
1444 Reference
<XInterface
>(), (sal_Int16
) dispparams
.cArgs
);
1447 //Set up the array of DISPIDs (DISPPARAMS::rgdispidNamedArgs)
1448 //for the named arguments.
1449 //If there is only one named arg and if it is because of a property put
1450 //operation, then we need not set up the DISPID array.
1451 if (dispparams
.cNamedArgs
> 0 &&
1452 ! (dispparams
.cNamedArgs
== 1 &&
1453 (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
||
1454 aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
)))
1456 //set up an array containing the member and parameter names
1457 //which is then used in ITypeInfo::GetIDsOfNames
1458 //First determine the size of the array of names which is passed to
1459 //ITypeInfo::GetIDsOfNames. It must hold the method names + the named
1461 int nSizeAr
= dispparams
.cNamedArgs
+ 1;
1462 if (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
1463 || aFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
1465 nSizeAr
= dispparams
.cNamedArgs
; //counts the DISID_PROPERTYPUT
1468 scoped_array
<OLECHAR
*> saNames(new OLECHAR
*[nSizeAr
]);
1469 OLECHAR
** arNames
= saNames
.get();
1470 arNames
[0] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(sFuncName
.getStr()));
1473 for (size_t iParams
= 0; iParams
< dispparams
.cArgs
; iParams
++)
1475 const Any
& curArg
= Params
[iParams
];
1476 if (curArg
.getValueType() == getCppuType((NamedArgument
*) 0))
1478 const NamedArgument
& arg
= *(NamedArgument
const*) curArg
.getValue();
1479 //We put the parameter names in reverse order into the array,
1480 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1481 //The first name in the array is the method name
1482 arNames
[nSizeAr
- 1 - cNamedArg
++] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(arg
.Name
.getStr()));
1486 //Prepare the array of DISPIDs for ITypeInfo::GetIDsOfNames
1487 //it must be big enough to contain the DISPIDs of the member + parameters
1488 arDispidNamedArgs
.reset(new DISPID
[nSizeAr
]);
1489 HRESULT hr
= getTypeInfo()->GetIDsOfNames(arNames
, nSizeAr
,
1490 arDispidNamedArgs
.get());
1491 if ( hr
== E_NOTIMPL
)
1492 hr
= m_spDispatch
->GetIDsOfNames(IID_NULL
, arNames
, nSizeAr
, LOCALE_USER_DEFAULT
, arDispidNamedArgs
.get() );
1496 // In a "property put" operation, the property value is a named param with the
1497 //special DISPID DISPID_PROPERTYPUT
1498 if (aFuncDesc
->invkind
== DISPATCH_PROPERTYPUT
1499 || aFuncDesc
->invkind
== DISPATCH_PROPERTYPUTREF
)
1501 //Element at index 0 in the DISPID array must be DISPID_PROPERTYPUT
1502 //The first item in the array arDispidNamedArgs is the DISPID for
1503 //the method. We replace it with DISPID_PROPERTYPUT.
1504 DISPID
* arIDs
= arDispidNamedArgs
.get();
1505 arIDs
[0] = DISPID_PROPERTYPUT
;
1506 dispparams
.rgdispidNamedArgs
= arIDs
;
1510 //The first item in the array arDispidNamedArgs is the DISPID for
1511 //the method. It must be removed
1512 DISPID
* arIDs
= arDispidNamedArgs
.get();
1513 dispparams
.rgdispidNamedArgs
= & arIDs
[1];
1516 else if (hr
== DISP_E_UNKNOWNNAME
)
1518 throw IllegalArgumentException(
1519 OUSTR("[automation bridge]One of the named arguments is wrong!"),
1520 Reference
<XInterface
>(), 0);
1524 throw InvocationTargetException(
1525 OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ")
1526 + OUString::valueOf((sal_Int32
) hr
, 16), Reference
<XInterface
>(), Any());
1531 ptrArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1532 ptrRefArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1533 arArgs
= ptrArgs
.get();
1534 arRefArgs
= ptrRefArgs
.get();
1537 for (i
= 0; i
< (sal_Int32
) dispparams
.cArgs
; i
++)
1539 revIndex
= dispparams
.cArgs
- i
-1;
1540 arRefArgs
[revIndex
].byref
=0;
1543 anyArg
= Params
.getConstArray()[i
];
1545 //Test if the current parameter is a "vararg" parameter.
1546 if (bVarargParam
|| (aFuncDesc
->cParamsOpt
== -1 &&
1547 aFuncDesc
->cParams
== (i
+ 1)))
1548 { //This parameter is from the variable argument list. There is no
1549 //type info available, except that it must be a VARIANT
1550 bVarargParam
= true;
1553 unsigned short paramFlags
= PARAMFLAG_FOPT
| PARAMFLAG_FIN
;
1554 VARTYPE varType
= VT_VARIANT
;
1555 if ( ! bVarargParam
)
1558 aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
1559 varType
= getElementTypeDesc(
1560 & aFuncDesc
->lprgelemdescParam
[i
].tdesc
);
1562 //Make sure that there is a UNO parameter for every
1563 // expected parameter. If there is no UNO parameter where the
1564 // called function expects one, then it must be optional. Otherwise
1565 // its a UNO programming error.
1566 if (i
>= nUnoArgs
&& !(paramFlags
& PARAMFLAG_FOPT
))
1568 OUStringBuffer
buf(256);
1569 buf
.appendAscii("ole automation bridge: The called function expects an argument at"
1570 "position: "); //a different number of arguments")),
1571 buf
.append(OUString::valueOf((sal_Int32
) i
));
1572 buf
.appendAscii(" (index starting at 0).");
1573 throw IllegalArgumentException( buf
.makeStringAndClear(),
1574 Reference
<XInterface
>(), (sal_Int16
) i
);
1576 //make sure we get no void any for an in parameter. In StarBasic
1577 //this may be caused by
1580 //A void any is allowed if the parameter is optional
1581 if ( ! (aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
& PARAMFLAG_FOPT
)
1582 && (i
< nUnoArgs
) && (paramFlags
& PARAMFLAG_FIN
) &&
1583 Params
.getConstArray()[i
].getValueTypeClass() == TypeClass_VOID
)
1585 OUStringBuffer
buf(256);
1586 buf
.appendAscii("ole automation bridge: The argument at position: ");
1587 buf
.append(OUString::valueOf((sal_Int32
) i
));
1588 buf
.appendAscii(" (index starts with 0) is uninitialized.");
1589 throw IllegalArgumentException( buf
.makeStringAndClear(),
1590 Reference
<XInterface
>(), (sal_Int16
) i
);
1593 // Property Put arguments
1594 if (anyArg
.getValueType() == getCppuType((PropertyPutArgument
*)0))
1596 PropertyPutArgument arg
;
1598 anyArg
<<= arg
.Value
;
1601 if (anyArg
.getValueType() == getCppuType((NamedArgument
*) 0))
1603 NamedArgument aNamedArgument
;
1604 anyArg
>>= aNamedArgument
;
1605 anyArg
<<= aNamedArgument
.Value
;
1608 if (paramFlags
& PARAMFLAG_FOUT
&&
1609 ! (paramFlags
& PARAMFLAG_FIN
) )
1611 VARTYPE type
= ::sal::static_int_cast
< VARTYPE
, int >( varType
^ VT_BYREF
);
1614 arRefArgs
[revIndex
].vt
= type
;
1619 arRefArgs
[revIndex
].vt
= VT_ERROR
;
1620 arRefArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1622 if( type
== VT_VARIANT
)
1624 arArgs
[revIndex
].vt
= VT_VARIANT
| VT_BYREF
;
1625 arArgs
[revIndex
].byref
= &arRefArgs
[revIndex
];
1629 arArgs
[revIndex
].vt
= varType
;
1630 if (type
== VT_DECIMAL
)
1631 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].decVal
;
1633 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].byref
;
1636 // in/out + in byref params
1637 else if (varType
& VT_BYREF
)
1639 VARTYPE type
= ::sal::static_int_cast
< VARTYPE
, int >( varType
^ VT_BYREF
);
1642 if (i
< nUnoArgs
&& anyArg
.getValueTypeClass() != TypeClass_VOID
)
1644 anyToVariant( & arRefArgs
[revIndex
], anyArg
, type
);
1646 else if (paramFlags
& PARAMFLAG_FHASDEFAULT
)
1648 //optional arg with default
1649 VariantCopy( & arRefArgs
[revIndex
],
1650 & aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.
1651 pparamdescex
->varDefaultValue
);
1656 //e.g: call func(x) in basic : func() ' no arg supplied
1657 OSL_ASSERT(paramFlags
& PARAMFLAG_FOPT
);
1658 arRefArgs
[revIndex
].vt
= VT_ERROR
;
1659 arRefArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1662 // Set the converted arguments in the array which will be
1663 // DISPPARAMS::rgvarg
1664 // byref arg VT_XXX |VT_BYREF
1665 arArgs
[revIndex
].vt
= varType
;
1666 if (revIndex
== 0 && aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
)
1668 arArgs
[revIndex
] = arRefArgs
[revIndex
];
1670 else if (type
== VT_DECIMAL
)
1672 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].decVal
;
1674 else if (type
== VT_VARIANT
)
1676 if ( ! (paramFlags
& PARAMFLAG_FOUT
))
1677 arArgs
[revIndex
] = arRefArgs
[revIndex
];
1679 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
];
1683 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].byref
;
1684 arArgs
[revIndex
].vt
= ::sal::static_int_cast
< VARTYPE
, int >( arRefArgs
[revIndex
].vt
| VT_BYREF
);
1688 // in parameter no VT_BYREF except for array, interfaces
1690 { // void any stands for optional param
1691 if (i
< nUnoArgs
&& anyArg
.getValueTypeClass() != TypeClass_VOID
)
1693 anyToVariant( & arArgs
[revIndex
], anyArg
, varType
);
1695 //optional arg but no void any supplied
1696 //Basic: obj.func() ' first parameter left out because it is optional
1697 else if (paramFlags
& PARAMFLAG_FHASDEFAULT
)
1699 //optional arg with defaulteithter as direct arg : VT_XXX or
1700 VariantCopy( & arArgs
[revIndex
],
1701 & aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.
1702 pparamdescex
->varDefaultValue
);
1706 OSL_ASSERT(paramFlags
& PARAMFLAG_FOPT
);
1707 arArgs
[revIndex
].vt
= VT_ERROR
;
1708 arArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1713 catch (IllegalArgumentException
& e
)
1715 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, sal_Int32
>( i
);
1718 catch (CannotConvertException
& e
)
1720 e
.ArgumentIndex
= i
;
1723 dispparams
.rgvarg
= arArgs
;
1724 // invoking OLE method
1725 DWORD localeId
= LOCALE_USER_DEFAULT
;
1726 result
= m_spDispatch
->Invoke(aFuncDesc
->memid
,
1729 ::sal::static_int_cast
< WORD
, INVOKEKIND
>( aFuncDesc
->invkind
),
1735 // converting return value and out parameter back to UNO
1739 // allocate space for the out param Sequence and indices Sequence
1740 int outParamsCount
= 0; // includes in/out parameter
1741 for (int i
= 0; i
< aFuncDesc
->cParams
; i
++)
1743 if (aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
&
1748 OutParamIndex
.realloc(outParamsCount
);
1749 OutParam
.realloc(outParamsCount
);
1750 // Convert out params
1753 int outParamIndex
=0;
1754 for (int paramIndex
= 0; paramIndex
< nUnoArgs
; paramIndex
++)
1756 //Determine the index within the method sinature
1757 int realParamIndex
= paramIndex
;
1758 int revParamIndex
= dispparams
.cArgs
- paramIndex
- 1;
1759 if (Params
[paramIndex
].getValueType()
1760 == getCppuType((NamedArgument
*) 0))
1762 //dispparams.rgdispidNamedArgs contains the mapping from index
1763 //of named args list to index of parameter list
1764 realParamIndex
= dispparams
.rgdispidNamedArgs
[revParamIndex
];
1767 // no named arg, always come before named args
1768 if (! (aFuncDesc
->lprgelemdescParam
[realParamIndex
].paramdesc
.wParamFlags
1772 // variantToAny is called with the "reduce range" parameter set to sal_False.
1773 // That causes VT_I4 values not to be converted down to a "lower" type. That
1774 // feature exist for JScript only because it only uses VT_I4 for integer types.
1777 variantToAny( & arRefArgs
[revParamIndex
], outAny
, sal_False
);
1779 catch (IllegalArgumentException
& e
)
1781 e
.ArgumentPosition
= (sal_Int16
)paramIndex
;
1784 catch (CannotConvertException
& e
)
1786 e
.ArgumentIndex
= paramIndex
;
1789 OutParam
[outParamIndex
] = outAny
;
1790 OutParamIndex
[outParamIndex
] = ::sal::static_int_cast
< sal_Int16
, int >( paramIndex
);
1793 OutParam
.realloc(outParamIndex
);
1794 OutParamIndex
.realloc(outParamIndex
);
1797 variantToAny(&varResult
, ret
, sal_False
);
1800 // map error codes to exceptions
1806 case DISP_E_BADPARAMCOUNT
:
1807 throw IllegalArgumentException(OUSTR("[automation bridge] Wrong "
1808 "number of arguments. Object returned DISP_E_BADPARAMCOUNT."),
1811 case DISP_E_BADVARTYPE
:
1812 throw RuntimeException(OUSTR("[automation bridge] One or more "
1813 "arguments have the wrong type. Object returned "
1814 "DISP_E_BADVARTYPE."), 0);
1816 case DISP_E_EXCEPTION
:
1817 message
= OUSTR("[automation bridge]: ");
1818 message
+= OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
),
1819 ::SysStringLen(excepinfo
.bstrDescription
));
1820 throw InvocationTargetException(message
, Reference
<XInterface
>(), Any());
1822 case DISP_E_MEMBERNOTFOUND
:
1823 message
= OUSTR("[automation bridge]: A function with the name \"")
1824 + sFuncName
+ OUSTR("\" is not supported. Object returned "
1825 "DISP_E_MEMBERNOTFOUND.");
1826 throw IllegalArgumentException(message
, 0, 0);
1828 case DISP_E_NONAMEDARGS
:
1829 throw IllegalArgumentException(OUSTR("[automation bridge] Object "
1830 "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1832 case DISP_E_OVERFLOW
:
1833 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")),
1834 static_cast<XInterface
*>(
1835 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
1837 case DISP_E_PARAMNOTFOUND
:
1838 throw IllegalArgumentException(OUSTR("[automation bridge]Call failed."
1839 "Object returned DISP_E_PARAMNOTFOUND."),
1840 0, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1842 case DISP_E_TYPEMISMATCH
:
1843 throw CannotConvertException(OUSTR("[automation bridge] Call failed. "
1844 "Object returned DISP_E_TYPEMISMATCH"),
1845 static_cast<XInterface
*>(
1846 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::UNKNOWN
, uArgErr
);
1848 case DISP_E_UNKNOWNINTERFACE
:
1849 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
1850 "Object returned DISP_E_UNKNOWNINTERFACE."),0);
1852 case DISP_E_UNKNOWNLCID
:
1853 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
1854 "Object returned DISP_E_UNKNOWNLCID."),0);
1856 case DISP_E_PARAMNOTOPTIONAL
:
1857 throw CannotConvertException(OUSTR("[automation bridge] Call failed."
1858 "Object returned DISP_E_PARAMNOTOPTIONAL"),
1859 static_cast<XInterface
*>(static_cast<XWeak
*>(this)),
1860 TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
1863 throw RuntimeException();
1870 void IUnknownWrapper_Impl::getFuncDescForInvoke(const OUString
& sFuncName
,
1871 const Sequence
<Any
> & seqArgs
,
1872 FUNCDESC
** pFuncDesc
)
1874 int nUnoArgs
= seqArgs
.getLength();
1875 const Any
* arArgs
= seqArgs
.getConstArray();
1876 ITypeInfo
* pInfo
= getTypeInfo();
1878 //If the last of the positional arguments is a PropertyPutArgument
1879 //then obtain the type info for the property put operation.
1881 //The property value is always the last argument, in a positional argument list
1882 //or in a list of named arguments. A PropertyPutArgument is actually a named argument
1883 //hence it must not be put in an extra NamedArgument structure
1885 arArgs
[nUnoArgs
- 1].getValueType() == getCppuType((PropertyPutArgument
*) 0))
1887 // DISPATCH_PROPERTYPUT
1888 FuncDesc
aDescGet(pInfo
);
1889 FuncDesc
aDescPut(pInfo
);
1890 VarDesc
aVarDesc(pInfo
);
1891 getPropDesc(sFuncName
, & aDescGet
, & aDescPut
, & aVarDesc
);
1894 throw IllegalArgumentException(
1895 OUSTR("[automation bridge] The object does not have a writeable property: ")
1896 + sFuncName
, Reference
<XInterface
>(), 0);
1898 *pFuncDesc
= aDescPut
.Detach();
1901 { // DISPATCH_METHOD
1902 FuncDesc
aFuncDesc(pInfo
);
1903 getFuncDesc(sFuncName
, & aFuncDesc
);
1906 // Fallback: DISPATCH_PROPERTYGET can mostly be called as
1908 ITypeInfo
* pInfo
= getTypeInfo();
1909 FuncDesc
aDescPut(pInfo
);
1910 VarDesc
aVarDesc(pInfo
);
1911 getPropDesc(sFuncName
, & aFuncDesc
, & aDescPut
, & aVarDesc
);
1914 throw IllegalArgumentException(
1915 OUSTR("[automation bridge] The object does not have a function"
1916 "or readable property \"")
1917 + sFuncName
, Reference
<XInterface
>(), 0);
1920 *pFuncDesc
= aFuncDesc
.Detach();
1923 bool IUnknownWrapper_Impl::getDispid(const OUString
& sFuncName
, DISPID
* id
)
1925 OSL_ASSERT(m_spDispatch
);
1926 LPOLESTR lpsz
= const_cast<LPOLESTR
> (reinterpret_cast<LPCOLESTR
>(sFuncName
.getStr()));
1927 HRESULT hr
= m_spDispatch
->GetIDsOfNames(IID_NULL
, &lpsz
, 1, LOCALE_USER_DEFAULT
, id
);
1928 return hr
== S_OK
? true : false;
1930 void IUnknownWrapper_Impl::getFuncDesc(const OUString
& sFuncName
, FUNCDESC
** pFuncDesc
)
1933 OSL_ASSERT( * pFuncDesc
== 0);
1935 typedef TLBFuncIndexMap::const_iterator cit
;
1936 typedef TLBFuncIndexMap::iterator it
;
1937 //We assume there is only one entry with the function name. A property
1938 //would have two entries.
1939 cit itIndex
= m_mapComFunc
.find(sFuncName
);
1940 if (itIndex
== m_mapComFunc
.end())
1942 //try case insensive with IDispatch::GetIDsOfNames
1944 if (getDispid(sFuncName
, &id
))
1946 CComBSTR memberName
;
1947 unsigned int pcNames
=0;
1948 // get the case sensitive name
1949 if( SUCCEEDED(getTypeInfo()->GetNames( id
, & memberName
, 1, &pcNames
)))
1951 //get the associated index and add an entry to the map
1952 //with the name sFuncName which differs in the casing of the letters to
1953 //the actual name as obtained from ITypeInfo
1954 cit itOrg
= m_mapComFunc
.find(OUString(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
))));
1955 OSL_ASSERT(itOrg
!= m_mapComFunc
.end());
1957 m_mapComFunc
.insert( TLBFuncIndexMap::value_type
1958 ( make_pair(sFuncName
, itOrg
->second
) ));
1963 #if OSL_DEBUG_LEVEL >= 1
1964 // There must only be one entry if sFuncName represents a function or two
1965 // if it is a property
1966 pair
<cit
, cit
> p
= m_mapComFunc
.equal_range(sFuncName
.toAsciiLowerCase());
1968 for ( ;p
.first
!= p
.second
; p
.first
++, numEntries
++);
1969 OSL_ASSERT( ! (numEntries
> 3) );
1971 if( itIndex
!= m_mapComFunc
.end())
1973 ITypeInfo
* pType
= getTypeInfo();
1974 FUNCDESC
* pDesc
= NULL
;
1975 if (SUCCEEDED(pType
->GetFuncDesc(itIndex
->second
, & pDesc
)))
1977 if (pDesc
->invkind
== INVOKE_FUNC
)
1979 (*pFuncDesc
) = pDesc
;
1983 pType
->ReleaseFuncDesc(pDesc
);
1988 throw BridgeRuntimeError(OUSTR("[automation bridge] Could not get "
1989 "FUNCDESC for ") + sFuncName
);
1992 //else no entry found for sFuncName, pFuncDesc will not be filled in
1995 void IUnknownWrapper_Impl::getPropDesc(const OUString
& sFuncName
, FUNCDESC
** pFuncDescGet
,
1996 FUNCDESC
** pFuncDescPut
, VARDESC
** pVarDesc
)
1998 OSL_ASSERT( * pFuncDescGet
== 0 && * pFuncDescPut
== 0);
2000 typedef TLBFuncIndexMap::const_iterator cit
;
2001 pair
<cit
, cit
> p
= m_mapComFunc
.equal_range(sFuncName
);
2002 if (p
.first
== m_mapComFunc
.end())
2004 //try case insensive with IDispatch::GetIDsOfNames
2006 if (getDispid(sFuncName
, &id
))
2008 CComBSTR memberName
;
2009 unsigned int pcNames
=0;
2010 // get the case sensitive name
2011 if( SUCCEEDED(getTypeInfo()->GetNames( id
, & memberName
, 1, &pcNames
)))
2013 //As opposed to getFuncDesc, we do not add the value because we would
2014 // need to find the get and set description for the property. This would
2015 //mean to iterate over all FUNCDESCs again.
2016 p
= m_mapComFunc
.equal_range(OUString(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
))));
2021 for ( int i
= 0 ;p
.first
!= p
.second
; p
.first
++, i
++)
2023 // There are a maximum of two entries, property put and property get
2024 OSL_ASSERT( ! (i
> 2) );
2025 ITypeInfo
* pType
= getTypeInfo();
2026 FUNCDESC
* pFuncDesc
= NULL
;
2027 if (SUCCEEDED( pType
->GetFuncDesc(p
.first
->second
, & pFuncDesc
)))
2029 if (pFuncDesc
->invkind
== INVOKE_PROPERTYGET
)
2031 (*pFuncDescGet
) = pFuncDesc
;
2033 else if (pFuncDesc
->invkind
== INVOKE_PROPERTYPUT
||
2034 pFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
2036 //a property can have 3 entries, put, put ref, get
2037 // If INVOKE_PROPERTYPUTREF or INVOKE_PROPERTYPUT is used
2038 //depends on what is found first.
2039 if ( * pFuncDescPut
)
2041 //we already have found one
2042 pType
->ReleaseFuncDesc(pFuncDesc
);
2046 (*pFuncDescPut
) = pFuncDesc
;
2051 pType
->ReleaseFuncDesc(pFuncDesc
);
2054 //ITypeInfo::GetFuncDesc may even provide a funcdesc for a VARDESC
2055 // with invkind = INVOKE_FUNC. Since this function should only return
2056 //a value for a real property (XInvokation::hasMethod, ..::hasProperty
2057 //we need to make sure that sFuncName represents a real property.
2058 VARDESC
* pVD
= NULL
;
2059 if (SUCCEEDED(pType
->GetVarDesc(p
.first
->second
, & pVD
)))
2062 //else no entry for sFuncName, pFuncDesc will not be filled in
2065 VARTYPE
IUnknownWrapper_Impl::getElementTypeDesc(const TYPEDESC
*desc
)
2067 VARTYPE
_type( VT_NULL
);
2069 if (desc
->vt
== VT_PTR
)
2071 _type
= getElementTypeDesc(desc
->lptdesc
);
2074 else if (desc
->vt
== VT_SAFEARRAY
)
2076 _type
= getElementTypeDesc(desc
->lptdesc
);
2079 else if (desc
->vt
== VT_USERDEFINED
)
2081 ITypeInfo
* thisInfo
= getTypeInfo(); //kept by this instance
2082 CComPtr
<ITypeInfo
> spRefInfo
;
2083 thisInfo
->GetRefTypeInfo(desc
->hreftype
, & spRefInfo
.p
);
2086 TypeAttr
attr(spRefInfo
);
2087 spRefInfo
->GetTypeAttr( & attr
);
2088 if (attr
->typekind
== TKIND_ENUM
)
2090 //We use the type of the first enum value.
2091 if (attr
->cVars
== 0)
2093 throw BridgeRuntimeError(OUSTR("[automation bridge] Could "
2094 "not obtain type description"));
2096 VarDesc
var(spRefInfo
);
2097 spRefInfo
->GetVarDesc(0, & var
);
2098 _type
= var
->lpvarValue
->vt
;
2100 else if (attr
->typekind
== TKIND_INTERFACE
)
2104 else if (attr
->typekind
== TKIND_DISPATCH
)
2106 _type
= VT_DISPATCH
;
2110 throw BridgeRuntimeError(OUSTR("[automation bridge] "
2111 "Unhandled user defined type."));
2122 void IUnknownWrapper_Impl::buildComTlbIndex()
2124 if ( ! m_bComTlbIndexInit
)
2126 MutexGuard
guard(getBridgeMutex());
2128 if ( ! m_bComTlbIndexInit
)
2131 ITypeInfo
* pType
= getTypeInfo();
2132 TypeAttr
typeAttr(pType
);
2133 if( SUCCEEDED( pType
->GetTypeAttr( &typeAttr
)))
2135 for( long i
= 0; i
< typeAttr
->cFuncs
; i
++)
2137 FuncDesc
funcDesc(pType
);
2138 if( SUCCEEDED( pType
->GetFuncDesc( i
, &funcDesc
)))
2140 CComBSTR memberName
;
2141 unsigned int pcNames
=0;
2142 if( SUCCEEDED(pType
->GetNames( funcDesc
->memid
, & memberName
, 1, &pcNames
)))
2144 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
)));
2145 m_mapComFunc
.insert( TLBFuncIndexMap::value_type( usName
, i
));
2149 sError
= OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2150 "ITypeInfo::GetNames failed.");
2154 sError
= OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2155 "ITypeInfo::GetFuncDesc failed.");
2158 //If we create an Object in JScript and a a property then it
2159 //has VARDESC instead of FUNCDESC
2160 for (long i
= 0; i
< typeAttr
->cVars
; i
++)
2162 VarDesc
varDesc(pType
);
2163 if (SUCCEEDED(pType
->GetVarDesc(i
, & varDesc
)))
2165 CComBSTR memberName
;
2166 unsigned int pcNames
= 0;
2167 if (SUCCEEDED(pType
->GetNames(varDesc
->memid
, & memberName
, 1, &pcNames
)))
2169 if (varDesc
->varkind
== VAR_DISPATCH
)
2171 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
)));
2172 m_mapComFunc
.insert(TLBFuncIndexMap::value_type(
2178 sError
= OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2179 "ITypeInfo::GetNames failed.");
2183 sError
= OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2184 "ITypeInfo::GetVarDesc failed.");
2189 sError
= OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2190 "ITypeInfo::GetTypeAttr failed.");
2192 if (sError
.getLength())
2194 throw BridgeRuntimeError(sError
);
2197 m_bComTlbIndexInit
= true;
2203 ITypeInfo
* IUnknownWrapper_Impl::getTypeInfo()
2207 throw BridgeRuntimeError(OUSTR("The object has no IDispatch interface!"));
2212 MutexGuard
guard(getBridgeMutex());
2215 CComPtr
< ITypeInfo
> spType
;
2216 if( SUCCEEDED( m_spDispatch
->GetTypeInfo( 0, LOCALE_USER_DEFAULT
, &spType
.p
)))
2219 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
2221 //If this is a dual interface then TYPEATTR::typekind is usually TKIND_INTERFACE
2222 //We need to get the type description for TKIND_DISPATCH
2223 TypeAttr
typeAttr(spType
.p
);
2224 if( SUCCEEDED(spType
->GetTypeAttr( &typeAttr
)))
2226 if (typeAttr
->typekind
== TKIND_INTERFACE
&&
2227 typeAttr
->wTypeFlags
& TYPEFLAG_FDUAL
)
2229 HREFTYPE refDispatch
;
2230 if (SUCCEEDED(spType
->GetRefTypeOfImplType(::sal::static_int_cast
< UINT
, int >( -1 ), &refDispatch
)))
2232 CComPtr
<ITypeInfo
> spTypeDisp
;
2233 if (SUCCEEDED(spType
->GetRefTypeInfo(refDispatch
, & spTypeDisp
)))
2234 m_spTypeInfo
= spTypeDisp
;
2238 throw BridgeRuntimeError(
2239 OUSTR("[automation bridge] Could not obtain type information "
2240 "for dispatch interface." ));
2243 else if (typeAttr
->typekind
== TKIND_DISPATCH
)
2245 m_spTypeInfo
= spType
;
2249 throw BridgeRuntimeError(
2250 OUSTR("[automation bridge] Automation object does not "
2251 "provide type information."));
2257 throw BridgeRuntimeError(OUSTR("[automation bridge]The dispatch object does not "
2258 "support ITypeInfo!"));
2262 return m_spTypeInfo
;