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