1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
30 #include "ole2uno.hxx"
31 #include "rtl/ustrbuf.hxx"
34 #include "osl/diagnose.h"
35 #include "osl/doublecheckedlocking.h"
36 #include "osl/thread.h"
38 #include "boost/scoped_array.hpp"
39 #include <com/sun/star/script/FailReason.hpp>
40 #include <com/sun/star/beans/XMaterialHolder.hpp>
41 #include <com/sun/star/script/XTypeConverter.hpp>
42 #include <com/sun/star/script/FinishEngineEvent.hpp>
43 #include <com/sun/star/script/InterruptReason.hpp>
44 #include <com/sun/star/script/XEngineListener.hpp>
45 #include <com/sun/star/script/XDebugging.hpp>
46 #include <com/sun/star/script/XInvocation.hpp>
47 #include <com/sun/star/script/ContextInformation.hpp>
48 #include <com/sun/star/script/FinishReason.hpp>
49 #include <com/sun/star/script/XEngine.hpp>
50 #include <com/sun/star/script/InterruptEngineEvent.hpp>
51 #include <com/sun/star/script/XLibraryAccess.hpp>
52 #include <com/sun/star/bridge/ModelDependent.hpp>
54 #include "com/sun/star/bridge/oleautomation/NamedArgument.hpp"
55 #include "com/sun/star/bridge/oleautomation/PropertyPutArgument.hpp"
57 #include <typelib/typedescription.hxx>
59 #include <rtl/memory.h>
60 #include <rtl/ustring.hxx>
62 #include "jscriptclasses.hxx"
64 #include "oleobjw.hxx"
65 #include "unoobjw.hxx"
68 using namespace boost
;
72 using namespace com::sun::star::script
;
73 using namespace com::sun::star::lang
;
74 using namespace com::sun::star::bridge
;
75 using namespace com::sun::star::bridge::oleautomation
;
76 using namespace com::sun::star::bridge::ModelDependent
;
78 #define JSCRIPT_ID_PROPERTY L"_environment"
79 #define JSCRIPT_ID L"jscript"
84 // key: XInterface pointer created by Invocation Adapter Factory
85 // value: XInterface pointer to the wrapper class.
86 // Entries to the map are made within
87 // Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType);
88 // Entries are being deleted if the wrapper class's destructor has been
90 // Before UNO object is wrapped to COM object this map is checked
91 // to see if the UNO object is already a wrapper.
92 hash_map
<sal_uInt32
, sal_uInt32
> AdapterToWrapperMap
;
93 // key: XInterface of the wrapper object.
94 // value: XInterface of the Interface created by the Invocation Adapter Factory.
95 // A COM wrapper is responsible for removing the corresponding entry
96 // in AdapterToWrappperMap if it is being destroyed. Because the wrapper does not
97 // know about its adapted interface it uses WrapperToAdapterMap to get the
98 // adapted interface which is then used to locate the entry in AdapterToWrapperMap.
99 hash_map
<sal_uInt32
,sal_uInt32
> WrapperToAdapterMap
;
101 hash_map
<sal_uInt32
, WeakReference
<XInterface
> > ComPtrToWrapperMap
;
102 /*****************************************************************************
104 class implementation IUnknownWrapper_Impl
106 *****************************************************************************/
108 IUnknownWrapper_Impl::IUnknownWrapper_Impl( Reference
<XMultiServiceFactory
>& xFactory
,
109 sal_uInt8 unoWrapperClass
, sal_uInt8 comWrapperClass
):
110 UnoConversionUtilities
<IUnknownWrapper_Impl
>( xFactory
, unoWrapperClass
, comWrapperClass
),
111 m_pxIdlClass( NULL
), m_eJScript( JScriptUndefined
),
112 m_bComTlbIndexInit(false), m_bHasDfltMethod(false), m_bHasDfltProperty(false)
117 IUnknownWrapper_Impl::~IUnknownWrapper_Impl()
119 o2u_attachCurrentThread();
120 MutexGuard
guard(getBridgeMutex());
121 XInterface
* xIntRoot
= (OWeakObject
*)this;
122 #if OSL_DEBUG_LEVEL > 0
123 acquire(); // make sure we don't delete us twice because of Reference
124 OSL_ASSERT( Reference
<XInterface
>( static_cast<XWeak
*>(this), UNO_QUERY
).get() == xIntRoot
);
127 // remove entries in global maps
128 typedef hash_map
<sal_uInt32
, sal_uInt32
>::iterator _IT
;
129 _IT it
= WrapperToAdapterMap
.find( (sal_uInt32
) xIntRoot
);
130 if( it
!= WrapperToAdapterMap
.end())
132 sal_uInt32 adapter
= it
->second
;
134 AdapterToWrapperMap
.erase( adapter
);
135 WrapperToAdapterMap
.erase( it
);
138 IT_Com it_c
= ComPtrToWrapperMap
.find( (sal_uInt32
) m_spUnknown
.p
);
139 if(it_c
!= ComPtrToWrapperMap
.end())
140 ComPtrToWrapperMap
.erase(it_c
);
142 #if OSL_DEBUG_LEVEL > 0
143 fprintf(stderr
,"[automation bridge] ComPtrToWrapperMap contains: %i \n",
144 ComPtrToWrapperMap
.size());
148 Any
IUnknownWrapper_Impl::queryInterface(const Type
& t
)
149 throw (RuntimeException
)
151 if (t
== getCppuType(static_cast<Reference
<XDefaultMethod
>*>( 0)) && !m_bHasDfltMethod
)
153 if (t
== getCppuType(static_cast<Reference
<XDefaultProperty
>*>( 0)) && !m_bHasDfltProperty
)
155 if (t
== getCppuType(static_cast<Reference
<XInvocation
>*>( 0)) && !m_spDispatch
)
158 return WeakImplHelper6
<XInvocation
, XBridgeSupplier2
,
159 XInitialization
, XAutomationObject
, XDefaultProperty
, XDefaultMethod
>::queryInterface(t
);
162 Reference
<XIntrospectionAccess
> SAL_CALL
IUnknownWrapper_Impl::getIntrospection(void)
163 throw (RuntimeException
)
165 Reference
<XIntrospectionAccess
> ret
;
172 Any SAL_CALL
IUnknownWrapper_Impl::invoke( const OUString
& aFunctionName
,
173 const Sequence
< Any
>& aParams
, Sequence
< sal_Int16
>& aOutParamIndex
,
174 Sequence
< Any
>& aOutParam
)
175 throw(IllegalArgumentException
, CannotConvertException
, InvocationTargetException
,
178 if ( ! m_spDispatch
)
180 throw RuntimeException(
181 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
182 Reference
<XInterface
>());
189 o2u_attachCurrentThread();
191 TypeDescription methodDesc
;
192 getMethodInfo(aFunctionName
, methodDesc
);
195 ret
= invokeWithDispIdUnoTlb(aFunctionName
,
202 ret
= invokeWithDispIdComTlb( aFunctionName
,
208 catch (IllegalArgumentException
&)
212 catch (CannotConvertException
&)
216 catch (BridgeRuntimeError
& e
)
218 throw RuntimeException(e
.message
, Reference
<XInterface
>());
220 catch (Exception
& e
)
222 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
223 "IUnknownWrapper_Impl::invoke ! Message : \n") +
224 e
.Message
, Reference
<XInterface
>());
229 throw RuntimeException(
230 OUSTR("[automation bridge] unexpected exception in "
231 "IUnknownWrapper_Impl::Invoke !"), Reference
<XInterface
>());
236 void SAL_CALL
IUnknownWrapper_Impl::setValue( const OUString
& aPropertyName
,
238 throw(UnknownPropertyException
, CannotConvertException
, InvocationTargetException
,
241 if ( ! m_spDispatch
)
243 throw RuntimeException(
244 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
245 Reference
<XInterface
>());
249 o2u_attachCurrentThread();
251 ITypeInfo
* pInfo
= getTypeInfo();
252 FuncDesc
aDescGet(pInfo
);
253 FuncDesc
aDescPut(pInfo
);
254 VarDesc
aVarDesc(pInfo
);
255 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
256 //check if there is such a property at all or if it is read only
257 if ( ! aDescPut
&& ! aDescGet
&& ! aVarDesc
)
259 OUString
msg(OUSTR("[automation bridge]Property \"") + aPropertyName
+
260 OUSTR("\" is not supported"));
261 throw UnknownPropertyException(msg
, Reference
<XInterface
>());
264 if ( (! aDescPut
&& aDescGet
) || aVarDesc
265 && aVarDesc
->wVarFlags
== VARFLAG_FREADONLY
)
268 OUString
msg(OUSTR("[automation bridge] Property ") + aPropertyName
+
269 OUSTR(" is read-only"));
270 OString sMsg
= OUStringToOString(msg
, osl_getThreadTextEncoding());
271 OSL_ENSURE(0, sMsg
.getStr());
277 DISPPARAMS dispparams
;
279 CComVariant varRefArg
;
280 CComVariant varResult
;
282 unsigned int uArgErr
;
284 // converting UNO value to OLE variant
285 DISPID dispidPut
= DISPID_PROPERTYPUT
;
286 dispparams
.rgdispidNamedArgs
= &dispidPut
;
287 dispparams
.cArgs
= 1;
288 dispparams
.cNamedArgs
= 1;
289 dispparams
.rgvarg
= & varArg
;
291 OSL_ASSERT(aDescPut
|| aVarDesc
);
295 INVOKEKIND invkind
= INVOKE_PROPERTYPUT
;
296 //determine the expected type, dispid, invoke kind (DISPATCH_PROPERTYPUT,
297 //DISPATCH_PROPERTYPUTREF)
300 vt
= getElementTypeDesc(& aDescPut
->lprgelemdescParam
[0].tdesc
);
301 dispid
= aDescPut
->memid
;
302 invkind
= aDescPut
->invkind
;
306 vt
= getElementTypeDesc( & aVarDesc
->elemdescVar
.tdesc
);
307 dispid
= aVarDesc
->memid
;
308 if (vt
== VT_UNKNOWN
|| vt
== VT_DISPATCH
||
309 (vt
& VT_ARRAY
) || (vt
& VT_BYREF
))
311 invkind
= INVOKE_PROPERTYPUTREF
;
315 // convert the uno argument
318 anyToVariant( & varRefArg
, aValue
, ::sal::static_int_cast
< VARTYPE
, int >( vt
^ VT_BYREF
) );
320 if( (vt
& VT_TYPEMASK
) == VT_VARIANT
)
321 varArg
.byref
= & varRefArg
;
322 else if ((vt
& VT_TYPEMASK
) == VT_DECIMAL
)
323 varArg
.byref
= & varRefArg
.decVal
;
325 varArg
.byref
= & varRefArg
.byref
;
329 anyToVariant(& varArg
, aValue
, vt
);
332 hr
= m_spDispatch
->Invoke(dispid
, IID_NULL
, LOCALE_USER_DEFAULT
, ::sal::static_int_cast
< WORD
, INVOKEKIND
>( invkind
),
333 &dispparams
, & varResult
, & excepinfo
, &uArgErr
);
340 case DISP_E_BADPARAMCOUNT
:
341 throw RuntimeException();
343 case DISP_E_BADVARTYPE
:
344 throw RuntimeException();
346 case DISP_E_EXCEPTION
:
347 throw InvocationTargetException();
349 case DISP_E_MEMBERNOTFOUND
:
350 throw UnknownPropertyException();
352 case DISP_E_NONAMEDARGS
:
353 throw RuntimeException();
355 case DISP_E_OVERFLOW
:
356 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
357 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
359 case DISP_E_PARAMNOTFOUND
:
360 throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
361 static_cast<XWeak
*>(this)), ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
)) ;
363 case DISP_E_TYPEMISMATCH
:
364 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
365 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::UNKNOWN
, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
367 case DISP_E_UNKNOWNINTERFACE
:
368 throw RuntimeException();
370 case DISP_E_UNKNOWNLCID
:
371 throw RuntimeException();
373 case DISP_E_PARAMNOTOPTIONAL
:
374 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface
*>(
375 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
378 throw RuntimeException();
382 catch (CannotConvertException
&)
386 catch (UnknownPropertyException
&)
390 catch (BridgeRuntimeError
& e
)
392 throw RuntimeException(
393 e
.message
, Reference
<XInterface
>());
395 catch (Exception
& e
)
397 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
398 "IUnknownWrapper_Impl::setValue ! Message : \n") +
399 e
.Message
, Reference
<XInterface
>());
404 throw RuntimeException(
405 OUSTR("[automation bridge] unexpected exception in "
406 "IUnknownWrapper_Impl::setValue !"), Reference
<XInterface
>());
410 Any SAL_CALL
IUnknownWrapper_Impl::getValue( const OUString
& aPropertyName
)
411 throw(UnknownPropertyException
, RuntimeException
)
413 if ( ! m_spDispatch
)
415 throw RuntimeException(
416 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
417 Reference
<XInterface
>());
422 o2u_attachCurrentThread();
423 ITypeInfo
* pInfo
= getTypeInfo();
424 // I was going to implement an XServiceInfo interface to allow the type
425 // of the automation object to be exposed.. but it seems
426 // from looking at comments in the code that it is possible for
427 // this object to actually wrap an UNO object ( I guess if automation is
428 // used from MSO to create Openoffice objects ) Therefore, those objects
429 // will more than likely already have their own XServiceInfo interface.
430 // Instead here I chose a name that should be illegal both in COM and
431 // UNO ( from an IDL point of view ) therefore I think this is a safe
433 if ( aPropertyName
.equals( rtl::OUString::createFromAscii("$GetTypeName") ))
435 if ( pInfo
&& m_sTypeName
.getLength() == 0 )
437 m_sTypeName
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IDispatch") );
440 if ( SUCCEEDED( pInfo
->GetDocumentation( -1, &sName
, NULL
, NULL
, NULL
) ) )
442 rtl::OUString
sTmp( reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(sName
)));
443 if ( sTmp
.indexOf('_') == 0 )
445 // do we own the memory for pTypeLib, msdn doco is vague
447 CComPtr
< ITypeLib
> pTypeLib
;
449 if ( SUCCEEDED( pInfo
->GetContainingTypeLib( &pTypeLib
.p
, &index
)) )
451 if ( SUCCEEDED( pTypeLib
->GetDocumentation( -1, &sName
, NULL
, NULL
, NULL
) ) )
453 rtl::OUString
sLibName( reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(sName
)));
454 m_sTypeName
= sLibName
.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".") ) ).concat( sTmp
);
464 FuncDesc
aDescGet(pInfo
);
465 FuncDesc
aDescPut(pInfo
);
466 VarDesc
aVarDesc(pInfo
);
467 getPropDesc(aPropertyName
, & aDescGet
, & aDescPut
, & aVarDesc
);
468 if ( ! aDescGet
&& ! aDescPut
&& ! aVarDesc
)
471 OUString
msg(OUSTR("[automation bridge]Property \"") + aPropertyName
+
472 OUSTR("\" is not supported"));
473 throw UnknownPropertyException(msg
, Reference
<XInterface
>());
475 // write-only should not be possible
476 OSL_ASSERT( aDescGet
|| ! aDescPut
);
479 DISPPARAMS dispparams
= {0, 0, 0, 0};
480 CComVariant varResult
;
482 unsigned int uArgErr
;
485 dispid
= aDescGet
->memid
;
487 dispid
= aVarDesc
->memid
;
489 dispid
= aDescPut
->memid
;
491 hr
= m_spDispatch
->Invoke(dispid
,
494 DISPATCH_PROPERTYGET
,
500 // converting return value and out parameter back to UNO
503 // If the com object implements uno interfaces then we have
504 // to convert the attribute into the expected type.
505 TypeDescription attrInfo
;
506 getAttributeInfo(aPropertyName
, attrInfo
);
508 variantToAny( &varResult
, ret
, Type( attrInfo
.get()->pWeakRef
));
510 variantToAny(&varResult
, ret
);
518 case DISP_E_BADPARAMCOUNT
:
519 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
520 Reference
<XInterface
>());
522 case DISP_E_BADVARTYPE
:
523 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
524 Reference
<XInterface
>());
526 case DISP_E_EXCEPTION
:
527 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
528 Reference
<XInterface
>());
530 case DISP_E_MEMBERNOTFOUND
:
531 throw UnknownPropertyException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
532 Reference
<XInterface
>());
534 case DISP_E_NONAMEDARGS
:
535 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
536 Reference
<XInterface
>());
538 case DISP_E_OVERFLOW
:
539 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
540 Reference
<XInterface
>());
542 case DISP_E_PARAMNOTFOUND
:
543 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
544 Reference
<XInterface
>());
546 case DISP_E_TYPEMISMATCH
:
547 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
548 Reference
<XInterface
>());
550 case DISP_E_UNKNOWNINTERFACE
:
551 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
552 Reference
<XInterface
>());
554 case DISP_E_UNKNOWNLCID
:
555 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
556 Reference
<XInterface
>());
558 case DISP_E_PARAMNOTOPTIONAL
:
559 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
560 Reference
<XInterface
>());
563 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
)),
564 Reference
<XInterface
>());
568 catch (UnknownPropertyException
& )
572 catch (BridgeRuntimeError
& e
)
574 throw RuntimeException(
575 e
.message
, Reference
<XInterface
>());
577 catch (Exception
& e
)
579 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
580 "IUnknownWrapper_Impl::getValue ! Message : \n") +
581 e
.Message
, Reference
<XInterface
>());
585 throw RuntimeException(
586 OUSTR("[automation bridge] unexpected exception in "
587 "IUnknownWrapper_Impl::getValue !"), Reference
<XInterface
>());
592 sal_Bool SAL_CALL
IUnknownWrapper_Impl::hasMethod( const OUString
& aName
)
593 throw(RuntimeException
)
595 if ( ! m_spDispatch
)
597 throw RuntimeException(
598 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
599 Reference
<XInterface
>());
601 sal_Bool ret
= sal_False
;
605 o2u_attachCurrentThread();
606 ITypeInfo
* pInfo
= getTypeInfo();
607 FuncDesc
aDesc(pInfo
);
608 getFuncDesc(aName
, & aDesc
);
609 // Automation properties can have arguments. Those are treated as methods and
610 //are called through XInvocation::invoke.
613 FuncDesc
aDescGet(pInfo
);
614 FuncDesc
aDescPut(pInfo
);
615 VarDesc
aVarDesc(pInfo
);
616 getPropDesc( aName
, & aDescGet
, & aDescPut
, & aVarDesc
);
617 if (aDescGet
&& aDescGet
->cParams
> 0
618 || aDescPut
&& aDescPut
->cParams
> 0)
624 catch (BridgeRuntimeError
& e
)
626 throw RuntimeException(e
.message
, Reference
<XInterface
>());
628 catch (Exception
& e
)
630 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
631 "IUnknownWrapper_Impl::hasMethod ! Message : \n") +
632 e
.Message
, Reference
<XInterface
>());
636 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
637 "IUnknownWrapper_Impl::hasMethod !"), Reference
<XInterface
>());;
642 sal_Bool SAL_CALL
IUnknownWrapper_Impl::hasProperty( const OUString
& aName
)
643 throw(RuntimeException
)
645 if ( ! m_spDispatch
)
647 throw RuntimeException(OUSTR("[automation bridge] The object does not have an "
648 "IDispatch interface"), Reference
<XInterface
>());
651 sal_Bool ret
= sal_False
;
654 o2u_attachCurrentThread();
656 ITypeInfo
* pInfo
= getTypeInfo();
657 FuncDesc
aDescGet(pInfo
);
658 FuncDesc
aDescPut(pInfo
);
659 VarDesc
aVarDesc(pInfo
);
660 getPropDesc(aName
, & aDescGet
, & aDescPut
, & aVarDesc
);
661 // Automation properties can have parameters. If so, we access them through
662 // XInvocation::invoke. Thas is, hasProperty must return false for such a
665 || aDescPut
&& aDescPut
->cParams
== 0
666 || aDescGet
&& aDescGet
->cParams
== 0)
671 catch (BridgeRuntimeError
& e
)
673 throw RuntimeException(e
.message
, Reference
<XInterface
>());
675 catch (Exception
& e
)
677 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
678 "IUnknownWrapper_Impl::hasProperty ! Message : \n") +
679 e
.Message
, Reference
<XInterface
>());
684 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
685 "IUnknownWrapper_Impl::hasProperty !"), Reference
<XInterface
>());
690 Any SAL_CALL
IUnknownWrapper_Impl::createBridge( const Any
& modelDepObject
,
691 const Sequence
< sal_Int8
>& /*aProcessId*/, sal_Int16 sourceModelType
,
692 sal_Int16 destModelType
)
693 throw( IllegalArgumentException
, RuntimeException
)
696 o2u_attachCurrentThread();
699 (sourceModelType
== UNO
) &&
700 (destModelType
== OLE
) &&
701 (modelDepObject
.getValueTypeClass() == TypeClass_INTERFACE
)
704 Reference
<XInterface
> xInt( *(XInterface
**) modelDepObject
.getValue());
705 Reference
<XInterface
> xSelf( (OWeakObject
*)this);
709 VARIANT
* pVariant
= (VARIANT
*) CoTaskMemAlloc(sizeof(VARIANT
));
711 VariantInit(pVariant
);
712 if (m_bOriginalDispatch
== sal_True
)
714 pVariant
->vt
= VT_DISPATCH
;
715 pVariant
->pdispVal
= m_spDispatch
;
716 pVariant
->pdispVal
->AddRef();
720 pVariant
->vt
= VT_UNKNOWN
;
721 pVariant
->punkVal
= m_spUnknown
;
722 pVariant
->punkVal
->AddRef();
725 ret
.setValue((void*)&pVariant
, getCppuType( (sal_uInt32
*) 0));
732 @exception IllegalArgumentException
733 @exception CannotConvertException
734 @exception InvocationTargetException
737 Any
IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString
& sFunctionName
,
738 const Sequence
< Any
>& Params
,
739 Sequence
< sal_Int16
>& OutParamIndex
,
740 Sequence
< Any
>& OutParam
)
745 sal_Int32 parameterCount
= Params
.getLength();
746 sal_Int32 outParameterCount
= 0;
747 typelib_InterfaceMethodTypeDescription
* pMethod
= NULL
;
748 TypeDescription methodDesc
;
749 getMethodInfo(sFunctionName
, methodDesc
);
751 // We need to know whether the IDispatch is from a JScript object.
752 // Then out and in/out parameters have to be treated differently than
753 // with common COM objects.
754 sal_Bool bJScriptObject
= isJScriptObject();
755 scoped_array
<CComVariant
> sarParams
;
756 scoped_array
<CComVariant
> sarParamsRef
;
757 CComVariant
*pVarParams
= NULL
;
758 CComVariant
*pVarParamsRef
= NULL
;
759 sal_Bool bConvRet
= sal_True
;
763 pMethod
= (typelib_InterfaceMethodTypeDescription
* )methodDesc
.get();
764 parameterCount
= pMethod
->nParams
;
765 // Create the Array for the array being passed in DISPPARAMS
766 // the array also contains the outparameter (but not the values)
767 if( pMethod
->nParams
> 0)
769 sarParams
.reset(new CComVariant
[ parameterCount
]);
770 pVarParams
= sarParams
.get();
773 // Create the Array for the out an in/out parameter. These values
774 // are referenced by the VT_BYREF VARIANTs in DISPPARAMS.
775 // We need to find out the number of out and in/out parameter.
776 for( sal_Int32 i
=0; i
< parameterCount
; i
++)
778 if( pMethod
->pParams
[i
].bOut
)
784 sarParamsRef
.reset(new CComVariant
[outParameterCount
]);
785 pVarParamsRef
= sarParamsRef
.get();
786 // build up the parameters for IDispatch::Invoke
787 sal_Int32 outParamIndex
=0;
791 for( i
= 0; i
< parameterCount
; i
++)
794 if( pMethod
->pParams
[i
].bIn
== sal_True
&& ! pMethod
->pParams
[i
].bOut
)
796 anyToVariant( &pVarParams
[parameterCount
- i
-1], Params
.getConstArray()[i
]);
798 // Out parameter + in/out parameter
799 else if( pMethod
->pParams
[i
].bOut
== sal_True
)
802 if(pMethod
->pParams
[i
].bIn
)
804 anyToVariant( & var
,Params
[i
]);
805 pVarParamsRef
[outParamIndex
] = var
;
808 switch( pMethod
->pParams
[i
].pTypeRef
->eTypeClass
)
810 case TypeClass_INTERFACE
:
811 case TypeClass_STRUCT
:
812 if( ! pMethod
->pParams
[i
].bIn
)
814 pVarParamsRef
[ outParamIndex
].vt
= VT_DISPATCH
;
815 pVarParamsRef
[ outParamIndex
].pdispVal
= 0;
817 pVarParams
[parameterCount
- i
-1].vt
= VT_DISPATCH
| VT_BYREF
;
818 pVarParams
[parameterCount
- i
-1].ppdispVal
= &pVarParamsRef
[outParamIndex
].pdispVal
;
822 case TypeClass_UNSIGNED_LONG
:
823 if( ! pMethod
->pParams
[i
].bIn
)
825 pVarParamsRef
[ outParamIndex
].vt
= VT_I4
;
826 pVarParamsRef
[ outParamIndex
].lVal
= 0;
828 pVarParams
[parameterCount
- i
-1].vt
= VT_I4
| VT_BYREF
;
829 pVarParams
[parameterCount
- i
-1].plVal
= &pVarParamsRef
[outParamIndex
].lVal
;
831 case TypeClass_SEQUENCE
:
832 if( ! pMethod
->pParams
[i
].bIn
)
834 pVarParamsRef
[ outParamIndex
].vt
= VT_ARRAY
| VT_VARIANT
;
835 pVarParamsRef
[ outParamIndex
].parray
= NULL
;
837 pVarParams
[parameterCount
- i
-1].vt
= VT_ARRAY
| VT_BYREF
| VT_VARIANT
;
838 pVarParams
[parameterCount
- i
-1].pparray
= &pVarParamsRef
[outParamIndex
].parray
;
841 if( ! pMethod
->pParams
[i
].bIn
)
843 pVarParamsRef
[ outParamIndex
].vt
= VT_EMPTY
;
844 pVarParamsRef
[ outParamIndex
].lVal
= 0;
846 pVarParams
[parameterCount
- i
-1].vt
= VT_VARIANT
| VT_BYREF
;
847 pVarParams
[parameterCount
- i
-1].pvarVal
= &pVarParamsRef
[outParamIndex
];
849 case TypeClass_BOOLEAN
:
850 if( ! pMethod
->pParams
[i
].bIn
)
852 pVarParamsRef
[ outParamIndex
].vt
= VT_BOOL
;
853 pVarParamsRef
[ outParamIndex
].boolVal
= 0;
855 pVarParams
[parameterCount
- i
-1].vt
= VT_BOOL
| VT_BYREF
;
856 pVarParams
[parameterCount
- i
-1].pboolVal
=
857 & pVarParamsRef
[outParamIndex
].boolVal
;
860 case TypeClass_STRING
:
861 if( ! pMethod
->pParams
[i
].bIn
)
863 pVarParamsRef
[ outParamIndex
].vt
= VT_BSTR
;
864 pVarParamsRef
[ outParamIndex
].bstrVal
= 0;
866 pVarParams
[parameterCount
- i
-1].vt
= VT_BSTR
| VT_BYREF
;
867 pVarParams
[parameterCount
- i
-1].pbstrVal
=
868 & pVarParamsRef
[outParamIndex
].bstrVal
;
871 case TypeClass_FLOAT
:
872 if( ! pMethod
->pParams
[i
].bIn
)
874 pVarParamsRef
[ outParamIndex
].vt
= VT_R4
;
875 pVarParamsRef
[ outParamIndex
].fltVal
= 0;
877 pVarParams
[parameterCount
- i
-1].vt
= VT_R4
| VT_BYREF
;
878 pVarParams
[parameterCount
- i
-1].pfltVal
=
879 & pVarParamsRef
[outParamIndex
].fltVal
;
881 case TypeClass_DOUBLE
:
882 if( ! pMethod
->pParams
[i
].bIn
)
884 pVarParamsRef
[ outParamIndex
].vt
= VT_R8
;
885 pVarParamsRef
[ outParamIndex
].dblVal
= 0;
887 pVarParams
[parameterCount
- i
-1].vt
= VT_R8
| VT_BYREF
;
888 pVarParams
[parameterCount
- i
-1].pdblVal
=
889 & pVarParamsRef
[outParamIndex
].dblVal
;
892 if( ! pMethod
->pParams
[i
].bIn
)
894 pVarParamsRef
[ outParamIndex
].vt
= VT_UI1
;
895 pVarParamsRef
[ outParamIndex
].bVal
= 0;
897 pVarParams
[parameterCount
- i
-1].vt
= VT_UI1
| VT_BYREF
;
898 pVarParams
[parameterCount
- i
-1].pbVal
=
899 & pVarParamsRef
[outParamIndex
].bVal
;
902 case TypeClass_SHORT
:
903 case TypeClass_UNSIGNED_SHORT
:
904 if( ! pMethod
->pParams
[i
].bIn
)
906 pVarParamsRef
[ outParamIndex
].vt
= VT_I2
;
907 pVarParamsRef
[ outParamIndex
].iVal
= 0;
909 pVarParams
[parameterCount
- i
-1].vt
= VT_I2
| VT_BYREF
;
910 pVarParams
[parameterCount
- i
-1].piVal
=
911 & pVarParamsRef
[outParamIndex
].iVal
;
915 if( ! pMethod
->pParams
[i
].bIn
)
917 pVarParamsRef
[ outParamIndex
].vt
= VT_EMPTY
;
918 pVarParamsRef
[ outParamIndex
].lVal
= 0;
920 pVarParams
[parameterCount
- i
-1].vt
= VT_VARIANT
| VT_BYREF
;
921 pVarParams
[parameterCount
- i
-1].pvarVal
=
922 & pVarParamsRef
[outParamIndex
];
928 catch (IllegalArgumentException
& e
)
930 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
933 catch (CannotConvertException
& e
)
939 else // it is an JScriptObject
944 for( ; i
< parameterCount
; i
++)
947 if( pMethod
->pParams
[i
].bIn
== sal_True
&& ! pMethod
->pParams
[i
].bOut
)
949 anyToVariant( &pVarParams
[parameterCount
- i
-1], Params
.getConstArray()[i
]);
951 // Out parameter + in/out parameter
952 else if( pMethod
->pParams
[i
].bOut
== sal_True
)
954 CComObject
<JScriptOutParam
>* pParamObject
;
955 if( SUCCEEDED( CComObject
<JScriptOutParam
>::CreateInstance( &pParamObject
)))
957 CComPtr
<IUnknown
> pUnk(pParamObject
->GetUnknown());
959 CComQIPtr
<IDispatch
, &__uuidof(IDispatch
)> pDisp( pUnk
);
961 CComQIPtr
<IDispatch
> pDisp( pUnk
);
964 pVarParams
[ parameterCount
- i
-1].vt
= VT_DISPATCH
;
965 pVarParams
[ parameterCount
- i
-1].pdispVal
= pDisp
;
966 pVarParams
[ parameterCount
- i
-1].pdispVal
->AddRef();
967 // if the param is in/out then put the parameter on index 0
968 if( pMethod
->pParams
[i
].bIn
== sal_True
) // in / out
970 CComVariant varParam
;
971 anyToVariant( &varParam
, Params
.getConstArray()[i
]);
972 CComDispatchDriver
dispDriver( pDisp
);
973 if(FAILED( dispDriver
.PutPropertyByName( L
"0", &varParam
)))
974 throw BridgeRuntimeError(
975 OUSTR("[automation bridge]IUnknownWrapper_Impl::"
976 "invokeWithDispIdUnoTlb\n"
977 "Could not set property \"0\" for the in/out "
984 throw BridgeRuntimeError(
985 OUSTR("[automation bridge]IUnknownWrapper_Impl::"
986 "invokeWithDispIdUnoTlb\n"
987 "Could not create out parameter at index: ") +
988 OUString::valueOf((sal_Int32
) i
));
994 catch (IllegalArgumentException
& e
)
996 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
999 catch (CannotConvertException
& e
)
1001 e
.ArgumentIndex
= i
;
1006 // No type description Available, that is we have to deal with a COM component,
1007 // that does not implements UNO interfaces ( IDispatch based)
1010 //We should not run into this block, because invokeWithDispIdComTlb should
1011 //have been called instead.
1016 CComVariant varResult
;
1017 ExcepInfo excepinfo
;
1018 unsigned int uArgErr
;
1019 DISPPARAMS dispparams
= { pVarParams
, NULL
, parameterCount
, 0};
1021 FuncDesc
aDesc(getTypeInfo());
1022 getFuncDesc(sFunctionName
, & aDesc
);
1023 // invoking OLE method
1024 hr
= m_spDispatch
->Invoke(aDesc
->memid
,
1026 LOCALE_USER_DEFAULT
,
1033 // converting return value and out parameter back to UNO
1036 if( outParameterCount
&& pMethod
)
1038 OutParamIndex
.realloc( outParameterCount
);
1039 OutParam
.realloc( outParameterCount
);
1040 sal_Int32 outIndex
=0;
1044 for( ; i
< parameterCount
; i
++)
1046 if( pMethod
->pParams
[i
].bOut
)
1048 OutParamIndex
[outIndex
]= (sal_Int16
) i
;
1050 if( !bJScriptObject
)
1052 variantToAny( &pVarParamsRef
[outIndex
], outAny
,
1053 Type(pMethod
->pParams
[i
].pTypeRef
), sal_False
);
1054 OutParam
[outIndex
++]= outAny
;
1056 else //JScriptObject
1058 if( pVarParams
[i
].vt
== VT_DISPATCH
)
1060 CComDispatchDriver
pDisp( pVarParams
[i
].pdispVal
);
1064 if( SUCCEEDED( pDisp
.GetPropertyByName( L
"0", &varOut
)))
1066 variantToAny( &varOut
, outAny
,
1067 Type(pMethod
->pParams
[parameterCount
- 1 - i
].pTypeRef
), sal_False
);
1068 OutParam
[outParameterCount
- 1 - outIndex
++]= outAny
;
1071 bConvRet
= sal_False
;
1074 bConvRet
= sal_False
;
1077 bConvRet
= sal_False
;
1080 if( !bConvRet
) break;
1083 catch(IllegalArgumentException
& e
)
1085 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, int >( i
);
1088 catch(CannotConvertException
& e
)
1090 e
.ArgumentIndex
= i
;
1094 // return value, no type information available
1100 variantToAny(&varResult
, ret
, Type( pMethod
->pReturnTypeRef
), sal_False
);
1102 variantToAny(&varResult
, ret
, sal_False
);
1104 catch (IllegalArgumentException
& e
)
1107 OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1108 "Could not convert return value! \n Message: \n") + e
.Message
;
1111 catch (CannotConvertException
& e
)
1114 OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1115 "Could not convert return value! \n Message: \n") + e
.Message
;
1121 if( !bConvRet
) // conversion of return or out parameter failed
1122 throw CannotConvertException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Call to COM object failed. Conversion of return or out value failed")),
1123 Reference
<XInterface
>( static_cast<XWeak
*>(this), UNO_QUERY
), TypeClass_UNKNOWN
,
1124 FailReason::UNKNOWN
, 0);// lookup error code
1125 // conversion of return or out parameter failed
1130 case DISP_E_BADPARAMCOUNT
:
1131 throw IllegalArgumentException();
1133 case DISP_E_BADVARTYPE
:
1134 throw RuntimeException();
1136 case DISP_E_EXCEPTION
:
1137 throw InvocationTargetException();
1139 case DISP_E_MEMBERNOTFOUND
:
1140 throw IllegalArgumentException();
1142 case DISP_E_NONAMEDARGS
:
1143 throw IllegalArgumentException();
1145 case DISP_E_OVERFLOW
:
1146 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
1147 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
1149 case DISP_E_PARAMNOTFOUND
:
1150 throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
1151 static_cast<XWeak
*>(this)), ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1153 case DISP_E_TYPEMISMATCH
:
1154 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface
*>(
1155 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::UNKNOWN
, uArgErr
);
1157 case DISP_E_UNKNOWNINTERFACE
:
1158 throw RuntimeException() ;
1160 case DISP_E_UNKNOWNLCID
:
1161 throw RuntimeException() ;
1163 case DISP_E_PARAMNOTOPTIONAL
:
1164 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface
*>(
1165 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
1168 throw RuntimeException();
1177 // --------------------------
1179 void SAL_CALL
IUnknownWrapper_Impl::initialize( const Sequence
< Any
>& aArguments
) throw(Exception
, RuntimeException
)
1181 // 1.parameter is IUnknown
1182 // 2.parameter is a boolean which indicates if the the COM pointer was a IUnknown or IDispatch
1183 // 3.parameter is a Sequence<Type>
1184 o2u_attachCurrentThread();
1185 OSL_ASSERT(aArguments
.getLength() == 3);
1187 m_spUnknown
= *(IUnknown
**) aArguments
[0].getValue();
1189 m_spUnknown
->QueryInterface(IID_IDispatch
, reinterpret_cast<LPVOID
*>( & m_spDispatch
.p
));
1191 m_spUnknown
.QueryInterface( & m_spDispatch
.p
);
1194 aArguments
[1] >>= m_bOriginalDispatch
;
1195 aArguments
[2] >>= m_seqTypes
;
1197 ITypeInfo
* pType
= NULL
;
1200 // a COM object implementation that has no TypeInfo is still a legal COM object;
1201 // such objects can at least be transported through UNO using the bridge
1202 // so we should allow to create wrappers for them as well
1203 pType
= getTypeInfo();
1205 catch( BridgeRuntimeError
& )
1214 // Get Default member
1215 CComBSTR defaultMemberName
;
1216 if ( SUCCEEDED( pType
->GetDocumentation(0, &defaultMemberName
, 0, 0, 0 ) ) )
1218 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(defaultMemberName
)));
1219 FuncDesc
aDescGet(pType
);
1220 FuncDesc
aDescPut(pType
);
1221 VarDesc
aVarDesc(pType
);
1222 // see if this is a property first ( more likely to be a property then a method )
1223 getPropDesc( usName
, & aDescGet
, & aDescPut
, & aVarDesc
);
1225 if ( !aDescGet
&& !aDescPut
)
1227 getFuncDesc( usName
, &aDescGet
);
1229 throw BridgeRuntimeError( OUSTR("[automation bridge]IUnknownWrapper_Impl::initialize() Failed to get Function or Property desc. for " ) + usName
);
1231 // now for some funny heuristics to make basic understand what to do
1232 // a single aDescGet ( that doesn't take any params ) would be
1233 // a read only ( defaultmember ) property e.g. this object
1234 // should implement XDefaultProperty
1235 // a single aDescGet ( that *does* ) take params is basically a
1236 // default method e.g. implement XDefaultMethod
1238 // 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 )
1239 if ( aDescPut
|| ( aDescGet
&& aDescGet
->cParams
== 0 ) )
1240 m_bHasDfltProperty
= true;
1241 if ( aDescGet
->cParams
> 0 )
1242 m_bHasDfltMethod
= true;
1243 if ( m_bHasDfltProperty
|| m_bHasDfltMethod
)
1244 m_sDefaultMember
= usName
;
1247 catch ( BridgeRuntimeError
& e
)
1249 throw RuntimeException( e
.message
, Reference
<XInterface
>() );
1251 catch( Exception
& e
)
1253 throw RuntimeException(
1254 OUSTR("[automation bridge] unexpected exception in IUnknownWrapper_Impl::initialiase() error message: \n") + e
.Message
,
1255 Reference
<XInterface
>() );
1260 // UnoConversionUtilities --------------------------------------------------------------------------------
1261 Reference
< XInterface
> IUnknownWrapper_Impl::createUnoWrapperInstance()
1263 if( m_nUnoWrapperClass
== INTERFACE_OLE_WRAPPER_IMPL
)
1265 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new InterfaceOleWrapper_Impl(
1266 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1267 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1269 else if( m_nUnoWrapperClass
== UNO_OBJECT_WRAPPER_REMOTE_OPT
)
1271 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new UnoObjectWrapperRemoteOpt(
1272 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1273 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1276 return Reference
<XInterface
>();
1278 Reference
<XInterface
> IUnknownWrapper_Impl::createComWrapperInstance()
1280 Reference
<XWeak
> xWeak
= static_cast<XWeak
*>( new IUnknownWrapper_Impl(
1281 m_smgr
, m_nUnoWrapperClass
, m_nComWrapperClass
));
1282 return Reference
<XInterface
>( xWeak
, UNO_QUERY
);
1287 void IUnknownWrapper_Impl::getMethodInfo(const OUString
& sName
, TypeDescription
& methodInfo
)
1289 TypeDescription desc
= getInterfaceMemberDescOfCurrentCall(sName
);
1292 typelib_TypeDescription
* pMember
= desc
.get();
1293 if( pMember
->eTypeClass
== TypeClass_INTERFACE_METHOD
)
1294 methodInfo
= pMember
;
1298 void IUnknownWrapper_Impl::getAttributeInfo(const OUString
& sName
, TypeDescription
& attributeInfo
)
1300 TypeDescription desc
= getInterfaceMemberDescOfCurrentCall(sName
);
1303 typelib_TypeDescription
* pMember
= desc
.get();
1304 if( pMember
->eTypeClass
== TypeClass_INTERFACE_ATTRIBUTE
)
1306 attributeInfo
= ((typelib_InterfaceAttributeTypeDescription
*)pMember
)->pAttributeTypeRef
;
1310 TypeDescription
IUnknownWrapper_Impl::getInterfaceMemberDescOfCurrentCall(const OUString
& sName
)
1312 TypeDescription ret
;
1314 for( sal_Int32 i
=0; i
< m_seqTypes
.getLength(); i
++)
1316 TypeDescription
_curDesc( m_seqTypes
[i
]);
1317 _curDesc
.makeComplete();
1318 typelib_InterfaceTypeDescription
* pInterface
= (typelib_InterfaceTypeDescription
*) _curDesc
.get();
1321 typelib_InterfaceMemberTypeDescription
* pMember
= NULL
;
1322 //find the member description of the current call
1323 for( int i
=0; i
< pInterface
->nAllMembers
; i
++)
1325 typelib_TypeDescriptionReference
* pTypeRefMember
= pInterface
->ppAllMembers
[i
];
1326 typelib_TypeDescription
* pDescMember
= NULL
;
1327 TYPELIB_DANGER_GET( &pDescMember
, pTypeRefMember
)
1329 typelib_InterfaceMemberTypeDescription
* pInterfaceMember
=
1330 (typelib_InterfaceMemberTypeDescription
*) pDescMember
;
1331 if( OUString( pInterfaceMember
->pMemberName
) == sName
)
1333 pMember
= pInterfaceMember
;
1336 TYPELIB_DANGER_RELEASE( pDescMember
)
1341 ret
= (typelib_TypeDescription
*)pMember
;
1342 TYPELIB_DANGER_RELEASE( (typelib_TypeDescription
*)pMember
);
1351 sal_Bool
IUnknownWrapper_Impl::isJScriptObject()
1353 if( m_eJScript
== JScriptUndefined
)
1355 CComDispatchDriver
disp( m_spDispatch
);
1359 if( SUCCEEDED( disp
.GetPropertyByName( JSCRIPT_ID_PROPERTY
, &result
)))
1361 if(result
.vt
== VT_BSTR
)
1363 CComBSTR
name( result
.bstrVal
);
1365 if( name
== CComBSTR(JSCRIPT_ID
))
1366 m_eJScript
= IsJScript
;
1370 if( m_eJScript
== JScriptUndefined
)
1371 m_eJScript
= NoJScript
;
1374 return m_eJScript
== NoJScript
? sal_False
: sal_True
;
1380 The function ultimately calls IDispatch::Invoke on the wrapped COM object.
1381 The COM object does not implement UNO Interfaces ( via IDispatch). This
1382 is the case when the OleObjectFactory service has been used to create a
1384 @exception IllegalArgumentException
1385 @exception CannotConvertException
1386 @InvocationTargetException
1390 Any
IUnknownWrapper_Impl::invokeWithDispIdComTlb(const OUString
& sFuncName
,
1391 const Sequence
< Any
>& Params
,
1392 Sequence
< sal_Int16
>& OutParamIndex
,
1393 Sequence
< Any
>& OutParam
)
1398 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
1399 CComVariant varResult
;
1400 ExcepInfo excepinfo
;
1401 unsigned int uArgErr
;
1403 sal_Int32 nUnoArgs
= Params
.getLength();
1404 DISPID idPropertyPut
= DISPID_PROPERTYPUT
;
1405 scoped_array
<DISPID
> arDispidNamedArgs
;
1406 scoped_array
<CComVariant
> ptrArgs
;
1407 scoped_array
<CComVariant
> ptrRefArgs
; // referenced arguments
1408 CComVariant
* arArgs
= NULL
;
1409 CComVariant
* arRefArgs
= NULL
;
1410 sal_Int32 revIndex
= 0;
1411 bool bVarargParam
= false;
1413 // Get type info for the call. It can be a method call or property put or
1414 // property get operation.
1415 FuncDesc
aFuncDesc(getTypeInfo());
1416 getFuncDescForInvoke(sFuncName
, Params
, & aFuncDesc
);
1418 //Set the array of DISPIDs for named args if it is a property put operation.
1419 //If there are other named arguments another array is set later on.
1420 if (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
1421 || aFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
1422 dispparams
.rgdispidNamedArgs
= & idPropertyPut
;
1424 //Determine the number of named arguments
1425 for (int iParam
= 0; iParam
< nUnoArgs
; iParam
++)
1427 const Any
& curArg
= Params
[iParam
];
1428 if (curArg
.getValueType() == getCppuType((NamedArgument
*) 0))
1429 dispparams
.cNamedArgs
++;
1431 //In a property put operation a property value is a named argument (DISPID_PROPERTYPUT).
1432 //Therefore the number of named arguments is increased by one.
1433 //Although named, the argument is not named in a actual language, such as Basic,
1434 //therefore it is never a com.sun.star.bridge.oleautomation.NamedArgument
1435 if (aFuncDesc
->invkind
== DISPATCH_PROPERTYPUT
1436 || aFuncDesc
->invkind
== DISPATCH_PROPERTYPUTREF
)
1437 dispparams
.cNamedArgs
++;
1439 //Determine the number of all arguments and named arguments
1440 if (aFuncDesc
->cParamsOpt
== -1)
1442 //Attribute vararg is set on this method. "Unlimited" number of args
1443 //supported. There can be no optional or defaultvalue on any of the arguments.
1444 dispparams
.cArgs
= nUnoArgs
;
1448 //If there are namesd arguments, then the dispparams.cArgs
1449 //is the number of supplied args, otherwise it is the expected number.
1450 if (dispparams
.cNamedArgs
)
1451 dispparams
.cArgs
= nUnoArgs
;
1453 dispparams
.cArgs
= aFuncDesc
->cParams
;
1456 //check if there are not to many arguments supplied
1457 if (::sal::static_int_cast
< sal_uInt32
, int >( nUnoArgs
) > dispparams
.cArgs
)
1459 OUStringBuffer
buf(256);
1460 buf
.appendAscii("[automation bridge] There are too many arguments for this method");
1461 throw IllegalArgumentException( buf
.makeStringAndClear(),
1462 Reference
<XInterface
>(), (sal_Int16
) dispparams
.cArgs
);
1465 //Set up the array of DISPIDs (DISPPARAMS::rgdispidNamedArgs)
1466 //for the named arguments.
1467 //If there is only one named arg and if it is because of a property put
1468 //operation, then we need not set up the DISPID array.
1469 if (dispparams
.cNamedArgs
> 0 &&
1470 ! (dispparams
.cNamedArgs
== 1 &&
1471 (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
||
1472 aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
)))
1474 //set up an array containing the member and parameter names
1475 //which is then used in ITypeInfo::GetIDsOfNames
1476 //First determine the size of the array of names which is passed to
1477 //ITypeInfo::GetIDsOfNames. It must hold the method names + the named
1479 int nSizeAr
= dispparams
.cNamedArgs
+ 1;
1480 if (aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
1481 || aFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
1483 nSizeAr
= dispparams
.cNamedArgs
; //counts the DISID_PROPERTYPUT
1486 scoped_array
<OLECHAR
*> saNames(new OLECHAR
*[nSizeAr
]);
1487 OLECHAR
** arNames
= saNames
.get();
1488 arNames
[0] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(sFuncName
.getStr()));
1491 for (size_t iParams
= 0; iParams
< dispparams
.cArgs
; iParams
++)
1493 const Any
& curArg
= Params
[iParams
];
1494 if (curArg
.getValueType() == getCppuType((NamedArgument
*) 0))
1496 const NamedArgument
& arg
= *(NamedArgument
const*) curArg
.getValue();
1497 //We put the parameter names in reverse order into the array,
1498 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1499 //The first name in the array is the method name
1500 arNames
[nSizeAr
- 1 - cNamedArg
++] = const_cast<OLECHAR
*>(reinterpret_cast<LPCOLESTR
>(arg
.Name
.getStr()));
1504 //Prepare the array of DISPIDs for ITypeInfo::GetIDsOfNames
1505 //it must be big enough to contain the DISPIDs of the member + parameters
1506 arDispidNamedArgs
.reset(new DISPID
[nSizeAr
]);
1507 HRESULT hr
= getTypeInfo()->GetIDsOfNames(arNames
, nSizeAr
,
1508 arDispidNamedArgs
.get());
1509 if ( hr
== E_NOTIMPL
)
1510 hr
= m_spDispatch
->GetIDsOfNames(IID_NULL
, arNames
, nSizeAr
, LOCALE_USER_DEFAULT
, arDispidNamedArgs
.get() );
1514 // In a "property put" operation, the property value is a named param with the
1515 //special DISPID DISPID_PROPERTYPUT
1516 if (aFuncDesc
->invkind
== DISPATCH_PROPERTYPUT
1517 || aFuncDesc
->invkind
== DISPATCH_PROPERTYPUTREF
)
1519 //Element at index 0 in the DISPID array must be DISPID_PROPERTYPUT
1520 //The first item in the array arDispidNamedArgs is the DISPID for
1521 //the method. We replace it with DISPID_PROPERTYPUT.
1522 DISPID
* arIDs
= arDispidNamedArgs
.get();
1523 arIDs
[0] = DISPID_PROPERTYPUT
;
1524 dispparams
.rgdispidNamedArgs
= arIDs
;
1528 //The first item in the array arDispidNamedArgs is the DISPID for
1529 //the method. It must be removed
1530 DISPID
* arIDs
= arDispidNamedArgs
.get();
1531 dispparams
.rgdispidNamedArgs
= & arIDs
[1];
1534 else if (hr
== DISP_E_UNKNOWNNAME
)
1536 throw IllegalArgumentException(
1537 OUSTR("[automation bridge]One of the named arguments is wrong!"),
1538 Reference
<XInterface
>(), 0);
1542 throw InvocationTargetException(
1543 OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ")
1544 + OUString::valueOf((sal_Int32
) hr
, 16), Reference
<XInterface
>(), Any());
1549 ptrArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1550 ptrRefArgs
.reset(new CComVariant
[dispparams
.cArgs
]);
1551 arArgs
= ptrArgs
.get();
1552 arRefArgs
= ptrRefArgs
.get();
1555 for (i
= 0; i
< (sal_Int32
) dispparams
.cArgs
; i
++)
1557 revIndex
= dispparams
.cArgs
- i
-1;
1558 arRefArgs
[revIndex
].byref
=0;
1561 anyArg
= Params
.getConstArray()[i
];
1563 //Test if the current parameter is a "vararg" parameter.
1564 if (bVarargParam
|| (aFuncDesc
->cParamsOpt
== -1 &&
1565 aFuncDesc
->cParams
== (i
+ 1)))
1566 { //This parameter is from the variable argument list. There is no
1567 //type info available, except that it must be a VARIANT
1568 bVarargParam
= true;
1571 unsigned short paramFlags
= PARAMFLAG_FOPT
| PARAMFLAG_FIN
;
1572 VARTYPE varType
= VT_VARIANT
;
1573 if ( ! bVarargParam
)
1576 aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
1577 varType
= getElementTypeDesc(
1578 & aFuncDesc
->lprgelemdescParam
[i
].tdesc
);
1580 //Make sure that there is a UNO parameter for every
1581 // expected parameter. If there is no UNO parameter where the
1582 // called function expects one, then it must be optional. Otherwise
1583 // its a UNO programming error.
1584 if (i
>= nUnoArgs
&& !(paramFlags
& PARAMFLAG_FOPT
))
1586 OUStringBuffer
buf(256);
1587 buf
.appendAscii("ole automation bridge: The called function expects an argument at"
1588 "position: "); //a different number of arguments")),
1589 buf
.append(OUString::valueOf((sal_Int32
) i
));
1590 buf
.appendAscii(" (index starting at 0).");
1591 throw IllegalArgumentException( buf
.makeStringAndClear(),
1592 Reference
<XInterface
>(), (sal_Int16
) i
);
1594 //make sure we get no void any for an in parameter. In StarBasic
1595 //this may be caused by
1598 //A void any is allowed if the parameter is optional
1599 if ( ! (aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
& PARAMFLAG_FOPT
)
1600 && (i
< nUnoArgs
) && (paramFlags
& PARAMFLAG_FIN
) &&
1601 Params
.getConstArray()[i
].getValueTypeClass() == TypeClass_VOID
)
1603 OUStringBuffer
buf(256);
1604 buf
.appendAscii("ole automation bridge: The argument at position: ");
1605 buf
.append(OUString::valueOf((sal_Int32
) i
));
1606 buf
.appendAscii(" (index starts with 0) is uninitialized.");
1607 throw IllegalArgumentException( buf
.makeStringAndClear(),
1608 Reference
<XInterface
>(), (sal_Int16
) i
);
1611 // Property Put arguments
1612 if (anyArg
.getValueType() == getCppuType((PropertyPutArgument
*)0))
1614 PropertyPutArgument arg
;
1616 anyArg
<<= arg
.Value
;
1619 if (anyArg
.getValueType() == getCppuType((NamedArgument
*) 0))
1621 NamedArgument aNamedArgument
;
1622 anyArg
>>= aNamedArgument
;
1623 anyArg
<<= aNamedArgument
.Value
;
1626 if (paramFlags
& PARAMFLAG_FOUT
&&
1627 ! (paramFlags
& PARAMFLAG_FIN
) )
1629 VARTYPE type
= ::sal::static_int_cast
< VARTYPE
, int >( varType
^ VT_BYREF
);
1632 arRefArgs
[revIndex
].vt
= type
;
1637 arRefArgs
[revIndex
].vt
= VT_ERROR
;
1638 arRefArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1640 if( type
== VT_VARIANT
)
1642 arArgs
[revIndex
].vt
= VT_VARIANT
| VT_BYREF
;
1643 arArgs
[revIndex
].byref
= &arRefArgs
[revIndex
];
1647 arArgs
[revIndex
].vt
= varType
;
1648 if (type
== VT_DECIMAL
)
1649 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].decVal
;
1651 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].byref
;
1654 // in/out + in byref params
1655 else if (varType
& VT_BYREF
)
1657 VARTYPE type
= ::sal::static_int_cast
< VARTYPE
, int >( varType
^ VT_BYREF
);
1660 if (i
< nUnoArgs
&& anyArg
.getValueTypeClass() != TypeClass_VOID
)
1662 anyToVariant( & arRefArgs
[revIndex
], anyArg
, type
);
1664 else if (paramFlags
& PARAMFLAG_FHASDEFAULT
)
1666 //optional arg with default
1667 VariantCopy( & arRefArgs
[revIndex
],
1668 & aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.
1669 pparamdescex
->varDefaultValue
);
1674 //e.g: call func(x) in basic : func() ' no arg supplied
1675 OSL_ASSERT(paramFlags
& PARAMFLAG_FOPT
);
1676 arRefArgs
[revIndex
].vt
= VT_ERROR
;
1677 arRefArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1680 // Set the converted arguments in the array which will be
1681 // DISPPARAMS::rgvarg
1682 // byref arg VT_XXX |VT_BYREF
1683 arArgs
[revIndex
].vt
= varType
;
1684 if (revIndex
== 0 && aFuncDesc
->invkind
== INVOKE_PROPERTYPUT
)
1686 arArgs
[revIndex
] = arRefArgs
[revIndex
];
1688 else if (type
== VT_DECIMAL
)
1690 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].decVal
;
1692 else if (type
== VT_VARIANT
)
1694 if ( ! (paramFlags
& PARAMFLAG_FOUT
))
1695 arArgs
[revIndex
] = arRefArgs
[revIndex
];
1697 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
];
1701 arArgs
[revIndex
].byref
= & arRefArgs
[revIndex
].byref
;
1702 arArgs
[revIndex
].vt
= ::sal::static_int_cast
< VARTYPE
, int >( arRefArgs
[revIndex
].vt
| VT_BYREF
);
1706 // in parameter no VT_BYREF except for array, interfaces
1708 { // void any stands for optional param
1709 if (i
< nUnoArgs
&& anyArg
.getValueTypeClass() != TypeClass_VOID
)
1711 anyToVariant( & arArgs
[revIndex
], anyArg
, varType
);
1713 //optional arg but no void any supplied
1714 //Basic: obj.func() ' first parameter left out because it is optional
1715 else if (paramFlags
& PARAMFLAG_FHASDEFAULT
)
1717 //optional arg with defaulteithter as direct arg : VT_XXX or
1718 VariantCopy( & arArgs
[revIndex
],
1719 & aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.
1720 pparamdescex
->varDefaultValue
);
1724 OSL_ASSERT(paramFlags
& PARAMFLAG_FOPT
);
1725 arArgs
[revIndex
].vt
= VT_ERROR
;
1726 arArgs
[revIndex
].scode
= DISP_E_PARAMNOTFOUND
;
1731 catch (IllegalArgumentException
& e
)
1733 e
.ArgumentPosition
= ::sal::static_int_cast
< sal_Int16
, sal_Int32
>( i
);
1736 catch (CannotConvertException
& e
)
1738 e
.ArgumentIndex
= i
;
1741 dispparams
.rgvarg
= arArgs
;
1742 // invoking OLE method
1743 DWORD localeId
= LOCALE_USER_DEFAULT
;
1744 result
= m_spDispatch
->Invoke(aFuncDesc
->memid
,
1747 ::sal::static_int_cast
< WORD
, INVOKEKIND
>( aFuncDesc
->invkind
),
1753 // converting return value and out parameter back to UNO
1757 // allocate space for the out param Sequence and indices Sequence
1758 int outParamsCount
= 0; // includes in/out parameter
1759 for (int i
= 0; i
< aFuncDesc
->cParams
; i
++)
1761 if (aFuncDesc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
&
1766 OutParamIndex
.realloc(outParamsCount
);
1767 OutParam
.realloc(outParamsCount
);
1768 // Convert out params
1771 int outParamIndex
=0;
1772 for (int paramIndex
= 0; paramIndex
< nUnoArgs
; paramIndex
++)
1774 //Determine the index within the method sinature
1775 int realParamIndex
= paramIndex
;
1776 int revParamIndex
= dispparams
.cArgs
- paramIndex
- 1;
1777 if (Params
[paramIndex
].getValueType()
1778 == getCppuType((NamedArgument
*) 0))
1780 //dispparams.rgdispidNamedArgs contains the mapping from index
1781 //of named args list to index of parameter list
1782 realParamIndex
= dispparams
.rgdispidNamedArgs
[revParamIndex
];
1785 // no named arg, always come before named args
1786 if (! (aFuncDesc
->lprgelemdescParam
[realParamIndex
].paramdesc
.wParamFlags
1790 // variantToAny is called with the "reduce range" parameter set to sal_False.
1791 // That causes VT_I4 values not to be converted down to a "lower" type. That
1792 // feature exist for JScript only because it only uses VT_I4 for integer types.
1795 variantToAny( & arRefArgs
[revParamIndex
], outAny
, sal_False
);
1797 catch (IllegalArgumentException
& e
)
1799 e
.ArgumentPosition
= (sal_Int16
)paramIndex
;
1802 catch (CannotConvertException
& e
)
1804 e
.ArgumentIndex
= paramIndex
;
1807 OutParam
[outParamIndex
] = outAny
;
1808 OutParamIndex
[outParamIndex
] = ::sal::static_int_cast
< sal_Int16
, int >( paramIndex
);
1811 OutParam
.realloc(outParamIndex
);
1812 OutParamIndex
.realloc(outParamIndex
);
1815 variantToAny(&varResult
, ret
, sal_False
);
1818 // map error codes to exceptions
1824 case DISP_E_BADPARAMCOUNT
:
1825 throw IllegalArgumentException(OUSTR("[automation bridge] Wrong "
1826 "number of arguments. Object returned DISP_E_BADPARAMCOUNT."),
1829 case DISP_E_BADVARTYPE
:
1830 throw RuntimeException(OUSTR("[automation bridge] One or more "
1831 "arguments have the wrong type. Object returned "
1832 "DISP_E_BADVARTYPE."), 0);
1834 case DISP_E_EXCEPTION
:
1835 message
= OUSTR("[automation bridge]: ");
1836 message
+= OUString(reinterpret_cast<const sal_Unicode
*>(excepinfo
.bstrDescription
),
1837 ::SysStringLen(excepinfo
.bstrDescription
));
1838 throw InvocationTargetException(message
, Reference
<XInterface
>(), Any());
1840 case DISP_E_MEMBERNOTFOUND
:
1841 message
= OUSTR("[automation bridge]: A function with the name \"")
1842 + sFuncName
+ OUSTR("\" is not supported. Object returned "
1843 "DISP_E_MEMBERNOTFOUND.");
1844 throw IllegalArgumentException(message
, 0, 0);
1846 case DISP_E_NONAMEDARGS
:
1847 throw IllegalArgumentException(OUSTR("[automation bridge] Object "
1848 "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1850 case DISP_E_OVERFLOW
:
1851 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")),
1852 static_cast<XInterface
*>(
1853 static_cast<XWeak
*>(this)), TypeClass_UNKNOWN
, FailReason::OUT_OF_RANGE
, uArgErr
);
1855 case DISP_E_PARAMNOTFOUND
:
1856 throw IllegalArgumentException(OUSTR("[automation bridge]Call failed."
1857 "Object returned DISP_E_PARAMNOTFOUND."),
1858 0, ::sal::static_int_cast
< sal_Int16
, unsigned int >( uArgErr
));
1860 case DISP_E_TYPEMISMATCH
:
1861 throw CannotConvertException(OUSTR("[automation bridge] Call failed. "
1862 "Object returned DISP_E_TYPEMISMATCH"),
1863 static_cast<XInterface
*>(
1864 static_cast<XWeak
*>(this)) , TypeClass_UNKNOWN
, FailReason::UNKNOWN
, uArgErr
);
1866 case DISP_E_UNKNOWNINTERFACE
:
1867 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
1868 "Object returned DISP_E_UNKNOWNINTERFACE."),0);
1870 case DISP_E_UNKNOWNLCID
:
1871 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
1872 "Object returned DISP_E_UNKNOWNLCID."),0);
1874 case DISP_E_PARAMNOTOPTIONAL
:
1875 throw CannotConvertException(OUSTR("[automation bridge] Call failed."
1876 "Object returned DISP_E_PARAMNOTOPTIONAL"),
1877 static_cast<XInterface
*>(static_cast<XWeak
*>(this)),
1878 TypeClass_UNKNOWN
, FailReason::NO_DEFAULT_AVAILABLE
, uArgErr
);
1881 throw RuntimeException();
1888 void IUnknownWrapper_Impl::getFuncDescForInvoke(const OUString
& sFuncName
,
1889 const Sequence
<Any
> & seqArgs
,
1890 FUNCDESC
** pFuncDesc
)
1892 int nUnoArgs
= seqArgs
.getLength();
1893 const Any
* arArgs
= seqArgs
.getConstArray();
1894 ITypeInfo
* pInfo
= getTypeInfo();
1896 //If the last of the positional arguments is a PropertyPutArgument
1897 //then obtain the type info for the property put operation.
1899 //The property value is always the last argument, in a positional argument list
1900 //or in a list of named arguments. A PropertyPutArgument is actually a named argument
1901 //hence it must not be put in an extra NamedArgument structure
1903 arArgs
[nUnoArgs
- 1].getValueType() == getCppuType((PropertyPutArgument
*) 0))
1905 // DISPATCH_PROPERTYPUT
1906 FuncDesc
aDescGet(pInfo
);
1907 FuncDesc
aDescPut(pInfo
);
1908 VarDesc
aVarDesc(pInfo
);
1909 getPropDesc(sFuncName
, & aDescGet
, & aDescPut
, & aVarDesc
);
1912 throw IllegalArgumentException(
1913 OUSTR("[automation bridge] The object does not have a writeable property: ")
1914 + sFuncName
, Reference
<XInterface
>(), 0);
1916 *pFuncDesc
= aDescPut
.Detach();
1919 { // DISPATCH_METHOD
1920 FuncDesc
aFuncDesc(pInfo
);
1921 getFuncDesc(sFuncName
, & aFuncDesc
);
1924 // Fallback: DISPATCH_PROPERTYGET can mostly be called as
1926 ITypeInfo
* pInfo
= getTypeInfo();
1927 FuncDesc
aDescPut(pInfo
);
1928 VarDesc
aVarDesc(pInfo
);
1929 getPropDesc(sFuncName
, & aFuncDesc
, & aDescPut
, & aVarDesc
);
1932 throw IllegalArgumentException(
1933 OUSTR("[automation bridge] The object does not have a function"
1934 "or readable property \"")
1935 + sFuncName
, Reference
<XInterface
>(), 0);
1938 *pFuncDesc
= aFuncDesc
.Detach();
1941 bool IUnknownWrapper_Impl::getDispid(const OUString
& sFuncName
, DISPID
* id
)
1943 OSL_ASSERT(m_spDispatch
);
1944 LPOLESTR lpsz
= const_cast<LPOLESTR
> (reinterpret_cast<LPCOLESTR
>(sFuncName
.getStr()));
1945 HRESULT hr
= m_spDispatch
->GetIDsOfNames(IID_NULL
, &lpsz
, 1, LOCALE_USER_DEFAULT
, id
);
1946 return hr
== S_OK
? true : false;
1948 void IUnknownWrapper_Impl::getFuncDesc(const OUString
& sFuncName
, FUNCDESC
** pFuncDesc
)
1951 OSL_ASSERT( * pFuncDesc
== 0);
1953 typedef TLBFuncIndexMap::const_iterator cit
;
1954 typedef TLBFuncIndexMap::iterator it
;
1955 //We assume there is only one entry with the function name. A property
1956 //would have two entries.
1957 cit itIndex
= m_mapComFunc
.find(sFuncName
);
1958 if (itIndex
== m_mapComFunc
.end())
1960 //try case insensive with IDispatch::GetIDsOfNames
1962 if (getDispid(sFuncName
, &id
))
1964 CComBSTR memberName
;
1965 unsigned int pcNames
=0;
1966 // get the case sensitive name
1967 if( SUCCEEDED(getTypeInfo()->GetNames( id
, & memberName
, 1, &pcNames
)))
1969 //get the associated index and add an entry to the map
1970 //with the name sFuncName which differs in the casing of the letters to
1971 //the actual name as obtained from ITypeInfo
1972 cit itOrg
= m_mapComFunc
.find(OUString(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
))));
1973 OSL_ASSERT(itOrg
!= m_mapComFunc
.end());
1975 m_mapComFunc
.insert( TLBFuncIndexMap::value_type
1976 ( make_pair(sFuncName
, itOrg
->second
) ));
1981 #if OSL_DEBUG_LEVEL >= 1
1982 // There must only be one entry if sFuncName represents a function or two
1983 // if it is a property
1984 pair
<cit
, cit
> p
= m_mapComFunc
.equal_range(sFuncName
.toAsciiLowerCase());
1986 for ( ;p
.first
!= p
.second
; p
.first
++, numEntries
++);
1987 OSL_ASSERT( ! (numEntries
> 3) );
1989 if( itIndex
!= m_mapComFunc
.end())
1991 ITypeInfo
* pType
= getTypeInfo();
1992 FUNCDESC
* pDesc
= NULL
;
1993 if (SUCCEEDED(pType
->GetFuncDesc(itIndex
->second
, & pDesc
)))
1995 if (pDesc
->invkind
== INVOKE_FUNC
)
1997 (*pFuncDesc
) = pDesc
;
2001 pType
->ReleaseFuncDesc(pDesc
);
2006 throw BridgeRuntimeError(OUSTR("[automation bridge] Could not get "
2007 "FUNCDESC for ") + sFuncName
);
2010 //else no entry found for sFuncName, pFuncDesc will not be filled in
2013 void IUnknownWrapper_Impl::getPropDesc(const OUString
& sFuncName
, FUNCDESC
** pFuncDescGet
,
2014 FUNCDESC
** pFuncDescPut
, VARDESC
** pVarDesc
)
2016 OSL_ASSERT( * pFuncDescGet
== 0 && * pFuncDescPut
== 0);
2018 typedef TLBFuncIndexMap::const_iterator cit
;
2019 pair
<cit
, cit
> p
= m_mapComFunc
.equal_range(sFuncName
);
2020 if (p
.first
== m_mapComFunc
.end())
2022 //try case insensive with IDispatch::GetIDsOfNames
2024 if (getDispid(sFuncName
, &id
))
2026 CComBSTR memberName
;
2027 unsigned int pcNames
=0;
2028 // get the case sensitive name
2029 if( SUCCEEDED(getTypeInfo()->GetNames( id
, & memberName
, 1, &pcNames
)))
2031 //As opposed to getFuncDesc, we do not add the value because we would
2032 // need to find the get and set description for the property. This would
2033 //mean to iterate over all FUNCDESCs again.
2034 p
= m_mapComFunc
.equal_range(OUString(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
))));
2039 for ( int i
= 0 ;p
.first
!= p
.second
; p
.first
++, i
++)
2041 // There are a maximum of two entries, property put and property get
2042 OSL_ASSERT( ! (i
> 2) );
2043 ITypeInfo
* pType
= getTypeInfo();
2044 FUNCDESC
* pFuncDesc
= NULL
;
2045 if (SUCCEEDED( pType
->GetFuncDesc(p
.first
->second
, & pFuncDesc
)))
2047 if (pFuncDesc
->invkind
== INVOKE_PROPERTYGET
)
2049 (*pFuncDescGet
) = pFuncDesc
;
2051 else if (pFuncDesc
->invkind
== INVOKE_PROPERTYPUT
||
2052 pFuncDesc
->invkind
== INVOKE_PROPERTYPUTREF
)
2054 //a property can have 3 entries, put, put ref, get
2055 // If INVOKE_PROPERTYPUTREF or INVOKE_PROPERTYPUT is used
2056 //depends on what is found first.
2057 if ( * pFuncDescPut
)
2059 //we already have found one
2060 pType
->ReleaseFuncDesc(pFuncDesc
);
2064 (*pFuncDescPut
) = pFuncDesc
;
2069 pType
->ReleaseFuncDesc(pFuncDesc
);
2072 //ITypeInfo::GetFuncDesc may even provide a funcdesc for a VARDESC
2073 // with invkind = INVOKE_FUNC. Since this function should only return
2074 //a value for a real property (XInvokation::hasMethod, ..::hasProperty
2075 //we need to make sure that sFuncName represents a real property.
2076 VARDESC
* pVD
= NULL
;
2077 if (SUCCEEDED(pType
->GetVarDesc(p
.first
->second
, & pVD
)))
2080 //else no entry for sFuncName, pFuncDesc will not be filled in
2083 VARTYPE
IUnknownWrapper_Impl::getElementTypeDesc(const TYPEDESC
*desc
)
2085 VARTYPE
_type( VT_NULL
);
2087 if (desc
->vt
== VT_PTR
)
2089 _type
= getElementTypeDesc(desc
->lptdesc
);
2092 else if (desc
->vt
== VT_SAFEARRAY
)
2094 _type
= getElementTypeDesc(desc
->lptdesc
);
2097 else if (desc
->vt
== VT_USERDEFINED
)
2099 ITypeInfo
* thisInfo
= getTypeInfo(); //kept by this instance
2100 CComPtr
<ITypeInfo
> spRefInfo
;
2101 thisInfo
->GetRefTypeInfo(desc
->hreftype
, & spRefInfo
.p
);
2104 TypeAttr
attr(spRefInfo
);
2105 spRefInfo
->GetTypeAttr( & attr
);
2106 if (attr
->typekind
== TKIND_ENUM
)
2108 //We use the type of the first enum value.
2109 if (attr
->cVars
== 0)
2111 throw BridgeRuntimeError(OUSTR("[automation bridge] Could "
2112 "not obtain type description"));
2114 VarDesc
var(spRefInfo
);
2115 spRefInfo
->GetVarDesc(0, & var
);
2116 _type
= var
->lpvarValue
->vt
;
2118 else if (attr
->typekind
== TKIND_INTERFACE
)
2122 else if (attr
->typekind
== TKIND_DISPATCH
)
2124 _type
= VT_DISPATCH
;
2128 throw BridgeRuntimeError(OUSTR("[automation bridge] "
2129 "Unhandled user defined type."));
2140 void IUnknownWrapper_Impl::buildComTlbIndex()
2142 if ( ! m_bComTlbIndexInit
)
2144 MutexGuard
guard(getBridgeMutex());
2146 if ( ! m_bComTlbIndexInit
)
2149 ITypeInfo
* pType
= getTypeInfo();
2150 TypeAttr
typeAttr(pType
);
2151 if( SUCCEEDED( pType
->GetTypeAttr( &typeAttr
)))
2153 for( long i
= 0; i
< typeAttr
->cFuncs
; i
++)
2155 FuncDesc
funcDesc(pType
);
2156 if( SUCCEEDED( pType
->GetFuncDesc( i
, &funcDesc
)))
2158 CComBSTR memberName
;
2159 unsigned int pcNames
=0;
2160 if( SUCCEEDED(pType
->GetNames( funcDesc
->memid
, & memberName
, 1, &pcNames
)))
2162 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
)));
2163 m_mapComFunc
.insert( TLBFuncIndexMap::value_type( usName
, i
));
2167 sError
= OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2168 "ITypeInfo::GetNames failed.");
2172 sError
= OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2173 "ITypeInfo::GetFuncDesc failed.");
2176 //If we create an Object in JScript and a a property then it
2177 //has VARDESC instead of FUNCDESC
2178 for (long i
= 0; i
< typeAttr
->cVars
; i
++)
2180 VarDesc
varDesc(pType
);
2181 if (SUCCEEDED(pType
->GetVarDesc(i
, & varDesc
)))
2183 CComBSTR memberName
;
2184 unsigned int pcNames
= 0;
2185 if (SUCCEEDED(pType
->GetNames(varDesc
->memid
, & memberName
, 1, &pcNames
)))
2187 if (varDesc
->varkind
== VAR_DISPATCH
)
2189 OUString
usName(reinterpret_cast<const sal_Unicode
*>(LPCOLESTR(memberName
)));
2190 m_mapComFunc
.insert(TLBFuncIndexMap::value_type(
2196 sError
= OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2197 "ITypeInfo::GetNames failed.");
2201 sError
= OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2202 "ITypeInfo::GetVarDesc failed.");
2207 sError
= OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2208 "ITypeInfo::GetTypeAttr failed.");
2210 if (sError
.getLength())
2212 throw BridgeRuntimeError(sError
);
2215 m_bComTlbIndexInit
= true;
2221 ITypeInfo
* IUnknownWrapper_Impl::getTypeInfo()
2225 throw BridgeRuntimeError(OUSTR("The object has no IDispatch interface!"));
2230 MutexGuard
guard(getBridgeMutex());
2233 CComPtr
< ITypeInfo
> spType
;
2234 if( SUCCEEDED( m_spDispatch
->GetTypeInfo( 0, LOCALE_USER_DEFAULT
, &spType
.p
)))
2237 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
2239 //If this is a dual interface then TYPEATTR::typekind is usually TKIND_INTERFACE
2240 //We need to get the type description for TKIND_DISPATCH
2241 TypeAttr
typeAttr(spType
.p
);
2242 if( SUCCEEDED(spType
->GetTypeAttr( &typeAttr
)))
2244 if (typeAttr
->typekind
== TKIND_INTERFACE
&&
2245 typeAttr
->wTypeFlags
& TYPEFLAG_FDUAL
)
2247 HREFTYPE refDispatch
;
2248 if (SUCCEEDED(spType
->GetRefTypeOfImplType(::sal::static_int_cast
< UINT
, int >( -1 ), &refDispatch
)))
2250 CComPtr
<ITypeInfo
> spTypeDisp
;
2251 if (SUCCEEDED(spType
->GetRefTypeInfo(refDispatch
, & spTypeDisp
)))
2252 m_spTypeInfo
= spTypeDisp
;
2256 throw BridgeRuntimeError(
2257 OUSTR("[automation bridge] Could not obtain type information "
2258 "for dispatch interface." ));
2261 else if (typeAttr
->typekind
== TKIND_DISPATCH
)
2263 m_spTypeInfo
= spType
;
2267 throw BridgeRuntimeError(
2268 OUSTR("[automation bridge] Automation object does not "
2269 "provide type information."));
2275 throw BridgeRuntimeError(OUSTR("[automation bridge]The dispatch object does not "
2276 "support ITypeInfo!"));
2280 return m_spTypeInfo
;