xref: /aoo41x/main/extensions/source/ole/oleobjw.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
30 #include "ole2uno.hxx"
31 #include "rtl/ustrbuf.hxx"
32 
33 
34 #include "osl/diagnose.h"
35 #include "osl/doublecheckedlocking.h"
36 #include "osl/thread.h"
37 
38 #include "boost/scoped_array.hpp"
39 #include <com/sun/star/script/FailReason.hpp>
40 #include <com/sun/star/beans/XMaterialHolder.hpp>
41 #include <com/sun/star/script/XTypeConverter.hpp>
42 #include <com/sun/star/script/FinishEngineEvent.hpp>
43 #include <com/sun/star/script/InterruptReason.hpp>
44 #include <com/sun/star/script/XEngineListener.hpp>
45 #include <com/sun/star/script/XDebugging.hpp>
46 #include <com/sun/star/script/XInvocation.hpp>
47 #include <com/sun/star/script/ContextInformation.hpp>
48 #include <com/sun/star/script/FinishReason.hpp>
49 #include <com/sun/star/script/XEngine.hpp>
50 #include <com/sun/star/script/InterruptEngineEvent.hpp>
51 #include <com/sun/star/script/XLibraryAccess.hpp>
52 #include <com/sun/star/bridge/ModelDependent.hpp>
53 
54 #include "com/sun/star/bridge/oleautomation/NamedArgument.hpp"
55 #include "com/sun/star/bridge/oleautomation/PropertyPutArgument.hpp"
56 
57 #include <typelib/typedescription.hxx>
58 #include <rtl/uuid.h>
59 #include <rtl/memory.h>
60 #include <rtl/ustring.hxx>
61 
62 #include "jscriptclasses.hxx"
63 
64 #include "oleobjw.hxx"
65 #include "unoobjw.hxx"
66 #include <stdio.h>
67 using namespace std;
68 using namespace boost;
69 using namespace osl;
70 using namespace rtl;
71 using namespace cppu;
72 using namespace com::sun::star::script;
73 using namespace com::sun::star::lang;
74 using namespace com::sun::star::bridge;
75 using namespace com::sun::star::bridge::oleautomation;
76 using namespace com::sun::star::bridge::ModelDependent;
77 using namespace ::com::sun::star;
78 
79 #define JSCRIPT_ID_PROPERTY L"_environment"
80 #define JSCRIPT_ID			L"jscript"
81 namespace ole_adapter
82 {
83 
84 
85 // key: XInterface pointer created by Invocation Adapter Factory
86 // value: XInterface pointer to the wrapper class.
87 // Entries to the map are made within
88 // Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType);
89 // Entries are being deleted if the wrapper class's destructor has been
90 // called.
91 // Before UNO object is wrapped to COM object this map is checked
92 // to see if the UNO object is already a wrapper.
93 hash_map<sal_uInt32, sal_uInt32> AdapterToWrapperMap;
94 // key: XInterface of the wrapper object.
95 // value: XInterface of the Interface created by the Invocation Adapter Factory.
96 // A COM wrapper is responsible for removing the corresponding entry
97 // in AdapterToWrappperMap if it is being destroyed. Because the wrapper does not
98 // know about its adapted interface it uses WrapperToAdapterMap to get the
99 // adapted interface which is then used to locate the entry in AdapterToWrapperMap.
100 hash_map<sal_uInt32,sal_uInt32> WrapperToAdapterMap;
101 
102 hash_map<sal_uInt32, WeakReference<XInterface> > ComPtrToWrapperMap;
103 /*****************************************************************************
104 
105 	class implementation IUnknownWrapper_Impl
106 
107 *****************************************************************************/
108 
109 IUnknownWrapper_Impl::IUnknownWrapper_Impl( Reference<XMultiServiceFactory>& xFactory,
110 										   sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass):
111 	UnoConversionUtilities<IUnknownWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass),
112 	m_pxIdlClass( NULL), m_eJScript( JScriptUndefined),
113     m_bComTlbIndexInit(false),  m_bHasDfltMethod(false), m_bHasDfltProperty(false)
114 {
115 }
116 
117 
118 IUnknownWrapper_Impl::~IUnknownWrapper_Impl()
119 {
120     o2u_attachCurrentThread();
121     MutexGuard guard(getBridgeMutex());
122     XInterface * xIntRoot = (OWeakObject *)this;
123 #if OSL_DEBUG_LEVEL > 0
124     acquire(); // make sure we don't delete us twice because of Reference
125 	OSL_ASSERT( Reference<XInterface>( static_cast<XWeak*>(this), UNO_QUERY).get() == xIntRoot );
126 #endif
127 
128 	// remove entries in global maps
129 	typedef hash_map<sal_uInt32, sal_uInt32>::iterator _IT;
130 	_IT it=	WrapperToAdapterMap.find( (sal_uInt32) xIntRoot);
131 	if( it != WrapperToAdapterMap.end())
132 	{
133 		sal_uInt32 adapter= it->second;
134 
135 		AdapterToWrapperMap.erase( adapter);
136 		WrapperToAdapterMap.erase( it);
137 	}
138 
139  	IT_Com it_c= ComPtrToWrapperMap.find( (sal_uInt32) m_spUnknown.p);
140     if(it_c != ComPtrToWrapperMap.end())
141         ComPtrToWrapperMap.erase(it_c);
142 
143 #if OSL_DEBUG_LEVEL > 0
144     fprintf(stderr,"[automation bridge] ComPtrToWrapperMap  contains: %i \n",
145             ComPtrToWrapperMap.size());
146 #endif
147 }
148 
149 Any IUnknownWrapper_Impl::queryInterface(const Type& t)
150     throw (RuntimeException)
151 {
152     if (t == getCppuType(static_cast<Reference<XDefaultMethod>*>( 0)) && !m_bHasDfltMethod )
153         return Any();
154     if (t == getCppuType(static_cast<Reference<XDefaultProperty>*>( 0)) && !m_bHasDfltProperty )
155         return Any();
156     if (t == getCppuType(static_cast<Reference<XInvocation>*>( 0)) && !m_spDispatch)
157         return Any();
158 
159     return WeakImplHelper7<XInvocation, XBridgeSupplier2,
160         XInitialization, XAutomationObject, XDefaultProperty, XDefaultMethod, XDirectInvocation>::queryInterface(t);
161 }
162 
163 Reference<XIntrospectionAccess> SAL_CALL IUnknownWrapper_Impl::getIntrospection(void)
164 	throw (RuntimeException )
165 {
166 	Reference<XIntrospectionAccess> ret;
167 
168 	return ret;
169 }
170 
171 
172 
173 Any SAL_CALL IUnknownWrapper_Impl::invoke( const OUString& aFunctionName,
174 			 const Sequence< Any >& aParams, Sequence< sal_Int16 >& aOutParamIndex,
175 			 Sequence< Any >& aOutParam )
176 	throw(IllegalArgumentException, CannotConvertException, InvocationTargetException,
177 		  RuntimeException)
178 {
179     if ( ! m_spDispatch )
180     {
181         throw RuntimeException(
182             OUSTR("[automation bridge] The object does not have an IDispatch interface"),
183             Reference<XInterface>());
184     }
185 
186     Any ret;
187 
188     try
189     {
190 		o2u_attachCurrentThread();
191 
192         TypeDescription methodDesc;
193         getMethodInfo(aFunctionName, methodDesc);
194         if( methodDesc.is())
195         {
196             ret = invokeWithDispIdUnoTlb(aFunctionName,
197                                          aParams,
198                                          aOutParamIndex,
199                                          aOutParam);
200         }
201         else
202         {
203             ret= invokeWithDispIdComTlb( aFunctionName,
204                                          aParams,
205                                          aOutParamIndex,
206                                          aOutParam);
207         }
208     }
209 	catch (IllegalArgumentException &)
210 	{
211 		throw;
212 	}
213 	catch (CannotConvertException &)
214 	{
215 		throw;
216 	}
217     catch (BridgeRuntimeError & e)
218     {
219          throw RuntimeException(e.message, Reference<XInterface>());
220     }
221     catch (Exception & e)
222     {
223         throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
224                                      "IUnknownWrapper_Impl::invoke ! Message : \n") +
225                                e.Message, Reference<XInterface>());
226 
227     }
228     catch(...)
229     {
230         throw RuntimeException(
231             OUSTR("[automation bridge] unexpected exception in "
232                   "IUnknownWrapper_Impl::Invoke !"), Reference<XInterface>());
233     }
234 	return ret;
235 }
236 
237 void SAL_CALL IUnknownWrapper_Impl::setValue( const OUString& aPropertyName,
238 				 const Any& aValue )
239 	throw(UnknownPropertyException, CannotConvertException, InvocationTargetException,
240 		  RuntimeException)
241 {
242     if ( ! m_spDispatch )
243     {
244         throw RuntimeException(
245             OUSTR("[automation bridge] The object does not have an IDispatch interface"),
246             Reference<XInterface>());
247     }
248     try
249 	{
250 		o2u_attachCurrentThread();
251 
252 		ITypeInfo * pInfo = getTypeInfo();
253         FuncDesc aDescGet(pInfo);
254         FuncDesc aDescPut(pInfo);
255         VarDesc aVarDesc(pInfo);
256         getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc);
257         //check if there is such a property at all or if it is read only
258         if ( ! aDescPut && ! aDescGet && ! aVarDesc)
259         {
260             OUString msg(OUSTR("[automation bridge]Property \"") + aPropertyName +
261                          OUSTR("\" is not supported"));
262             throw UnknownPropertyException(msg, Reference<XInterface>());
263         }
264 
265         if ( (! aDescPut && aDescGet) || aVarDesc
266              && aVarDesc->wVarFlags == VARFLAG_FREADONLY )
267         {
268             //read-only
269             OUString msg(OUSTR("[automation bridge] Property ") + aPropertyName +
270                          OUSTR(" is read-only"));
271             OString sMsg = OUStringToOString(msg, osl_getThreadTextEncoding());
272             OSL_ENSURE(0, sMsg.getStr());
273             // ignore silently
274             return;
275         }
276 
277         HRESULT hr= S_OK;
278         DISPPARAMS dispparams;
279         CComVariant varArg;
280         CComVariant varRefArg;
281         CComVariant varResult;
282         ExcepInfo excepinfo;
283         unsigned int uArgErr;
284 
285         // converting UNO value to OLE variant
286         DISPID dispidPut= DISPID_PROPERTYPUT;
287         dispparams.rgdispidNamedArgs = &dispidPut;
288         dispparams.cArgs = 1;
289         dispparams.cNamedArgs = 1;
290         dispparams.rgvarg = & varArg;
291 
292         OSL_ASSERT(aDescPut || aVarDesc);
293 
294         VARTYPE vt = 0;
295         DISPID dispid = 0;
296         INVOKEKIND invkind = INVOKE_PROPERTYPUT;
297         //determine the expected type, dispid, invoke kind (DISPATCH_PROPERTYPUT,
298         //DISPATCH_PROPERTYPUTREF)
299         if (aDescPut)
300         {
301             vt = getElementTypeDesc(& aDescPut->lprgelemdescParam[0].tdesc);
302             dispid = aDescPut->memid;
303             invkind = aDescPut->invkind;
304         }
305         else
306         {
307             vt = getElementTypeDesc( & aVarDesc->elemdescVar.tdesc);
308             dispid = aVarDesc->memid;
309             if (vt == VT_UNKNOWN || vt == VT_DISPATCH ||
310                 (vt & VT_ARRAY) || (vt & VT_BYREF))
311             {
312                 invkind = INVOKE_PROPERTYPUTREF;
313             }
314         }
315 
316         // convert the uno argument
317         if (vt & VT_BYREF)
318         {
319             anyToVariant( & varRefArg, aValue, ::sal::static_int_cast< VARTYPE, int >( vt ^ VT_BYREF ) );
320             varArg.vt = vt;
321             if( (vt & VT_TYPEMASK) == VT_VARIANT)
322                 varArg.byref = & varRefArg;
323 			else if ((vt & VT_TYPEMASK) == VT_DECIMAL)
324 				varArg.byref = & varRefArg.decVal;
325             else
326                 varArg.byref = & varRefArg.byref;
327         }
328         else
329         {
330             anyToVariant(& varArg, aValue, vt);
331         }
332         // call to IDispatch
333         hr = m_spDispatch->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, ::sal::static_int_cast< WORD, INVOKEKIND >( invkind ),
334                                  &dispparams, & varResult, & excepinfo, &uArgErr);
335 
336         // lookup error code
337         switch (hr)
338         {
339 		case S_OK:
340 			break;
341 		case DISP_E_BADPARAMCOUNT:
342 			throw RuntimeException();
343 			break;
344 		case DISP_E_BADVARTYPE:
345 			throw RuntimeException();
346 			break;
347 		case DISP_E_EXCEPTION:
348 			throw InvocationTargetException();
349 			break;
350 		case DISP_E_MEMBERNOTFOUND:
351 			throw UnknownPropertyException();
352 			break;
353 		case DISP_E_NONAMEDARGS:
354 			throw RuntimeException();
355 			break;
356 		case DISP_E_OVERFLOW:
357 			throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
358                                              static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
359 			break;
360 		case DISP_E_PARAMNOTFOUND:
361 			throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
362                                             static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )) ;
363 			break;
364 		case DISP_E_TYPEMISMATCH:
365 			throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
366                                              static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::UNKNOWN, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
367 			break;
368 		case DISP_E_UNKNOWNINTERFACE:
369 			throw RuntimeException();
370 			break;
371 		case DISP_E_UNKNOWNLCID:
372 			throw RuntimeException();
373 			break;
374 		case DISP_E_PARAMNOTOPTIONAL:
375 			throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface*>(
376                                              static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
377 			break;
378 		default:
379 			throw  RuntimeException();
380 			break;
381         }
382 	}
383 	catch (CannotConvertException &)
384 	{
385 		throw;
386 	}
387     catch (UnknownPropertyException &)
388     {
389         throw;
390     }
391 	catch (BridgeRuntimeError& e)
392 	{
393         throw RuntimeException(
394             e.message, Reference<XInterface>());
395 	}
396     catch (Exception & e)
397     {
398         throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
399                                      "IUnknownWrapper_Impl::setValue ! Message : \n") +
400                                e.Message, Reference<XInterface>());
401 
402     }
403 	catch (...)
404 	{
405 		throw RuntimeException(
406             OUSTR("[automation bridge] unexpected exception in "
407 			"IUnknownWrapper_Impl::setValue !"), Reference<XInterface>());
408 	}
409 }
410 
411 Any SAL_CALL IUnknownWrapper_Impl::getValue( const OUString& aPropertyName )
412 		throw(UnknownPropertyException, RuntimeException)
413 {
414     if ( ! m_spDispatch )
415     {
416         throw RuntimeException(
417             OUSTR("[automation bridge] The object does not have an IDispatch interface"),
418             Reference<XInterface>());
419     }
420 	Any ret;
421     try
422     {
423         o2u_attachCurrentThread();
424         ITypeInfo * pInfo = getTypeInfo();
425         // I was going to implement an XServiceInfo interface to allow the type
426         // of the automation object to be exposed.. but it seems
427         // from looking at comments in the code that it is possible for
428         // this object to actually wrap an UNO object ( I guess if automation is
429         // used from MSO to create Openoffice objects ) Therefore, those objects
430         // will more than likely already have their own XServiceInfo interface.
431         // Instead here I chose a name that should be illegal both in COM and
432         // UNO ( from an IDL point of view ) therefore I think this is a safe
433         // hack
434         if ( aPropertyName.equals( rtl::OUString::createFromAscii("$GetTypeName") ))
435         {
436             if ( pInfo && m_sTypeName.getLength() == 0 )
437             {
438             	 m_sTypeName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("IDispatch") );
439                 CComBSTR sName;
440 
441                 if ( SUCCEEDED( pInfo->GetDocumentation( -1, &sName, NULL, NULL, NULL  ) ) )
442                 {
443                     rtl::OUString sTmp( reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName)));
444                     if ( sTmp.indexOf('_')  == 0 )
445                        sTmp = sTmp.copy(1);
446                     // do we own the memory for pTypeLib, msdn doco is vague
447                     // I'll assume we do
448                     CComPtr< ITypeLib > pTypeLib;
449                     unsigned int index;
450                     if ( SUCCEEDED(  pInfo->GetContainingTypeLib(  &pTypeLib.p, &index )) )
451                     {
452                         if ( SUCCEEDED( pTypeLib->GetDocumentation( -1, &sName, NULL, NULL, NULL  ) ) )
453                         {
454                             rtl::OUString sLibName( reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName)));
455                             m_sTypeName = sLibName.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".") ) ).concat( sTmp );
456 
457                         }
458                     }
459                 }
460 
461             }
462             ret <<= m_sTypeName;
463             return ret;
464         }
465         FuncDesc aDescGet(pInfo);
466         FuncDesc aDescPut(pInfo);
467         VarDesc aVarDesc(pInfo);
468         getPropDesc(aPropertyName, & aDescGet, & aDescPut, & aVarDesc);
469         if ( ! aDescGet && ! aDescPut && ! aVarDesc)
470         {
471             //property not found
472             OUString msg(OUSTR("[automation bridge]Property \"") + aPropertyName +
473                          OUSTR("\" is not supported"));
474             throw UnknownPropertyException(msg, Reference<XInterface>());
475         }
476         // write-only should not be possible
477         OSL_ASSERT(  aDescGet  || ! aDescPut);
478 
479         HRESULT hr;
480         DISPPARAMS dispparams = {0, 0, 0, 0};
481         CComVariant varResult;
482         ExcepInfo excepinfo;
483         unsigned int uArgErr;
484         DISPID dispid;
485         if (aDescGet)
486             dispid = aDescGet->memid;
487         else if (aVarDesc)
488             dispid = aVarDesc->memid;
489         else
490             dispid = aDescPut->memid;
491 
492         hr = m_spDispatch->Invoke(dispid,
493 								 IID_NULL,
494 								 LOCALE_USER_DEFAULT,
495 								 DISPATCH_PROPERTYGET,
496 								 &dispparams,
497 								 &varResult,
498 								 &excepinfo,
499 								 &uArgErr);
500 
501         // converting return value and out parameter back to UNO
502         if (hr == S_OK)
503         {
504             // If the com object implements uno interfaces then we have
505             // to convert the attribute into the expected type.
506             TypeDescription attrInfo;
507             getAttributeInfo(aPropertyName, attrInfo);
508 			if( attrInfo.is() )
509 				variantToAny( &varResult, ret, Type( attrInfo.get()->pWeakRef));
510 			else
511 				variantToAny(&varResult, ret);
512         }
513 
514         // lookup error code
515         switch (hr)
516         {
517 		case S_OK:
518 			break;
519 		case DISP_E_BADPARAMCOUNT:
520 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
521                                    Reference<XInterface>());
522 			break;
523 		case DISP_E_BADVARTYPE:
524 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
525                                    Reference<XInterface>());
526 			break;
527 		case DISP_E_EXCEPTION:
528 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
529                                    Reference<XInterface>());
530 			break;
531 		case DISP_E_MEMBERNOTFOUND:
532 			throw UnknownPropertyException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
533                                    Reference<XInterface>());
534 			break;
535 		case DISP_E_NONAMEDARGS:
536 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
537                                    Reference<XInterface>());
538 			break;
539 		case DISP_E_OVERFLOW:
540 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
541                                    Reference<XInterface>());
542 			break;
543 		case DISP_E_PARAMNOTFOUND:
544 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
545                                    Reference<XInterface>());
546 			break;
547 		case DISP_E_TYPEMISMATCH:
548 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
549                                    Reference<XInterface>());
550 			break;
551 		case DISP_E_UNKNOWNINTERFACE:
552 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
553                                    Reference<XInterface>());
554 			break;
555 		case DISP_E_UNKNOWNLCID:
556 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
557                                    Reference<XInterface>());
558 			break;
559 		case DISP_E_PARAMNOTOPTIONAL:
560 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
561                                    Reference<XInterface>());
562 			break;
563 		default:
564 			throw RuntimeException(OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription)),
565                                    Reference<XInterface>());
566 			break;
567         }
568     }
569     catch (UnknownPropertyException& )
570     {
571         throw;
572     }
573     catch (BridgeRuntimeError& e)
574 	{
575         throw RuntimeException(
576             e.message, Reference<XInterface>());
577 	}
578     catch (Exception & e)
579     {
580         throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
581                                      "IUnknownWrapper_Impl::getValue ! Message : \n") +
582                                e.Message, Reference<XInterface>());
583     }
584 	catch (...)
585 	{
586 		throw RuntimeException(
587             OUSTR("[automation bridge] unexpected exception in "
588 			"IUnknownWrapper_Impl::getValue !"), Reference<XInterface>());
589 	}
590 	return ret;
591 }
592 
593 sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMethod( const OUString& aName )
594 		throw(RuntimeException)
595 {
596     if ( ! m_spDispatch )
597     {
598         throw RuntimeException(
599             OUSTR("[automation bridge] The object does not have an IDispatch interface"),
600             Reference<XInterface>());
601     }
602 	sal_Bool ret = sal_False;
603 
604 	try
605 	{
606 		o2u_attachCurrentThread();
607 		ITypeInfo* pInfo = getTypeInfo();
608         FuncDesc aDesc(pInfo);
609         getFuncDesc(aName, & aDesc);
610 		// Automation properties can have arguments. Those are treated as methods and
611 		//are called through XInvocation::invoke.
612 		if ( ! aDesc)
613 		{
614 			FuncDesc aDescGet(pInfo);
615 			FuncDesc aDescPut(pInfo);
616             VarDesc aVarDesc(pInfo);
617 			getPropDesc( aName, & aDescGet, & aDescPut, & aVarDesc);
618 			if (aDescGet  && aDescGet->cParams > 0
619                 || aDescPut && aDescPut->cParams > 0)
620 				ret = sal_True;
621 		}
622 		else
623 			ret = sal_True;
624 	}
625 	catch (BridgeRuntimeError& e)
626 	{
627 		throw RuntimeException(e.message, Reference<XInterface>());
628 	}
629     catch (Exception & e)
630     {
631         throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
632                                      "IUnknownWrapper_Impl::hasMethod ! Message : \n") +
633                                e.Message, Reference<XInterface>());
634     }
635 	catch (...)
636 	{
637 		throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
638 			"IUnknownWrapper_Impl::hasMethod !"), Reference<XInterface>());;
639 	}
640     return ret;
641 }
642 
643 sal_Bool SAL_CALL IUnknownWrapper_Impl::hasProperty( const OUString& aName )
644 		throw(RuntimeException)
645 {
646     if ( ! m_spDispatch )
647     {
648         throw RuntimeException(OUSTR("[automation bridge] The object does not have an "
649 			"IDispatch interface"), Reference<XInterface>());
650 		return sal_False;
651 	}
652 	sal_Bool ret = sal_False;
653 	try
654 	{
655 		o2u_attachCurrentThread();
656 
657 		ITypeInfo * pInfo = getTypeInfo();
658         FuncDesc aDescGet(pInfo);
659         FuncDesc aDescPut(pInfo);
660         VarDesc aVarDesc(pInfo);
661         getPropDesc(aName, & aDescGet, & aDescPut, & aVarDesc);
662 		// Automation properties can have parameters. If so, we access them through
663 		// XInvocation::invoke. Thas is, hasProperty must return false for such a
664 		// property
665         if (aVarDesc
666             || aDescPut && aDescPut->cParams == 0
667             || aDescGet && aDescGet->cParams == 0)
668         {
669             ret = sal_True;
670         }
671 	}
672 	catch (BridgeRuntimeError& e)
673 	{
674 		throw RuntimeException(e.message, Reference<XInterface>());
675 	}
676     catch (Exception & e)
677     {
678         throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
679                                      "IUnknownWrapper_Impl::hasProperty ! Message : \n") +
680                                e.Message, Reference<XInterface>());
681 
682     }
683 	catch (...)
684 	{
685 		throw RuntimeException(OUSTR("[automation bridge] unexpected exception in "
686 			"IUnknownWrapper_Impl::hasProperty !"), Reference<XInterface>());
687 	}
688 	return ret;
689 }
690 
691 Any SAL_CALL IUnknownWrapper_Impl::createBridge( const Any& modelDepObject,
692 				const Sequence< sal_Int8 >& /*aProcessId*/, sal_Int16 sourceModelType,
693 				 sal_Int16 destModelType )
694 	throw( IllegalArgumentException, RuntimeException)
695 {
696 	Any ret;
697 	o2u_attachCurrentThread();
698 
699 	if (
700 		(sourceModelType == UNO) &&
701 		(destModelType == OLE) &&
702 		(modelDepObject.getValueTypeClass() == TypeClass_INTERFACE)
703 	   )
704 	{
705 		Reference<XInterface> xInt( *(XInterface**) modelDepObject.getValue());
706 		Reference<XInterface> xSelf( (OWeakObject*)this);
707 
708 		if (xInt == xSelf)
709 		{
710 			VARIANT* pVariant = (VARIANT*) CoTaskMemAlloc(sizeof(VARIANT));
711 
712 			VariantInit(pVariant);
713             if (m_bOriginalDispatch == sal_True)
714             {
715 				pVariant->vt = VT_DISPATCH;
716 				pVariant->pdispVal = m_spDispatch;
717 				pVariant->pdispVal->AddRef();
718 			}
719 			else
720 			{
721 				pVariant->vt = VT_UNKNOWN;
722 				pVariant->punkVal = m_spUnknown;
723 				pVariant->punkVal->AddRef();
724 			}
725 
726 			ret.setValue((void*)&pVariant, getCppuType( (sal_uInt32*) 0));
727 		}
728 	}
729 
730 	return ret;
731 }
732 /** @internal
733     @exception IllegalArgumentException
734     @exception CannotConvertException
735     @exception InvocationTargetException
736     @RuntimeException
737 */
738 Any  IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString& sFunctionName,
739                                                   const Sequence< Any >& Params,
740                                                   Sequence< sal_Int16 >& OutParamIndex,
741                                                   Sequence< Any >& OutParam)
742 {
743 	Any ret;
744 	HRESULT hr= S_OK;
745 
746 	sal_Int32 parameterCount= Params.getLength();
747 	sal_Int32 outParameterCount= 0;
748 	typelib_InterfaceMethodTypeDescription* pMethod= NULL;
749 	TypeDescription methodDesc;
750 	getMethodInfo(sFunctionName, methodDesc);
751 
752 	// We need to know whether the IDispatch is from a JScript object.
753 	// Then out and in/out parameters have to be treated differently than
754 	// with common COM objects.
755 	sal_Bool bJScriptObject= isJScriptObject();
756     scoped_array<CComVariant> sarParams;
757     scoped_array<CComVariant> sarParamsRef;
758 	CComVariant *pVarParams= NULL;
759 	CComVariant *pVarParamsRef= NULL;
760 	sal_Bool bConvRet= sal_True;
761 
762 	if( methodDesc.is())
763 	{
764 		pMethod = (typelib_InterfaceMethodTypeDescription* )methodDesc.get();
765 		parameterCount = pMethod->nParams;
766 		// Create the Array for the array being passed in DISPPARAMS
767 		// the array also contains the outparameter (but not the values)
768 		if( pMethod->nParams > 0)
769         {
770             sarParams.reset(new CComVariant[ parameterCount]);
771             pVarParams = sarParams.get();
772         }
773 
774 		// Create the Array for the out an in/out parameter. These values
775 		// are referenced by the VT_BYREF VARIANTs in DISPPARAMS.
776 		// We need to find out the number of out and in/out parameter.
777 		for( sal_Int32 i=0; i < parameterCount; i++)
778 		{
779 			if( pMethod->pParams[i].bOut)
780 				outParameterCount++;
781 		}
782 
783 		if( !bJScriptObject)
784 		{
785             sarParamsRef.reset(new CComVariant[outParameterCount]);
786 			pVarParamsRef = sarParamsRef.get();
787 			// build up the parameters for IDispatch::Invoke
788 			sal_Int32 outParamIndex=0;
789 			int i = 0;
790 			try
791 			{
792 				for( i= 0; i < parameterCount; i++)
793 				{
794 					// In parameter
795 					if( pMethod->pParams[i].bIn == sal_True && ! pMethod->pParams[i].bOut)
796 					{
797 						anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]);
798 					}
799 					// Out parameter + in/out parameter
800 					else if( pMethod->pParams[i].bOut == sal_True)
801 					{
802 						CComVariant var;
803 						if(pMethod->pParams[i].bIn)
804 						{
805 							anyToVariant( & var,Params[i]);
806 							pVarParamsRef[outParamIndex] = var;
807 						}
808 
809 						switch( pMethod->pParams[i].pTypeRef->eTypeClass)
810 						{
811 						case TypeClass_INTERFACE:
812 						case TypeClass_STRUCT:
813 							if( ! pMethod->pParams[i].bIn)
814 							{
815 								pVarParamsRef[ outParamIndex].vt= VT_DISPATCH;
816 								pVarParamsRef[ outParamIndex].pdispVal= 0;
817 							}
818 							pVarParams[parameterCount - i -1].vt = VT_DISPATCH | VT_BYREF;
819 							pVarParams[parameterCount - i -1].ppdispVal= &pVarParamsRef[outParamIndex].pdispVal;
820 							break;
821 						case TypeClass_ENUM:
822 						case TypeClass_LONG:
823 						case TypeClass_UNSIGNED_LONG:
824 							if( ! pMethod->pParams[i].bIn)
825 							{
826 								pVarParamsRef[ outParamIndex].vt = VT_I4;
827 								pVarParamsRef[ outParamIndex].lVal = 0;
828 							}
829 							pVarParams[parameterCount - i -1].vt = VT_I4 | VT_BYREF;
830 							pVarParams[parameterCount - i -1].plVal= &pVarParamsRef[outParamIndex].lVal;
831 							break;
832 						case TypeClass_SEQUENCE:
833 							if( ! pMethod->pParams[i].bIn)
834 							{
835 								pVarParamsRef[ outParamIndex].vt = VT_ARRAY| VT_VARIANT;
836 								pVarParamsRef[ outParamIndex].parray= NULL;
837 							}
838 							pVarParams[parameterCount - i -1].vt = VT_ARRAY| VT_BYREF | VT_VARIANT;
839 							pVarParams[parameterCount - i -1].pparray= &pVarParamsRef[outParamIndex].parray;
840 							break;
841 						case TypeClass_ANY:
842 							if( ! pMethod->pParams[i].bIn)
843 							{
844 								pVarParamsRef[ outParamIndex].vt = VT_EMPTY;
845 								pVarParamsRef[ outParamIndex].lVal = 0;
846 							}
847 							pVarParams[parameterCount - i -1].vt = VT_VARIANT | VT_BYREF;
848 							pVarParams[parameterCount - i -1].pvarVal = &pVarParamsRef[outParamIndex];
849 							break;
850 						case TypeClass_BOOLEAN:
851 							if( ! pMethod->pParams[i].bIn)
852 							{
853 								pVarParamsRef[ outParamIndex].vt = VT_BOOL;
854 								pVarParamsRef[ outParamIndex].boolVal = 0;
855 							}
856 							pVarParams[parameterCount - i -1].vt = VT_BOOL| VT_BYREF;
857 							pVarParams[parameterCount - i -1].pboolVal =
858 								& pVarParamsRef[outParamIndex].boolVal;
859 							break;
860 
861 						case TypeClass_STRING:
862 							if( ! pMethod->pParams[i].bIn)
863 							{
864 								pVarParamsRef[ outParamIndex].vt = VT_BSTR;
865 								pVarParamsRef[ outParamIndex].bstrVal= 0;
866 							}
867 							pVarParams[parameterCount - i -1].vt = VT_BSTR| VT_BYREF;
868 							pVarParams[parameterCount - i -1].pbstrVal=
869 								& pVarParamsRef[outParamIndex].bstrVal;
870 							break;
871 
872 						case TypeClass_FLOAT:
873 							if( ! pMethod->pParams[i].bIn)
874 							{
875 								pVarParamsRef[ outParamIndex].vt = VT_R4;
876 								pVarParamsRef[ outParamIndex].fltVal= 0;
877 							}
878 							pVarParams[parameterCount - i -1].vt = VT_R4| VT_BYREF;
879 							pVarParams[parameterCount - i -1].pfltVal =
880 								& pVarParamsRef[outParamIndex].fltVal;
881 							break;
882 						case TypeClass_DOUBLE:
883 							if( ! pMethod->pParams[i].bIn)
884 							{
885 								pVarParamsRef[ outParamIndex].vt = VT_R8;
886 								pVarParamsRef[ outParamIndex].dblVal= 0;
887 							}
888 							pVarParams[parameterCount - i -1].vt = VT_R8| VT_BYREF;
889 							pVarParams[parameterCount - i -1].pdblVal=
890 								& pVarParamsRef[outParamIndex].dblVal;
891 							break;
892 						case TypeClass_BYTE:
893 							if( ! pMethod->pParams[i].bIn)
894 							{
895 								pVarParamsRef[ outParamIndex].vt = VT_UI1;
896 								pVarParamsRef[ outParamIndex].bVal= 0;
897 							}
898 							pVarParams[parameterCount - i -1].vt = VT_UI1| VT_BYREF;
899 							pVarParams[parameterCount - i -1].pbVal=
900 								& pVarParamsRef[outParamIndex].bVal;
901 							break;
902 						case TypeClass_CHAR:
903 						case TypeClass_SHORT:
904 						case TypeClass_UNSIGNED_SHORT:
905 							if( ! pMethod->pParams[i].bIn)
906 							{
907 								pVarParamsRef[ outParamIndex].vt = VT_I2;
908 								pVarParamsRef[ outParamIndex].iVal = 0;
909 							}
910 							pVarParams[parameterCount - i -1].vt = VT_I2| VT_BYREF;
911 							pVarParams[parameterCount - i -1].piVal=
912 								& pVarParamsRef[outParamIndex].iVal;
913 							break;
914 
915 						default:
916 							if( ! pMethod->pParams[i].bIn)
917 							{
918 								pVarParamsRef[ outParamIndex].vt = VT_EMPTY;
919 								pVarParamsRef[ outParamIndex].lVal = 0;
920 							}
921 							pVarParams[parameterCount - i -1].vt = VT_VARIANT | VT_BYREF;
922 							pVarParams[parameterCount - i -1].pvarVal =
923 								& pVarParamsRef[outParamIndex];
924 						}
925 						outParamIndex++;
926 					} // end else if
927 				} // end for
928 			}
929 			catch (IllegalArgumentException & e)
930 			{
931                 e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
932 				throw;
933 			}
934 			catch (CannotConvertException & e)
935 			{
936 				e.ArgumentIndex = i;
937 				throw;
938 			}
939 		}
940 		else // it is an JScriptObject
941 		{
942 			int i = 0;
943 			try
944 			{
945 				for( ; i< parameterCount; i++)
946 				{
947 					// In parameter
948 					if( pMethod->pParams[i].bIn == sal_True && ! pMethod->pParams[i].bOut)
949 					{
950 						anyToVariant( &pVarParams[parameterCount - i -1], Params.getConstArray()[i]);
951 					}
952 					// Out parameter + in/out parameter
953 					else if( pMethod->pParams[i].bOut == sal_True)
954 					{
955 						CComObject<JScriptOutParam>* pParamObject;
956 						if( SUCCEEDED( CComObject<JScriptOutParam>::CreateInstance( &pParamObject)))
957 						{
958 							CComPtr<IUnknown> pUnk(pParamObject->GetUnknown());
959 #ifdef __MINGW32__
960 							CComQIPtr<IDispatch, &__uuidof(IDispatch)> pDisp( pUnk);
961 #else
962 							CComQIPtr<IDispatch> pDisp( pUnk);
963 #endif
964 
965 							pVarParams[ parameterCount - i -1].vt= VT_DISPATCH;
966 							pVarParams[ parameterCount - i -1].pdispVal= pDisp;
967 							pVarParams[ parameterCount - i -1].pdispVal->AddRef();
968 							// if the param is in/out then put the parameter on index 0
969 							if( pMethod->pParams[i].bIn == sal_True ) // in / out
970 							{
971 								CComVariant varParam;
972 								anyToVariant( &varParam, Params.getConstArray()[i]);
973 								CComDispatchDriver dispDriver( pDisp);
974 								if(FAILED( dispDriver.PutPropertyByName( L"0", &varParam)))
975 									throw BridgeRuntimeError(
976                                         OUSTR("[automation bridge]IUnknownWrapper_Impl::"
977                                               "invokeWithDispIdUnoTlb\n"
978                                               "Could not set property \"0\" for the in/out "
979                                               "param!"));
980 
981 							}
982 						}
983 						else
984 						{
985                             throw BridgeRuntimeError(
986                                 OUSTR("[automation bridge]IUnknownWrapper_Impl::"
987                                       "invokeWithDispIdUnoTlb\n"
988                                       "Could not create out parameter at index: ") +
989                                 OUString::valueOf((sal_Int32) i));
990 						}
991 
992 					}
993 				}
994 			}
995 			catch (IllegalArgumentException & e)
996 			{
997 				e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
998 				throw;
999 			}
1000 			catch (CannotConvertException & e)
1001 			{
1002 				e.ArgumentIndex = i;
1003 				throw;
1004 			}
1005 		}
1006 	}
1007 	// No type description Available, that is we have to deal with a COM component,
1008 	// that does not implements UNO interfaces ( IDispatch based)
1009 	else
1010 	{
1011         //We should not run into this block, because invokeWithDispIdComTlb should
1012         //have been called instead.
1013         OSL_ASSERT(0);
1014 	}
1015 
1016 
1017     CComVariant		varResult;
1018     ExcepInfo 		excepinfo;
1019     unsigned int 	uArgErr;
1020     DISPPARAMS dispparams= { pVarParams, NULL, parameterCount, 0};
1021     // Get the DISPID
1022     FuncDesc aDesc(getTypeInfo());
1023     getFuncDesc(sFunctionName, & aDesc);
1024     // invoking OLE method
1025     hr = m_spDispatch->Invoke(aDesc->memid,
1026                              IID_NULL,
1027                              LOCALE_USER_DEFAULT,
1028                              DISPATCH_METHOD,
1029                              &dispparams,
1030                              &varResult,
1031                              &excepinfo,
1032                              &uArgErr);
1033 
1034     // converting return value and out parameter back to UNO
1035     if (hr == S_OK)
1036     {
1037         if( outParameterCount && pMethod)
1038         {
1039             OutParamIndex.realloc( outParameterCount);
1040             OutParam.realloc( outParameterCount);
1041             sal_Int32 outIndex=0;
1042 			int i = 0;
1043 			try
1044 			{
1045 				for( ; i < parameterCount; i++)
1046 				{
1047 					if( pMethod->pParams[i].bOut )
1048 					{
1049 						OutParamIndex[outIndex]= (sal_Int16) i;
1050 						Any outAny;
1051 						if( !bJScriptObject)
1052 						{
1053 							variantToAny( &pVarParamsRef[outIndex], outAny,
1054 										Type(pMethod->pParams[i].pTypeRef), sal_False);
1055 							OutParam[outIndex++]= outAny;
1056 						}
1057 						else //JScriptObject
1058 						{
1059 							if( pVarParams[i].vt == VT_DISPATCH)
1060 							{
1061 								CComDispatchDriver pDisp( pVarParams[i].pdispVal);
1062 								if( pDisp)
1063 								{
1064 									CComVariant varOut;
1065 									if( SUCCEEDED( pDisp.GetPropertyByName( L"0", &varOut)))
1066 									{
1067 										variantToAny( &varOut, outAny,
1068 													Type(pMethod->pParams[parameterCount - 1 - i].pTypeRef), sal_False);
1069 										OutParam[outParameterCount - 1 - outIndex++]= outAny;
1070 									}
1071 									else
1072 										bConvRet= sal_False;
1073 								}
1074 								else
1075 									bConvRet= sal_False;
1076 							}
1077 							else
1078 								bConvRet= sal_False;
1079 						}
1080 					}
1081 					if( !bConvRet) break;
1082 				}
1083 			}
1084 			catch(IllegalArgumentException & e)
1085 			{
1086 				e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, int >( i );
1087 				throw;
1088 			}
1089 			catch(CannotConvertException & e)
1090 			{
1091 				e.ArgumentIndex = i;
1092 				throw;
1093 			}
1094         }
1095         // return value, no type information available
1096         if ( bConvRet)
1097 		{
1098 			try
1099 			{
1100 				if( pMethod	)
1101 					variantToAny(&varResult, ret, Type( pMethod->pReturnTypeRef), sal_False);
1102 				else
1103 					variantToAny(&varResult, ret, sal_False);
1104 			}
1105 			catch (IllegalArgumentException & e)
1106 			{
1107 				e.Message =
1108 					OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1109 					"Could not convert return value! \n Message: \n") + e.Message;
1110 				throw;
1111 			}
1112 			catch (CannotConvertException & e)
1113 			{
1114 				e.Message =
1115 					OUSTR("[automation bridge]IUnknownWrapper_Impl::invokeWithDispIdUnoTlb\n"
1116 					"Could not convert return value! \n Message: \n") + e.Message;
1117 				throw;
1118 			}
1119 		}
1120     }
1121 
1122     if( !bConvRet) // conversion of return or out parameter failed
1123         throw CannotConvertException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Call to COM object failed. Conversion of return or out value failed")),
1124                                       Reference<XInterface>( static_cast<XWeak*>(this), UNO_QUERY	), TypeClass_UNKNOWN,
1125                                       FailReason::UNKNOWN, 0);// lookup error code
1126     // conversion of return or out parameter failed
1127     switch (hr)
1128     {
1129     case S_OK:
1130         break;
1131     case DISP_E_BADPARAMCOUNT:
1132         throw IllegalArgumentException();
1133         break;
1134     case DISP_E_BADVARTYPE:
1135         throw RuntimeException();
1136         break;
1137     case DISP_E_EXCEPTION:
1138         throw InvocationTargetException();
1139         break;
1140     case DISP_E_MEMBERNOTFOUND:
1141         throw IllegalArgumentException();
1142         break;
1143     case DISP_E_NONAMEDARGS:
1144         throw IllegalArgumentException();
1145         break;
1146     case DISP_E_OVERFLOW:
1147         throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
1148                                          static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
1149         break;
1150     case DISP_E_PARAMNOTFOUND:
1151         throw IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
1152                                            static_cast<XWeak*>(this)), ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
1153         break;
1154     case DISP_E_TYPEMISMATCH:
1155         throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")),static_cast<XInterface*>(
1156                                          static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr);
1157         break;
1158     case DISP_E_UNKNOWNINTERFACE:
1159         throw RuntimeException() ;
1160         break;
1161     case DISP_E_UNKNOWNLCID:
1162         throw RuntimeException() ;
1163         break;
1164     case DISP_E_PARAMNOTOPTIONAL:
1165         throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("call to OLE object failed")), static_cast<XInterface*>(
1166                                          static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
1167 				break;
1168     default:
1169         throw RuntimeException();
1170         break;
1171     }
1172 
1173 	return ret;
1174 }
1175 
1176 
1177 
1178 // --------------------------
1179 // XInitialization
1180 void SAL_CALL IUnknownWrapper_Impl::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException)
1181 {
1182 	// 1.parameter is IUnknown
1183 	// 2.parameter is a boolean which indicates if the the COM pointer was a IUnknown or IDispatch
1184 	// 3.parameter is a Sequence<Type>
1185 	o2u_attachCurrentThread();
1186 	OSL_ASSERT(aArguments.getLength() == 3);
1187 
1188     m_spUnknown= *(IUnknown**) aArguments[0].getValue();
1189 #ifdef __MINGW32__
1190     m_spUnknown->QueryInterface(IID_IDispatch, reinterpret_cast<LPVOID*>( & m_spDispatch.p));
1191 #else
1192     m_spUnknown.QueryInterface( & m_spDispatch.p);
1193 #endif
1194 
1195     aArguments[1] >>= m_bOriginalDispatch;
1196 	aArguments[2] >>= m_seqTypes;
1197 
1198     ITypeInfo* pType = NULL;
1199     try
1200     {
1201         // a COM object implementation that has no TypeInfo is still a legal COM object;
1202         // such objects can at least be transported through UNO using the bridge
1203         // so we should allow to create wrappers for them as well
1204         pType = getTypeInfo();
1205     }
1206     catch( BridgeRuntimeError& )
1207     {}
1208     catch( Exception& )
1209     {}
1210 
1211     if ( pType )
1212     {
1213         try
1214         {
1215             // Get Default member
1216             CComBSTR defaultMemberName;
1217             if ( SUCCEEDED( pType->GetDocumentation(0, &defaultMemberName, 0, 0, 0 ) ) )
1218             {
1219                 OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(defaultMemberName)));
1220                 FuncDesc aDescGet(pType);
1221                 FuncDesc aDescPut(pType);
1222                 VarDesc aVarDesc(pType);
1223                 // see if this is a property first ( more likely to be a property then a method )
1224                 getPropDesc( usName, & aDescGet, & aDescPut, & aVarDesc);
1225 
1226                 if ( !aDescGet && !aDescPut )
1227                 {
1228                     getFuncDesc( usName, &aDescGet );
1229                     if ( !aDescGet )
1230                         throw BridgeRuntimeError( OUSTR("[automation bridge]IUnknownWrapper_Impl::initialize() Failed to get Function or Property desc. for " ) + usName );
1231                 }
1232                 // now for some funny heuristics to make basic understand what to do
1233                 // a single aDescGet ( that doesn't take any params ) would be
1234                 // a read only ( defaultmember ) property e.g. this object
1235                 // should implement XDefaultProperty
1236                 // a single aDescGet ( that *does* ) take params is basically a
1237                 // default method e.g. implement XDefaultMethod
1238 
1239                 // 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 )
1240                 if ( aDescPut || ( aDescGet && aDescGet->cParams == 0 ) )
1241                     m_bHasDfltProperty = true;
1242                 if ( aDescGet->cParams > 0 )
1243                     m_bHasDfltMethod = true;
1244                 if ( m_bHasDfltProperty || m_bHasDfltMethod )
1245                     m_sDefaultMember = usName;
1246             }
1247         }
1248         catch ( BridgeRuntimeError & e )
1249         {
1250             throw RuntimeException( e.message, Reference<XInterface>() );
1251         }
1252         catch( Exception& e )
1253         {
1254             throw RuntimeException(
1255                     OUSTR("[automation bridge] unexpected exception in IUnknownWrapper_Impl::initialiase() error message: \n") + e.Message,
1256                     Reference<XInterface>() );
1257         }
1258     }
1259 }
1260 
1261 // --------------------------
1262 // XDirectInvocation
1263 uno::Any SAL_CALL IUnknownWrapper_Impl::directInvoke( const ::rtl::OUString& aName, const uno::Sequence< uno::Any >& aParams )
1264     throw (lang::IllegalArgumentException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException)
1265 {
1266 	Any aResult;
1267 
1268     if ( !m_spDispatch )
1269     {
1270         throw RuntimeException(
1271             OUSTR("[automation bridge] The object does not have an IDispatch interface"),
1272             Reference<XInterface>());
1273     }
1274 
1275     o2u_attachCurrentThread();
1276     DISPID dispid;
1277     if ( !getDispid( aName, &dispid ) )
1278         throw IllegalArgumentException(
1279             OUSTR( "[automation bridge] The object does not have a function or property " )
1280             + aName, Reference<XInterface>(), 0);
1281 
1282 	CComVariant		varResult;
1283 	ExcepInfo 		excepinfo;
1284 	unsigned int 	uArgErr = 0;
1285     INVOKEKIND pInvkinds[2];
1286     pInvkinds[0] = INVOKE_FUNC;
1287     pInvkinds[1] = aParams.getLength() ? INVOKE_PROPERTYPUT : INVOKE_PROPERTYGET;
1288     HRESULT hInvRes = E_FAIL;
1289 
1290     // try Invoke first, if it does not work, try put/get property
1291     for ( sal_Int32 nStep = 0; FAILED( hInvRes ) && nStep < 2; nStep++ )
1292     {
1293         DISPPARAMS 		dispparams = {NULL, NULL, 0, 0};
1294 
1295         DISPID idPropertyPut = DISPID_PROPERTYPUT;
1296         scoped_array<DISPID> arDispidNamedArgs;
1297         scoped_array<CComVariant> ptrArgs;
1298         scoped_array<CComVariant> ptrRefArgs; // referenced arguments
1299         CComVariant * arArgs = NULL;
1300         CComVariant * arRefArgs = NULL;
1301         bool bVarargParam = false;
1302 
1303         dispparams.cArgs = aParams.getLength();
1304 
1305         // Determine the number of named arguments
1306         for ( sal_Int32 nInd = 0; nInd < aParams.getLength(); nInd++ )
1307             if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0) )
1308                 dispparams.cNamedArgs ++;
1309 
1310         // fill the named arguments
1311         if ( dispparams.cNamedArgs > 0
1312           && !( dispparams.cNamedArgs == 1 && pInvkinds[nStep] == INVOKE_PROPERTYPUT ) )
1313         {
1314             int nSizeAr = dispparams.cNamedArgs + 1;
1315             if ( pInvkinds[nStep] == INVOKE_PROPERTYPUT )
1316                 nSizeAr = dispparams.cNamedArgs;
1317 
1318             scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]);
1319             OLECHAR ** pNames = saNames.get();
1320             pNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(aName.getStr()));
1321 
1322             int cNamedArg = 0;
1323             for ( size_t nInd = 0; nInd < dispparams.cArgs; nInd++ )
1324             {
1325                 if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0))
1326                 {
1327                     const NamedArgument& arg = *(NamedArgument const*)aParams[nInd].getValue();
1328 
1329                     //We put the parameter names in reverse order into the array,
1330                     //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1331                     //The first name in the array is the method name
1332                     pNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr()));
1333                 }
1334             }
1335 
1336             arDispidNamedArgs.reset( new DISPID[nSizeAr] );
1337             HRESULT hr = getTypeInfo()->GetIDsOfNames( pNames, nSizeAr, arDispidNamedArgs.get() );
1338             if ( hr == E_NOTIMPL )
1339                 hr = m_spDispatch->GetIDsOfNames(IID_NULL, pNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() );
1340 
1341             if ( SUCCEEDED( hr ) )
1342             {
1343                 if ( pInvkinds[nStep] == DISPATCH_PROPERTYPUT )
1344                 {
1345                     DISPID*  arIDs = arDispidNamedArgs.get();
1346                     arIDs[0] = DISPID_PROPERTYPUT;
1347                     dispparams.rgdispidNamedArgs = arIDs;
1348                 }
1349                 else
1350                 {
1351                     DISPID*  arIDs = arDispidNamedArgs.get();
1352                     dispparams.rgdispidNamedArgs = & arIDs[1];
1353                 }
1354             }
1355             else if (hr == DISP_E_UNKNOWNNAME)
1356             {
1357                  throw IllegalArgumentException(
1358                      OUSTR("[automation bridge]One of the named arguments is wrong!"),
1359                      Reference<XInterface>(), 0);
1360             }
1361             else
1362             {
1363                 throw InvocationTargetException(
1364                     OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ")
1365                     + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any());
1366             }
1367         }
1368 
1369         //Convert arguments
1370         ptrArgs.reset(new CComVariant[dispparams.cArgs]);
1371         ptrRefArgs.reset(new CComVariant[dispparams.cArgs]);
1372         arArgs = ptrArgs.get();
1373         arRefArgs = ptrRefArgs.get();
1374 
1375         sal_Int32 nInd = 0;
1376         try
1377         {
1378             sal_Int32 revIndex = 0;
1379             for ( nInd = 0; nInd < sal_Int32(dispparams.cArgs); nInd++)
1380             {
1381                 revIndex = dispparams.cArgs - nInd - 1;
1382                 arRefArgs[revIndex].byref = 0;
1383                 Any  anyArg;
1384                 if ( nInd < aParams.getLength() )
1385                     anyArg = aParams.getConstArray()[nInd];
1386 
1387                 // Property Put arguments
1388                 if ( anyArg.getValueType() == getCppuType((PropertyPutArgument*)0) )
1389                 {
1390                     PropertyPutArgument arg;
1391                     anyArg >>= arg;
1392                     anyArg <<= arg.Value;
1393                 }
1394                 // named argument
1395                 if (anyArg.getValueType() == getCppuType((NamedArgument*) 0))
1396                 {
1397                     NamedArgument aNamedArgument;
1398                     anyArg >>= aNamedArgument;
1399                     anyArg <<= aNamedArgument.Value;
1400                 }
1401 
1402 				if ( nInd < aParams.getLength() && anyArg.getValueTypeClass() != TypeClass_VOID )
1403 				{
1404 					anyToVariant( &arArgs[revIndex], anyArg, VT_VARIANT );
1405 				}
1406 				else
1407 				{
1408 					arArgs[revIndex].vt = VT_ERROR;
1409 					arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1410 				}
1411             }
1412         }
1413         catch (IllegalArgumentException & e)
1414         {
1415             e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( nInd );
1416             throw;
1417         }
1418         catch (CannotConvertException & e)
1419         {
1420             e.ArgumentIndex = nInd;
1421             throw;
1422         }
1423 
1424         dispparams.rgvarg = arArgs;
1425         // invoking OLE method
1426         DWORD localeId = LOCALE_USER_DEFAULT;
1427         hInvRes = m_spDispatch->Invoke( dispid,
1428                                         IID_NULL,
1429                                         localeId,
1430                                         ::sal::static_int_cast< WORD, INVOKEKIND >( pInvkinds[nStep] ),
1431                                         &dispparams,
1432                                         &varResult,
1433                                         &excepinfo,
1434                                         &uArgErr);
1435     }
1436 
1437 	// converting return value and out parameter back to UNO
1438 	if ( SUCCEEDED( hInvRes ) )
1439 		variantToAny( &varResult, aResult, sal_False );
1440     else
1441     {
1442         // map error codes to exceptions
1443         OUString message;
1444         switch ( hInvRes )
1445         {
1446             case S_OK:
1447                 break;
1448             case DISP_E_BADPARAMCOUNT:
1449                 throw IllegalArgumentException(OUSTR("[automation bridge] Wrong "
1450                       "number of arguments. Object returned DISP_E_BADPARAMCOUNT."),
1451                       0, 0);
1452                 break;
1453             case DISP_E_BADVARTYPE:
1454                 throw RuntimeException(OUSTR("[automation bridge] One or more "
1455                       "arguments have the wrong type. Object returned "
1456                       "DISP_E_BADVARTYPE."), 0);
1457                 break;
1458             case DISP_E_EXCEPTION:
1459                     message = OUSTR("[automation bridge]: ");
1460                     message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription),
1461                         ::SysStringLen(excepinfo.bstrDescription));
1462                     throw InvocationTargetException(message, Reference<XInterface>(), Any());
1463                     break;
1464             case DISP_E_MEMBERNOTFOUND:
1465                 message = OUSTR("[automation bridge]: A function with the name \"")
1466                     + aName + OUSTR("\" is not supported. Object returned "
1467                     "DISP_E_MEMBERNOTFOUND.");
1468                 throw IllegalArgumentException(message, 0, 0);
1469                 break;
1470             case DISP_E_NONAMEDARGS:
1471                 throw IllegalArgumentException(OUSTR("[automation bridge] Object "
1472                       "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
1473                 break;
1474             case DISP_E_OVERFLOW:
1475                 throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")),
1476                                              static_cast<XInterface*>(
1477                     static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
1478                 break;
1479             case DISP_E_PARAMNOTFOUND:
1480                 throw IllegalArgumentException(OUSTR("[automation bridge]Call failed."
1481                                                      "Object returned DISP_E_PARAMNOTFOUND."),
1482                                                0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
1483                 break;
1484             case DISP_E_TYPEMISMATCH:
1485                 throw CannotConvertException(OUSTR("[automation bridge] Call  failed. "
1486                                              "Object returned DISP_E_TYPEMISMATCH"),
1487                     static_cast<XInterface*>(
1488                     static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr);
1489                 break;
1490             case DISP_E_UNKNOWNINTERFACE:
1491                 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
1492                                            "Object returned DISP_E_UNKNOWNINTERFACE."),0);
1493                 break;
1494             case DISP_E_UNKNOWNLCID:
1495                 throw RuntimeException(OUSTR("[automation bridge] Call failed. "
1496                                            "Object returned DISP_E_UNKNOWNLCID."),0);
1497                 break;
1498             case DISP_E_PARAMNOTOPTIONAL:
1499                 throw CannotConvertException(OUSTR("[automation bridge] Call failed."
1500                       "Object returned DISP_E_PARAMNOTOPTIONAL"),
1501                             static_cast<XInterface*>(static_cast<XWeak*>(this)),
1502                                   TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
1503                 break;
1504             default:
1505                 throw RuntimeException();
1506                 break;
1507         }
1508     }
1509 
1510 	return aResult;
1511 }
1512 
1513 ::sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMember( const ::rtl::OUString& aName )
1514     throw (uno::RuntimeException)
1515 {
1516     if ( ! m_spDispatch )
1517     {
1518         throw RuntimeException(
1519             OUSTR("[automation bridge] The object does not have an IDispatch interface"),
1520             Reference<XInterface>());
1521     }
1522 
1523     o2u_attachCurrentThread();
1524     DISPID dispid;
1525     return getDispid( aName, &dispid );
1526 }
1527 
1528 
1529 // UnoConversionUtilities --------------------------------------------------------------------------------
1530 Reference< XInterface > IUnknownWrapper_Impl::createUnoWrapperInstance()
1531 {
1532 	if( m_nUnoWrapperClass == INTERFACE_OLE_WRAPPER_IMPL)
1533 	{
1534 		Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl(
1535 								m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1536 		return Reference<XInterface>( xWeak, UNO_QUERY);
1537 	}
1538 	else if( m_nUnoWrapperClass == UNO_OBJECT_WRAPPER_REMOTE_OPT)
1539 	{
1540 		Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt(
1541 								m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1542 		return Reference<XInterface>( xWeak, UNO_QUERY);
1543 	}
1544 	else
1545 		return Reference<XInterface>();
1546 }
1547 Reference<XInterface> IUnknownWrapper_Impl::createComWrapperInstance()
1548 {
1549 	Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl(
1550 							m_smgr, m_nUnoWrapperClass, m_nComWrapperClass));
1551 	return Reference<XInterface>( xWeak, UNO_QUERY);
1552 }
1553 
1554 
1555 
1556 void IUnknownWrapper_Impl::getMethodInfo(const OUString& sName, TypeDescription& methodInfo)
1557 {
1558 	TypeDescription desc= getInterfaceMemberDescOfCurrentCall(sName);
1559 	if( desc.is())
1560 	{
1561 		typelib_TypeDescription* pMember= desc.get();
1562 		if( pMember->eTypeClass == TypeClass_INTERFACE_METHOD )
1563 			methodInfo= pMember;
1564 	}
1565 }
1566 
1567 void IUnknownWrapper_Impl::getAttributeInfo(const OUString& sName, TypeDescription& attributeInfo)
1568 {
1569 	TypeDescription desc= getInterfaceMemberDescOfCurrentCall(sName);
1570 	if( desc.is())
1571 	{
1572 		typelib_TypeDescription* pMember= desc.get();
1573 		if( pMember->eTypeClass == TypeClass_INTERFACE_ATTRIBUTE )
1574 		{
1575 			attributeInfo= ((typelib_InterfaceAttributeTypeDescription*)pMember)->pAttributeTypeRef;
1576 		}
1577 	}
1578 }
1579 TypeDescription IUnknownWrapper_Impl::getInterfaceMemberDescOfCurrentCall(const OUString& sName)
1580 {
1581 	TypeDescription ret;
1582 
1583 	for( sal_Int32 i=0; i < m_seqTypes.getLength(); i++)
1584 	{
1585 		TypeDescription _curDesc( m_seqTypes[i]);
1586         _curDesc.makeComplete();
1587 		typelib_InterfaceTypeDescription * pInterface= (typelib_InterfaceTypeDescription*) _curDesc.get();
1588 		if( pInterface)
1589 		{
1590 			typelib_InterfaceMemberTypeDescription* pMember= NULL;
1591 			//find the member description of the current call
1592 			for( int i=0; i < pInterface->nAllMembers; i++)
1593 			{
1594 				typelib_TypeDescriptionReference* pTypeRefMember = pInterface->ppAllMembers[i];
1595 				typelib_TypeDescription* pDescMember= NULL;
1596 				TYPELIB_DANGER_GET( &pDescMember, pTypeRefMember)
1597 
1598 				typelib_InterfaceMemberTypeDescription* pInterfaceMember=
1599 					(typelib_InterfaceMemberTypeDescription*) pDescMember;
1600 				if( OUString( pInterfaceMember->pMemberName) == sName)
1601 				{
1602 					pMember= pInterfaceMember;
1603 					break;
1604 				}
1605 				TYPELIB_DANGER_RELEASE( pDescMember)
1606 			}
1607 
1608 			if( pMember)
1609 			{
1610 				ret= (typelib_TypeDescription*)pMember;
1611 				TYPELIB_DANGER_RELEASE( (typelib_TypeDescription*)pMember);
1612 			}
1613 		}
1614 		if( ret.is())
1615 			break;
1616 	}
1617 	return ret;
1618 }
1619 
1620 sal_Bool IUnknownWrapper_Impl::isJScriptObject()
1621 {
1622 	if(  m_eJScript == JScriptUndefined)
1623 	{
1624 		CComDispatchDriver disp( m_spDispatch);
1625 		if( disp)
1626 		{
1627 			CComVariant result;
1628 			if( SUCCEEDED(	disp.GetPropertyByName( JSCRIPT_ID_PROPERTY, &result)))
1629 			{
1630 				if(result.vt == VT_BSTR)
1631 				{
1632 					CComBSTR name( result.bstrVal);
1633 					name.ToLower();
1634 					if( name == CComBSTR(JSCRIPT_ID))
1635 						m_eJScript= IsJScript;
1636 				}
1637 			}
1638 		}
1639 		if( m_eJScript == JScriptUndefined)
1640 			m_eJScript= NoJScript;
1641 	}
1642 
1643 	return m_eJScript == NoJScript ? sal_False : sal_True;
1644 }
1645 
1646 
1647 
1648 /** @internal
1649     The function ultimately calls IDispatch::Invoke on the wrapped COM object.
1650     The COM object does not implement UNO Interfaces ( via IDispatch). This
1651     is the case when the OleObjectFactory service has been used to create a
1652     component.
1653     @exception IllegalArgumentException
1654     @exception CannotConvertException
1655     @InvocationTargetException
1656     @RuntimeException
1657     @BridgeRuntimeError
1658 */
1659 Any  IUnknownWrapper_Impl::invokeWithDispIdComTlb(const OUString& sFuncName,
1660                                                   const Sequence< Any >& Params,
1661                                                   Sequence< sal_Int16 >& OutParamIndex,
1662                                                   Sequence< Any >& OutParam)
1663 {
1664 	Any ret;
1665 	HRESULT result;
1666 
1667 	DISPPARAMS 		dispparams = {NULL, NULL, 0, 0};
1668 	CComVariant		varResult;
1669 	ExcepInfo 		excepinfo;
1670 	unsigned int 	uArgErr;
1671 	sal_Int32       i = 0;
1672     sal_Int32 nUnoArgs = Params.getLength();
1673     DISPID idPropertyPut = DISPID_PROPERTYPUT;
1674 	scoped_array<DISPID> arDispidNamedArgs;
1675 	scoped_array<CComVariant> ptrArgs;
1676 	scoped_array<CComVariant> ptrRefArgs; // referenced arguments
1677     CComVariant * arArgs = NULL;
1678     CComVariant * arRefArgs = NULL;
1679     sal_Int32 revIndex = 0;
1680     bool bVarargParam = false;
1681 
1682     // Get type info for the call. It can be a method call or property put or
1683     // property get operation.
1684     FuncDesc aFuncDesc(getTypeInfo());
1685     getFuncDescForInvoke(sFuncName, Params, & aFuncDesc);
1686 
1687     //Set the array of DISPIDs for named args if it is a property put operation.
1688     //If there are other named arguments another array is set later on.
1689     if (aFuncDesc->invkind == INVOKE_PROPERTYPUT
1690         || aFuncDesc->invkind == INVOKE_PROPERTYPUTREF)
1691         dispparams.rgdispidNamedArgs = & idPropertyPut;
1692 
1693     //Determine the number of named arguments
1694     for (int iParam = 0; iParam < nUnoArgs; iParam ++)
1695     {
1696         const Any & curArg = Params[iParam];
1697         if (curArg.getValueType() == getCppuType((NamedArgument*) 0))
1698             dispparams.cNamedArgs ++;
1699     }
1700     //In a property put operation a property value is a named argument (DISPID_PROPERTYPUT).
1701     //Therefore the number of named arguments is increased by one.
1702     //Although named, the argument is not named in a actual language, such as  Basic,
1703     //therefore it is never a com.sun.star.bridge.oleautomation.NamedArgument
1704     if (aFuncDesc->invkind == DISPATCH_PROPERTYPUT
1705         || aFuncDesc->invkind == DISPATCH_PROPERTYPUTREF)
1706         dispparams.cNamedArgs ++;
1707 
1708     //Determine the number of all arguments and named arguments
1709     if (aFuncDesc->cParamsOpt == -1)
1710     {
1711         //Attribute vararg is set on this method. "Unlimited" number of args
1712         //supported. There can be no optional or defaultvalue on any of the arguments.
1713         dispparams.cArgs = nUnoArgs;
1714     }
1715     else
1716     {
1717         //If there are namesd arguments, then the dispparams.cArgs
1718         //is the number of supplied args, otherwise it is the expected number.
1719         if (dispparams.cNamedArgs)
1720             dispparams.cArgs = nUnoArgs;
1721         else
1722             dispparams.cArgs = aFuncDesc->cParams;
1723     }
1724 
1725 	//check if there are not to many arguments supplied
1726     if (::sal::static_int_cast< sal_uInt32, int >( nUnoArgs ) > dispparams.cArgs)
1727 	{
1728 	    OUStringBuffer buf(256);
1729         buf.appendAscii("[automation bridge] There are too many arguments for this method");
1730 	    throw IllegalArgumentException( buf.makeStringAndClear(),
1731 			Reference<XInterface>(), (sal_Int16) dispparams.cArgs);
1732 	}
1733 
1734     //Set up the array of DISPIDs (DISPPARAMS::rgdispidNamedArgs)
1735     //for the named arguments.
1736     //If there is only one named arg and if it is because of a property put
1737     //operation, then we need not set up the DISPID array.
1738     if (dispparams.cNamedArgs > 0 &&
1739         ! (dispparams.cNamedArgs == 1 &&
1740            (aFuncDesc->invkind == INVOKE_PROPERTYPUT ||
1741             aFuncDesc->invkind == INVOKE_PROPERTYPUT)))
1742     {
1743         //set up an array containing the member and parameter names
1744         //which is then used in ITypeInfo::GetIDsOfNames
1745         //First determine the size of the array of names which is passed to
1746         //ITypeInfo::GetIDsOfNames. It must hold the method names + the named
1747         //args.
1748         int nSizeAr = dispparams.cNamedArgs + 1;
1749         if (aFuncDesc->invkind == INVOKE_PROPERTYPUT
1750             || aFuncDesc->invkind == INVOKE_PROPERTYPUTREF)
1751         {
1752             nSizeAr = dispparams.cNamedArgs; //counts the DISID_PROPERTYPUT
1753         }
1754 
1755         scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]);
1756         OLECHAR ** arNames = saNames.get();
1757         arNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(sFuncName.getStr()));
1758 
1759         int cNamedArg = 0;
1760         for (size_t iParams = 0; iParams < dispparams.cArgs; iParams ++)
1761         {
1762             const Any &  curArg = Params[iParams];
1763             if (curArg.getValueType() == getCppuType((NamedArgument*) 0))
1764             {
1765                 const NamedArgument& arg = *(NamedArgument const*) curArg.getValue();
1766 				//We put the parameter names in reverse order into the array,
1767 				//so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs
1768                 //The first name in the array is the method name
1769                 arNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr()));
1770             }
1771         }
1772 
1773         //Prepare the array of DISPIDs for ITypeInfo::GetIDsOfNames
1774         //it must be big enough to contain the DISPIDs of the member + parameters
1775         arDispidNamedArgs.reset(new DISPID[nSizeAr]);
1776         HRESULT hr = getTypeInfo()->GetIDsOfNames(arNames, nSizeAr,
1777                                                   arDispidNamedArgs.get());
1778         if ( hr == E_NOTIMPL )
1779             hr = m_spDispatch->GetIDsOfNames(IID_NULL, arNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() );
1780 
1781 		if (hr == S_OK)
1782         {
1783             // In a "property put" operation, the property value is a named param with the
1784             //special DISPID DISPID_PROPERTYPUT
1785             if (aFuncDesc->invkind == DISPATCH_PROPERTYPUT
1786                 || aFuncDesc->invkind == DISPATCH_PROPERTYPUTREF)
1787             {
1788                 //Element at index 0 in the DISPID array must be DISPID_PROPERTYPUT
1789                 //The first item in the array arDispidNamedArgs is the DISPID for
1790                 //the method. We replace it with DISPID_PROPERTYPUT.
1791                 DISPID*  arIDs = arDispidNamedArgs.get();
1792                 arIDs[0] = DISPID_PROPERTYPUT;
1793                 dispparams.rgdispidNamedArgs = arIDs;
1794             }
1795             else
1796             {
1797                 //The first item in the array arDispidNamedArgs is the DISPID for
1798                 //the method. It must be removed
1799                 DISPID*  arIDs = arDispidNamedArgs.get();
1800                 dispparams.rgdispidNamedArgs = & arIDs[1];
1801             }
1802         }
1803         else if (hr == DISP_E_UNKNOWNNAME)
1804         {
1805              throw IllegalArgumentException(
1806                  OUSTR("[automation bridge]One of the named arguments is wrong!"),
1807                  Reference<XInterface>(), 0);
1808         }
1809         else
1810         {
1811             throw InvocationTargetException(
1812                 OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ")
1813                 + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any());
1814         }
1815     }
1816 
1817     //Convert arguments
1818     ptrArgs.reset(new CComVariant[dispparams.cArgs]);
1819     ptrRefArgs.reset(new CComVariant[dispparams.cArgs]);
1820     arArgs = ptrArgs.get();
1821     arRefArgs = ptrRefArgs.get();
1822 	try
1823 	{
1824 		for (i = 0; i < (sal_Int32) dispparams.cArgs; i++)
1825 		{
1826 			revIndex= dispparams.cArgs - i -1;
1827 			arRefArgs[revIndex].byref=0;
1828 			Any  anyArg;
1829 			if ( i < nUnoArgs)
1830 				anyArg= Params.getConstArray()[i];
1831 
1832 			//Test if the current parameter is a "vararg" parameter.
1833 			if (bVarargParam || (aFuncDesc->cParamsOpt == -1 &&
1834 								aFuncDesc->cParams == (i + 1)))
1835 			{   //This parameter is from the variable argument list. There is no
1836 				//type info available, except that it must be a VARIANT
1837 				bVarargParam = true;
1838 			}
1839 
1840 			unsigned short paramFlags = PARAMFLAG_FOPT | PARAMFLAG_FIN;
1841 			VARTYPE varType = VT_VARIANT;
1842 			if ( ! bVarargParam)
1843 			{
1844 				paramFlags =
1845 					aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags;
1846 				varType = getElementTypeDesc(
1847 					& aFuncDesc->lprgelemdescParam[i].tdesc);
1848 			}
1849 			//Make sure that there is a UNO parameter for every
1850 			// expected parameter. If there is no UNO parameter where the
1851 			// called function expects one, then it must be optional. Otherwise
1852 			// its a UNO programming error.
1853 			if (i  >= nUnoArgs && !(paramFlags & PARAMFLAG_FOPT))
1854 			{
1855 				OUStringBuffer buf(256);
1856 				buf.appendAscii("ole automation bridge: The called function expects an argument at"
1857 								"position: "); //a different number of arguments")),
1858 				buf.append(OUString::valueOf((sal_Int32) i));
1859 				buf.appendAscii(" (index starting at 0).");
1860 				throw IllegalArgumentException( buf.makeStringAndClear(),
1861 												Reference<XInterface>(), (sal_Int16) i);
1862 			}
1863 
1864 			// Property Put arguments
1865 			if (anyArg.getValueType() == getCppuType((PropertyPutArgument*)0))
1866 			{
1867 				PropertyPutArgument arg;
1868 				anyArg >>= arg;
1869 				anyArg <<= arg.Value;
1870 			}
1871 			// named argument
1872 			if (anyArg.getValueType() == getCppuType((NamedArgument*) 0))
1873 			{
1874 				NamedArgument aNamedArgument;
1875 				anyArg >>= aNamedArgument;
1876 				anyArg <<= aNamedArgument.Value;
1877 			}
1878 			// out param
1879 			if (paramFlags & PARAMFLAG_FOUT &&
1880 				! (paramFlags & PARAMFLAG_FIN)  )
1881 			{
1882                 VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF );
1883 				if (i < nUnoArgs)
1884 				{
1885 					arRefArgs[revIndex].vt= type;
1886 				}
1887 				else
1888 				{
1889 					//optional arg
1890 					arRefArgs[revIndex].vt = VT_ERROR;
1891 					arRefArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1892 				}
1893 				if( type == VT_VARIANT )
1894 				{
1895 					arArgs[revIndex].vt= VT_VARIANT | VT_BYREF;
1896 					arArgs[revIndex].byref= &arRefArgs[revIndex];
1897 				}
1898 				else
1899 				{
1900 					arArgs[revIndex].vt= varType;
1901 					if (type == VT_DECIMAL)
1902 						arArgs[revIndex].byref= & arRefArgs[revIndex].decVal;
1903 					else
1904 						arArgs[revIndex].byref= & arRefArgs[revIndex].byref;
1905 				}
1906 			}
1907 			// in/out  + in byref params
1908 			else if (varType & VT_BYREF)
1909 			{
1910                 VARTYPE type = ::sal::static_int_cast< VARTYPE, int >( varType ^ VT_BYREF );
1911 				CComVariant var;
1912 
1913 				if (i < nUnoArgs && anyArg.getValueTypeClass() != TypeClass_VOID)
1914 				{
1915 					anyToVariant( & arRefArgs[revIndex], anyArg, type);
1916 				}
1917 				else if (paramFlags & PARAMFLAG_FHASDEFAULT)
1918 				{
1919 					//optional arg with default
1920 					VariantCopy( & arRefArgs[revIndex],
1921 								& aFuncDesc->lprgelemdescParam[i].paramdesc.
1922 								pparamdescex->varDefaultValue);
1923 				}
1924 				else
1925 				{
1926 					//optional arg
1927 					//e.g: call func(x) in basic : func() ' no arg supplied
1928 					OSL_ASSERT(paramFlags & PARAMFLAG_FOPT);
1929 					arRefArgs[revIndex].vt = VT_ERROR;
1930 					arRefArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1931 				}
1932 
1933 				// Set the converted arguments in the array which will be
1934 				// DISPPARAMS::rgvarg
1935 				// byref arg VT_XXX |VT_BYREF
1936 				arArgs[revIndex].vt = varType;
1937 				if (revIndex == 0 && aFuncDesc->invkind == INVOKE_PROPERTYPUT)
1938 				{
1939 					arArgs[revIndex] = arRefArgs[revIndex];
1940 				}
1941 				else if (type == VT_DECIMAL)
1942 				{
1943 					arArgs[revIndex].byref= & arRefArgs[revIndex].decVal;
1944 				}
1945 				else if (type == VT_VARIANT)
1946 				{
1947 					if ( ! (paramFlags & PARAMFLAG_FOUT))
1948 						arArgs[revIndex] = arRefArgs[revIndex];
1949 					else
1950 						arArgs[revIndex].byref = & arRefArgs[revIndex];
1951 				}
1952 				else
1953 				{
1954 					arArgs[revIndex].byref = & arRefArgs[revIndex].byref;
1955                     arArgs[revIndex].vt = ::sal::static_int_cast< VARTYPE, int >( arRefArgs[revIndex].vt | VT_BYREF );
1956 				}
1957 
1958 			}
1959 			// in parameter no VT_BYREF except for array, interfaces
1960 			else
1961 			{	// void any stands for optional param
1962 				if (i < nUnoArgs && anyArg.getValueTypeClass() != TypeClass_VOID)
1963 				{
1964 					anyToVariant( & arArgs[revIndex], anyArg, varType);
1965 				}
1966 				//optional arg but no void any supplied
1967 				//Basic:  obj.func() ' first parameter left out because it is optional
1968 				else if (paramFlags & PARAMFLAG_FHASDEFAULT)
1969 				{
1970 					//optional arg with defaulteithter as direct arg : VT_XXX or
1971 					VariantCopy( & arArgs[revIndex],
1972 						& aFuncDesc->lprgelemdescParam[i].paramdesc.
1973 							pparamdescex->varDefaultValue);
1974 				}
1975 				else if (paramFlags & PARAMFLAG_FOPT)
1976 				{
1977 					arArgs[revIndex].vt = VT_ERROR;
1978 					arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND;
1979 				}
1980                 else
1981                 {
1982                     arArgs[revIndex].vt = VT_EMPTY;
1983                     arArgs[revIndex].lVal = 0;
1984                 }
1985 			}
1986 		}
1987 	}
1988     catch (IllegalArgumentException & e)
1989 	{
1990 		e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( i );
1991 		throw;
1992 	}
1993 	catch (CannotConvertException & e)
1994 	{
1995 		e.ArgumentIndex = i;
1996 		throw;
1997 	}
1998 	dispparams.rgvarg= arArgs;
1999 	// invoking OLE method
2000     DWORD localeId = LOCALE_USER_DEFAULT;
2001 	result = m_spDispatch->Invoke(aFuncDesc->memid,
2002 								 IID_NULL,
2003 								 localeId,
2004 								 ::sal::static_int_cast< WORD, INVOKEKIND >( aFuncDesc->invkind ),
2005 								 &dispparams,
2006 								 &varResult,
2007 								 &excepinfo,
2008 								 &uArgErr);
2009 
2010 	// converting return value and out parameter back to UNO
2011 	if (result == S_OK)
2012 	{
2013 
2014         // allocate space for the out param Sequence and indices Sequence
2015         int outParamsCount= 0; // includes in/out parameter
2016         for (int i = 0; i < aFuncDesc->cParams; i++)
2017         {
2018             if (aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags &
2019                 PARAMFLAG_FOUT)
2020                 outParamsCount++;
2021         }
2022 
2023         OutParamIndex.realloc(outParamsCount);
2024         OutParam.realloc(outParamsCount);
2025         // Convert out params
2026         if (outParamsCount)
2027         {
2028             int outParamIndex=0;
2029             for (int paramIndex = 0; paramIndex < nUnoArgs; paramIndex ++)
2030             {
2031                 //Determine the index within the method sinature
2032                 int realParamIndex = paramIndex;
2033                 int revParamIndex = dispparams.cArgs - paramIndex - 1;
2034                 if (Params[paramIndex].getValueType()
2035                     == getCppuType((NamedArgument*) 0))
2036                 {
2037                     //dispparams.rgdispidNamedArgs contains the mapping from index
2038                     //of named args list to index of parameter list
2039                     realParamIndex = dispparams.rgdispidNamedArgs[revParamIndex];
2040                 }
2041 
2042                 // no named arg, always come before named args
2043                 if (! (aFuncDesc->lprgelemdescParam[realParamIndex].paramdesc.wParamFlags
2044                        & PARAMFLAG_FOUT))
2045                     continue;
2046                 Any outAny;
2047                 // variantToAny is called with the "reduce range" parameter set to sal_False.
2048                 // That causes VT_I4 values not to be converted down to a "lower" type. That
2049                 // feature exist for JScript only because it only uses VT_I4 for integer types.
2050 				try
2051 				{
2052 					variantToAny( & arRefArgs[revParamIndex], outAny, sal_False );
2053 				}
2054 				catch (IllegalArgumentException & e)
2055 				{
2056 					e.ArgumentPosition = (sal_Int16)paramIndex;
2057 					throw;
2058 				}
2059 				catch (CannotConvertException & e)
2060 				{
2061 					e.ArgumentIndex = paramIndex;
2062 					throw;
2063 				}
2064                 OutParam[outParamIndex] = outAny;
2065                 OutParamIndex[outParamIndex] = ::sal::static_int_cast< sal_Int16, int >( paramIndex );
2066                 outParamIndex++;
2067             }
2068             OutParam.realloc(outParamIndex);
2069             OutParamIndex.realloc(outParamIndex);
2070         }
2071         // Return value
2072 		variantToAny(&varResult, ret, sal_False);
2073 	}
2074 
2075 	// map error codes to exceptions
2076 	OUString message;
2077 	switch (result)
2078 	{
2079 		case S_OK:
2080 			break;
2081 		case DISP_E_BADPARAMCOUNT:
2082 			throw IllegalArgumentException(OUSTR("[automation bridge] Wrong "
2083                   "number of arguments. Object returned DISP_E_BADPARAMCOUNT."),
2084                   0, 0);
2085 			break;
2086 		case DISP_E_BADVARTYPE:
2087 			throw RuntimeException(OUSTR("[automation bridge] One or more "
2088                   "arguments have the wrong type. Object returned "
2089                   "DISP_E_BADVARTYPE."), 0);
2090 			break;
2091 		case DISP_E_EXCEPTION:
2092 				message = OUSTR("[automation bridge]: ");
2093 				message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription),
2094 					::SysStringLen(excepinfo.bstrDescription));
2095 				throw InvocationTargetException(message, Reference<XInterface>(), Any());
2096 				break;
2097 		case DISP_E_MEMBERNOTFOUND:
2098             message = OUSTR("[automation bridge]: A function with the name \"")
2099                 + sFuncName + OUSTR("\" is not supported. Object returned "
2100                 "DISP_E_MEMBERNOTFOUND.");
2101 			throw IllegalArgumentException(message, 0, 0);
2102 			break;
2103 		case DISP_E_NONAMEDARGS:
2104 			throw IllegalArgumentException(OUSTR("[automation bridge] Object "
2105                   "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
2106 			break;
2107 		case DISP_E_OVERFLOW:
2108 			throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")),
2109                                          static_cast<XInterface*>(
2110 				static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr);
2111 			break;
2112 		case DISP_E_PARAMNOTFOUND:
2113 			throw IllegalArgumentException(OUSTR("[automation bridge]Call failed."
2114                                                  "Object returned DISP_E_PARAMNOTFOUND."),
2115                                            0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr ));
2116 			break;
2117 		case DISP_E_TYPEMISMATCH:
2118 			throw CannotConvertException(OUSTR("[automation bridge] Call  failed. "
2119                                          "Object returned DISP_E_TYPEMISMATCH"),
2120 				static_cast<XInterface*>(
2121 				static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr);
2122 			break;
2123 		case DISP_E_UNKNOWNINTERFACE:
2124 			throw RuntimeException(OUSTR("[automation bridge] Call failed. "
2125                                        "Object returned DISP_E_UNKNOWNINTERFACE."),0);
2126 			break;
2127 		case DISP_E_UNKNOWNLCID:
2128 			throw RuntimeException(OUSTR("[automation bridge] Call failed. "
2129                                        "Object returned DISP_E_UNKNOWNLCID."),0);
2130 			break;
2131 		case DISP_E_PARAMNOTOPTIONAL:
2132 			throw CannotConvertException(OUSTR("[automation bridge] Call failed."
2133                   "Object returned DISP_E_PARAMNOTOPTIONAL"),
2134                         static_cast<XInterface*>(static_cast<XWeak*>(this)),
2135                               TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr);
2136 			break;
2137 		default:
2138 			throw RuntimeException();
2139 			break;
2140 	}
2141 
2142 	return ret;
2143 }
2144 
2145 void IUnknownWrapper_Impl::getFuncDescForInvoke(const OUString & sFuncName,
2146                                                 const Sequence<Any> & seqArgs,
2147                                                 FUNCDESC** pFuncDesc)
2148 {
2149     int nUnoArgs = seqArgs.getLength();
2150     const Any * arArgs = seqArgs.getConstArray();
2151     ITypeInfo* pInfo = getTypeInfo();
2152 
2153     //If the last of the positional arguments is a PropertyPutArgument
2154     //then obtain the type info for the property put operation.
2155 
2156     //The property value is always the last argument, in a positional argument list
2157     //or in a list of named arguments. A PropertyPutArgument is actually a named argument
2158     //hence it must not be put in an extra NamedArgument structure
2159     if (nUnoArgs > 0 &&
2160         arArgs[nUnoArgs - 1].getValueType() == getCppuType((PropertyPutArgument*) 0))
2161     {
2162         // DISPATCH_PROPERTYPUT
2163         FuncDesc aDescGet(pInfo);
2164         FuncDesc aDescPut(pInfo);
2165         VarDesc aVarDesc(pInfo);
2166         getPropDesc(sFuncName, & aDescGet, & aDescPut, & aVarDesc);
2167         if ( ! aDescPut)
2168         {
2169             throw IllegalArgumentException(
2170                 OUSTR("[automation bridge] The object does not have a writeable property: ")
2171                 + sFuncName, Reference<XInterface>(), 0);
2172         }
2173         *pFuncDesc = aDescPut.Detach();
2174     }
2175     else
2176     {   // DISPATCH_METHOD
2177         FuncDesc aFuncDesc(pInfo);
2178         getFuncDesc(sFuncName, & aFuncDesc);
2179         if ( ! aFuncDesc)
2180         {
2181             // Fallback: DISPATCH_PROPERTYGET can mostly be called as
2182             // DISPATCH_METHOD
2183             ITypeInfo * pInfo = getTypeInfo();
2184             FuncDesc aDescPut(pInfo);
2185             VarDesc aVarDesc(pInfo);
2186             getPropDesc(sFuncName, & aFuncDesc, & aDescPut, & aVarDesc);
2187             if ( ! aFuncDesc )
2188             {
2189                 throw IllegalArgumentException(
2190                     OUSTR("[automation bridge] The object does not have a function"
2191                           "or readable property \"")
2192                     + sFuncName, Reference<XInterface>(), 0);
2193             }
2194         }
2195         *pFuncDesc = aFuncDesc.Detach();
2196     }
2197 }
2198 bool IUnknownWrapper_Impl::getDispid(const OUString& sFuncName, DISPID * id)
2199 {
2200 	OSL_ASSERT(m_spDispatch);
2201 	LPOLESTR lpsz = const_cast<LPOLESTR> (reinterpret_cast<LPCOLESTR>(sFuncName.getStr()));
2202 	HRESULT	hr = m_spDispatch->GetIDsOfNames(IID_NULL, &lpsz, 1, LOCALE_USER_DEFAULT, id);
2203 	return hr == S_OK ? true : false;
2204 }
2205 void IUnknownWrapper_Impl::getFuncDesc(const OUString & sFuncName, FUNCDESC ** pFuncDesc)
2206 
2207 {
2208     OSL_ASSERT( * pFuncDesc == 0);
2209     buildComTlbIndex();
2210     typedef TLBFuncIndexMap::const_iterator cit;
2211 	    typedef TLBFuncIndexMap::iterator it;
2212     //We assume there is only one entry with the function name. A property
2213     //would have two entries.
2214 	cit itIndex= m_mapComFunc.find(sFuncName);
2215 	if (itIndex == m_mapComFunc.end())
2216 	{
2217 		//try case insensive with IDispatch::GetIDsOfNames
2218 		DISPID id;
2219 		if (getDispid(sFuncName, &id))
2220 		{
2221 			CComBSTR memberName;
2222             unsigned int pcNames=0;
2223 			// get the case sensitive name
2224             if( SUCCEEDED(getTypeInfo()->GetNames( id, & memberName, 1, &pcNames)))
2225 			{
2226 				//get the associated index and add an entry to the map
2227 				//with the name sFuncName which differs in the casing of the letters to
2228 				//the actual name as obtained from ITypeInfo
2229 				cit itOrg  = m_mapComFunc.find(OUString(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName))));
2230 				OSL_ASSERT(itOrg != m_mapComFunc.end());
2231 				itIndex =
2232 					m_mapComFunc.insert( TLBFuncIndexMap::value_type
2233 					( make_pair(sFuncName, itOrg->second ) ));
2234 			}
2235 		}
2236 	}
2237 
2238 #if OSL_DEBUG_LEVEL >= 1
2239     // There must only be one entry if sFuncName represents a function or two
2240     // if it is a property
2241     pair<cit, cit> p = m_mapComFunc.equal_range(sFuncName.toAsciiLowerCase());
2242     int numEntries = 0;
2243     for ( ;p.first != p.second; p.first ++, numEntries ++);
2244     OSL_ASSERT( ! (numEntries > 3) );
2245 #endif
2246 	if( itIndex != m_mapComFunc.end())
2247 	{
2248         ITypeInfo* pType= getTypeInfo();
2249         FUNCDESC * pDesc = NULL;
2250         if (SUCCEEDED(pType->GetFuncDesc(itIndex->second, & pDesc)))
2251         {
2252             if (pDesc->invkind == INVOKE_FUNC)
2253             {
2254                 (*pFuncDesc) = pDesc;
2255             }
2256             else
2257             {
2258                 pType->ReleaseFuncDesc(pDesc);
2259             }
2260         }
2261         else
2262         {
2263             throw BridgeRuntimeError(OUSTR("[automation bridge] Could not get "
2264                                            "FUNCDESC for ") + sFuncName);
2265         }
2266     }
2267    //else no entry found for sFuncName, pFuncDesc will not be filled in
2268 }
2269 
2270 void IUnknownWrapper_Impl::getPropDesc(const OUString & sFuncName, FUNCDESC ** pFuncDescGet,
2271                                        FUNCDESC** pFuncDescPut, VARDESC** pVarDesc)
2272 {
2273     OSL_ASSERT( * pFuncDescGet == 0 && * pFuncDescPut == 0);
2274     buildComTlbIndex();
2275     typedef TLBFuncIndexMap::const_iterator cit;
2276     pair<cit, cit> p = m_mapComFunc.equal_range(sFuncName);
2277     if (p.first == m_mapComFunc.end())
2278 	{
2279 		//try case insensive with IDispatch::GetIDsOfNames
2280 		DISPID id;
2281 		if (getDispid(sFuncName, &id))
2282 		{
2283 			CComBSTR memberName;
2284             unsigned int pcNames=0;
2285 			// get the case sensitive name
2286             if( SUCCEEDED(getTypeInfo()->GetNames( id, & memberName, 1, &pcNames)))
2287 			{
2288 				//As opposed to getFuncDesc, we do not add the value because we would
2289 				// need to find the get and set description for the property. This would
2290 				//mean to iterate over all FUNCDESCs again.
2291 				p = m_mapComFunc.equal_range(OUString(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName))));
2292 			}
2293 		}
2294 	}
2295 
2296 	for ( int i = 0 ;p.first != p.second; p.first ++, i ++)
2297 	{
2298         // There are a maximum of two entries, property put and property get
2299         OSL_ASSERT( ! (i > 2) );
2300         ITypeInfo* pType= getTypeInfo();
2301         FUNCDESC * pFuncDesc = NULL;
2302         if (SUCCEEDED( pType->GetFuncDesc(p.first->second, & pFuncDesc)))
2303         {
2304             if (pFuncDesc->invkind == INVOKE_PROPERTYGET)
2305             {
2306                 (*pFuncDescGet) = pFuncDesc;
2307             }
2308             else if (pFuncDesc->invkind == INVOKE_PROPERTYPUT ||
2309                      pFuncDesc->invkind == INVOKE_PROPERTYPUTREF)
2310             {
2311                 //a property can have 3 entries, put, put ref, get
2312                 // If INVOKE_PROPERTYPUTREF or INVOKE_PROPERTYPUT is used
2313                 //depends on what is found first.
2314                 if ( * pFuncDescPut)
2315                 {
2316                     //we already have found one
2317                     pType->ReleaseFuncDesc(pFuncDesc);
2318                 }
2319                 else
2320                 {
2321                     (*pFuncDescPut) = pFuncDesc;
2322                 }
2323             }
2324             else
2325             {
2326                 pType->ReleaseFuncDesc(pFuncDesc);
2327             }
2328         }
2329         //ITypeInfo::GetFuncDesc may even provide a funcdesc for a VARDESC
2330         // with invkind = INVOKE_FUNC. Since this function should only return
2331         //a value for a real property (XInvokation::hasMethod, ..::hasProperty
2332         //we need to make sure that sFuncName represents a real property.
2333         VARDESC * pVD = NULL;
2334         if (SUCCEEDED(pType->GetVarDesc(p.first->second, & pVD)))
2335             (*pVarDesc) = pVD;
2336     }
2337    //else no entry for sFuncName, pFuncDesc will not be filled in
2338 }
2339 
2340 VARTYPE IUnknownWrapper_Impl::getElementTypeDesc(const TYPEDESC *desc)
2341 {
2342 	VARTYPE _type( VT_NULL );
2343 
2344 	if (desc->vt == VT_PTR)
2345 	{
2346 		_type = getElementTypeDesc(desc->lptdesc);
2347         _type |= VT_BYREF;
2348 	}
2349 	else if (desc->vt == VT_SAFEARRAY)
2350 	{
2351 		_type = getElementTypeDesc(desc->lptdesc);
2352         _type |= VT_ARRAY;
2353 	}
2354 	else if (desc->vt == VT_USERDEFINED)
2355 	{
2356 		ITypeInfo* thisInfo = getTypeInfo(); //kept by this instance
2357 		CComPtr<ITypeInfo>	spRefInfo;
2358 		thisInfo->GetRefTypeInfo(desc->hreftype, & spRefInfo.p);
2359 		if (spRefInfo)
2360 		{
2361 			TypeAttr  attr(spRefInfo);
2362 			spRefInfo->GetTypeAttr( & attr);
2363 			if (attr->typekind == TKIND_ENUM)
2364 			{
2365 				//We use the type of the first enum value.
2366 				if (attr->cVars == 0)
2367 				{
2368 					throw BridgeRuntimeError(OUSTR("[automation bridge] Could "
2369 						"not obtain type description"));
2370 				}
2371 				VarDesc var(spRefInfo);
2372 				spRefInfo->GetVarDesc(0, & var);
2373 				_type = var->lpvarValue->vt;
2374 			}
2375 			else if (attr->typekind == TKIND_INTERFACE)
2376 			{
2377 				_type = VT_UNKNOWN;
2378 			}
2379 			else if (attr->typekind == TKIND_DISPATCH)
2380 			{
2381 				_type = VT_DISPATCH;
2382 			}
2383 			else
2384 			{
2385 				throw BridgeRuntimeError(OUSTR("[automation bridge] "
2386 					"Unhandled user defined type."));
2387 			}
2388 		}
2389 	}
2390 	else
2391 	{
2392 		_type = desc->vt;
2393 	}
2394 	return _type;
2395 }
2396 
2397 void IUnknownWrapper_Impl::buildComTlbIndex()
2398 {
2399     if ( ! m_bComTlbIndexInit)
2400     {
2401         MutexGuard guard(getBridgeMutex());
2402         {
2403             if ( ! m_bComTlbIndexInit)
2404             {
2405                 OUString sError;
2406                 ITypeInfo* pType= getTypeInfo();
2407                 TypeAttr typeAttr(pType);
2408                 if( SUCCEEDED( pType->GetTypeAttr( &typeAttr)))
2409                 {
2410                     for( long i= 0; i < typeAttr->cFuncs; i++)
2411                     {
2412                         FuncDesc funcDesc(pType);
2413                         if( SUCCEEDED( pType->GetFuncDesc( i, &funcDesc)))
2414                         {
2415                             CComBSTR memberName;
2416                             unsigned int pcNames=0;
2417                             if( SUCCEEDED(pType->GetNames( funcDesc->memid, & memberName, 1, &pcNames)))
2418                             {
2419 								OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName)));
2420                                 m_mapComFunc.insert( TLBFuncIndexMap::value_type( usName, i));
2421                             }
2422                             else
2423                             {
2424                                 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2425                                                 "ITypeInfo::GetNames failed.");
2426                             }
2427                         }
2428                         else
2429                             sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2430                                             "ITypeInfo::GetFuncDesc failed.");
2431                     }
2432 
2433 					//If we create an Object in JScript and a a property then it
2434 					//has VARDESC instead of FUNCDESC
2435                     for (long i = 0; i < typeAttr->cVars; i++)
2436                     {
2437                         VarDesc varDesc(pType);
2438                         if (SUCCEEDED(pType->GetVarDesc(i, & varDesc)))
2439                         {
2440                             CComBSTR memberName;
2441                             unsigned int pcNames = 0;
2442                             if (SUCCEEDED(pType->GetNames(varDesc->memid, & memberName, 1, &pcNames)))
2443                             {
2444 								if (varDesc->varkind == VAR_DISPATCH)
2445                                 {
2446 									OUString usName(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(memberName)));
2447                                     m_mapComFunc.insert(TLBFuncIndexMap::value_type(
2448                                                         usName, i));
2449                                 }
2450                             }
2451                             else
2452                             {
2453                                 sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2454                                                 "ITypeInfo::GetNames failed.");
2455                             }
2456                         }
2457                         else
2458                             sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2459                                            "ITypeInfo::GetVarDesc failed.");
2460 
2461                     }
2462                 }
2463                 else
2464                     sError = OUSTR("[automation bridge] IUnknownWrapper_Impl::buildComTlbIndex, " \
2465                                     "ITypeInfo::GetTypeAttr failed.");
2466 
2467                 if (sError.getLength())
2468                 {
2469                     throw BridgeRuntimeError(sError);
2470                 }
2471 
2472                 m_bComTlbIndexInit = true;
2473             }
2474         }
2475     }
2476 }
2477 
2478 ITypeInfo* IUnknownWrapper_Impl::getTypeInfo()
2479 {
2480 	if( !m_spDispatch)
2481     {
2482         throw BridgeRuntimeError(OUSTR("The object has no IDispatch interface!"));
2483     }
2484 
2485 	if( !m_spTypeInfo )
2486 	{
2487         MutexGuard guard(getBridgeMutex());
2488         if( ! m_spTypeInfo)
2489         {
2490             CComPtr< ITypeInfo > spType;
2491             if( SUCCEEDED( m_spDispatch->GetTypeInfo( 0, LOCALE_USER_DEFAULT, &spType.p)))
2492 
2493             {
2494                 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
2495 
2496 				//If this is a dual interface then TYPEATTR::typekind is usually TKIND_INTERFACE
2497 				//We need to get the type description for TKIND_DISPATCH
2498 				TypeAttr typeAttr(spType.p);
2499                 if( SUCCEEDED(spType->GetTypeAttr( &typeAttr)))
2500 				{
2501 					if (typeAttr->typekind == TKIND_INTERFACE &&
2502 							typeAttr->wTypeFlags & TYPEFLAG_FDUAL)
2503 					{
2504 						HREFTYPE refDispatch;
2505 						if (SUCCEEDED(spType->GetRefTypeOfImplType(::sal::static_int_cast< UINT, int >( -1 ), &refDispatch)))
2506 						{
2507 							CComPtr<ITypeInfo> spTypeDisp;
2508 							if (SUCCEEDED(spType->GetRefTypeInfo(refDispatch, & spTypeDisp)))
2509 								m_spTypeInfo= spTypeDisp;
2510 						}
2511 						else
2512 						{
2513 							throw BridgeRuntimeError(
2514 								OUSTR("[automation bridge] Could not obtain type information "
2515 								"for dispatch interface." ));
2516 						}
2517 					}
2518 					else if (typeAttr->typekind == TKIND_DISPATCH)
2519 					{
2520 						m_spTypeInfo= spType;
2521 					}
2522 					else
2523 					{
2524 						throw BridgeRuntimeError(
2525 							OUSTR("[automation bridge] Automation object does not "
2526 							"provide type information."));
2527 					}
2528 				}
2529             }
2530             else
2531             {
2532                 throw BridgeRuntimeError(OUSTR("[automation bridge]The dispatch object does not "
2533                                                "support ITypeInfo!"));
2534             }
2535         }
2536     }
2537 	return m_spTypeInfo;
2538 }
2539 
2540 } // end namespace
2541 
2542