update credits
[LibreOffice.git] / extensions / source / ole / oleobjw.cxx
blobd487a15aabeddb9ea1aee865ba8d8f42daeba875
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 // http://stackoverflow.com/questions/5839292/error-c1189-after-installing-visual-studio-2010
21 #define _WIN32_WINNT 0x0403
23 #include "ole2uno.hxx"
24 #include "rtl/ustrbuf.hxx"
27 #include "osl/diagnose.h"
28 #include "osl/doublecheckedlocking.h"
29 #include "osl/thread.h"
31 #include "boost/scoped_array.hpp"
32 #include <com/sun/star/script/FailReason.hpp>
33 #include <com/sun/star/beans/XMaterialHolder.hpp>
34 #include <com/sun/star/script/XTypeConverter.hpp>
35 #include <com/sun/star/script/FinishEngineEvent.hpp>
36 #include <com/sun/star/script/InterruptReason.hpp>
37 #include <com/sun/star/script/XEngineListener.hpp>
38 #include <com/sun/star/script/XDebugging.hpp>
39 #include <com/sun/star/script/XInvocation.hpp>
40 #include <com/sun/star/script/ContextInformation.hpp>
41 #include <com/sun/star/script/FinishReason.hpp>
42 #include <com/sun/star/script/XEngine.hpp>
43 #include <com/sun/star/script/InterruptEngineEvent.hpp>
44 #include <com/sun/star/script/XLibraryAccess.hpp>
45 #include <com/sun/star/bridge/ModelDependent.hpp>
47 #include "com/sun/star/bridge/oleautomation/NamedArgument.hpp"
48 #include "com/sun/star/bridge/oleautomation/PropertyPutArgument.hpp"
50 #include <typelib/typedescription.hxx>
51 #include <rtl/uuid.h>
52 #include <rtl/ustring.hxx>
54 #include "jscriptclasses.hxx"
56 #include "oleobjw.hxx"
57 #include "unoobjw.hxx"
58 #include <stdio.h>
59 using namespace std;
60 using namespace boost;
61 using namespace osl;
62 using namespace cppu;
63 using namespace com::sun::star::script;
64 using namespace com::sun::star::lang;
65 using namespace com::sun::star::bridge;
66 using namespace com::sun::star::bridge::oleautomation;
67 using namespace com::sun::star::bridge::ModelDependent;
68 using namespace ::com::sun::star;
71 #define JSCRIPT_ID_PROPERTY L"_environment"
72 #define JSCRIPT_ID L"jscript"
73 namespace ole_adapter
77 // key: XInterface pointer created by Invocation Adapter Factory
78 // value: XInterface pointer to the wrapper class.
79 // Entries to the map are made within
80 // Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType);
81 // Entries are being deleted if the wrapper class's destructor has been
82 // called.
83 // Before UNO object is wrapped to COM object this map is checked
84 // to see if the UNO object is already a wrapper.
85 boost::unordered_map<sal_uInt32, sal_uInt32> AdapterToWrapperMap;
86 // key: XInterface of the wrapper object.
87 // value: XInterface of the Interface created by the Invocation Adapter Factory.
88 // A COM wrapper is responsible for removing the corresponding entry
89 // in AdapterToWrappperMap if it is being destroyed. Because the wrapper does not
90 // know about its adapted interface it uses WrapperToAdapterMap to get the
91 // adapted interface which is then used to locate the entry in AdapterToWrapperMap.
92 boost::unordered_map<sal_uInt32,sal_uInt32> WrapperToAdapterMap;
94 boost::unordered_map<sal_uInt32, WeakReference<XInterface> > ComPtrToWrapperMap;
95 /*****************************************************************************
97 class implementation IUnknownWrapper_Impl
99 *****************************************************************************/
101 IUnknownWrapper_Impl::IUnknownWrapper_Impl( Reference<XMultiServiceFactory>& xFactory,
102 sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
103 UnoConversionUtilities<IUnknownWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass),
104 m_pxIdlClass( NULL), m_eJScript( JScriptUndefined),
105 m_bComTlbIndexInit(false), m_bHasDfltMethod(false), m_bHasDfltProperty(false)
110 IUnknownWrapper_Impl::~IUnknownWrapper_Impl()
112 o2u_attachCurrentThread();
113 MutexGuard guard(getBridgeMutex());
114 XInterface * xIntRoot = (OWeakObject *)this;
115 #if OSL_DEBUG_LEVEL > 0
116 acquire(); // make sure we don't delete us twice because of Reference
117 OSL_ASSERT( Reference<XInterface>( static_cast<XWeak*>(this), UNO_QUERY).get() == xIntRoot );
118 #endif
120 // remove entries in global maps
121 typedef boost::unordered_map<sal_uInt32, sal_uInt32>::iterator _IT;
122 _IT it= WrapperToAdapterMap.find( (sal_uInt32) xIntRoot);
123 if( it != WrapperToAdapterMap.end())
125 sal_uInt32 adapter= it->second;
127 AdapterToWrapperMap.erase( adapter);
128 WrapperToAdapterMap.erase( it);
131 IT_Com it_c= ComPtrToWrapperMap.find( (sal_uInt32) m_spUnknown.p);
132 if(it_c != ComPtrToWrapperMap.end())
133 ComPtrToWrapperMap.erase(it_c);
135 #if OSL_DEBUG_LEVEL > 0
136 fprintf(stderr,"[automation bridge] ComPtrToWrapperMap contains: %i \n",
137 ComPtrToWrapperMap.size());
138 #endif
141 Any IUnknownWrapper_Impl::queryInterface(const Type& t)
142 throw (RuntimeException)
144 if (t == getCppuType(static_cast<Reference<XDefaultMethod>*>( 0)) && !m_bHasDfltMethod )
145 return Any();
146 if (t == getCppuType(static_cast<Reference<XDefaultProperty>*>( 0)) && !m_bHasDfltProperty )
147 return Any();
148 if ( ( t == getCppuType(static_cast<Reference<XInvocation>*>( 0)) || t == getCppuType(static_cast<Reference<XAutomationInvocation>*>( 0)) ) && !m_spDispatch)
149 return Any();
150 // XDirectInvocation seems to be an oracle replacement for XAutomationInvocation, however it is flawed esecially wrt. assumptions about whether to invoke a
151 // Put or Get property, the implementation code has no business guessing that, it's up to the caller to decide that. Worse XDirectInvocation duplicates lots of code.
152 // XAutomationInvocation provides separate calls for put& get
153 // properties. Note: Currently the basic runtime doesn't call put properties directly, it should... after all the basic runtime should know whether it is calling a put or get property.
154 // For the moment for ease of merging we will let the XDirectInvoke and XAuthomationInvocation interfaces stay side by side ( and for the momemnt at least I would prefer the basic
155 // runtime to call XAutomationInvocation instead of XDirectInvoke
156 return WeakImplHelper7<XBridgeSupplier2,
157 XInitialization, XAutomationObject, XDefaultProperty, XDefaultMethod, XDirectInvocation, XAutomationInvocation >::queryInterface(t);
160 Reference<XIntrospectionAccess> SAL_CALL IUnknownWrapper_Impl::getIntrospection(void)
161 throw (RuntimeException )
163 Reference<XIntrospectionAccess> ret;
165 return ret;
168 Any SAL_CALL IUnknownWrapper_Impl::invokeGetProperty( const OUString& aPropertyName, const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam )
170 Any aResult;
173 o2u_attachCurrentThread();
174 ITypeInfo * pInfo = getTypeInfo();
175 FuncDesc aDescGet(pInfo);
176 FuncDesc aDescPut(pInfo);
177 VarDesc aVarDesc(pInfo);
178 getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc);
179 if ( !aDescGet )
181 OUString msg("[automation bridge]Property \"" + aPropertyName +
182 "\" is not supported");
183 throw UnknownPropertyException(msg, Reference<XInterface>());
185 aResult = invokeWithDispIdComTlb( aDescGet, aPropertyName, aParams, aOutParamIndex, aOutParam );
187 catch ( const Exception& e )
189 throw RuntimeException("[automation bridge] unexpected exception in "
190 "IUnknownWrapper_Impl::invokeGetProperty ! Message : \n" +
191 e.Message, Reference<XInterface>());
193 return aResult;
196 Any SAL_CALL IUnknownWrapper_Impl::invokePutProperty( const OUString& aPropertyName, const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam )
198 Any aResult;
201 o2u_attachCurrentThread();
202 ITypeInfo * pInfo = getTypeInfo();
203 FuncDesc aDescGet(pInfo);
204 FuncDesc aDescPut(pInfo);
205 VarDesc aVarDesc(pInfo);
206 getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc);
207 if ( !aDescPut )
209 OUString msg("[automation bridge]Property \"" + aPropertyName +
210 "\" is not supported");
211 throw UnknownPropertyException(msg, Reference<XInterface>());
213 aResult = invokeWithDispIdComTlb( aDescPut, aPropertyName, aParams, aOutParamIndex, aOutParam );
215 catch ( const Exception& e )
217 throw RuntimeException("[automation bridge] unexpected exception in "
218 "IUnknownWrapper_Impl::invokePutProperty ! Message : \n" +
219 e.Message, Reference<XInterface>());
221 return aResult;
225 Any SAL_CALL IUnknownWrapper_Impl::invoke( const OUString& aFunctionName,
226 const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex,
227 Sequence< Any >& aOutParam )
228 throw(IllegalArgumentException, CannotConvertException, InvocationTargetException,
229 RuntimeException)
231 if ( ! m_spDispatch )
233 throw RuntimeException(
234 "[automation bridge] The object does not have an IDispatch interface",
235 Reference<XInterface>());
238 Any ret;
242 o2u_attachCurrentThread();
244 TypeDescription methodDesc;
245 getMethodInfo(aFunctionName, methodDesc);
246 if( methodDesc.is())
248 ret = invokeWithDispIdUnoTlb(aFunctionName,
249 aParams,
250 aOutParamIndex,
251 aOutParam);
253 else
255 ret= invokeWithDispIdComTlb( aFunctionName,
256 aParams,
257 aOutParamIndex,
258 aOutParam);
261 catch (const IllegalArgumentException &)
263 throw;
265 catch (const CannotConvertException &)
267 throw;
269 catch (const BridgeRuntimeError & e)
271 throw RuntimeException(e.message, Reference<XInterface>());
273 catch (const Exception & e)
275 throw RuntimeException("[automation bridge] unexpected exception in "
276 "IUnknownWrapper_Impl::invoke ! Message : \n" +
277 e.Message, Reference<XInterface>());
280 catch(...)
282 throw RuntimeException("[automation bridge] unexpected exception in "
283 "IUnknownWrapper_Impl::Invoke !", Reference<XInterface>());
285 return ret;
288 void SAL_CALL IUnknownWrapper_Impl::setValue( const OUString& aPropertyName,
289 const Any& aValue )
290 throw(UnknownPropertyException, CannotConvertException, InvocationTargetException,
291 RuntimeException)
293 if ( ! m_spDispatch )
295 throw RuntimeException(
296 "[automation bridge] The object does not have an IDispatch interface",
297 Reference<XInterface>());
301 o2u_attachCurrentThread();
303 ITypeInfo * pInfo = getTypeInfo();
304 FuncDesc aDescGet(pInfo);
305 FuncDesc aDescPut(pInfo);
306 VarDesc aVarDesc(pInfo);
307 getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc);
308 //check if there is such a property at all or if it is read only
309 if ( ! aDescPut && ! aDescGet && ! aVarDesc)
311 OUString msg("[automation bridge]Property \"" + aPropertyName +
312 "\" is not supported");
313 throw UnknownPropertyException(msg, Reference<XInterface>());
316 if ( (! aDescPut && aDescGet) || aVarDesc
317 && aVarDesc->wVarFlags == VARFLAG_FREADONLY )
319 //read-only
320 OUString msg("[automation bridge] Property " + aPropertyName +
321 " is read-only");
322 OString sMsg = OUStringToOString(msg, osl_getThreadTextEncoding());
323 OSL_FAIL(sMsg.getStr());
324 // ignore silently
325 return;
328 HRESULT hr= S_OK;
329 DISPPARAMS dispparams;
330 CComVariant varArg;
331 CComVariant varRefArg;
332 CComVariant varResult;
333 ExcepInfo excepinfo;
334 unsigned int uArgErr;
336 // converting UNO value to OLE variant
337 DISPID dispidPut= DISPID_PROPERTYPUT;
338 dispparams.rgdispidNamedArgs = &dispidPut;
339 dispparams.cArgs = 1;
340 dispparams.cNamedArgs = 1;
341 dispparams.rgvarg = & varArg;
343 OSL_ASSERT(aDescPut || aVarDesc);
345 VARTYPE vt = 0;
346 DISPID dispid = 0;
347 INVOKEKIND invkind = INVOKE_PROPERTYPUT;
348 //determine the expected type, dispid, invoke kind (DISPATCH_PROPERTYPUT,
349 //DISPATCH_PROPERTYPUTREF)
350 if (aDescPut)
352 vt = getElementTypeDesc(& aDescPut->lprgelemdescParam[0].tdesc);
353 dispid = aDescPut->memid;
354 invkind = aDescPut->invkind;
356 else
358 vt = getElementTypeDesc( & aVarDesc->elemdescVar.tdesc);
359 dispid = aVarDesc->memid;
360 if (vt == VT_UNKNOWN || vt == VT_DISPATCH ||
361 (vt & VT_ARRAY) || (vt & VT_BYREF))
363 invkind = INVOKE_PROPERTYPUTREF;
367 // convert the uno argument
368 if (vt & VT_BYREF)
370 anyToVariant( & varRefArg, aValue, ::sal::static_int_cast< VARTYPE, int >( vt ^ VT_BYREF ) );
371 varArg.vt = vt;
372 if( (vt & VT_TYPEMASK) == VT_VARIANT)
373 varArg.byref = & varRefArg;
374 else if ((vt & VT_TYPEMASK) == VT_DECIMAL)
375 varArg.byref = & varRefArg.decVal;
376 else
377 varArg.byref = & varRefArg.byref;
379 else
381 anyToVariant(& varArg, aValue, vt);
383 // call to IDispatch
384 hr = m_spDispatch->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, ::sal::static_int_cast< WORD, INVOKEKIND >( invkind ),
385 &dispparams, & varResult, & excepinfo, &uArgErr);
387 // lookup error code
388 switch (hr)
390 case S_OK:
391 break;
392 case DISP_E_BADPARAMCOUNT:
393 throw RuntimeException();
394 break;
395 case DISP_E_BADVARTYPE:
396 throw RuntimeException();
397 break;
398 case DISP_E_EXCEPTION:
399 throw InvocationTargetException();
400 break;
401 case DISP_E_MEMBERNOTFOUND:
402 throw UnknownPropertyException();
403 break;
404 case DISP_E_NONAMEDARGS:
405 throw RuntimeException();
406 break;
407 case DISP_E_OVERFLOW:
408 throw CannotConvertException(OUString("call to OLE object failed"), static_cast<XInterface*>(
409 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
410 break;
411 case DISP_E_PARAMNOTFOUND:
412 throw IllegalArgumentException(OUString("call to OLE object failed"), static_cast<XInterface*>(
413 static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )) ;
414 break;
415 case DISP_E_TYPEMISMATCH:
416 throw CannotConvertException(OUString("call to OLE object failed"), static_cast<XInterface*>(
417 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::UNKNOWN, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
418 break;
419 case DISP_E_UNKNOWNINTERFACE:
420 throw RuntimeException();
421 break;
422 case DISP_E_UNKNOWNLCID:
423 throw RuntimeException();
424 break;
425 case DISP_E_PARAMNOTOPTIONAL:
426 throw CannotConvertException(OUString("call to OLE object failed"),static_cast<XInterface*>(
427 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
428 break;
429 default:
430 throw RuntimeException();
431 break;
434 catch (const CannotConvertException &)
436 throw;
438 catch (const UnknownPropertyException &)
440 throw;
442 catch (const BridgeRuntimeError& e)
444 throw RuntimeException(
445 e.message, Reference<XInterface>());
447 catch (const Exception & e)
449 throw RuntimeException("[automation bridge] unexpected exception in "
450 "IUnknownWrapper_Impl::setValue ! Message : \n" +
451 e.Message, Reference<XInterface>());
454 catch (...)
456 throw RuntimeException(
457 "[automation bridge] unexpected exception in "
458 "IUnknownWrapper_Impl::setValue !", Reference<XInterface>());
462 Any SAL_CALL IUnknownWrapper_Impl::getValue( const OUString& aPropertyName )
463 throw(UnknownPropertyException, RuntimeException)
465 if ( ! m_spDispatch )
467 throw RuntimeException(
468 "[automation bridge] The object does not have an IDispatch interface",
469 Reference<XInterface>());
471 Any ret;
474 o2u_attachCurrentThread();
475 ITypeInfo * pInfo = getTypeInfo();
476 // I was going to implement an XServiceInfo interface to allow the type
477 // of the automation object to be exposed.. but it seems
478 // from looking at comments in the code that it is possible for
479 // this object to actually wrap an UNO object ( I guess if automation is
480 // used from MSO to create Openoffice objects ) Therefore, those objects
481 // will more than likely already have their own XServiceInfo interface.
482 // Instead here I chose a name that should be illegal both in COM and
483 // UNO ( from an IDL point of view ) therefore I think this is a safe
484 // hack
485 if ( aPropertyName == "$GetTypeName" )
487 if ( pInfo && m_sTypeName.getLength() == 0 )
489 m_sTypeName = OUString("IDispatch");
490 CComBSTR sName;
492 if ( SUCCEEDED( pInfo->GetDocumentation( -1, &sName, NULL, NULL, NULL ) ) )
494 OUString sTmp( reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName)));
495 if ( sTmp.indexOf('_') == 0 )
496 sTmp = sTmp.copy(1);
497 // do we own the memory for pTypeLib, msdn doco is vague
498 // I'll assume we do
499 CComPtr< ITypeLib > pTypeLib;
500 unsigned int index;
501 if ( SUCCEEDED( pInfo->GetContainingTypeLib( &pTypeLib.p, &index )) )
503 if ( SUCCEEDED( pTypeLib->GetDocumentation( -1, &sName, NULL, NULL, NULL ) ) )
505 OUString sLibName( reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName)));
506 m_sTypeName = sLibName.concat( OUString(".") ).concat( sTmp );
513 ret <<= m_sTypeName;
514 return ret;
516 FuncDesc aDescGet(pInfo);
517 FuncDesc aDescPut(pInfo);
518 VarDesc aVarDesc(pInfo);
519 getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc);
520 if ( ! aDescGet && ! aDescPut && ! aVarDesc)
522 //property not found
523 OUString msg("[automation bridge]Property \"" + aPropertyName +
524 "\" is not supported");
525 throw UnknownPropertyException(msg, Reference<XInterface>());
527 // write-only should not be possible
528 OSL_ASSERT( aDescGet || ! aDescPut);
530 HRESULT hr;
531 DISPPARAMS dispparams = {0, 0, 0, 0};
532 CComVariant varResult;
533 ExcepInfo excepinfo;
534 unsigned int uArgErr;
535 DISPID dispid;
536 if (aDescGet)
537 dispid = aDescGet->memid;
538 else if (aVarDesc)
539 dispid = aVarDesc->memid;
540 else
541 dispid = aDescPut->memid;
543 hr = m_spDispatch->Invoke(dispid,
544 IID_NULL,
545 LOCALE_USER_DEFAULT,
546 DISPATCH_PROPERTYGET,
547 &dispparams,
548 &varResult,
549 &excepinfo,
550 &uArgErr);
552 // converting return value and out parameter back to UNO
553 if (hr == S_OK)
555 // If the com object implements uno interfaces then we have
556 // to convert the attribute into the expected type.
557 TypeDescription attrInfo;
558 getAttributeInfo(aPropertyName, attrInfo);
559 if( attrInfo.is() )
560 variantToAny( &varResult, ret, Type( attrInfo.get()->pWeakRef));
561 else
562 variantToAny(&varResult, ret);
565 // lookup error code
566 switch (hr)
568 case S_OK:
569 break;
570 case DISP_E_BADPARAMCOUNT:
571 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
572 Reference<XInterface>());
573 break;
574 case DISP_E_BADVARTYPE:
575 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
576 Reference<XInterface>());
577 break;
578 case DISP_E_EXCEPTION:
579 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
580 Reference<XInterface>());
581 break;
582 case DISP_E_MEMBERNOTFOUND:
583 throw UnknownPropertyException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
584 Reference<XInterface>());
585 break;
586 case DISP_E_NONAMEDARGS:
587 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
588 Reference<XInterface>());
589 break;
590 case DISP_E_OVERFLOW:
591 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
592 Reference<XInterface>());
593 break;
594 case DISP_E_PARAMNOTFOUND:
595 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
596 Reference<XInterface>());
597 break;
598 case DISP_E_TYPEMISMATCH:
599 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
600 Reference<XInterface>());
601 break;
602 case DISP_E_UNKNOWNINTERFACE:
603 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
604 Reference<XInterface>());
605 break;
606 case DISP_E_UNKNOWNLCID:
607 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
608 Reference<XInterface>());
609 break;
610 case DISP_E_PARAMNOTOPTIONAL:
611 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
612 Reference<XInterface>());
613 break;
614 default:
615 throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
616 Reference<XInterface>());
617 break;
620 catch ( const UnknownPropertyException& )
622 throw;
624 catch (const BridgeRuntimeError& e)
626 throw RuntimeException(
627 e.message, Reference<XInterface>());
629 catch (const Exception & e)
631 throw RuntimeException("[automation bridge] unexpected exception in "
632 "IUnknownWrapper_Impl::getValue ! Message : \n" +
633 e.Message, Reference<XInterface>());
635 catch (...)
637 throw RuntimeException(
638 "[automation bridge] unexpected exception in "
639 "IUnknownWrapper_Impl::getValue !", Reference<XInterface>());
641 return ret;
644 sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMethod( const OUString& aName )
645 throw(RuntimeException)
647 if ( ! m_spDispatch )
649 throw RuntimeException(
650 "[automation bridge] The object does not have an IDispatch interface",
651 Reference<XInterface>());
653 sal_Bool ret = sal_False;
657 o2u_attachCurrentThread();
658 ITypeInfo* pInfo = getTypeInfo();
659 FuncDesc aDesc(pInfo);
660 getFuncDesc(aName, & aDesc);
661 // Automation properties can have arguments. Those are treated as methods and
662 //are called through XInvocation::invoke.
663 if ( ! aDesc)
665 FuncDesc aDescGet(pInfo);
666 FuncDesc aDescPut(pInfo);
667 VarDesc aVarDesc(pInfo);
668 getPropDesc( aName, & aDescGet, & aDescPut, & aVarDesc);
669 if (aDescGet && aDescGet->cParams > 0
670 || aDescPut && aDescPut->cParams > 0)
671 ret = sal_True;
673 else
674 ret = sal_True;
676 catch (const BridgeRuntimeError& e)
678 throw RuntimeException(e.message, Reference<XInterface>());
680 catch (const Exception & e)
682 throw RuntimeException("[automation bridge] unexpected exception in "
683 "IUnknownWrapper_Impl::hasMethod ! Message : \n" +
684 e.Message, Reference<XInterface>());
686 catch (...)
688 throw RuntimeException("[automation bridge] unexpected exception in "
689 "IUnknownWrapper_Impl::hasMethod !", Reference<XInterface>());
691 return ret;
694 sal_Bool SAL_CALL IUnknownWrapper_Impl::hasProperty( const OUString& aName )
695 throw(RuntimeException)
697 if ( ! m_spDispatch )
699 throw RuntimeException("[automation bridge] The object does not have an "
700 "IDispatch interface", Reference<XInterface>());
702 sal_Bool ret = sal_False;
705 o2u_attachCurrentThread();
707 ITypeInfo * pInfo = getTypeInfo();
708 FuncDesc aDescGet(pInfo);
709 FuncDesc aDescPut(pInfo);
710 VarDesc aVarDesc(pInfo);
711 getPropDesc(aName, & aDescGet, & aDescPut, & aVarDesc);
713 // we should probably just check the funckind
714 // basic has been modified to handle properties ( 'get' ) props at
715 // least with parameters
716 // additionally you can call invoke(Get|Set)Property on the bridge
717 // you can determine if a property has parameter is hasMethod
718 // returns true for the name
719 if (aVarDesc
720 || aDescPut
721 || aDescGet )
723 ret = sal_True;
726 catch (const BridgeRuntimeError& e)
728 throw RuntimeException(e.message, Reference<XInterface>());
730 catch (const Exception & e)
732 throw RuntimeException("[automation bridge] unexpected exception in "
733 "IUnknownWrapper_Impl::hasProperty ! Message : \n" +
734 e.Message, Reference<XInterface>());
737 catch (...)
739 throw RuntimeException("[automation bridge] unexpected exception in "
740 "IUnknownWrapper_Impl::hasProperty !", Reference<XInterface>());
742 return ret;
745 Any SAL_CALL IUnknownWrapper_Impl::createBridge( const Any& modelDepObject,
746 const Sequence< sal_Int8 >& /*aProcessId*/, sal_Int16 sourceModelType,
747 sal_Int16 destModelType )
748 throw( IllegalArgumentException, RuntimeException)
750 Any ret;
751 o2u_attachCurrentThread();
753 if (
754 (sourceModelType == UNO) &&
755 (destModelType == OLE) &&
756 (modelDepObject.getValueTypeClass() == TypeClass_INTERFACE)
759 Reference<XInterface> xInt( *(XInterface**) modelDepObject.getValue());
760 Reference<XInterface> xSelf( (OWeakObject*)this);
762 if (xInt == xSelf)
764 VARIANT* pVariant = (VARIANT*) CoTaskMemAlloc(sizeof(VARIANT));
766 VariantInit(pVariant);
767 if (m_bOriginalDispatch == sal_True)
769 pVariant->vt = VT_DISPATCH;
770 pVariant->pdispVal = m_spDispatch;
771 pVariant->pdispVal->AddRef();
773 else
775 pVariant->vt = VT_UNKNOWN;
776 pVariant->punkVal = m_spUnknown;
777 pVariant->punkVal->AddRef();
780 ret.setValue((void*)&pVariant, getCppuType( (sal_uInt32*) 0));
784 return ret;
786 /** @internal
787 @exception IllegalArgumentException
788 @exception CannotConvertException
789 @exception InvocationTargetException
790 @RuntimeException
792 Any IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString& sFunctionName,
793 const Sequence< Any >& Params,
794 Sequence< sal_Int16 >& OutParamIndex,
795 Sequence< Any >& OutParam)
797 Any ret;
798 HRESULT hr= S_OK;
800 sal_Int32 parameterCount= Params.getLength();
801 sal_Int32 outParameterCount= 0;
802 typelib_InterfaceMethodTypeDescription* pMethod= NULL;
803 TypeDescription methodDesc;
804 getMethodInfo(sFunctionName, methodDesc);
806 // We need to know whether the IDispatch is from a JScript object.
807 // Then out and in/out parameters have to be treated differently than
808 // with common COM objects.
809 sal_Bool bJScriptObject= isJScriptObject();
810 scoped_array<CComVariant> sarParams;
811 scoped_array<CComVariant> sarParamsRef;
812 CComVariant *pVarParams= NULL;
813 CComVariant *pVarParamsRef= NULL;
814 sal_Bool bConvRet= sal_True;
816 if( methodDesc.is())
818 pMethod = (typelib_InterfaceMethodTypeDescription* )methodDesc.get();
819 parameterCount = pMethod->nParams;
820 // Create the Array for the array being passed in DISPPARAMS
821 // the array also contains the outparameter (but not the values)
822 if( pMethod->nParams > 0)
824 sarParams.reset(new CComVariant[ parameterCount]);
825 pVarParams = sarParams.get();
828 // Create the Array for the out an in/out parameter. These values
829 // are referenced by the VT_BYREF VARIANTs in DISPPARAMS.
830 // We need to find out the number of out and in/out parameter.
831 for( sal_Int32 i=0; i < parameterCount; i++)
833 if( pMethod->pParams[i].bOut)
834 outParameterCount++;
837 if( !bJScriptObject)
839 sarParamsRef.reset(new CComVariant[outParameterCount]);
840 pVarParamsRef = sarParamsRef.get();
841 // build up the parameters for IDispatch::Invoke
842 sal_Int32 outParamIndex=0;
843 int i = 0;
846 for( i= 0; i < parameterCount; i++)
848 // In parameter
849 if( pMethod->pParams[i].bIn == sal_True && ! pMethod->pParams[i].bOut)
851 anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]);
853 // Out parameter + in/out parameter
854 else if( pMethod->pParams[i].bOut == sal_True)
856 CComVariant var;
857 if(pMethod->pParams[i].bIn)
859 anyToVariant( & var,Params[i]);
860 pVarParamsRef[outParamIndex] = var;
863 switch( pMethod->pParams[i].pTypeRef->eTypeClass)
865 case TypeClass_INTERFACE:
866 case TypeClass_STRUCT:
867 if( ! pMethod->pParams[i].bIn)
869 pVarParamsRef[ outParamIndex].vt= VT_DISPATCH;
870 pVarParamsRef[ outParamIndex].pdispVal= 0;
872 pVarParams[parameterCount - i -1].vt = VT_DISPATCH | VT_BYREF;
873 pVarParams[parameterCount - i -1].ppdispVal= &pVarParamsRef[outParamIndex].pdispVal;
874 break;
875 case TypeClass_ENUM:
876 case TypeClass_LONG:
877 case TypeClass_UNSIGNED_LONG:
878 if( ! pMethod->pParams[i].bIn)
880 pVarParamsRef[ outParamIndex].vt = VT_I4;
881 pVarParamsRef[ outParamIndex].lVal = 0;
883 pVarParams[parameterCount - i -1].vt = VT_I4 | VT_BYREF;
884 pVarParams[parameterCount - i -1].plVal= &pVarParamsRef[outParamIndex].lVal;
885 break;
886 case TypeClass_SEQUENCE:
887 if( ! pMethod->pParams[i].bIn)
889 pVarParamsRef[ outParamIndex].vt = VT_ARRAY| VT_VARIANT;
890 pVarParamsRef[ outParamIndex].parray= NULL;
892 pVarParams[parameterCount - i -1].vt = VT_ARRAY| VT_BYREF | VT_VARIANT;
893 pVarParams[parameterCount - i -1].pparray= &pVarParamsRef[outParamIndex].parray;
894 break;
895 case TypeClass_ANY:
896 if( ! pMethod->pParams[i].bIn)
898 pVarParamsRef[ outParamIndex].vt = VT_EMPTY;
899 pVarParamsRef[ outParamIndex].lVal = 0;
901 pVarParams[parameterCount - i -1].vt = VT_VARIANT | VT_BYREF;
902 pVarParams[parameterCount - i -1].pvarVal = &pVarParamsRef[outParamIndex];
903 break;
904 case TypeClass_BOOLEAN:
905 if( ! pMethod->pParams[i].bIn)
907 pVarParamsRef[ outParamIndex].vt = VT_BOOL;
908 pVarParamsRef[ outParamIndex].boolVal = 0;
910 pVarParams[parameterCount - i -1].vt = VT_BOOL| VT_BYREF;
911 pVarParams[parameterCount - i -1].pboolVal =
912 & pVarParamsRef[outParamIndex].boolVal;
913 break;
915 case TypeClass_STRING:
916 if( ! pMethod->pParams[i].bIn)
918 pVarParamsRef[ outParamIndex].vt = VT_BSTR;
919 pVarParamsRef[ outParamIndex].bstrVal= 0;
921 pVarParams[parameterCount - i -1].vt = VT_BSTR| VT_BYREF;
922 pVarParams[parameterCount - i -1].pbstrVal=
923 & pVarParamsRef[outParamIndex].bstrVal;
924 break;
926 case TypeClass_FLOAT:
927 if( ! pMethod->pParams[i].bIn)
929 pVarParamsRef[ outParamIndex].vt = VT_R4;
930 pVarParamsRef[ outParamIndex].fltVal= 0;
932 pVarParams[parameterCount - i -1].vt = VT_R4| VT_BYREF;
933 pVarParams[parameterCount - i -1].pfltVal =
934 & pVarParamsRef[outParamIndex].fltVal;
935 break;
936 case TypeClass_DOUBLE:
937 if( ! pMethod->pParams[i].bIn)
939 pVarParamsRef[ outParamIndex].vt = VT_R8;
940 pVarParamsRef[ outParamIndex].dblVal= 0;
942 pVarParams[parameterCount - i -1].vt = VT_R8| VT_BYREF;
943 pVarParams[parameterCount - i -1].pdblVal=
944 & pVarParamsRef[outParamIndex].dblVal;
945 break;
946 case TypeClass_BYTE:
947 if( ! pMethod->pParams[i].bIn)
949 pVarParamsRef[ outParamIndex].vt = VT_UI1;
950 pVarParamsRef[ outParamIndex].bVal= 0;
952 pVarParams[parameterCount - i -1].vt = VT_UI1| VT_BYREF;
953 pVarParams[parameterCount - i -1].pbVal=
954 & pVarParamsRef[outParamIndex].bVal;
955 break;
956 case TypeClass_CHAR:
957 case TypeClass_SHORT:
958 case TypeClass_UNSIGNED_SHORT:
959 if( ! pMethod->pParams[i].bIn)
961 pVarParamsRef[ outParamIndex].vt = VT_I2;
962 pVarParamsRef[ outParamIndex].iVal = 0;
964 pVarParams[parameterCount - i -1].vt = VT_I2| VT_BYREF;
965 pVarParams[parameterCount - i -1].piVal=
966 & pVarParamsRef[outParamIndex].iVal;
967 break;
969 default:
970 if( ! pMethod->pParams[i].bIn)
972 pVarParamsRef[ outParamIndex].vt = VT_EMPTY;
973 pVarParamsRef[ outParamIndex].lVal = 0;
975 pVarParams[parameterCount - i -1].vt = VT_VARIANT | VT_BYREF;
976 pVarParams[parameterCount - i -1].pvarVal =
977 & pVarParamsRef[outParamIndex];
979 outParamIndex++;
980 } // end else if
981 } // end for
983 catch (IllegalArgumentException & e)
985 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
986 throw;
988 catch (CannotConvertException & e)
990 e.ArgumentIndex = i;
991 throw;
994 else // it is an JScriptObject
996 int i = 0;
999 for( ; i< parameterCount; i++)
1001 // In parameter
1002 if( pMethod->pParams[i].bIn == sal_True && ! pMethod->pParams[i].bOut)
1004 anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]);
1006 // Out parameter + in/out parameter
1007 else if( pMethod->pParams[i].bOut == sal_True)
1009 CComObject<JScriptOutParam>* pParamObject;
1010 if( SUCCEEDED( CComObject<JScriptOutParam>::CreateInstance( &pParamObject)))
1012 CComPtr<IUnknown> pUnk(pParamObject->GetUnknown());
1013 #ifdef __MINGW32__
1014 CComQIPtr<IDispatch, &__uuidof(IDispatch)> pDisp( pUnk);
1015 #else
1016 CComQIPtr<IDispatch> pDisp( pUnk);
1017 #endif
1019 pVarParams[ parameterCount - i -1].vt= VT_DISPATCH;
1020 pVarParams[ parameterCount - i -1].pdispVal= pDisp;
1021 pVarParams[ parameterCount - i -1].pdispVal->AddRef();
1022 // if the param is in/out then put the parameter on index 0
1023 if( pMethod->pParams[i].bIn == sal_True ) // in / out
1025 CComVariant varParam;
1026 anyToVariant( &varParam, Params.getConstArray()[i]);
1027 CComDispatchDriver dispDriver( pDisp);
1028 if(FAILED( dispDriver.PutPropertyByName( L"0", &varParam)))
1029 throw BridgeRuntimeError(
1030 "[automation bridge]IUnknownWrapper_Impl::"
1031 "invokeWithDispIdUnoTlb\n"
1032 "Could not set property \"0\" for the in/out "
1033 "param!");
1037 else
1039 throw BridgeRuntimeError(
1040 "[automation bridge]IUnknownWrapper_Impl::"
1041 "invokeWithDispIdUnoTlb\n"
1042 "Could not create out parameter at index: " +
1043 OUString::valueOf((sal_Int32) i));
1049 catch (IllegalArgumentException & e)
1051 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
1052 throw;
1054 catch (CannotConvertException & e)
1056 e.ArgumentIndex = i;
1057 throw;
1061 // No type description Available, that is we have to deal with a COM component,
1062 // that does not implements UNO interfaces ( IDispatch based)
1063 else
1065 //We should not run into this block, because invokeWithDispIdComTlb should
1066 //have been called instead.
1067 OSL_ASSERT(0);
1071 CComVariant varResult;
1072 ExcepInfo excepinfo;
1073 unsigned int uArgErr;
1074 DISPPARAMS dispparams= { pVarParams, NULL, parameterCount, 0};
1075 // Get the DISPID
1076 FuncDesc aDesc(getTypeInfo());
1077 getFuncDesc(sFunctionName, & aDesc);
1078 // invoking OLE method
1079 hr = m_spDispatch->Invoke(aDesc->memid,
1080 IID_NULL,
1081 LOCALE_USER_DEFAULT,
1082 DISPATCH_METHOD,
1083 &dispparams,
1084 &varResult,
1085 &excepinfo,
1086 &uArgErr);
1088 // converting return value and out parameter back to UNO
1089 if (hr == S_OK)
1091 if( outParameterCount && pMethod)
1093 OutParamIndex.realloc( outParameterCount);
1094 OutParam.realloc( outParameterCount);
1095 sal_Int32 outIndex=0;
1096 int i = 0;
1099 for( ; i < parameterCount; i++)
1101 if( pMethod->pParams[i].bOut )
1103 OutParamIndex[outIndex]= (sal_Int16) i;
1104 Any outAny;
1105 if( !bJScriptObject)
1107 variantToAny( &pVarParamsRef[outIndex], outAny,
1108 Type(pMethod->pParams[i].pTypeRef), sal_False);
1109 OutParam[outIndex++]= outAny;
1111 else //JScriptObject
1113 if( pVarParams[i].vt == VT_DISPATCH)
1115 CComDispatchDriver pDisp( pVarParams[i].pdispVal);
1116 if( pDisp)
1118 CComVariant varOut;
1119 if( SUCCEEDED( pDisp.GetPropertyByName( L"0", &varOut)))
1121 variantToAny( &varOut, outAny,
1122 Type(pMethod->pParams[parameterCount - 1 - i].pTypeRef), sal_False);
1123 OutParam[outParameterCount - 1 - outIndex++]= outAny;
1125 else
1126 bConvRet= sal_False;
1128 else
1129 bConvRet= sal_False;
1131 else
1132 bConvRet= sal_False;
1135 if( !bConvRet) break;
1138 catch(IllegalArgumentException & e)
1140 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
1141 throw;
1143 catch(CannotConvertException & e)
1145 e.ArgumentIndex = i;
1146 throw;
1149 // return value, no type information available
1150 if ( bConvRet)
1154 if( pMethod )
1155 variantToAny(&varResult, ret, Type( pMethod->pReturnTypeRef), sal_False);
1156 else
1157 variantToAny(&varResult, ret, sal_False);
1159 catch (IllegalArgumentException & e)
1161 e.Message =
1162 "[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1163 "Could not convert return value! \n Message: \n" + e.Message;
1164 throw;
1166 catch (CannotConvertException & e)
1168 e.Message =
1169 "[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1170 "Could not convert return value! \n Message: \n" + e.Message;
1171 throw;
1176 if( !bConvRet) // conversion of return or out parameter failed
1177 throw CannotConvertException( OUString("Call to COM object failed. Conversion of return or out value failed"),
1178 Reference<XInterface>( static_cast<XWeak*>(this), UNO_QUERY ), TypeClass_UNKNOWN,
1179 FailReason::UNKNOWN, 0);// lookup error code
1180 // conversion of return or out parameter failed
1181 switch (hr)
1183 case S_OK:
1184 break;
1185 case DISP_E_BADPARAMCOUNT:
1186 throw IllegalArgumentException();
1187 break;
1188 case DISP_E_BADVARTYPE:
1189 throw RuntimeException();
1190 break;
1191 case DISP_E_EXCEPTION:
1192 throw InvocationTargetException();
1193 break;
1194 case DISP_E_MEMBERNOTFOUND:
1195 throw IllegalArgumentException();
1196 break;
1197 case DISP_E_NONAMEDARGS:
1198 throw IllegalArgumentException();
1199 break;
1200 case DISP_E_OVERFLOW:
1201 throw CannotConvertException(OUString("call to OLE object failed"), static_cast<XInterface*>(
1202 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
1203 break;
1204 case DISP_E_PARAMNOTFOUND:
1205 throw IllegalArgumentException(OUString("call to OLE object failed"), static_cast<XInterface*>(
1206 static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
1207 break;
1208 case DISP_E_TYPEMISMATCH:
1209 throw CannotConvertException(OUString("call to OLE object failed"),static_cast<XInterface*>(
1210 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr);
1211 break;
1212 case DISP_E_UNKNOWNINTERFACE:
1213 throw RuntimeException() ;
1214 break;
1215 case DISP_E_UNKNOWNLCID:
1216 throw RuntimeException() ;
1217 break;
1218 case DISP_E_PARAMNOTOPTIONAL:
1219 throw CannotConvertException(OUString("call to OLE object failed"), static_cast<XInterface*>(
1220 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
1221 break;
1222 default:
1223 throw RuntimeException();
1224 break;
1227 return ret;
1232 // --------------------------
1233 // XInitialization
1234 void SAL_CALL IUnknownWrapper_Impl::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException)
1236 // 1.parameter is IUnknown
1237 // 2.parameter is a boolean which indicates if the COM pointer was a IUnknown or IDispatch
1238 // 3.parameter is a Sequence<Type>
1239 o2u_attachCurrentThread();
1240 OSL_ASSERT(aArguments.getLength() == 3);
1242 m_spUnknown= *(IUnknown**) aArguments[0].getValue();
1243 #ifdef __MINGW32__
1244 m_spUnknown->QueryInterface(IID_IDispatch, reinterpret_cast<LPVOID*>( & m_spDispatch.p));
1245 #else
1246 m_spUnknown.QueryInterface( & m_spDispatch.p);
1247 #endif
1249 aArguments[1] >>= m_bOriginalDispatch;
1250 aArguments[2] >>= m_seqTypes;
1252 ITypeInfo* pType = NULL;
1255 // a COM object implementation that has no TypeInfo is still a legal COM object;
1256 // such objects can at least be transported through UNO using the bridge
1257 // so we should allow to create wrappers for them as well
1258 pType = getTypeInfo();
1260 catch( const BridgeRuntimeError& )
1262 catch( const Exception& )
1265 if ( pType )
1269 // Get Default member
1270 CComBSTR defaultMemberName;
1271 if ( SUCCEEDED( pType->GetDocumentation(0, &defaultMemberName, 0, 0, 0 ) ) )
1273 OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(defaultMemberName)));
1274 FuncDesc aDescGet(pType);
1275 FuncDesc aDescPut(pType);
1276 VarDesc aVarDesc(pType);
1277 // see if this is a property first ( more likely to be a property then a method )
1278 getPropDesc( usName, & aDescGet, & aDescPut, & aVarDesc);
1280 if ( !aDescGet && !aDescPut )
1282 getFuncDesc( usName, &aDescGet );
1283 if ( !aDescGet )
1284 throw BridgeRuntimeError( "[automation bridge]IUnknownWrapper_Impl::initialize() Failed to get Function or Property desc. for " + usName );
1286 // now for some funny heuristics to make basic understand what to do
1287 // a single aDescGet ( that doesn't take any params ) would be
1288 // a read only ( defaultmember ) property e.g. this object
1289 // should implement XDefaultProperty
1290 // a single aDescGet ( that *does* ) take params is basically a
1291 // default method e.g. implement XDefaultMethod
1293 // 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 )
1294 if ( aDescPut || ( aDescGet && aDescGet->cParams == 0 ) )
1295 m_bHasDfltProperty = true;
1296 if ( aDescGet->cParams > 0 )
1297 m_bHasDfltMethod = true;
1298 if ( m_bHasDfltProperty || m_bHasDfltMethod )
1299 m_sDefaultMember = usName;
1302 catch ( const BridgeRuntimeError & e )
1304 throw RuntimeException( e.message, Reference<XInterface>() );
1306 catch( const Exception& e )
1308 throw RuntimeException(
1309 "[automation bridge] unexpected exception in IUnknownWrapper_Impl::initialiase() error message: \n" + e.Message,
1310 Reference<XInterface>() );
1315 // --------------------------
1316 // XDirectInvocation
1317 uno::Any SAL_CALL IUnknownWrapper_Impl::directInvoke( const OUString& aName, const uno::Sequence< uno::Any >& aParams )
1318 throw (lang::IllegalArgumentException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException)
1320 Any aResult;
1322 if ( !m_spDispatch )
1324 throw RuntimeException(
1325 "[automation bridge] The object does not have an IDispatch interface",
1326 Reference<XInterface>());
1329 o2u_attachCurrentThread();
1330 DISPID dispid;
1331 if ( !getDispid( aName, &dispid ) )
1332 throw IllegalArgumentException(
1333 "[automation bridge] The object does not have a function or property "
1334 + aName, Reference<XInterface>(), 0);
1336 CComVariant varResult;
1337 ExcepInfo excepinfo;
1338 unsigned int uArgErr = 0;
1339 INVOKEKIND pInvkinds[2];
1340 pInvkinds[0] = INVOKE_FUNC;
1341 pInvkinds[1] = aParams.getLength() ? INVOKE_PROPERTYPUT : INVOKE_PROPERTYGET;
1342 HRESULT hInvRes = E_FAIL;
1344 // try Invoke first, if it does not work, try put/get property
1345 for ( sal_Int32 nStep = 0; FAILED( hInvRes ) && nStep < 2; nStep++ )
1347 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1349 DISPID idPropertyPut = DISPID_PROPERTYPUT;
1350 scoped_array<DISPID> arDispidNamedArgs;
1351 scoped_array<CComVariant> ptrArgs;
1352 scoped_array<CComVariant> ptrRefArgs; // referenced arguments
1353 CComVariant * arArgs = NULL;
1354 CComVariant * arRefArgs = NULL;
1356 dispparams.cArgs = aParams.getLength();
1358 // Determine the number of named arguments
1359 for ( sal_Int32 nInd = 0; nInd < aParams.getLength(); nInd++ )
1360 if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0) )
1361 dispparams.cNamedArgs ++;
1363 // fill the named arguments
1364 if ( dispparams.cNamedArgs > 0
1365 && !( dispparams.cNamedArgs == 1 && pInvkinds[nStep] == INVOKE_PROPERTYPUT ) )
1367 int nSizeAr = dispparams.cNamedArgs + 1;
1368 if ( pInvkinds[nStep] == INVOKE_PROPERTYPUT )
1369 nSizeAr = dispparams.cNamedArgs;
1371 scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]);
1372 OLECHAR ** pNames = saNames.get();
1373 pNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(aName.getStr()));
1375 int cNamedArg = 0;
1376 for ( size_t nInd = 0; nInd < dispparams.cArgs; nInd++ )
1378 if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0))
1380 const NamedArgument& arg = *(NamedArgument const*)aParams[nInd].getValue();
1382 //We put the parameter names in reverse order into the array,
1383 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1384 //The first name in the array is the method name
1385 pNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr()));
1389 arDispidNamedArgs.reset( new DISPID[nSizeAr] );
1390 HRESULT hr = getTypeInfo()->GetIDsOfNames( pNames, nSizeAr, arDispidNamedArgs.get() );
1391 if ( hr == E_NOTIMPL )
1392 hr = m_spDispatch->GetIDsOfNames(IID_NULL, pNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() );
1394 if ( SUCCEEDED( hr ) )
1396 if ( pInvkinds[nStep] == DISPATCH_PROPERTYPUT )
1398 DISPID* arIDs = arDispidNamedArgs.get();
1399 arIDs[0] = DISPID_PROPERTYPUT;
1400 dispparams.rgdispidNamedArgs = arIDs;
1402 else
1404 DISPID* arIDs = arDispidNamedArgs.get();
1405 dispparams.rgdispidNamedArgs = & arIDs[1];
1408 else if (hr == DISP_E_UNKNOWNNAME)
1410 throw IllegalArgumentException(
1411 "[automation bridge]One of the named arguments is wrong!",
1412 Reference<XInterface>(), 0);
1414 else
1416 throw InvocationTargetException(
1417 "[automation bridge] ITypeInfo::GetIDsOfNames returned error "
1418 + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any());
1422 //Convert arguments
1423 ptrArgs.reset(new CComVariant[dispparams.cArgs]);
1424 ptrRefArgs.reset(new CComVariant[dispparams.cArgs]);
1425 arArgs = ptrArgs.get();
1426 arRefArgs = ptrRefArgs.get();
1428 sal_Int32 nInd = 0;
1431 sal_Int32 revIndex = 0;
1432 for ( nInd = 0; nInd < sal_Int32(dispparams.cArgs); nInd++)
1434 revIndex = dispparams.cArgs - nInd - 1;
1435 arRefArgs[revIndex].byref = 0;
1436 Any anyArg;
1437 if ( nInd < aParams.getLength() )
1438 anyArg = aParams.getConstArray()[nInd];
1440 // Property Put arguments
1441 if ( anyArg.getValueType() == getCppuType((PropertyPutArgument*)0) )
1443 PropertyPutArgument arg;
1444 anyArg >>= arg;
1445 anyArg <<= arg.Value;
1447 // named argument
1448 if (anyArg.getValueType() == getCppuType((NamedArgument*) 0))
1450 NamedArgument aNamedArgument;
1451 anyArg >>= aNamedArgument;
1452 anyArg <<= aNamedArgument.Value;
1455 if ( nInd < aParams.getLength() && anyArg.getValueTypeClass() != TypeClass_VOID )
1457 anyToVariant( &arArgs[revIndex], anyArg, VT_VARIANT );
1459 else
1461 arArgs[revIndex].vt = VT_ERROR;
1462 arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1466 catch (IllegalArgumentException & e)
1468 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( nInd );
1469 throw;
1471 catch (CannotConvertException & e)
1473 e.ArgumentIndex = nInd;
1474 throw;
1477 dispparams.rgvarg = arArgs;
1478 // invoking OLE method
1479 DWORD localeId = LOCALE_USER_DEFAULT;
1480 hInvRes = m_spDispatch->Invoke( dispid,
1481 IID_NULL,
1482 localeId,
1483 ::sal::static_int_cast< WORD, INVOKEKIND >( pInvkinds[nStep] ),
1484 &dispparams,
1485 &varResult,
1486 &excepinfo,
1487 &uArgErr);
1490 // converting return value and out parameter back to UNO
1491 if ( SUCCEEDED( hInvRes ) )
1492 variantToAny( &varResult, aResult, sal_False );
1493 else
1495 // map error codes to exceptions
1496 OUString message;
1497 switch ( hInvRes )
1499 case S_OK:
1500 break;
1501 case DISP_E_BADPARAMCOUNT:
1502 throw IllegalArgumentException("[automation bridge] Wrong "
1503 "number of arguments. Object returned DISP_E_BADPARAMCOUNT.",
1504 0, 0);
1505 break;
1506 case DISP_E_BADVARTYPE:
1507 throw RuntimeException("[automation bridge] One or more "
1508 "arguments have the wrong type. Object returned "
1509 "DISP_E_BADVARTYPE.", 0);
1510 break;
1511 case DISP_E_EXCEPTION:
1512 message = "[automation bridge]: ";
1513 message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription),
1514 ::SysStringLen(excepinfo.bstrDescription));
1515 throw InvocationTargetException(message, Reference<XInterface>(), Any());
1516 break;
1517 case DISP_E_MEMBERNOTFOUND:
1518 message = "[automation bridge]: A function with the name \""
1519 + aName + "\" is not supported. Object returned "
1520 "DISP_E_MEMBERNOTFOUND.";
1521 throw IllegalArgumentException(message, 0, 0);
1522 break;
1523 case DISP_E_NONAMEDARGS:
1524 throw IllegalArgumentException("[automation bridge] Object "
1525 "returned DISP_E_NONAMEDARGS",0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
1526 break;
1527 case DISP_E_OVERFLOW:
1528 throw CannotConvertException(OUString("[automation bridge] Call failed."),
1529 static_cast<XInterface*>(
1530 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
1531 break;
1532 case DISP_E_PARAMNOTFOUND:
1533 throw IllegalArgumentException("[automation bridge]Call failed."
1534 "Object returned DISP_E_PARAMNOTFOUND.",
1535 0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
1536 break;
1537 case DISP_E_TYPEMISMATCH:
1538 throw CannotConvertException("[automation bridge] Call failed. "
1539 "Object returned DISP_E_TYPEMISMATCH",
1540 static_cast<XInterface*>(
1541 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr);
1542 break;
1543 case DISP_E_UNKNOWNINTERFACE:
1544 throw RuntimeException("[automation bridge] Call failed. "
1545 "Object returned DISP_E_UNKNOWNINTERFACE.",0);
1546 break;
1547 case DISP_E_UNKNOWNLCID:
1548 throw RuntimeException("[automation bridge] Call failed. "
1549 "Object returned DISP_E_UNKNOWNLCID.",0);
1550 break;
1551 case DISP_E_PARAMNOTOPTIONAL:
1552 throw CannotConvertException("[automation bridge] Call failed."
1553 "Object returned DISP_E_PARAMNOTOPTIONAL",
1554 static_cast<XInterface*>(static_cast<XWeak*>(this)),
1555 TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
1556 break;
1557 default:
1558 throw RuntimeException();
1559 break;
1563 return aResult;
1566 ::sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMember( const OUString& aName )
1567 throw (uno::RuntimeException)
1569 if ( ! m_spDispatch )
1571 throw RuntimeException(
1572 "[automation bridge] The object does not have an IDispatch interface",
1573 Reference<XInterface>());
1576 o2u_attachCurrentThread();
1577 DISPID dispid;
1578 return getDispid( aName, &dispid );
1582 // UnoConversionUtilities --------------------------------------------------------------------------------
1583 Reference< XInterface > IUnknownWrapper_Impl::createUnoWrapperInstance()
1585 if( m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL)
1587 Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl(
1588 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1589 return Reference<XInterface>( xWeak, UNO_QUERY);
1591 else if( m_nUnoWrapperClass == UNO_OBJECT_WRAPPER_REMOTE_OPT)
1593 Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
1594 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1595 return Reference<XInterface>( xWeak, UNO_QUERY);
1597 else
1598 return Reference<XInterface>();
1600 Reference<XInterface> IUnknownWrapper_Impl::createComWrapperInstance()
1602 Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl(
1603 m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1604 return Reference<XInterface>( xWeak, UNO_QUERY);
1609 void IUnknownWrapper_Impl::getMethodInfo(const OUString& sName, TypeDescription& methodInfo)
1611 TypeDescription desc= getInterfaceMemberDescOfCurrentCall(sName);
1612 if( desc.is())
1614 typelib_TypeDescription* pMember= desc.get();
1615 if( pMember->eTypeClass == TypeClass_INTERFACE_METHOD )
1616 methodInfo= pMember;
1620 void IUnknownWrapper_Impl::getAttributeInfo(const OUString& sName, TypeDescription& attributeInfo)
1622 TypeDescription desc= getInterfaceMemberDescOfCurrentCall(sName);
1623 if( desc.is())
1625 typelib_TypeDescription* pMember= desc.get();
1626 if( pMember->eTypeClass == TypeClass_INTERFACE_ATTRIBUTE )
1628 attributeInfo= ((typelib_InterfaceAttributeTypeDescription*)pMember)->pAttributeTypeRef;
1632 TypeDescription IUnknownWrapper_Impl::getInterfaceMemberDescOfCurrentCall(const OUString& sName)
1634 TypeDescription ret;
1636 for( sal_Int32 i=0; i < m_seqTypes.getLength(); i++)
1638 TypeDescription _curDesc( m_seqTypes[i]);
1639 _curDesc.makeComplete();
1640 typelib_InterfaceTypeDescription * pInterface= (typelib_InterfaceTypeDescription*) _curDesc.get();
1641 if( pInterface)
1643 typelib_InterfaceMemberTypeDescription* pMember= NULL;
1644 //find the member description of the current call
1645 for( int i=0; i < pInterface->nAllMembers; i++)
1647 typelib_TypeDescriptionReference* pTypeRefMember = pInterface->ppAllMembers[i];
1648 typelib_TypeDescription* pDescMember= NULL;
1649 TYPELIB_DANGER_GET( &pDescMember, pTypeRefMember)
1651 typelib_InterfaceMemberTypeDescription* pInterfaceMember=
1652 (typelib_InterfaceMemberTypeDescription*) pDescMember;
1653 if( OUString( pInterfaceMember->pMemberName) == sName)
1655 pMember= pInterfaceMember;
1656 break;
1658 TYPELIB_DANGER_RELEASE( pDescMember)
1661 if( pMember)
1663 ret= (typelib_TypeDescription*)pMember;
1664 TYPELIB_DANGER_RELEASE( (typelib_TypeDescription*)pMember);
1667 if( ret.is())
1668 break;
1670 return ret;
1673 sal_Bool IUnknownWrapper_Impl::isJScriptObject()
1675 if( m_eJScript == JScriptUndefined)
1677 CComDispatchDriver disp( m_spDispatch);
1678 if( disp)
1680 CComVariant result;
1681 if( SUCCEEDED( disp.GetPropertyByName( JSCRIPT_ID_PROPERTY, &result)))
1683 if(result.vt == VT_BSTR)
1685 CComBSTR name( result.bstrVal);
1686 name.ToLower();
1687 if( name == CComBSTR(JSCRIPT_ID))
1688 m_eJScript= IsJScript;
1692 if( m_eJScript == JScriptUndefined)
1693 m_eJScript= NoJScript;
1696 return m_eJScript == NoJScript ? sal_False : sal_True;
1701 /** @internal
1702 The function ultimately calls IDispatch::Invoke on the wrapped COM object.
1703 The COM object does not implement UNO Interfaces ( via IDispatch). This
1704 is the case when the OleObjectFactory service has been used to create a
1705 component.
1706 @exception IllegalArgumentException
1707 @exception CannotConvertException
1708 @InvocationTargetException
1709 @RuntimeException
1710 @BridgeRuntimeError
1712 Any IUnknownWrapper_Impl::invokeWithDispIdComTlb(const OUString& sFuncName,
1713 const Sequence< Any >& Params,
1714 Sequence< sal_Int16 >& OutParamIndex,
1715 Sequence< Any >& OutParam)
1717 // Get type info for the call. It can be a method call or property put or
1718 // property get operation.
1719 FuncDesc aFuncDesc(getTypeInfo());
1720 getFuncDescForInvoke(sFuncName, Params, & aFuncDesc);
1721 return invokeWithDispIdComTlb( aFuncDesc, sFuncName, Params, OutParamIndex, OutParam );
1724 Any IUnknownWrapper_Impl::invokeWithDispIdComTlb(FuncDesc& aFuncDesc,
1725 const OUString& sFuncName,
1726 const Sequence< Any >& Params,
1727 Sequence< sal_Int16 >& OutParamIndex,
1728 Sequence< Any >& OutParam)
1730 Any ret;
1731 HRESULT result;
1733 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1734 CComVariant varResult;
1735 ExcepInfo excepinfo;
1736 unsigned int uArgErr;
1737 sal_Int32 i = 0;
1738 sal_Int32 nUnoArgs = Params.getLength();
1739 DISPID idPropertyPut = DISPID_PROPERTYPUT;
1740 scoped_array<DISPID> arDispidNamedArgs;
1741 scoped_array<CComVariant> ptrArgs;
1742 scoped_array<CComVariant> ptrRefArgs; // referenced arguments
1743 CComVariant * arArgs = NULL;
1744 CComVariant * arRefArgs = NULL;
1745 sal_Int32 revIndex = 0;
1747 //Set the array of DISPIDs for named args if it is a property put operation.
1748 //If there are other named arguments another array is set later on.
1749 if (aFuncDesc->invkind == INVOKE_PROPERTYPUT
1750 || aFuncDesc->invkind == INVOKE_PROPERTYPUTREF)
1751 dispparams.rgdispidNamedArgs = & idPropertyPut;
1753 //Determine the number of named arguments
1754 for (int iParam = 0; iParam < nUnoArgs; iParam ++)
1756 const Any & curArg = Params[iParam];
1757 if (curArg.getValueType() == getCppuType((NamedArgument*) 0))
1758 dispparams.cNamedArgs ++;
1760 //In a property put operation a property value is a named argument (DISPID_PROPERTYPUT).
1761 //Therefore the number of named arguments is increased by one.
1762 //Although named, the argument is not named in a actual language, such as Basic,
1763 //therefore it is never a com.sun.star.bridge.oleautomation.NamedArgument
1764 if (aFuncDesc->invkind == DISPATCH_PROPERTYPUT
1765 || aFuncDesc->invkind == DISPATCH_PROPERTYPUTREF)
1766 dispparams.cNamedArgs ++;
1768 //Determine the number of all arguments and named arguments
1769 if (aFuncDesc->cParamsOpt == -1)
1771 //Attribute vararg is set on this method. "Unlimited" number of args
1772 //supported. There can be no optional or defaultvalue on any of the arguments.
1773 dispparams.cArgs = nUnoArgs;
1775 else
1777 //If there are namesd arguments, then the dispparams.cArgs
1778 //is the number of supplied args, otherwise it is the expected number.
1779 if (dispparams.cNamedArgs)
1780 dispparams.cArgs = nUnoArgs;
1781 else
1782 dispparams.cArgs = aFuncDesc->cParams;
1785 //check if there are not to many arguments supplied
1786 if (::sal::static_int_cast< sal_uInt32, int >( nUnoArgs ) > dispparams.cArgs)
1788 OUStringBuffer buf(256);
1789 buf.appendAscii("[automation bridge] There are too many arguments for this method");
1790 throw IllegalArgumentException( buf.makeStringAndClear(),
1791 Reference<XInterface>(), (sal_Int16) dispparams.cArgs);
1794 //Set up the array of DISPIDs (DISPPARAMS::rgdispidNamedArgs)
1795 //for the named arguments.
1796 //If there is only one named arg and if it is because of a property put
1797 //operation, then we need not set up the DISPID array.
1798 if (dispparams.cNamedArgs > 0 &&
1799 ! (dispparams.cNamedArgs == 1 &&
1800 (aFuncDesc->invkind == INVOKE_PROPERTYPUT ||
1801 aFuncDesc->invkind == INVOKE_PROPERTYPUTREF)))
1803 //set up an array containing the member and parameter names
1804 //which is then used in ITypeInfo::GetIDsOfNames
1805 //First determine the size of the array of names which is passed to
1806 //ITypeInfo::GetIDsOfNames. It must hold the method names + the named
1807 //args.
1808 int nSizeAr = dispparams.cNamedArgs + 1;
1809 if (aFuncDesc->invkind == INVOKE_PROPERTYPUT
1810 || aFuncDesc->invkind == INVOKE_PROPERTYPUTREF)
1812 nSizeAr = dispparams.cNamedArgs; //counts the DISID_PROPERTYPUT
1815 scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]);
1816 OLECHAR ** arNames = saNames.get();
1817 arNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(sFuncName.getStr()));
1819 int cNamedArg = 0;
1820 for (size_t iParams = 0; iParams < dispparams.cArgs; iParams ++)
1822 const Any & curArg = Params[iParams];
1823 if (curArg.getValueType() == getCppuType((NamedArgument*) 0))
1825 const NamedArgument& arg = *(NamedArgument const*) curArg.getValue();
1826 //We put the parameter names in reverse order into the array,
1827 //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1828 //The first name in the array is the method name
1829 arNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr()));
1833 //Prepare the array of DISPIDs for ITypeInfo::GetIDsOfNames
1834 //it must be big enough to contain the DISPIDs of the member + parameters
1835 arDispidNamedArgs.reset(new DISPID[nSizeAr]);
1836 HRESULT hr = getTypeInfo()->GetIDsOfNames(arNames, nSizeAr,
1837 arDispidNamedArgs.get());
1838 if ( hr == E_NOTIMPL )
1839 hr = m_spDispatch->GetIDsOfNames(IID_NULL, arNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() );
1841 if (hr == S_OK)
1843 // In a "property put" operation, the property value is a named param with the
1844 //special DISPID DISPID_PROPERTYPUT
1845 if (aFuncDesc->invkind == DISPATCH_PROPERTYPUT
1846 || aFuncDesc->invkind == DISPATCH_PROPERTYPUTREF)
1848 //Element at index 0 in the DISPID array must be DISPID_PROPERTYPUT
1849 //The first item in the array arDispidNamedArgs is the DISPID for
1850 //the method. We replace it with DISPID_PROPERTYPUT.
1851 DISPID* arIDs = arDispidNamedArgs.get();
1852 arIDs[0] = DISPID_PROPERTYPUT;
1853 dispparams.rgdispidNamedArgs = arIDs;
1855 else
1857 //The first item in the array arDispidNamedArgs is the DISPID for
1858 //the method. It must be removed
1859 DISPID* arIDs = arDispidNamedArgs.get();
1860 dispparams.rgdispidNamedArgs = & arIDs[1];
1863 else if (hr == DISP_E_UNKNOWNNAME)
1865 throw IllegalArgumentException(
1866 "[automation bridge]One of the named arguments is wrong!",
1867 Reference<XInterface>(), 0);
1869 else
1871 throw InvocationTargetException(
1872 "[automation bridge] ITypeInfo::GetIDsOfNames returned error "
1873 + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any());
1877 //Convert arguments
1878 ptrArgs.reset(new CComVariant[dispparams.cArgs]);
1879 ptrRefArgs.reset(new CComVariant[dispparams.cArgs]);
1880 arArgs = ptrArgs.get();
1881 arRefArgs = ptrRefArgs.get();
1884 for (i = 0; i < (sal_Int32) dispparams.cArgs; i++)
1886 revIndex= dispparams.cArgs - i -1;
1887 arRefArgs[revIndex].byref=0;
1888 Any anyArg;
1889 if ( i < nUnoArgs)
1890 anyArg= Params.getConstArray()[i];
1892 unsigned short paramFlags = PARAMFLAG_FOPT | PARAMFLAG_FIN;
1893 VARTYPE varType = VT_VARIANT;
1894 if (aFuncDesc->cParamsOpt != -1 || aFuncDesc->cParams != (i + 1))
1896 paramFlags = aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags;
1897 varType = getElementTypeDesc(&aFuncDesc->lprgelemdescParam[i].tdesc);
1900 // Make sure that there is a UNO parameter for every
1901 // expected parameter. If there is no UNO parameter where the
1902 // called function expects one, then it must be optional. Otherwise
1903 // its a UNO programming error.
1904 if (i >= nUnoArgs && !(paramFlags & PARAMFLAG_FOPT))
1906 OUStringBuffer buf(256);
1907 buf.appendAscii("ole automation bridge: The called function expects an argument at"
1908 "position: "); //a different number of arguments")),
1909 buf.append(OUString::valueOf((sal_Int32) i));
1910 buf.appendAscii(" (index starting at 0).");
1911 throw IllegalArgumentException( buf.makeStringAndClear(),
1912 Reference<XInterface>(), (sal_Int16) i);
1915 // Property Put arguments
1916 if (anyArg.getValueType() == getCppuType((PropertyPutArgument*)0))
1918 PropertyPutArgument arg;
1919 anyArg >>= arg;
1920 anyArg <<= arg.Value;
1922 // named argument
1923 if (anyArg.getValueType() == getCppuType((NamedArgument*) 0))
1925 NamedArgument aNamedArgument;
1926 anyArg >>= aNamedArgument;
1927 anyArg <<= aNamedArgument.Value;
1929 // out param
1930 if (paramFlags & PARAMFLAG_FOUT &&
1931 ! (paramFlags & PARAMFLAG_FIN) )
1933 VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF );
1934 if (i < nUnoArgs)
1936 arRefArgs[revIndex].vt= type;
1938 else
1940 //optional arg
1941 arRefArgs[revIndex].vt = VT_ERROR;
1942 arRefArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1944 if( type == VT_VARIANT )
1946 arArgs[revIndex].vt= VT_VARIANT | VT_BYREF;
1947 arArgs[revIndex].byref= &arRefArgs[revIndex];
1949 else
1951 arArgs[revIndex].vt= varType;
1952 if (type == VT_DECIMAL)
1953 arArgs[revIndex].byref= & arRefArgs[revIndex].decVal;
1954 else
1955 arArgs[revIndex].byref= & arRefArgs[revIndex].byref;
1958 // in/out + in byref params
1959 else if (varType & VT_BYREF)
1961 VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF );
1962 CComVariant var;
1964 if (i < nUnoArgs && anyArg.getValueTypeClass() != TypeClass_VOID)
1966 anyToVariant( & arRefArgs[revIndex], anyArg, type);
1968 else if (paramFlags & PARAMFLAG_FHASDEFAULT)
1970 //optional arg with default
1971 VariantCopy( & arRefArgs[revIndex],
1972 & aFuncDesc->lprgelemdescParam[i].paramdesc.
1973 pparamdescex->varDefaultValue);
1975 else
1977 //optional arg
1978 //e.g: call func(x) in basic : func() ' no arg supplied
1979 OSL_ASSERT(paramFlags & PARAMFLAG_FOPT);
1980 arRefArgs[revIndex].vt = VT_ERROR;
1981 arRefArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1984 // Set the converted arguments in the array which will be
1985 // DISPPARAMS::rgvarg
1986 // byref arg VT_XXX |VT_BYREF
1987 arArgs[revIndex].vt = varType;
1988 if (revIndex == 0 && aFuncDesc->invkind == INVOKE_PROPERTYPUT)
1990 arArgs[revIndex] = arRefArgs[revIndex];
1992 else if (type == VT_DECIMAL)
1994 arArgs[revIndex].byref= & arRefArgs[revIndex].decVal;
1996 else if (type == VT_VARIANT)
1998 if ( ! (paramFlags & PARAMFLAG_FOUT))
1999 arArgs[revIndex] = arRefArgs[revIndex];
2000 else
2001 arArgs[revIndex].byref = & arRefArgs[revIndex];
2003 else
2005 arArgs[revIndex].byref = & arRefArgs[revIndex].byref;
2006 arArgs[revIndex].vt = ::sal::static_int_cast< VARTYPE, int >( arRefArgs[revIndex].vt | VT_BYREF );
2010 // in parameter no VT_BYREF except for array, interfaces
2011 else
2012 { // void any stands for optional param
2013 if (i < nUnoArgs && anyArg.getValueTypeClass() != TypeClass_VOID)
2015 anyToVariant( & arArgs[revIndex], anyArg, varType);
2017 //optional arg but no void any supplied
2018 //Basic: obj.func() ' first parameter left out because it is optional
2019 else if (paramFlags & PARAMFLAG_FHASDEFAULT)
2021 //optional arg with defaulteithter as direct arg : VT_XXX or
2022 VariantCopy( & arArgs[revIndex],
2023 & aFuncDesc->lprgelemdescParam[i].paramdesc.
2024 pparamdescex->varDefaultValue);
2026 else if (paramFlags & PARAMFLAG_FOPT)
2028 arArgs[revIndex].vt = VT_ERROR;
2029 arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
2031 else
2033 arArgs[revIndex].vt = VT_EMPTY;
2034 arArgs[revIndex].lVal = 0;
2039 catch (IllegalArgumentException & e)
2041 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( i );
2042 throw;
2044 catch (CannotConvertException & e)
2046 e.ArgumentIndex = i;
2047 throw;
2049 dispparams.rgvarg= arArgs;
2050 // invoking OLE method
2051 DWORD localeId = LOCALE_USER_DEFAULT;
2052 result = m_spDispatch->Invoke(aFuncDesc->memid,
2053 IID_NULL,
2054 localeId,
2055 ::sal::static_int_cast< WORD, INVOKEKIND >( aFuncDesc->invkind ),
2056 &dispparams,
2057 &varResult,
2058 &excepinfo,
2059 &uArgErr);
2061 // converting return value and out parameter back to UNO
2062 if (result == S_OK)
2065 // allocate space for the out param Sequence and indices Sequence
2066 int outParamsCount= 0; // includes in/out parameter
2067 for (int i = 0; i < aFuncDesc->cParams; i++)
2069 if (aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags &
2070 PARAMFLAG_FOUT)
2071 outParamsCount++;
2074 OutParamIndex.realloc(outParamsCount);
2075 OutParam.realloc(outParamsCount);
2076 // Convert out params
2077 if (outParamsCount)
2079 int outParamIndex=0;
2080 for (int paramIndex = 0; paramIndex < nUnoArgs; paramIndex ++)
2082 //Determine the index within the method sinature
2083 int realParamIndex = paramIndex;
2084 int revParamIndex = dispparams.cArgs - paramIndex - 1;
2085 if (Params[paramIndex].getValueType()
2086 == getCppuType((NamedArgument*) 0))
2088 //dispparams.rgdispidNamedArgs contains the mapping from index
2089 //of named args list to index of parameter list
2090 realParamIndex = dispparams.rgdispidNamedArgs[revParamIndex];
2093 // no named arg, always come before named args
2094 if (! (aFuncDesc->lprgelemdescParam[realParamIndex].paramdesc.wParamFlags
2095 & PARAMFLAG_FOUT))
2096 continue;
2097 Any outAny;
2098 // variantToAny is called with the "reduce range" parameter set to sal_False.
2099 // That causes VT_I4 values not to be converted down to a "lower" type. That
2100 // feature exist for JScript only because it only uses VT_I4 for integer types.
2103 variantToAny( & arRefArgs[revParamIndex], outAny, sal_False );
2105 catch (IllegalArgumentException & e)
2107 e.ArgumentPosition = (sal_Int16)paramIndex;
2108 throw;
2110 catch (CannotConvertException & e)
2112 e.ArgumentIndex = paramIndex;
2113 throw;
2115 OutParam[outParamIndex] = outAny;
2116 OutParamIndex[outParamIndex] = ::sal::static_int_cast< sal_Int16, int >( paramIndex );
2117 outParamIndex++;
2119 OutParam.realloc(outParamIndex);
2120 OutParamIndex.realloc(outParamIndex);
2122 // Return value
2123 variantToAny(&varResult, ret, sal_False);
2126 // map error codes to exceptions
2127 OUString message;
2128 switch (result)
2130 case S_OK:
2131 break;
2132 case DISP_E_BADPARAMCOUNT:
2133 throw IllegalArgumentException("[automation bridge] Wrong "
2134 "number of arguments. Object returned DISP_E_BADPARAMCOUNT.",
2135 0, 0);
2136 break;
2137 case DISP_E_BADVARTYPE:
2138 throw RuntimeException("[automation bridge] One or more "
2139 "arguments have the wrong type. Object returned "
2140 "DISP_E_BADVARTYPE.", 0);
2141 break;
2142 case DISP_E_EXCEPTION:
2143 message = "[automation bridge]: ";
2144 message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription),
2145 ::SysStringLen(excepinfo.bstrDescription));
2147 throw InvocationTargetException(message, Reference<XInterface>(), Any());
2148 break;
2149 case DISP_E_MEMBERNOTFOUND:
2150 message = "[automation bridge]: A function with the name \""
2151 + sFuncName + "\" is not supported. Object returned "
2152 "DISP_E_MEMBERNOTFOUND.";
2153 throw IllegalArgumentException(message, 0, 0);
2154 break;
2155 case DISP_E_NONAMEDARGS:
2156 throw IllegalArgumentException("[automation bridge] Object "
2157 "returned DISP_E_NONAMEDARGS",0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
2158 break;
2159 case DISP_E_OVERFLOW:
2160 throw CannotConvertException(OUString("[automation bridge] Call failed."),
2161 static_cast<XInterface*>(
2162 static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
2163 break;
2164 case DISP_E_PARAMNOTFOUND:
2165 throw IllegalArgumentException("[automation bridge]Call failed."
2166 "Object returned DISP_E_PARAMNOTFOUND.",
2167 0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
2168 break;
2169 case DISP_E_TYPEMISMATCH:
2170 throw CannotConvertException("[automation bridge] Call failed. "
2171 "Object returned DISP_E_TYPEMISMATCH",
2172 static_cast<XInterface*>(
2173 static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr);
2174 break;
2175 case DISP_E_UNKNOWNINTERFACE:
2176 throw RuntimeException("[automation bridge] Call failed. "
2177 "Object returned DISP_E_UNKNOWNINTERFACE.",0);
2178 break;
2179 case DISP_E_UNKNOWNLCID:
2180 throw RuntimeException("[automation bridge] Call failed. "
2181 "Object returned DISP_E_UNKNOWNLCID.",0);
2182 break;
2183 case DISP_E_PARAMNOTOPTIONAL:
2184 throw CannotConvertException("[automation bridge] Call failed."
2185 "Object returned DISP_E_PARAMNOTOPTIONAL",
2186 static_cast<XInterface*>(static_cast<XWeak*>(this)),
2187 TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
2188 break;
2189 default:
2190 throw RuntimeException();
2191 break;
2194 return ret;
2197 void IUnknownWrapper_Impl::getFuncDescForInvoke(const OUString & sFuncName,
2198 const Sequence<Any> & seqArgs,
2199 FUNCDESC** pFuncDesc)
2201 int nUnoArgs = seqArgs.getLength();
2202 const Any * arArgs = seqArgs.getConstArray();
2203 ITypeInfo* pInfo = getTypeInfo();
2205 //If the last of the positional arguments is a PropertyPutArgument
2206 //then obtain the type info for the property put operation.
2208 //The property value is always the last argument, in a positional argument list
2209 //or in a list of named arguments. A PropertyPutArgument is actually a named argument
2210 //hence it must not be put in an extra NamedArgument structure
2211 if (nUnoArgs > 0 &&
2212 arArgs[nUnoArgs - 1].getValueType() == getCppuType((PropertyPutArgument*) 0))
2214 // DISPATCH_PROPERTYPUT
2215 FuncDesc aDescGet(pInfo);
2216 FuncDesc aDescPut(pInfo);
2217 VarDesc aVarDesc(pInfo);
2218 getPropDesc(sFuncName, & aDescGet, & aDescPut, & aVarDesc);
2219 if ( ! aDescPut)
2221 throw IllegalArgumentException(
2222 "[automation bridge] The object does not have a writeable property: "
2223 + sFuncName, Reference<XInterface>(), 0);
2225 *pFuncDesc = aDescPut.Detach();
2227 else
2228 { // DISPATCH_METHOD
2229 FuncDesc aFuncDesc(pInfo);
2230 getFuncDesc(sFuncName, & aFuncDesc);
2231 if ( ! aFuncDesc)
2233 // Fallback: DISPATCH_PROPERTYGET can mostly be called as
2234 // DISPATCH_METHOD
2235 ITypeInfo * pInfo = getTypeInfo();
2236 FuncDesc aDescPut(pInfo);
2237 VarDesc aVarDesc(pInfo);
2238 getPropDesc(sFuncName, & aFuncDesc, & aDescPut, & aVarDesc);
2239 if ( ! aFuncDesc )
2241 throw IllegalArgumentException(
2242 "[automation bridge] The object does not have a function"
2243 "or readable property \""
2244 + sFuncName, Reference<XInterface>(), 0);
2247 *pFuncDesc = aFuncDesc.Detach();
2250 bool IUnknownWrapper_Impl::getDispid(const OUString& sFuncName, DISPID * id)
2252 OSL_ASSERT(m_spDispatch);
2253 LPOLESTR lpsz = const_cast<LPOLESTR> (reinterpret_cast<LPCOLESTR>(sFuncName.getStr()));
2254 HRESULT hr = m_spDispatch->GetIDsOfNames(IID_NULL, &lpsz, 1, LOCALE_USER_DEFAULT, id);
2255 return hr == S_OK ? true : false;
2257 void IUnknownWrapper_Impl::getFuncDesc(const OUString & sFuncName, FUNCDESC ** pFuncDesc)
2260 OSL_ASSERT( * pFuncDesc == 0);
2261 buildComTlbIndex();
2262 typedef TLBFuncIndexMap::const_iterator cit;
2263 typedef TLBFuncIndexMap::iterator it;
2264 //We assume there is only one entry with the function name. A property
2265 //would have two entries.
2266 cit itIndex= m_mapComFunc.find(sFuncName);
2267 if (itIndex == m_mapComFunc.end())
2269 //try case insensive with IDispatch::GetIDsOfNames
2270 DISPID id;
2271 if (getDispid(sFuncName, &id))
2273 CComBSTR memberName;
2274 unsigned int pcNames=0;
2275 // get the case sensitive name
2276 if( SUCCEEDED(getTypeInfo()->GetNames( id, & memberName, 1, &pcNames)))
2278 //get the associated index and add an entry to the map
2279 //with the name sFuncName which differs in the casing of the letters to
2280 //the actual name as obtained from ITypeInfo
2281 OUString sRealName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName)));
2282 cit itOrg = m_mapComFunc.find(sRealName);
2283 OSL_ASSERT(itOrg != m_mapComFunc.end());
2284 // maybe this is a property, if so we need
2285 // to store either both id's ( put/get ) or
2286 // just the get. Storing both is more consistent
2287 pair<cit, cit> pItems = m_mapComFunc.equal_range( sRealName );
2288 for ( ;pItems.first != pItems.second; ++pItems.first )
2289 m_mapComFunc.insert( TLBFuncIndexMap::value_type ( make_pair(sFuncName, pItems.first->second ) ));
2290 itIndex =
2291 m_mapComFunc.find( sFuncName );
2296 #if OSL_DEBUG_LEVEL >= 1
2297 // There must only be one entry if sFuncName represents a function or two
2298 // if it is a property
2299 pair<cit, cit> p = m_mapComFunc.equal_range(sFuncName.toAsciiLowerCase());
2300 int numEntries = 0;
2301 for ( ;p.first != p.second; p.first ++, numEntries ++);
2302 OSL_ASSERT( ! (numEntries > 3) );
2303 #endif
2304 if( itIndex != m_mapComFunc.end())
2306 ITypeInfo* pType= getTypeInfo();
2307 FUNCDESC * pDesc = NULL;
2308 if (SUCCEEDED(pType->GetFuncDesc(itIndex->second, & pDesc)))
2310 if (pDesc->invkind == INVOKE_FUNC)
2312 (*pFuncDesc) = pDesc;
2314 else
2316 pType->ReleaseFuncDesc(pDesc);
2319 else
2321 throw BridgeRuntimeError("[automation bridge] Could not get "
2322 "FUNCDESC for " + sFuncName);
2325 //else no entry found for sFuncName, pFuncDesc will not be filled in
2328 void IUnknownWrapper_Impl::getPropDesc(const OUString & sFuncName, FUNCDESC ** pFuncDescGet,
2329 FUNCDESC** pFuncDescPut, VARDESC** pVarDesc)
2331 OSL_ASSERT( * pFuncDescGet == 0 && * pFuncDescPut == 0);
2332 buildComTlbIndex();
2333 typedef TLBFuncIndexMap::const_iterator cit;
2334 pair<cit, cit> p = m_mapComFunc.equal_range(sFuncName);
2335 if (p.first == m_mapComFunc.end())
2337 //try case insensive with IDispatch::GetIDsOfNames
2338 DISPID id;
2339 if (getDispid(sFuncName, &id))
2341 CComBSTR memberName;
2342 unsigned int pcNames=0;
2343 // get the case sensitive name
2344 if( SUCCEEDED(getTypeInfo()->GetNames( id, & memberName, 1, &pcNames)))
2346 //As opposed to getFuncDesc, we do not add the value because we would
2347 // need to find the get and set description for the property. This would
2348 //mean to iterate over all FUNCDESCs again.
2349 p = m_mapComFunc.equal_range(OUString(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName))));
2354 for ( int i = 0 ;p.first != p.second; p.first ++, i ++)
2356 // There are a maximum of two entries, property put and property get
2357 OSL_ASSERT( ! (i > 2) );
2358 ITypeInfo* pType= getTypeInfo();
2359 FUNCDESC * pFuncDesc = NULL;
2360 if (SUCCEEDED( pType->GetFuncDesc(p.first->second, & pFuncDesc)))
2362 if (pFuncDesc->invkind == INVOKE_PROPERTYGET)
2364 (*pFuncDescGet) = pFuncDesc;
2366 else if (pFuncDesc->invkind == INVOKE_PROPERTYPUT ||
2367 pFuncDesc->invkind == INVOKE_PROPERTYPUTREF)
2369 //a property can have 3 entries, put, put ref, get
2370 // If INVOKE_PROPERTYPUTREF or INVOKE_PROPERTYPUT is used
2371 //depends on what is found first.
2372 if ( * pFuncDescPut)
2374 //we already have found one
2375 pType->ReleaseFuncDesc(pFuncDesc);
2377 else
2379 (*pFuncDescPut) = pFuncDesc;
2382 else
2384 pType->ReleaseFuncDesc(pFuncDesc);
2387 //ITypeInfo::GetFuncDesc may even provide a funcdesc for a VARDESC
2388 // with invkind = INVOKE_FUNC. Since this function should only return
2389 //a value for a real property (XInvokation::hasMethod, ..::hasProperty
2390 //we need to make sure that sFuncName represents a real property.
2391 VARDESC * pVD = NULL;
2392 if (SUCCEEDED(pType->GetVarDesc(p.first->second, & pVD)))
2393 (*pVarDesc) = pVD;
2395 //else no entry for sFuncName, pFuncDesc will not be filled in
2398 VARTYPE IUnknownWrapper_Impl::getUserDefinedElementType( ITypeInfo* pTypeInfo, const DWORD nHrefType )
2400 VARTYPE _type( VT_NULL );
2401 if ( pTypeInfo )
2403 CComPtr<ITypeInfo> spRefInfo;
2404 pTypeInfo->GetRefTypeInfo( nHrefType, &spRefInfo.p );
2405 if ( spRefInfo )
2407 TypeAttr attr( spRefInfo );
2408 spRefInfo->GetTypeAttr( &attr );
2409 if ( attr->typekind == TKIND_ENUM )
2411 // We use the type of the first enum value.
2412 if ( attr->cVars == 0 )
2414 throw BridgeRuntimeError("[automation bridge] Could not obtain type description");
2416 VarDesc var( spRefInfo );
2417 spRefInfo->GetVarDesc( 0, &var );
2418 _type = var->lpvarValue->vt;
2420 else if ( attr->typekind == TKIND_INTERFACE )
2422 _type = VT_UNKNOWN;
2424 else if ( attr->typekind == TKIND_DISPATCH )
2426 _type = VT_DISPATCH;
2428 else if ( attr->typekind == TKIND_ALIAS )
2430 // TKIND_ALIAS is a type that is an alias for another type. So get that alias type.
2431 _type = getUserDefinedElementType( pTypeInfo, attr->tdescAlias.hreftype );
2433 else
2435 throw BridgeRuntimeError( "[automation bridge] Unhandled user defined type." );
2439 return _type;
2442 VARTYPE IUnknownWrapper_Impl::getElementTypeDesc(const TYPEDESC *desc)
2444 VARTYPE _type( VT_NULL );
2446 if (desc->vt == VT_PTR)
2448 _type = getElementTypeDesc(desc->lptdesc);
2449 _type |= VT_BYREF;
2451 else if (desc->vt == VT_SAFEARRAY)
2453 _type = getElementTypeDesc(desc->lptdesc);
2454 _type |= VT_ARRAY;
2456 else if (desc->vt == VT_USERDEFINED)
2458 ITypeInfo* thisInfo = getTypeInfo(); //kept by this instance
2459 _type = getUserDefinedElementType( thisInfo, desc->hreftype );
2461 else
2463 _type = desc->vt;
2465 return _type;
2468 void IUnknownWrapper_Impl::buildComTlbIndex()
2470 if ( ! m_bComTlbIndexInit)
2472 MutexGuard guard(getBridgeMutex());
2474 if ( ! m_bComTlbIndexInit)
2476 OUString sError;
2477 ITypeInfo* pType= getTypeInfo();
2478 TypeAttr typeAttr(pType);
2479 if( SUCCEEDED( pType->GetTypeAttr( &typeAttr)))
2481 for( long i= 0; i < typeAttr->cFuncs; i++)
2483 FuncDesc funcDesc(pType);
2484 if( SUCCEEDED( pType->GetFuncDesc( i, &funcDesc)))
2486 CComBSTR memberName;
2487 unsigned int pcNames=0;
2488 if( SUCCEEDED(pType->GetNames( funcDesc->memid, & memberName, 1, &pcNames)))
2490 OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName)));
2491 m_mapComFunc.insert( TLBFuncIndexMap::value_type( usName, i));
2493 else
2495 sError = "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2496 "ITypeInfo::GetNames failed.";
2499 else
2500 sError = "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2501 "ITypeInfo::GetFuncDesc failed.";
2504 //If we create an Object in JScript and a a property then it
2505 //has VARDESC instead of FUNCDESC
2506 for (long i = 0; i < typeAttr->cVars; i++)
2508 VarDesc varDesc(pType);
2509 if (SUCCEEDED(pType->GetVarDesc(i, & varDesc)))
2511 CComBSTR memberName;
2512 unsigned int pcNames = 0;
2513 if (SUCCEEDED(pType->GetNames(varDesc->memid, & memberName, 1, &pcNames)))
2515 if (varDesc->varkind == VAR_DISPATCH)
2517 OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName)));
2518 m_mapComFunc.insert(TLBFuncIndexMap::value_type(
2519 usName, i));
2522 else
2524 sError = "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2525 "ITypeInfo::GetNames failed.";
2528 else
2529 sError = "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2530 "ITypeInfo::GetVarDesc failed.";
2534 else
2535 sError = "[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, "
2536 "ITypeInfo::GetTypeAttr failed.";
2538 if (sError.getLength())
2540 throw BridgeRuntimeError(sError);
2543 m_bComTlbIndexInit = true;
2549 ITypeInfo* IUnknownWrapper_Impl::getTypeInfo()
2551 if( !m_spDispatch)
2553 throw BridgeRuntimeError("The object has no IDispatch interface!");
2556 if( !m_spTypeInfo )
2558 MutexGuard guard(getBridgeMutex());
2559 if( ! m_spTypeInfo)
2561 CComPtr< ITypeInfo > spType;
2562 if( SUCCEEDED( m_spDispatch->GetTypeInfo( 0, LOCALE_USER_DEFAULT, &spType.p)))
2565 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
2567 //If this is a dual interface then TYPEATTR::typekind is usually TKIND_INTERFACE
2568 //We need to get the type description for TKIND_DISPATCH
2569 TypeAttr typeAttr(spType.p);
2570 if( SUCCEEDED(spType->GetTypeAttr( &typeAttr)))
2572 if (typeAttr->typekind == TKIND_INTERFACE &&
2573 typeAttr->wTypeFlags & TYPEFLAG_FDUAL)
2575 HREFTYPE refDispatch;
2576 if (SUCCEEDED(spType->GetRefTypeOfImplType(::sal::static_int_cast< UINT, int >( -1 ), &refDispatch)))
2578 CComPtr<ITypeInfo> spTypeDisp;
2579 if (SUCCEEDED(spType->GetRefTypeInfo(refDispatch, & spTypeDisp)))
2580 m_spTypeInfo= spTypeDisp;
2582 else
2584 throw BridgeRuntimeError(
2585 "[automation bridge] Could not obtain type information "
2586 "for dispatch interface." );
2589 else if (typeAttr->typekind == TKIND_DISPATCH)
2591 m_spTypeInfo= spType;
2593 else
2595 throw BridgeRuntimeError(
2596 "[automation bridge] Automation object does not "
2597 "provide type information.");
2601 else
2603 throw BridgeRuntimeError("[automation bridge]The dispatch object does not "
2604 "support ITypeInfo!");
2608 return m_spTypeInfo;
2611 } // end namespace
2613 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */