Update ooo320-m1
[ooovba.git] / extensions / source / ole / oleobjw.cxx
blobe132481e309342e64dfe46993743b917184fd2e3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: oleobjw.cxx,v $
10 * $Revision: 1.19 $
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>
61 #include <rtl/uuid.h>
62 #include <rtl/memory.h>
63 #include <rtl/ustring.hxx>
65 #include "jscriptclasses.hxx"
67 #include "oleobjw.hxx"
68 #include "unoobjw.hxx"
69 #include <stdio.h>
70 using namespace std;
71 using namespace boost;
72 using namespace osl;
73 using namespace rtl;
74 using namespace cppu;
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"
83 namespace ole_adapter
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
92 // called.
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 );
128 #endif
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());
148 #endif
151 Any IUnknownWrapper_Impl::queryInterface(const Type& t)
152 throw (RuntimeException)
154 if (t == getCppuType(static_cast<Reference<XDefaultMethod>*>( 0)) && !m_bHasDfltMethod )
155 return Any();
156 if (t == getCppuType(static_cast<Reference<XDefaultProperty>*>( 0)) && !m_bHasDfltProperty )
157 return Any();
158 if (t == getCppuType(static_cast<Reference<XInvocation>*>( 0)) && !m_spDispatch)
159 return Any();
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;
170 return 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,
179 RuntimeException)
181 if ( ! m_spDispatch )
183 throw RuntimeException(
184 OUSTR("[automation bridge] The object does not have an IDispatch interface"),
185 Reference<XInterface>());
188 Any ret;
192 o2u_attachCurrentThread();
194 TypeDescription methodDesc;
195 getMethodInfo(aFunctionName, methodDesc);
196 if( methodDesc.is())
198 ret = invokeWithDispIdUnoTlb(aFunctionName,
199 aParams,
200 aOutParamIndex,
201 aOutParam);
203 else
205 ret= invokeWithDispIdComTlb( aFunctionName,
206 aParams,
207 aOutParamIndex,
208 aOutParam);
211 catch (IllegalArgumentException &)
213 throw;
215 catch (CannotConvertException &)
217 throw;
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>());
230 catch(...)
232 throw RuntimeException(
233 OUSTR("[automation bridge] unexpected exception in "
234 "IUnknownWrapper_Impl::Invoke !"), Reference<XInterface>());
236 return ret;
239 void SAL_CALL IUnknownWrapper_Impl::setValue( const OUString& aPropertyName,
240 const Any& aValue )
241 throw(UnknownPropertyException, CannotConvertException, InvocationTargetException,
242 RuntimeException)
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 )
270 //read-only
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());
275 // ignore silently
276 return;
279 HRESULT hr= S_OK;
280 DISPPARAMS dispparams;
281 CComVariant varArg;
282 CComVariant varRefArg;
283 CComVariant varResult;
284 ExcepInfo excepinfo;
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);
296 VARTYPE vt = 0;
297 DISPID dispid = 0;
298 INVOKEKIND invkind = INVOKE_PROPERTYPUT;
299 //determine the expected type, dispid, invoke kind (DISPATCH_PROPERTYPUT,
300 //DISPATCH_PROPERTYPUTREF)
301 if (aDescPut)
303 vt = getElementTypeDesc(& aDescPut->lprgelemdescParam[0].tdesc);
304 dispid = aDescPut->memid;
305 invkind = aDescPut->invkind;
307 else
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
319 if (vt & VT_BYREF)
321 anyToVariant( & varRefArg, aValue, ::sal::static_int_cast< VARTYPE, int >( vt ^ VT_BYREF ) );
322 varArg.vt = vt;
323 if( (vt & VT_TYPEMASK) == VT_VARIANT)
324 varArg.byref = & varRefArg;
325 else if ((vt & VT_TYPEMASK) == VT_DECIMAL)
326 varArg.byref = & varRefArg.decVal;
327 else
328 varArg.byref = & varRefArg.byref;
330 else
332 anyToVariant(& varArg, aValue, vt);
334 // call to IDispatch
335 hr = m_spDispatch->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, ::sal::static_int_cast< WORD, INVOKEKIND >( invkind ),
336 &dispparams, & varResult, & excepinfo, &uArgErr);
338 // lookup error code
339 switch (hr)
341 case S_OK:
342 break;
343 case DISP_E_BADPARAMCOUNT:
344 throw RuntimeException();
345 break;
346 case DISP_E_BADVARTYPE:
347 throw RuntimeException();
348 break;
349 case DISP_E_EXCEPTION:
350 throw InvocationTargetException();
351 break;
352 case DISP_E_MEMBERNOTFOUND:
353 throw UnknownPropertyException();
354 break;
355 case DISP_E_NONAMEDARGS:
356 throw RuntimeException();
357 break;
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);
361 break;
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 )) ;
365 break;
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 ));
369 break;
370 case DISP_E_UNKNOWNINTERFACE:
371 throw RuntimeException();
372 break;
373 case DISP_E_UNKNOWNLCID:
374 throw RuntimeException();
375 break;
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);
379 break;
380 default:
381 throw RuntimeException();
382 break;
385 catch (CannotConvertException &)
387 throw;
389 catch (UnknownPropertyException &)
391 throw;
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>());
405 catch (...)
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>());
422 Any ret;
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
435 // hack
436 if ( aPropertyName.equals( rtl::OUString::createFromAscii("$GetTypeName") ))
438 if ( pInfo && m_sTypeName.getLength() == 0 )
440 m_sTypeName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IDispatch") );
441 CComBSTR sName;
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 )
447 sTmp = sTmp.copy(1);
448 // do we own the memory for pTypeLib, msdn doco is vague
449 // I'll assume we do
450 CComPtr< ITypeLib > pTypeLib;
451 unsigned int index;
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 );
464 ret <<= m_sTypeName;
465 return ret;
467 FuncDesc aDescGet(pInfo);
468 FuncDesc aDescPut(pInfo);
469 VarDesc aVarDesc(pInfo);
470 getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc);
471 if ( ! aDescGet && ! aDescPut && ! aVarDesc)
473 //property not found
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);
481 HRESULT hr;
482 DISPPARAMS dispparams = {0, 0, 0, 0};
483 CComVariant varResult;
484 ExcepInfo excepinfo;
485 unsigned int uArgErr;
486 DISPID dispid;
487 if (aDescGet)
488 dispid = aDescGet->memid;
489 else if (aVarDesc)
490 dispid = aVarDesc->memid;
491 else
492 dispid = aDescPut->memid;
494 hr = m_spDispatch->Invoke(dispid,
495 IID_NULL,
496 LOCALE_USER_DEFAULT,
497 DISPATCH_PROPERTYGET,
498 &dispparams,
499 &varResult,
500 &excepinfo,
501 &uArgErr);
503 // converting return value and out parameter back to UNO
504 if (hr == S_OK)
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);
510 if( attrInfo.is() )
511 variantToAny( &varResult, ret, Type( attrInfo.get()->pWeakRef));
512 else
513 variantToAny(&varResult, ret);
516 // lookup error code
517 switch (hr)
519 case S_OK:
520 break;
521 case DISP_E_BADPARAMCOUNT:
522 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
523 Reference<XInterface>());
524 break;
525 case DISP_E_BADVARTYPE:
526 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
527 Reference<XInterface>());
528 break;
529 case DISP_E_EXCEPTION:
530 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
531 Reference<XInterface>());
532 break;
533 case DISP_E_MEMBERNOTFOUND:
534 throw UnknownPropertyException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
535 Reference<XInterface>());
536 break;
537 case DISP_E_NONAMEDARGS:
538 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
539 Reference<XInterface>());
540 break;
541 case DISP_E_OVERFLOW:
542 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
543 Reference<XInterface>());
544 break;
545 case DISP_E_PARAMNOTFOUND:
546 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
547 Reference<XInterface>());
548 break;
549 case DISP_E_TYPEMISMATCH:
550 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
551 Reference<XInterface>());
552 break;
553 case DISP_E_UNKNOWNINTERFACE:
554 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
555 Reference<XInterface>());
556 break;
557 case DISP_E_UNKNOWNLCID:
558 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
559 Reference<XInterface>());
560 break;
561 case DISP_E_PARAMNOTOPTIONAL:
562 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
563 Reference<XInterface>());
564 break;
565 default:
566 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
567 Reference<XInterface>());
568 break;
571 catch (UnknownPropertyException& )
573 throw;
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>());
586 catch (...)
588 throw RuntimeException(
589 OUSTR("[automation bridge] unexpected exception in "
590 "IUnknownWrapper_Impl::getValue !"), Reference<XInterface>());
592 return ret;
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.
614 if ( ! aDesc)
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)
622 ret = sal_True;
624 else
625 ret = sal_True;
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>());
637 catch (...)
639 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
640 "IUnknownWrapper_Impl::hasMethod !"), Reference<XInterface>());;
642 return ret;
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>());
652 return sal_False;
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
666 // property
667 if (aVarDesc
668 || aDescPut && aDescPut->cParams == 0
669 || aDescGet && aDescGet->cParams == 0)
671 ret = sal_True;
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>());
685 catch (...)
687 throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
688 "IUnknownWrapper_Impl::hasProperty !"), Reference<XInterface>());
690 return ret;
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)
698 Any ret;
699 o2u_attachCurrentThread();
701 if (
702 (sourceModelType == UNO) &&
703 (destModelType == OLE) &&
704 (modelDepObject.getValueTypeClass() == TypeClass_INTERFACE)
707 Reference<XInterface> xInt( *(XInterface**) modelDepObject.getValue());
708 Reference<XInterface> xSelf( (OWeakObject*)this);
710 if (xInt == xSelf)
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();
721 else
723 pVariant->vt = VT_UNKNOWN;
724 pVariant->punkVal = m_spUnknown;
725 pVariant->punkVal->AddRef();
728 ret.setValue((void*)&pVariant, getCppuType( (sal_uInt32*) 0));
732 return ret;
734 /** @internal
735 @exception IllegalArgumentException
736 @exception CannotConvertException
737 @exception InvocationTargetException
738 @RuntimeException
740 Any IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString& sFunctionName,
741 const Sequence< Any >& Params,
742 Sequence< sal_Int16 >& OutParamIndex,
743 Sequence< Any >& OutParam)
745 Any ret;
746 HRESULT hr= S_OK;
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;
764 if( methodDesc.is())
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)
782 outParameterCount++;
785 if( !bJScriptObject)
787 sarParamsRef.reset(new CComVariant[outParameterCount]);
788 pVarParamsRef = sarParamsRef.get();
789 // build up the parameters for IDispatch::Invoke
790 sal_Int32 outParamIndex=0;
791 int i = 0;
792 try
794 for( i= 0; i < parameterCount; i++)
796 // In parameter
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)
804 CComVariant var;
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;
822 break;
823 case TypeClass_ENUM:
824 case TypeClass_LONG:
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;
833 break;
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;
842 break;
843 case TypeClass_ANY:
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];
851 break;
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;
861 break;
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;
872 break;
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;
883 break;
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;
893 break;
894 case TypeClass_BYTE:
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;
903 break;
904 case TypeClass_CHAR:
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;
915 break;
917 default:
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];
927 outParamIndex++;
928 } // end else if
929 } // end for
931 catch (IllegalArgumentException & e)
933 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
934 throw;
936 catch (CannotConvertException & e)
938 e.ArgumentIndex = i;
939 throw;
942 else // it is an JScriptObject
944 int i = 0;
947 for( ; i< parameterCount; i++)
949 // In parameter
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());
961 #ifdef __MINGW32__
962 CComQIPtr<IDispatch, &__uuidof(IDispatch)> pDisp( pUnk);
963 #else
964 CComQIPtr<IDispatch> pDisp( pUnk);
965 #endif
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 "
981 "param!"));
985 else
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 );
1000 throw;
1002 catch (CannotConvertException & e)
1004 e.ArgumentIndex = i;
1005 throw;
1009 // No type description Available, that is we have to deal with a COM component,
1010 // that does not implements UNO interfaces ( IDispatch based)
1011 else
1013 //We should not run into this block, because invokeWithDispIdComTlb should
1014 //have been called instead.
1015 OSL_ASSERT(0);
1019 CComVariant varResult;
1020 ExcepInfo excepinfo;
1021 unsigned int uArgErr;
1022 DISPPARAMS dispparams= { pVarParams, NULL, parameterCount, 0};
1023 // Get the DISPID
1024 FuncDesc aDesc(getTypeInfo());
1025 getFuncDesc(sFunctionName, & aDesc);
1026 // invoking OLE method
1027 hr = m_spDispatch->Invoke(aDesc->memid,
1028 IID_NULL,
1029 LOCALE_USER_DEFAULT,
1030 DISPATCH_METHOD,
1031 &dispparams,
1032 &varResult,
1033 &excepinfo,
1034 &uArgErr);
1036 // converting return value and out parameter back to UNO
1037 if (hr == S_OK)
1039 if( outParameterCount && pMethod)
1041 OutParamIndex.realloc( outParameterCount);
1042 OutParam.realloc( outParameterCount);
1043 sal_Int32 outIndex=0;
1044 int i = 0;
1047 for( ; i < parameterCount; i++)
1049 if( pMethod->pParams[i].bOut )
1051 OutParamIndex[outIndex]= (sal_Int16) i;
1052 Any outAny;
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);
1064 if( pDisp)
1066 CComVariant varOut;
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;
1073 else
1074 bConvRet= sal_False;
1076 else
1077 bConvRet= sal_False;
1079 else
1080 bConvRet= sal_False;
1083 if( !bConvRet) break;
1086 catch(IllegalArgumentException & e)
1088 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
1089 throw;
1091 catch(CannotConvertException & e)
1093 e.ArgumentIndex = i;
1094 throw;
1097 // return value, no type information available
1098 if ( bConvRet)
1102 if( pMethod )
1103 variantToAny(&varResult, ret, Type( pMethod->pReturnTypeRef), sal_False);
1104 else
1105 variantToAny(&varResult, ret, sal_False);
1107 catch (IllegalArgumentException & e)
1109 e.Message =
1110 OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1111 "Could not convert return value! \n Message: \n") + e.Message;
1112 throw;
1114 catch (CannotConvertException & e)
1116 e.Message =
1117 OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1118 "Could not convert return value! \n Message: \n") + e.Message;
1119 throw;
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
1129 switch (hr)
1131 case S_OK:
1132 break;
1133 case DISP_E_BADPARAMCOUNT:
1134 throw IllegalArgumentException();
1135 break;
1136 case DISP_E_BADVARTYPE:
1137 throw RuntimeException();
1138 break;
1139 case DISP_E_EXCEPTION:
1140 throw InvocationTargetException();
1141 break;
1142 case DISP_E_MEMBERNOTFOUND:
1143 throw IllegalArgumentException();
1144 break;
1145 case DISP_E_NONAMEDARGS:
1146 throw IllegalArgumentException();
1147 break;
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);
1151 break;
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 ));
1155 break;
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);
1159 break;
1160 case DISP_E_UNKNOWNINTERFACE:
1161 throw RuntimeException() ;
1162 break;
1163 case DISP_E_UNKNOWNLCID:
1164 throw RuntimeException() ;
1165 break;
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);
1169 break;
1170 default:
1171 throw RuntimeException();
1172 break;
1175 return ret;
1180 // --------------------------
1181 // XInitialization
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();
1191 #ifdef __MINGW32__
1192 m_spUnknown->QueryInterface(IID_IDispatch, reinterpret_cast<LPVOID*>( & m_spDispatch.p));
1193 #else
1194 m_spUnknown.QueryInterface( & m_spDispatch.p);
1195 #endif
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 );
1216 if ( !aDescGet )
1217 // we're knackered
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;
1237 catch( Exception& )
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);
1257 else
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);
1272 if( desc.is())
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);
1283 if( desc.is())
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();
1301 if( pInterface)
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;
1316 break;
1318 TYPELIB_DANGER_RELEASE( pDescMember)
1321 if( pMember)
1323 ret= (typelib_TypeDescription*)pMember;
1324 TYPELIB_DANGER_RELEASE( (typelib_TypeDescription*)pMember);
1327 if( ret.is())
1328 break;
1330 return ret;
1333 sal_Bool IUnknownWrapper_Impl::isJScriptObject()
1335 if( m_eJScript == JScriptUndefined)
1337 CComDispatchDriver disp( m_spDispatch);
1338 if( disp)
1340 CComVariant result;
1341 if( SUCCEEDED( disp.GetPropertyByName( JSCRIPT_ID_PROPERTY, &result)))
1343 if(result.vt == VT_BSTR)
1345 CComBSTR name( result.bstrVal);
1346 name.ToLower();
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;
1361 /** @internal
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
1365 component.
1366 @exception IllegalArgumentException
1367 @exception CannotConvertException
1368 @InvocationTargetException
1369 @RuntimeException
1370 @BridgeRuntimeError
1372 Any IUnknownWrapper_Impl::invokeWithDispIdComTlb(const OUString& sFuncName,
1373 const Sequence< Any >& Params,
1374 Sequence< sal_Int16 >& OutParamIndex,
1375 Sequence< Any >& OutParam)
1377 Any ret;
1378 HRESULT result;
1380 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1381 CComVariant varResult;
1382 ExcepInfo excepinfo;
1383 unsigned int uArgErr;
1384 sal_Int32 i = 0;
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;
1428 else
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;
1434 else
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
1460 //args.
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()));
1472 int cNamedArg = 0;
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() );
1494 if (hr == S_OK)
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;
1508 else
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);
1522 else
1524 throw InvocationTargetException(
1525 OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ")
1526 + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any());
1530 //Convert arguments
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;
1541 Any anyArg;
1542 if ( i < nUnoArgs)
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)
1557 paramFlags =
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
1578 // Dim arg
1579 // obj.func(arg)
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;
1597 anyArg >>= arg;
1598 anyArg <<= arg.Value;
1600 // named argument
1601 if (anyArg.getValueType() == getCppuType((NamedArgument*) 0))
1603 NamedArgument aNamedArgument;
1604 anyArg >>= aNamedArgument;
1605 anyArg <<= aNamedArgument.Value;
1607 // out param
1608 if (paramFlags & PARAMFLAG_FOUT &&
1609 ! (paramFlags & PARAMFLAG_FIN) )
1611 VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF );
1612 if (i < nUnoArgs)
1614 arRefArgs[revIndex].vt= type;
1616 else
1618 //optional arg
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];
1627 else
1629 arArgs[revIndex].vt= varType;
1630 if (type == VT_DECIMAL)
1631 arArgs[revIndex].byref= & arRefArgs[revIndex].decVal;
1632 else
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 );
1640 CComVariant var;
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);
1653 else
1655 //optional arg
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];
1678 else
1679 arArgs[revIndex].byref = & arRefArgs[revIndex];
1681 else
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
1689 else
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);
1704 else
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 );
1716 throw;
1718 catch (CannotConvertException & e)
1720 e.ArgumentIndex = i;
1721 throw;
1723 dispparams.rgvarg= arArgs;
1724 // invoking OLE method
1725 DWORD localeId = LOCALE_USER_DEFAULT;
1726 result = m_spDispatch->Invoke(aFuncDesc->memid,
1727 IID_NULL,
1728 localeId,
1729 ::sal::static_int_cast< WORD, INVOKEKIND >( aFuncDesc->invkind ),
1730 &dispparams,
1731 &varResult,
1732 &excepinfo,
1733 &uArgErr);
1735 // converting return value and out parameter back to UNO
1736 if (result == S_OK)
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 &
1744 PARAMFLAG_FOUT)
1745 outParamsCount++;
1748 OutParamIndex.realloc(outParamsCount);
1749 OutParam.realloc(outParamsCount);
1750 // Convert out params
1751 if (outParamsCount)
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
1769 & PARAMFLAG_FOUT))
1770 continue;
1771 Any outAny;
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;
1782 throw;
1784 catch (CannotConvertException & e)
1786 e.ArgumentIndex = paramIndex;
1787 throw;
1789 OutParam[outParamIndex] = outAny;
1790 OutParamIndex[outParamIndex] = ::sal::static_int_cast< sal_Int16, int >( paramIndex );
1791 outParamIndex++;
1793 OutParam.realloc(outParamIndex);
1794 OutParamIndex.realloc(outParamIndex);
1796 // Return value
1797 variantToAny(&varResult, ret, sal_False);
1800 // map error codes to exceptions
1801 OUString message;
1802 switch (result)
1804 case S_OK:
1805 break;
1806 case DISP_E_BADPARAMCOUNT:
1807 throw IllegalArgumentException(OUSTR("[automation bridge] Wrong "
1808 "number of arguments. Object returned DISP_E_BADPARAMCOUNT."),
1809 0, 0);
1810 break;
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);
1815 break;
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());
1821 break;
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);
1827 break;
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 ));
1831 break;
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);
1836 break;
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 ));
1841 break;
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);
1847 break;
1848 case DISP_E_UNKNOWNINTERFACE:
1849 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
1850 "Object returned DISP_E_UNKNOWNINTERFACE."),0);
1851 break;
1852 case DISP_E_UNKNOWNLCID:
1853 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
1854 "Object returned DISP_E_UNKNOWNLCID."),0);
1855 break;
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);
1861 break;
1862 default:
1863 throw RuntimeException();
1864 break;
1867 return ret;
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
1884 if (nUnoArgs > 0 &&
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);
1892 if ( ! aDescPut)
1894 throw IllegalArgumentException(
1895 OUSTR("[automation bridge] The object does not have a writeable property: ")
1896 + sFuncName, Reference<XInterface>(), 0);
1898 *pFuncDesc = aDescPut.Detach();
1900 else
1901 { // DISPATCH_METHOD
1902 FuncDesc aFuncDesc(pInfo);
1903 getFuncDesc(sFuncName, & aFuncDesc);
1904 if ( ! aFuncDesc)
1906 // Fallback: DISPATCH_PROPERTYGET can mostly be called as
1907 // DISPATCH_METHOD
1908 ITypeInfo * pInfo = getTypeInfo();
1909 FuncDesc aDescPut(pInfo);
1910 VarDesc aVarDesc(pInfo);
1911 getPropDesc(sFuncName, & aFuncDesc, & aDescPut, & aVarDesc);
1912 if ( ! aFuncDesc )
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);
1934 buildComTlbIndex();
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
1943 DISPID id;
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());
1956 itIndex =
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());
1967 int numEntries = 0;
1968 for ( ;p.first != p.second; p.first ++, numEntries ++);
1969 OSL_ASSERT( ! (numEntries > 3) );
1970 #endif
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;
1981 else
1983 pType->ReleaseFuncDesc(pDesc);
1986 else
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);
1999 buildComTlbIndex();
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
2005 DISPID id;
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);
2044 else
2046 (*pFuncDescPut) = pFuncDesc;
2049 else
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)))
2060 (*pVarDesc) = 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);
2072 _type |= VT_BYREF;
2074 else if (desc->vt == VT_SAFEARRAY)
2076 _type = getElementTypeDesc(desc->lptdesc);
2077 _type |= VT_ARRAY;
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);
2084 if (spRefInfo)
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)
2102 _type = VT_UNKNOWN;
2104 else if (attr->typekind == TKIND_DISPATCH)
2106 _type = VT_DISPATCH;
2108 else
2110 throw BridgeRuntimeError(OUSTR("[automation bridge] "
2111 "Unhandled user defined type."));
2115 else
2117 _type = desc->vt;
2119 return _type;
2122 void IUnknownWrapper_Impl::buildComTlbIndex()
2124 if ( ! m_bComTlbIndexInit)
2126 MutexGuard guard(getBridgeMutex());
2128 if ( ! m_bComTlbIndexInit)
2130 OUString sError;
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));
2147 else
2149 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2150 "ITypeInfo::GetNames failed.");
2153 else
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(
2173 usName, i));
2176 else
2178 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2179 "ITypeInfo::GetNames failed.");
2182 else
2183 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2184 "ITypeInfo::GetVarDesc failed.");
2188 else
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()
2205 if( !m_spDispatch)
2207 throw BridgeRuntimeError(OUSTR("The object has no IDispatch interface!"));
2210 if( !m_spTypeInfo )
2212 MutexGuard guard(getBridgeMutex());
2213 if( ! m_spTypeInfo)
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;
2236 else
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;
2247 else
2249 throw BridgeRuntimeError(
2250 OUSTR("[automation bridge] Automation object does not "
2251 "provide type information."));
2255 else
2257 throw BridgeRuntimeError(OUSTR("[automation bridge]The dispatch object does not "
2258 "support ITypeInfo!"));
2262 return m_spTypeInfo;
2265 } // end namespace