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