xref: /trunk/main/extensions/source/ole/oleobjw.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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