1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #ifndef _UNO_CONVERSION_UTILITIES
28 #define _UNO_CONVERSION_UTILITIES
29 
30 #include "boost/scoped_array.hpp"
31 #include "com/sun/star/script/XInvocationAdapterFactory.hpp"
32 #include "com/sun/star/script/XInvocationAdapterFactory2.hpp"
33 #include "com/sun/star/script/XTypeConverter.hpp"
34 #include "com/sun/star/script/FailReason.hpp"
35 #include "com/sun/star/bridge/oleautomation/Date.hpp"
36 #include "com/sun/star/bridge/oleautomation/Currency.hpp"
37 #include "com/sun/star/bridge/oleautomation/SCode.hpp"
38 #include "com/sun/star/bridge/oleautomation/Decimal.hpp"
39 #include "typelib/typedescription.hxx"
40 #include "ole2uno.hxx"
41 
42 #include "unotypewrapper.hxx"
43 #include <hash_map>
44 
45 // for some reason DECIMAL_NEG (wtypes.h) which contains BYTE is not resolved.
46 typedef unsigned char   BYTE;
47 // classes for wrapping uno objects
48 #define INTERFACE_OLE_WRAPPER_IMPL		1
49 #define UNO_OBJECT_WRAPPER_REMOTE_OPT	2
50 
51 #define INVOCATION_SERVICE reinterpret_cast<const sal_Unicode*>(L"com.sun.star.script.Invocation")
52 
53 
54 // classes for wrapping ole objects
55 #define IUNKNOWN_WRAPPER_IMPL			1
56 
57 #define INTERFACE_ADAPTER_FACTORY  reinterpret_cast<const sal_Unicode*>(L"com.sun.star.script.InvocationAdapterFactory")
58 // COM or JScript objects implementing UNO interfaces have to implement this property
59 #define SUPPORTED_INTERFACES_PROP L"_implementedInterfaces"
60 // Second property without leading underscore for use in VB
61 #define SUPPORTED_INTERFACES_PROP2 L"Bridge_ImplementedInterfaces"
62 
63 using namespace com::sun::star::script;
64 using namespace com::sun::star::beans;
65 using namespace com::sun::star::uno;
66 #ifdef __MINGW32__
67 using namespace com::sun::star::bridge;
68 using namespace com::sun::star::bridge::ModelDependent;
69 #endif
70 using namespace com::sun::star::bridge::oleautomation;
71 using namespace boost;
72 namespace ole_adapter
73 {
74 extern hash_map<sal_uInt32, sal_uInt32> AdapterToWrapperMap;
75 extern hash_map<sal_uInt32, sal_uInt32> WrapperToAdapterMap;
76 typedef hash_map<sal_uInt32, sal_uInt32>::iterator IT_Wrap;
77 typedef hash_map<sal_uInt32, sal_uInt32>::iterator CIT_Wrap;
78 //Maps IUnknown pointers to a weak reference of the respective wrapper class (e.g.
79 // IUnknownWrapperImpl. It is the responsibility of the wrapper to remove the entry when
80 // it is being destroyed.
81 // Used to ensure that an Automation object is always mapped to the same UNO objects.
82 extern hash_map<sal_uInt32, WeakReference<XInterface> > ComPtrToWrapperMap;
83 typedef hash_map<sal_uInt32, WeakReference<XInterface> >::iterator IT_Com;
84 typedef hash_map<sal_uInt32, WeakReference<XInterface> >::const_iterator CIT_Com;
85 
86 // Maps XInterface pointers to a weak reference of its wrapper class (i.e.
87 // InterfaceOleWrapper_Impl). It is the responsibility of the wrapper to remove the entry when
88 // it is being destroyed. It is used to ensure the identity of objects. That is, an UNO interface
89 // is mapped to IDispatch which is kept alive in the COM environment. If the same
90 // UNO interface is mapped again to COM then the IDispach of the first mapped instance
91 // must be returned.
92 extern hash_map<sal_uInt32, WeakReference<XInterface> > UnoObjToWrapperMap;
93 typedef hash_map<sal_uInt32, WeakReference<XInterface> >::iterator IT_Uno;
94 typedef hash_map<sal_uInt32, WeakReference<XInterface> >::const_iterator CIT_Uno;
95 #ifdef __MINGW32__
96 inline void reduceRange( Any& any);
97 #endif
98 
99 
100 
101 
102 // createUnoObjectWrapper gets a wrapper instance by calling createUnoWrapperInstance
103 	// and initializes it via XInitialization. The wrapper object is required to implement
104 	// XBridgeSupplier so that it can convert itself to IDispatch.
105 	// class T: Deriving class ( must implement XInterface )
106 /** All methods are allowed to throw at least a BridgeRuntimeError.
107  */
108 template< class >
109 class UnoConversionUtilities
110 {
111 public:
112 	UnoConversionUtilities( const Reference<XMultiServiceFactory> & smgr):
113 		m_nUnoWrapperClass( INTERFACE_OLE_WRAPPER_IMPL),
114 		m_nComWrapperClass( IUNKNOWN_WRAPPER_IMPL),
115 		m_smgr( smgr)
116 	{}
117 
118 	UnoConversionUtilities( const Reference<XMultiServiceFactory> & xFactory, sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass )
119 		: m_smgr( xFactory), m_nComWrapperClass( comWrapperClass), m_nUnoWrapperClass( unoWrapperClass)
120 	{}
121 
122     virtual ~UnoConversionUtilities() {}
123 	/** converts only into oleautomation types, that is there is no VT_I1, VT_UI2, VT_UI4
124         a sal_Unicode character is converted into a BSTR.
125         @exception com.sun.star.lang.IllegalArgumentException
126         If the any was inappropriate for conversion.
127         @exception com.sun.star.script.CannotConvertException
128         The any contains a type class for which no conversion is provided.
129     */
130     void anyToVariant(VARIANT* pVariant, const Any& rAny);
131 	void anyToVariant(VARIANT* pVariant, const Any& rAny, VARTYPE type);
132 
133     /** @exception com.sun.star.lang.IllegalArgumentException
134         If rSeq does not contain a sequence then the exception is thrown.
135     */
136 	SAFEARRAY* 	createUnoSequenceWrapper(const Any& rSeq);
137     /** @exception com.sun.star.lang.IllegalArgumentException
138         If rSeq does not contain a sequence or elemtype has no proper value
139         then the exception is thrown.
140     */
141 	SAFEARRAY*  createUnoSequenceWrapper(const Any& rSeq, VARTYPE elemtype);
142     /**
143        @exception com.sun.star.lang.IllegalArgumentException
144        If rObj does not contain a struct or interface
145      */
146 	void createUnoObjectWrapper(const Any & rObj, VARIANT * pVar);
147     /** @exception CannotConvertException
148         Thrown if the VARIANT contains a type that cannot be coerced in the expected Any.
149         ArgumentIndex is 0.
150         @IllegalArgumentException
151         Thrown if the VARIANT is inappropriate for conversion. ArgumentPosition is -1,
152      */
153     void variantToAny(const VARIANT* pVariant, Any& rAny, sal_Bool bReduceValueRange = sal_True);
154     /** This method converts variants arguments in calls from COM -> UNO. Only then
155         the expected UNO type is known.
156         @exception CannotConvertException
157         Thrown if the VARIANT contains a type that cannot be coerced in the expected Any.
158         ArgumentIndex is 0.
159         @IllegalArgumentException
160         Thrown if the VARIANT is inappropriate for conversion. ArgumentPosition is -1,
161      */
162     void variantToAny( const VARIANTARG* pArg, Any& rAny, const Type& ptype, sal_Bool bReduceValueRange = sal_True);
163 
164     /**
165        @exception IllegalArgumentException
166        -if pVar does not contain VT_UNKNOWN or VT_DISPATCH or
167        pVar is used for a particular UNO type which is not supported by pVar
168      */
169     Any createOleObjectWrapper(VARIANT* pVar, const Type& aType= Type());
170 
171     /*
172       Return true means var contained a ValueObject, and it was successfully converted.
173       The result is in any. It an error occurred a BridgeRuntimeError will be thrown.
174      */
175 	bool convertValueObject( const VARIANTARG *var, Any& any);
176 	void dispatchExObject2Sequence( const VARIANTARG* pvar, Any& anySeq, const Type& type);
177 
178 	Sequence<Any> createOleArrayWrapperOfDim(SAFEARRAY* pArray, unsigned int dimCount, unsigned int actDim, long* index,
179                                              VARTYPE type, const Type& unotype);
180 	Sequence<Any> createOleArrayWrapper(SAFEARRAY* pArray, VARTYPE type, const Type& unotype= Type());
181 
182 
183 	VARTYPE mapTypeClassToVartype( TypeClass type);
184 	Reference< XSingleServiceFactory > getInvocationFactory(const Any& anyObject);
185 
186 
187 	virtual Reference< XInterface > createUnoWrapperInstance()=0;
188 	virtual Reference< XInterface > createComWrapperInstance()=0;
189 
190 	static sal_Bool isJScriptArray(const VARIANT* pvar);
191 
192     Sequence<Type> getImplementedInterfaces(IUnknown* pUnk);
193 
194 protected:
195     Reference<XInterface> createAdapter(const Sequence<Type>& types, const Reference<XInterface>& receiver);
196 
197 	// helper function for Sequence conversion
198 	void getElementCountAndTypeOfSequence( const Any& rSeq, sal_Int32 dim, Sequence< sal_Int32 >& seqElementCounts, TypeDescription& typeDesc);
199 	// helper function for Sequence conversion
200 	sal_Bool incrementMultidimensionalIndex(sal_Int32 dimensions, const sal_Int32 * parDimensionLength,
201 									sal_Int32 * parMultidimensionalIndex);
202 	// helper function for Sequence conversion
203 	size_t getOleElementSize( VARTYPE type);
204 
205     Type getElementTypeOfSequence( const Type& seqType);
206 
207     //Provides a typeconverter
208     Reference<XTypeConverter> getTypeConverter();
209 
210 	// This member determines what class is used to convert a UNO object
211 	// or struct to a COM object. It is passed along to the o2u_anyToVariant
212 	// function in the createBridge function implementation
213 	sal_uInt8 m_nUnoWrapperClass;
214 	sal_uInt8 m_nComWrapperClass;
215 
216 	// The servicemanager is either a local smgr or remote when the service
217 	// com.sun.star.bridge.OleBridgeSupplierVar1 is used. This service can be
218 	// created by createInstanceWithArguments where one can supply a service
219 	// manager that is to be used.
220 	// Local service manager as supplied by the loader when the creator function
221 	// of the service is being called.
222 	Reference<XMultiServiceFactory> m_smgr;
223 	// An explicitly supplied service manager when the service
224 	// com.sun.star.bridge.OleBridgeSupplierVar1 is used. That can be a remote
225 	// manager.
226 	Reference<XMultiServiceFactory> m_smgrRemote;
227 	Reference<XSingleServiceFactory> m_xInvocationFactoryLocal;
228 	Reference<XSingleServiceFactory> m_xInvocationFactoryRemote;
229 
230 private:
231     // Holds the type converter which is used for sequence conversion etc.
232     // Use the getTypeConverter function to obtain the interface.
233     Reference<XTypeConverter> m_typeConverter;
234 
235 
236 };
237 
238 // ask the object for XBridgeSupplier2 and on success bridges
239 // the uno object to IUnknown or IDispatch.
240 // return  true the UNO object supports
241 template < class T >
242 bool convertSelfToCom( T& unoInterface, VARIANT * pVar)
243 {
244     bool ret = false;
245     Reference< XInterface > xInt( unoInterface, UNO_QUERY);
246 	if( xInt.is())
247 	{
248 		Reference< XBridgeSupplier2 > xSupplier( xInt, UNO_QUERY);
249 		if( xSupplier.is())
250 		{
251 			sal_Int8 arId[16];
252 			rtl_getGlobalProcessId( (sal_uInt8*)arId);
253 			Sequence<sal_Int8> seqId( arId, 16);
254 			Any anySource;
255 			anySource <<= xInt;
256 			Any anyDisp=	xSupplier->createBridge( anySource, seqId, UNO, OLE);
257 			if( anyDisp.getValueTypeClass() == TypeClass_UNSIGNED_LONG)
258 			{
259 				VARIANT* pvariant= *(VARIANT**)anyDisp.getValue();
260                 HRESULT hr;
261                 if (FAILED(hr = VariantCopy(pVar, pvariant)))
262                     throw BridgeRuntimeError(
263                         OUSTR("[automation bridge] convertSelfToCom\n"
264                               "VariantCopy failed! Error: ") +
265                         OUString::valueOf(hr));
266 				VariantClear( pvariant);
267 				CoTaskMemFree( pvariant);
268                 ret = true;
269 			}
270 		}
271 	}
272     return ret;
273 }
274 
275 
276 
277 // Gets the invocation factory depending on the Type in the Any.
278 // The factory can be created by a local or remote multi service factory.
279 // In case there is a remote multi service factory available there are
280 // some services or types for which the local factory is used. The exceptions
281 // are:  all structs.
282 // Param anyObject - contains the object ( interface, struct) for what we need an invocation object.
283 //
284 template<class T>
285 Reference< XSingleServiceFactory > UnoConversionUtilities<T>::getInvocationFactory(const Any& anyObject)
286 {
287 	Reference< XSingleServiceFactory > retVal;
288 	MutexGuard guard( getBridgeMutex());
289 	if( anyObject.getValueTypeClass() != TypeClass_STRUCT &&
290 		m_smgrRemote.is() )
291 	{
292 		if(  ! m_xInvocationFactoryRemote.is() )
293 			m_xInvocationFactoryRemote= Reference<XSingleServiceFactory>(
294 			m_smgrRemote->createInstance( INVOCATION_SERVICE), UNO_QUERY);
295 		retVal= m_xInvocationFactoryRemote;
296 	}
297 	else
298 	{
299 		if( ! m_xInvocationFactoryLocal.is() )
300 			m_xInvocationFactoryLocal= Reference<XSingleServiceFactory>(
301 			m_smgr->createInstance(INVOCATION_SERVICE ), UNO_QUERY);
302 		retVal= m_xInvocationFactoryLocal;
303 	}
304 	return retVal;
305 }
306 
307 template<class T>
308 void UnoConversionUtilities<T>::variantToAny( const VARIANTARG* pArg, Any& rAny, const Type& ptype,  sal_Bool bReduceValueRange /* = sal_True */)
309 {
310     try
311     {
312         HRESULT hr;
313         bool bFail = false;
314         bool bCannotConvert = false;
315         CComVariant var;
316 
317         // There is no need to support indirect values, since they're not supported by UNO
318         if( FAILED(hr= VariantCopyInd( &var, const_cast<VARIANTARG*>(pArg)))) // remove VT_BYREF
319             throw BridgeRuntimeError(
320                 OUSTR("[automation bridge] UnoConversionUtilities<T>::variantToAny \n"
321                       "VariantCopyInd failed for reason : ") + OUString::valueOf(hr));
322         bool bHandled = convertValueObject( & var, rAny);
323         if( bHandled)
324             OSL_ENSURE(  rAny.getValueType() == ptype, "type in Value Object must match the type parameter");
325 
326         if( ! bHandled)
327         {
328             // convert into a variant type that is the equivalent to the type
329             // the sequence expects. Thus variantToAny produces the correct type
330             // E.g. An Array object contains VT_I4 and the sequence expects shorts
331             // than the vartype must be changed. The reason is, you can't specify the
332             // type in JavaScript and the script engine determines the type beeing used.
333             switch( ptype.getTypeClass())
334             {
335             case TypeClass_CHAR: // could be: new Array( 12, 'w', "w")
336                 if( var.vt == VT_BSTR)
337                 {
338                     if(SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_BSTR)))
339                         rAny.setValue( (void*)V_BSTR( &var), ptype);
340 					else if (hr == DISP_E_TYPEMISMATCH)
341 						bCannotConvert = true;
342                     else
343                         bFail = true;
344                 }
345 				else
346 				{
347 					if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I2)))
348 						rAny.setValue((void*) & var.iVal, ptype);
349 					else if (hr == DISP_E_TYPEMISMATCH)
350 						bCannotConvert = true;
351 					else
352 						bFail = true;
353                 }
354                 break;
355             case TypeClass_INTERFACE: // could also be an IUnknown
356             case TypeClass_STRUCT:
357             {
358                 rAny = createOleObjectWrapper( & var, ptype);
359                 break;
360             }
361             case TypeClass_ENUM:
362                 if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I4)))
363                     rAny.setValue((void*) & var.lVal, ptype);
364                 else if (hr == DISP_E_TYPEMISMATCH)
365                     bCannotConvert = true;
366                 else
367                     bFail = true;
368                 break;
369             case TypeClass_SEQUENCE:
370                 // There are different ways of receiving a sequence:
371                 // 1: JScript, VARTYPE: VT_DISPATCH
372                 // 2. VBScript simple arraysVT_VARIANT|VT_BYREF the referenced VARIANT contains
373                 //		a VT_ARRAY|  <type>
374                 // 3. VBSrcript multi dimensional arrays: VT_ARRAY|VT_BYREF
375                 if( pArg->vt == VT_DISPATCH)
376                 {
377                     dispatchExObject2Sequence( pArg, rAny, ptype);
378                 }
379                 else
380                 {
381                     if ((var.vt & VT_ARRAY) != 0)
382                     {
383                         VARTYPE oleType = ::sal::static_int_cast< VARTYPE, int >( var.vt ^ VT_ARRAY );
384                         Sequence<Any> unoSeq = createOleArrayWrapper( var.parray, oleType, ptype);
385                         Reference<XTypeConverter> conv = getTypeConverter();
386                         if (conv.is())
387                         {
388                             try
389                             {
390                                 Any anySeq = makeAny(unoSeq);
391                                 Any convAny = conv->convertTo(anySeq, ptype);
392                                 rAny = convAny;
393                             }
394                             catch (IllegalArgumentException& e)
395                             {
396                                 throw BridgeRuntimeError(
397                                     OUSTR("[automation bridge]com.sun.star.lang.IllegalArgumentException "
398                                           "in UnoConversionUtilities<T>::variantToAny! Message: ") +
399                                     e.Message);
400                             }
401                             catch (CannotConvertException& e)
402                             {
403                                 throw BridgeRuntimeError(
404                                     OUSTR("[automation bridge]com.sun.star.script.CannotConvertException "
405                                           "in UnoConversionUtilities<T>::variantToAny! Message: ") +
406                                     e.Message);
407                             }
408                         }
409                     }
410                 }
411                 break;
412             case TypeClass_VOID:
413                 rAny.setValue(NULL,Type());
414                 break;
415             case TypeClass_ANY:		//  Any
416                 // There could be a JScript Array that needs special handling
417                 // If an Any is expected and this Any must contain a Sequence
418                 // then we cannot figure out what element type is required.
419                 // Therefore we convert to Sequence< Any >
420                 if( pArg->vt == VT_DISPATCH && 	isJScriptArray( pArg))
421                 {
422                     dispatchExObject2Sequence( pArg, rAny,
423                                                getCppuType((Sequence<Any>*) 0));
424                 }
425                 else if (pArg->vt == VT_DECIMAL)
426                 {
427                     //Decimal maps to hyper in calls from COM -> UNO
428                     // It does not matter if we create a sal_uInt64 or sal_Int64,
429                     // because the UNO object is called through invocation which
430                     //will do a type conversion if necessary
431                     if (var.decVal.sign == 0)
432                     {
433                         // positive value
434                         variantToAny( & var, rAny, getCppuType( (sal_uInt64*) 0),
435                                       bReduceValueRange);
436                     }
437                     else
438                     {
439                         //negative value
440                         variantToAny( & var, rAny, getCppuType( (sal_Int64*) 0),
441                                       bReduceValueRange);
442                     }
443                 }
444                 else
445                 {
446                     variantToAny( & var, rAny);
447                 }
448                 break;
449             case TypeClass_BOOLEAN:			// VARIANT could be VARIANT_BOOL or other
450                 if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_BOOL)))
451                     variantToAny( & var, rAny);
452                 else if (hr == DISP_E_TYPEMISMATCH)
453                     bCannotConvert = true;
454                 else
455                     bFail = true;
456                 break;
457             case TypeClass_STRING:		// UString
458                 if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_BSTR)))
459                     variantToAny( & var, rAny);
460                 else if (hr == DISP_E_TYPEMISMATCH)
461                     bCannotConvert = true;
462                 else
463                     bFail = true;
464                 break;
465             case TypeClass_FLOAT: 		// float
466                 if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_R4)))
467                     variantToAny( & var, rAny);
468                 else if (hr == DISP_E_TYPEMISMATCH)
469                     bCannotConvert = true;
470                 else
471                     bFail = true;
472                 break;
473             case TypeClass_DOUBLE: 		// double
474 			if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_R8)))
475 				variantToAny(& var, rAny);
476 			else if (hr == DISP_E_TYPEMISMATCH)
477                 bCannotConvert = true;
478             else
479 				bFail = true;
480 			break;
481             case TypeClass_BYTE:			// BYTE
482                 if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I1)))
483                     variantToAny( & var, rAny);
484                 else if (hr == DISP_E_TYPEMISMATCH)
485                     bCannotConvert = true;
486                 else
487                     bFail = true;
488                 break;
489             case TypeClass_SHORT: 		// INT16
490                 if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_I2)))
491                     variantToAny( & var, rAny);
492                 else if (hr == DISP_E_TYPEMISMATCH)
493                     bCannotConvert = true;
494                 else
495                     bFail = true;
496                 break;
497             case TypeClass_LONG:
498                 if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_I4)))
499                     variantToAny( & var, rAny, bReduceValueRange);
500                 else if (hr == DISP_E_TYPEMISMATCH)
501                     bCannotConvert = true;
502                 else
503                     bFail = true;
504                 break;
505             case TypeClass_HYPER:
506                 if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_DECIMAL)))
507                 {
508                     if (var.decVal.Lo64 > SAL_CONST_UINT64(0x8000000000000000)
509                         || var.decVal.Hi32 > 0
510                         || var.decVal.scale > 0)
511                     {
512                         bFail = true;
513                         break;
514                     }
515                     sal_Int64 value = var.decVal.Lo64;
516                     if (var.decVal.sign == DECIMAL_NEG)
517                         value |=  SAL_CONST_UINT64(0x8000000000000000);
518                     rAny <<= value;
519                 }
520                 else if (hr == DISP_E_TYPEMISMATCH)
521                     bCannotConvert = true;
522                 else
523                     bFail = true;
524                 break;
525             case TypeClass_UNSIGNED_SHORT:	// UINT16
526                 if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_UI2)))
527                     variantToAny( & var, rAny);
528                 else if (hr == DISP_E_TYPEMISMATCH)
529                     bCannotConvert = true;
530                 else
531                     bFail = true;
532                 break;
533             case TypeClass_UNSIGNED_LONG:
534                 if(SUCCEEDED(hr = VariantChangeType( & var, &var, 0, VT_UI4)))
535                     variantToAny( & var, rAny, bReduceValueRange);
536                 else if (hr == DISP_E_TYPEMISMATCH)
537                     bCannotConvert = true;
538                 else
539                     bFail = true;
540                 break;
541             case TypeClass_UNSIGNED_HYPER:
542                 if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_DECIMAL)))
543                 {
544                     if (var.decVal.Hi32 > 0 || var.decVal.scale > 0)
545                     {
546                         bFail = true;
547                         break;
548                     }
549                     rAny <<= var.decVal.Lo64;
550                 }
551                 else if (hr == DISP_E_TYPEMISMATCH)
552                     bCannotConvert = true;
553                 else
554                     bFail = true;
555                 break;
556             case TypeClass_TYPE:
557                 if(SUCCEEDED(hr = VariantChangeType(& var, &var, 0, VT_UNKNOWN)))
558                     variantToAny( & var, rAny);
559                 else if (hr == DISP_E_TYPEMISMATCH)
560                     bCannotConvert = true;
561                 else
562                     bFail = true;
563                 break;
564             default:
565 // case TypeClass_SERVICE:	break;	// meta construct
566 // case TypeClass_TYPEDEF: break;
567 // case TypeClass_UNION: 	break;
568 // case TypeClass_MODULE:	break;		// module
569 // case TypeClass_EXCEPTION: break;
570 // case TypeClass_ARRAY: break;    // there's no Array at the moment
571 // case TypeClass_UNKNOWN:	break;
572                 bCannotConvert = true;
573                 break;
574             }
575         }
576         if (bCannotConvert)
577             throw CannotConvertException(
578                 OUSTR("[automation bridge]UnoConversionUtilities<T>::variantToAny \n"
579                       "Cannot convert the value of vartype :\"") +
580                 OUString::valueOf((sal_Int32) var.vt) +
581                 OUSTR("\"  to the expected UNO type of type class: ") +
582                 OUString::valueOf((sal_Int32) ptype.getTypeClass()),
583                 0, TypeClass_UNKNOWN, FailReason::TYPE_NOT_SUPPORTED,0);
584 
585         if (bFail)
586             throw IllegalArgumentException(
587                 OUSTR("[automation bridge]UnoConversionUtilities<T>:variantToAny\n"
588                       "The provided VARIANT of type\" ") + OUString::valueOf((sal_Int32) var.vt) +
589                 OUSTR("\" is unappropriate for conversion!"), Reference<XInterface>(), -1);
590     }
591     catch (CannotConvertException &)
592     {
593         throw;
594     }
595     catch (IllegalArgumentException &)
596     {
597         throw;
598     }
599     catch (BridgeRuntimeError &)
600     {
601          throw;
602     }
603     catch (Exception & e)
604     {
605         throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in "
606                                        "UnoConversionUtilities<T>::variantToAny ! Message : \n") +
607                                e.Message);
608     }
609     catch(...)
610     {
611         throw BridgeRuntimeError(
612             OUSTR("[automation bridge] unexpected exception in "
613                   "UnoConversionUtilities<T>::variantToAny !"));
614     }
615 }
616 
617 // The function only converts Sequences to SAFEARRAYS with elements of the type
618 // specified by the parameter type. Everything else is forwarded to
619 // anyToVariant(VARIANT* pVariant, const Any& rAny)
620 // Param type must not be VT_BYREF
621 template<class T>
622 void UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& rAny, VARTYPE type)
623 {
624     try
625     {
626         HRESULT hr= S_OK;
627 
628         OSL_ASSERT( (type & VT_BYREF) == 0);
629         if (type & VT_ARRAY)
630         {
631             type ^= VT_ARRAY;
632             SAFEARRAY* ar= createUnoSequenceWrapper( rAny, type);
633             if( ar)
634             {
635                 VariantClear( pVariant);
636                 pVariant->vt= ::sal::static_int_cast< VARTYPE, int >( VT_ARRAY | type );
637                 pVariant->byref= ar;
638             }
639         }
640         else if(type == VT_VARIANT)
641         {
642             anyToVariant(pVariant, rAny);
643         }
644         else
645         {
646             CComVariant var;
647             anyToVariant( &var, rAny);
648             if(FAILED(hr = VariantChangeType(&var, &var, 0, type)))
649             {
650                 if (hr == DISP_E_TYPEMISMATCH)
651                     throw CannotConvertException(
652                         OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
653                               "Cannot convert the value of type :\"") +
654                         rAny.getValueTypeName() +
655                         OUSTR("\"  to the expected Automation type of VARTYPE: ") +
656                         OUString::valueOf((sal_Int32)type),
657                         0, TypeClass_UNKNOWN, FailReason::TYPE_NOT_SUPPORTED,0);
658 
659                 throw BridgeRuntimeError(
660                     OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
661                           "Conversion of any with ") +
662                     rAny.getValueType().getTypeName() +
663                     OUSTR(" to VARIANT with type: ") + OUString::valueOf((sal_Int32) type) +
664                     OUSTR(" failed! Error code: ") + OUString::valueOf(hr));
665 
666             }
667             if(FAILED(hr = VariantCopy(pVariant, &var)))
668             {
669                 throw BridgeRuntimeError(
670                     OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
671                           "VariantCopy failed for reason: ") + OUString::valueOf(hr));
672             }
673         }
674     }
675     catch (IllegalArgumentException &)
676     {
677         throw;
678     }
679     catch (CannotConvertException & )
680     {
681         throw;
682     }
683     catch (BridgeRuntimeError&)
684     {
685         throw;
686     }
687     catch(Exception & e)
688     {
689         throw BridgeRuntimeError(
690             OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
691                   "Unexpected exception occurred. Message: ") + e.Message);
692     }
693     catch(...)
694     {
695         throw BridgeRuntimeError(
696             OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
697                   "Unexpected exception occurred."));
698     }
699 }
700 
701 template<class T>
702 void UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& rAny)
703 {
704     bool bIllegal = false;
705     try
706     {
707         switch (rAny.getValueTypeClass())
708         {
709 		case TypeClass_INTERFACE:
710 		{
711 			Reference<XInterface> xInt;
712 			if (rAny >>= xInt)
713             {
714 				createUnoObjectWrapper(rAny, pVariant);
715 			}
716 			else
717 			{
718 				bIllegal = true;
719 			}
720 			break;
721 		}
722 		case TypeClass_STRUCT:
723         {
724             if (rAny.getValueType() == getCppuType((Date*)0))
725             {
726                 Date d;
727                 if (rAny >>= d)
728                 {
729                     pVariant->vt = VT_DATE;
730                     pVariant->date = d.Value;
731                 }
732                 else
733                 {
734                     bIllegal = true;
735                 }
736             }
737             else if(rAny.getValueType() == getCppuType((Decimal*)0))
738             {
739                 Decimal d;
740                 if (rAny >>= d)
741                 {
742                     pVariant->vt = VT_DECIMAL;
743                     pVariant->decVal.scale = d.Scale;
744                     pVariant->decVal.sign = d.Sign;
745                     pVariant->decVal.Lo32 = d.LowValue;
746                     pVariant->decVal.Mid32 = d.MiddleValue;
747                     pVariant->decVal.Hi32 = d.HighValue;
748                 }
749                 else
750                 {
751                     bIllegal = true;
752                 }
753             }
754             else if (rAny.getValueType() == getCppuType((Currency*)0))
755             {
756                 Currency c;
757                 if (rAny >>= c)
758                 {
759                     pVariant->vt = VT_CY;
760                     pVariant->cyVal.int64 = c.Value;
761                 }
762                 else
763                 {
764                     bIllegal = true;
765                 }
766             }
767             else if(rAny.getValueType() == getCppuType((SCode*)0))
768             {
769                 SCode s;
770                 if (rAny >>= s)
771                 {
772                     pVariant->vt = VT_ERROR;
773                     pVariant->scode = s.Value;
774                 }
775                 else
776                 {
777                     bIllegal = true;
778                 }
779             }
780             else
781             {
782                 createUnoObjectWrapper(rAny, pVariant);
783             }
784 			break;
785         }
786 		case TypeClass_SEQUENCE:		// sequence ??? SafeArray descriptor
787 		{
788 			SAFEARRAY* pArray = createUnoSequenceWrapper(rAny);
789 			if (pArray)
790 			{
791 				V_VT(pVariant) = VT_ARRAY | VT_VARIANT;
792 				V_ARRAY(pVariant) = pArray;
793 			}
794             else
795             {
796                 bIllegal = true;
797             }
798 			break;
799 		}
800 		case TypeClass_VOID:
801         {
802             HRESULT hr = S_OK;
803 			if (FAILED(hr = VariantClear(pVariant)))
804             {
805                 throw BridgeRuntimeError(
806                     OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant\n"
807                         "VariantClear failed with error:") + OUString::valueOf(hr));
808             }
809 			break;
810         }
811 		case TypeClass_BOOLEAN:
812 		{
813             sal_Bool value;
814             if (rAny >>= value)
815             {
816                 pVariant->vt = VT_BOOL;
817                 pVariant->boolVal = value == sal_True? VARIANT_TRUE: VARIANT_FALSE;
818             }
819             else
820             {
821                 bIllegal = true;
822             }
823             break;
824 		}
825 		case TypeClass_CHAR:
826         {
827             // Because VT_UI2 does not conform to oleautomation we convert into VT_I2 instead
828             sal_uInt16 value = *(sal_Unicode*) rAny.getValue();
829             pVariant->vt = VT_I2;
830             pVariant->iVal = value;
831 			break;
832         }
833 		case TypeClass_STRING:
834         {
835             OUString value;
836             if (rAny >>= value)
837             {
838                 pVariant->vt = VT_BSTR;
839                 pVariant->bstrVal = SysAllocString(reinterpret_cast<LPCOLESTR>(value.getStr()));
840             }
841             else
842             {
843                 bIllegal = true;
844             }
845 			break;
846         }
847 		case TypeClass_FLOAT:
848         {
849             float value;
850             if (rAny >>= value)
851             {
852                 pVariant->vt = VT_R4;
853                 pVariant->fltVal = value;
854             }
855             else
856             {
857                 bIllegal = true;
858             }
859 			break;
860         }
861 		case TypeClass_DOUBLE:
862         {
863             double value;
864             if (rAny >>= value)
865             {
866                 pVariant->vt = VT_R8;
867                 pVariant->dblVal = value;
868             }
869             else
870             {
871                 bIllegal = true;
872             }
873 			break;
874         }
875 		case TypeClass_BYTE:
876         {
877 			// ole automation does not know a signed char but only unsigned char
878             sal_Int8 value;
879             if (rAny >>= value)
880             {
881                 pVariant->vt = VT_UI1;
882                 pVariant->bVal = value;
883             }
884             else
885             {
886                 bIllegal = true;
887             }
888 			break;
889         }
890 		case TypeClass_SHORT: 		// INT16
891 		case TypeClass_UNSIGNED_SHORT:	// UINT16
892         {
893             sal_Int16 value;
894             if (rAny >>= value)
895             {
896                 pVariant->vt = VT_I2;
897                 pVariant->iVal = value;
898             }
899             else
900             {
901                 bIllegal = true;
902             }
903 			break;
904         }
905 		case TypeClass_ENUM:
906         {
907             sal_Int32 value = *(sal_Int32*) rAny.getValue();
908             pVariant->vt = VT_I4;
909             pVariant->lVal= value;
910             break;
911         }
912         case TypeClass_LONG:
913 		case TypeClass_UNSIGNED_LONG:
914         {
915             sal_Int32 value;
916             if (rAny >>= value)
917             {
918                 pVariant->vt = VT_I4;
919                 pVariant->lVal= value;
920             }
921             else
922             {
923                 bIllegal = true;
924             }
925 			break;
926         }
927         case TypeClass_HYPER:
928         {
929 
930             pVariant->vt = VT_DECIMAL;
931             pVariant->decVal.scale = 0;
932             pVariant->decVal.sign = 0;
933             pVariant->decVal.Hi32 = 0;
934 
935             sal_Int64 value;
936             rAny >>= value;
937 
938             if (value & SAL_CONST_UINT64(0x8000000000000000))
939                 pVariant->decVal.sign = DECIMAL_NEG;
940 
941             pVariant->decVal.Lo64 = value;
942             break;
943         }
944         case TypeClass_UNSIGNED_HYPER:
945         {
946             pVariant->vt = VT_DECIMAL;
947             pVariant->decVal.scale = 0;
948             pVariant->decVal.sign = 0;
949             pVariant->decVal.Hi32 = 0;
950 
951             sal_uInt64 value;
952             rAny >>= value;
953             pVariant->decVal.Lo64 = value;
954 			break;
955         }
956         case TypeClass_TYPE:
957         {
958             Type type;
959             rAny >>= type;
960             CComVariant var;
961             if (createUnoTypeWrapper(type.getTypeName(), & var) == false)
962                 throw BridgeRuntimeError(
963                     OUSTR("[automation bridge] UnoConversionUtilities<T>::anyToVariant \n"
964                           "Error during conversion of UNO type to Automation object!"));
965 
966             if (FAILED(VariantCopy(pVariant, &var)))
967                 throw BridgeRuntimeError(
968                     OUSTR("[automation bridge] UnoConversionUtilities<T>::anyToVariant \n"
969                           "Unexpected error!"));
970             break;
971         }
972 		default:
973             //TypeClass_SERVICE:
974             //TypeClass_EXCEPTION:
975             //When a InvocationTargetException is thrown when calling XInvocation::invoke
976             //on a UNO object, then the target exception is directly used to create a
977             //EXEPINFO structure
978             //TypeClass_TYPEDEF
979 		    //TypeClass_ANY:
980             //TypeClass_UNKNOWN:
981             //TypeClass_UNSIGNED_OCTET:
982             // TypeClass_UNION:
983 		    // TypeClass_ARRAY:
984             // TypeClass_UNSIGNED_INT:
985             // TypeClass_UNSIGNED_BYTE:
986 		    // TypeClass_MODULE:
987             throw CannotConvertException(
988                 OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant\n"
989                       "There is no conversion for this UNO type to a Automation type."
990                       "The destination type class is the type class of the UNO "
991                       "argument which was to be converted."),
992                 Reference<XInterface>(), rAny.getValueTypeClass(),
993                 FailReason::TYPE_NOT_SUPPORTED, 0);
994 
995             break;
996         }
997         if (bIllegal)
998         {
999             throw IllegalArgumentException(
1000                 OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant\n"
1001                       "The provided any of type\" ") + rAny.getValueType().getTypeName() +
1002                 OUSTR("\" is unappropriate for conversion!"), Reference<XInterface>(), -1);
1003 
1004         }
1005     }
1006     catch (CannotConvertException & )
1007     {
1008         throw;
1009     }
1010     catch (IllegalArgumentException & )
1011     {
1012         throw;
1013     }
1014     catch(BridgeRuntimeError&)
1015     {
1016         throw;
1017     }
1018     catch(Exception & e)
1019     {
1020         throw BridgeRuntimeError(
1021             OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
1022                   "Unexpected exception occurred. Message: ") + e.Message);
1023     }
1024     catch(...)
1025     {
1026         throw BridgeRuntimeError(
1027             OUSTR("[automation bridge]UnoConversionUtilities<T>::anyToVariant \n"
1028                   "Unexpected exception occurred. ") );
1029     }
1030 }
1031 
1032 // Creates an SAFEARRAY of the specified element and if necessary
1033 // creates a SAFEARRAY whith multiple dimensions.
1034 // Used by sal_Bool anyToVariant(VARIANT* pVariant, const Any& rAny, VARTYPE type);
1035 template<class T>
1036 SAFEARRAY*  UnoConversionUtilities<T>::createUnoSequenceWrapper(const Any& rSeq, VARTYPE elemtype)
1037 {
1038     if (rSeq.getValueTypeClass() != TypeClass_SEQUENCE)
1039         throw IllegalArgumentException(
1040             OUSTR("[automation bridge]UnoConversionUtilities<T>::createUnoSequenceWrapper \n"
1041                   "The any does not contain a sequence!"), 0, 0);
1042     if (elemtype == VT_NULL  ||  elemtype == VT_EMPTY)
1043         throw IllegalArgumentException(
1044             OUSTR("[automation bridge]UnoConversionUtilities<T>::createUnoSequenceWrapper \n"
1045                   "No element type supplied!"),0, -1);
1046 	SAFEARRAY*	pArray= NULL;
1047 	// Get the dimensions. This is done by examining the type name string
1048 	// The count of brackets determines the dimensions.
1049 	OUString sTypeName= rSeq.getValueType().getTypeName();
1050 	sal_Int32 dims=0;
1051 	for(sal_Int32 lastIndex=0;(lastIndex= sTypeName.indexOf( L'[', lastIndex)) != -1; lastIndex++,dims++);
1052 
1053 	//get the maximum number of elements per dimensions and the typedescription of the elements
1054 	Sequence<sal_Int32> seqElementCounts( dims);
1055 	TypeDescription elementTypeDesc;
1056 	getElementCountAndTypeOfSequence( rSeq, 1, seqElementCounts, elementTypeDesc );
1057 
1058 	if( elementTypeDesc.is() )
1059 	{
1060 		// set up the SAFEARRAY
1061         scoped_array<SAFEARRAYBOUND> sarSafeArrayBound(new SAFEARRAYBOUND[dims]);
1062 		SAFEARRAYBOUND* prgsabound= sarSafeArrayBound.get();
1063 		for( sal_Int32 i=0; i < dims; i++)
1064 		{
1065 			//prgsabound[0] is the right most dimension
1066  			prgsabound[dims - i - 1].lLbound = 0;
1067 			prgsabound[dims - i - 1].cElements = seqElementCounts[i];
1068 		}
1069 
1070 		typelib_TypeDescription* rawTypeDesc= elementTypeDesc.get();
1071 		sal_Int32 elementSize= rawTypeDesc->nSize;
1072 		size_t oleElementSize= getOleElementSize( elemtype);
1073 		// SafeArrayCreate clears the memory for the data itself.
1074 		pArray = SafeArrayCreate(elemtype, dims, prgsabound);
1075 
1076 		// convert the Sequence's elements and populate the SAFEARRAY
1077 		if( pArray)
1078 		{
1079 			// Iterate over every Sequence that contains the actual elements
1080 			void* pSAData;
1081 			if( SUCCEEDED( SafeArrayAccessData( pArray, &pSAData)))
1082 			{
1083 				const sal_Int32* parElementCount= seqElementCounts.getConstArray();
1084 				uno_Sequence * pMultiSeq= *(uno_Sequence* const*) rSeq.getValue();
1085 				sal_Int32 dimsSeq= dims - 1;
1086 
1087 				// arDimSeqIndizes contains the current index of a block of data.
1088 				// E.g. Sequence<Sequence<sal_Int32>> , the index would refer to Sequence<sal_Int32>
1089 				// In this case arDimSeqIndices would have the size 1. That is the elements are not counted
1090 				// but the Sequences that contain those elements.
1091 				// The indices ar 0 based
1092                 scoped_array<sal_Int32> sarDimsSeqIndices;
1093 				sal_Int32* arDimsSeqIndices= NULL;
1094 				if( dimsSeq > 0)
1095 				{
1096 					sarDimsSeqIndices.reset(new sal_Int32[dimsSeq]);
1097                     arDimsSeqIndices = sarDimsSeqIndices.get();
1098 					memset( arDimsSeqIndices, 0,  sizeof( sal_Int32 ) * dimsSeq);
1099 				}
1100 
1101 				char* psaCurrentData= (char*)pSAData;
1102 
1103 				do
1104 				{
1105 					// Get the Sequence at the current index , see arDimsSeqIndices
1106 					uno_Sequence * pCurrentSeq= pMultiSeq;
1107 					sal_Int32 curDim=1; // 1 based
1108 					sal_Bool skipSeq= sal_False;
1109 					while( curDim <= dimsSeq )
1110 					{
1111 						// get the Sequence at the index if valid
1112 						if( pCurrentSeq->nElements > arDimsSeqIndices[ curDim - 1] ) // don't point to Nirvana
1113 						{
1114 							// size of Sequence is 4
1115 							sal_Int32 offset= arDimsSeqIndices[ curDim - 1] * 4;
1116 							pCurrentSeq= *(uno_Sequence**) &pCurrentSeq->elements[ offset];
1117 							curDim++;
1118 						}
1119 						else
1120 						{
1121 							// There is no Sequence at this index, so skip this index
1122 							skipSeq= sal_True;
1123 							break;
1124 						}
1125 					}
1126 
1127 					if( skipSeq)
1128 						continue;
1129 
1130 					// Calculate the current position within the datablock of the SAFEARRAY
1131 					// for the next Sequence.
1132 					sal_Int32 memOffset= 0;
1133 					sal_Int32 dimWeight= parElementCount[ dims - 1]; // size of the rightmost dimension
1134 					for(sal_Int16 idims=0; idims < dimsSeq; idims++ )
1135 					{
1136 						memOffset+= arDimsSeqIndices[dimsSeq - 1 - idims] * dimWeight;
1137 						// now determine the weight of the dimension to the left of the current.
1138 						if( dims - 2 - idims >=0)
1139 							dimWeight*= parElementCount[dims - 2 - idims];
1140 					}
1141 					psaCurrentData= (char*)pSAData + memOffset * oleElementSize;
1142 					// convert the Sequence and put the elements into the Safearray
1143 					for( sal_Int32 i= 0; i < pCurrentSeq->nElements; i++)
1144 					{
1145 						Any unoElement( pCurrentSeq->elements + i * elementSize, rawTypeDesc );
1146 						// The any is being converted into an VARIANT which value is then copied
1147 						// to the SAFEARRAY's data block. When copying one has to follow the rules for
1148 						// copying certain types, as are VT_DISPATCH, VT_UNKNOWN, VT_VARIANT, VT_BSTR.
1149 						// To increase performance, we just do a memcpy of VARIANT::byref. This is possible
1150 						// because anyToVariant has already followed the copying rules. To make this
1151 						// work there must not be a VariantClear.
1152 						// One Exception is VARIANT because I don't know how VariantCopy works.
1153 
1154 						VARIANT var;
1155 						VariantInit( &var);
1156 						anyToVariant( &var, unoElement);
1157                         if( elemtype == VT_VARIANT )
1158                         {
1159                             VariantCopy( ( VARIANT*)psaCurrentData, &var);
1160                             VariantClear( &var);
1161                         }
1162                         else
1163                             memcpy( psaCurrentData, &var.byref, oleElementSize);
1164 
1165 						psaCurrentData+= oleElementSize;
1166 					}
1167 				}
1168 				while( incrementMultidimensionalIndex( dimsSeq, parElementCount, arDimsSeqIndices));
1169 
1170 				SafeArrayUnaccessData( pArray);
1171 			}
1172 		}
1173 	}
1174 	return pArray;
1175 }
1176 
1177 // Increments a multi dimensional index.
1178 // Returns true as long as the index has been successfully incremented, false otherwise.
1179 // False is also returned if an overflow of the most significant dimension occurs. E.g.
1180 // assume an array with the dimensions (2,2), then the lowest index is (0,0) and the highest
1181 // index is (1,1). If the function is being called with the index (1,1) then the overflow would
1182 // occur, with the result (0,0) and a sal_False as return value.
1183 // Param dimensions - number of dimensions
1184 // Param parDimensionsLength - The array contains the size of each dimension, that is the
1185 //								size of the array equals the parameter dimensions.
1186 //								The rightmost dimensions is the least significant one
1187 //								( parDimensionsLengths[ dimensions -1 ] ).
1188 // Param parMultiDimensionalIndex - The array contains the index. Each dimension index is
1189 //									0 based.
1190 template<class T>
1191 sal_Bool UnoConversionUtilities<T>::incrementMultidimensionalIndex(sal_Int32 dimensions,
1192 																   const sal_Int32 * parDimensionLengths,
1193 																   sal_Int32 * parMultidimensionalIndex)
1194 {
1195 	if( dimensions < 1)
1196 		return sal_False;
1197 
1198 	sal_Bool ret= sal_True;
1199 	sal_Bool carry= sal_True; // to get into the while loop
1200 
1201 	sal_Int32 currentDimension= dimensions; //most significant is 1
1202 	while( carry)
1203 	{
1204 		parMultidimensionalIndex[ currentDimension - 1]++;
1205 		// if carryover, set index to 0 and handle carry on a level above
1206 		if( parMultidimensionalIndex[ currentDimension - 1] > (parDimensionLengths[ currentDimension - 1] - 1))
1207 			parMultidimensionalIndex[ currentDimension - 1]= 0;
1208 		else
1209 			carry= sal_False;
1210 
1211 		currentDimension --;
1212 		// if dimensions drops below 1 and carry is set than then all indices are 0 again
1213 		// this is signalled by returning sal_False
1214 		if( currentDimension < 1 && carry)
1215 		{
1216 			carry= sal_False;
1217 			ret= sal_False;
1218 		}
1219 	}
1220 	return ret;
1221 }
1222 
1223 // Determines the size of a certain OLE type. The function takes
1224 // only those types into account which are oleautomation types and
1225 // can have a value ( unless VT_NULL, VT_EMPTY, VT_ARRAY, VT_BYREF).
1226 // Currently used in createUnoSequenceWrapper to calculate addresses
1227 // for data within a SAFEARRAY.
1228 template<class T>
1229 size_t UnoConversionUtilities<T>::getOleElementSize( VARTYPE type)
1230 {
1231 	size_t size;
1232 	switch( type)
1233 	{
1234 	case VT_BOOL: size= sizeof( VARIANT_BOOL);break;
1235 	case VT_UI1: size= sizeof( unsigned char);break;
1236 	case VT_R8: size= sizeof( double);break;
1237 	case VT_R4: size= sizeof( float);break;
1238 	case VT_I2: size= sizeof( short);break;
1239 	case VT_I4: size= sizeof( long);break;
1240 	case VT_BSTR: size= sizeof( BSTR); break;
1241 	case VT_ERROR: size= sizeof( SCODE); break;
1242 	case VT_DISPATCH:
1243 	case VT_UNKNOWN: size= sizeof( IUnknown*); break;
1244 	case VT_VARIANT: size= sizeof( VARIANT);break;
1245 	default: size= 0;
1246 	}
1247 	return size;
1248 }
1249 
1250 //If a Sequence is being converted into a SAFEARRAY then we possibly have
1251 // to create a SAFEARRAY with multiple dimensions. This is the case when a
1252 // Sequence contains Sequences ( Sequence< Sequence < XXX > > ). The leftmost
1253 // Sequence in the declaration is assumed to represent dimension 1. Because
1254 // all Sequence elements of a Sequence can have different length, we have to
1255 // determine the maximum length which is then the length of the respective
1256 // dimension.
1257 // getElementCountAndTypeOfSequence determines the length of each dimension and calls itself recursively
1258 // in the process.
1259 // param rSeq - an Any that has to contain a Sequence
1260 // param dim - the dimension for which the number of elements is being determined,
1261 //				must be one.
1262 // param seqElementCounts - countains the maximum number of elements for each
1263 //							dimension. Index 0 contains the number of dimension one.
1264 //							After return the Sequence contains the maximum number of
1265 //							elements for each dimension.
1266 //							The length of the Sequence must equal the number of dimensions.
1267 // param typeClass - TypeClass of the element type that is no Sequence, e.g.
1268 //							Sequence< Sequence <Sequence <sal_Int32> > > - type is sal_Int32)
1269 template<class T>
1270 void  UnoConversionUtilities<T>::getElementCountAndTypeOfSequence( const Any& rSeq, sal_Int32 dim,
1271 											 Sequence< sal_Int32 >& seqElementCounts, TypeDescription& typeDesc)
1272 {
1273 	sal_Int32 dimCount= (*(uno_Sequence* const *) rSeq.getValue())->nElements;
1274 	if( dimCount > seqElementCounts[ dim-1])
1275 		seqElementCounts[ dim-1]= dimCount;
1276 
1277 	// we need the element type to construct the any that is
1278 	// passed into getElementCountAndTypeOfSequence again
1279 	typelib_TypeDescription* pSeqDesc= NULL;
1280 	rSeq.getValueTypeDescription( &pSeqDesc);
1281 	typelib_TypeDescriptionReference* pElementDescRef= ((typelib_IndirectTypeDescription*)pSeqDesc)->pType;
1282 
1283 	// if the elements are Sequences than do recursion
1284 	if( dim < seqElementCounts.getLength() )
1285 	{
1286 		uno_Sequence* pSeq = *(uno_Sequence* const*) rSeq.getValue();
1287 		uno_Sequence** arSequences= (uno_Sequence**)pSeq->elements;
1288 		for( sal_Int32 i=0; i < dimCount; i++)
1289 		{
1290 			uno_Sequence* arElement=  arSequences[ i];
1291 			getElementCountAndTypeOfSequence( Any( &arElement, pElementDescRef), dim + 1 , seqElementCounts, typeDesc);
1292 		}
1293 	}
1294 	else
1295 	{
1296 		// determine the element type ( e.g. Sequence< Sequence <Sequence <sal_Int32> > > - type is sal_Int32)
1297 		typeDesc= pElementDescRef;
1298 	}
1299 	typelib_typedescription_release( pSeqDesc);
1300 }
1301 
1302 
1303 template<class T>
1304 SAFEARRAY* 	UnoConversionUtilities<T>::createUnoSequenceWrapper(const Any& rSeq)
1305 {
1306 	SAFEARRAY* pArray = NULL;
1307 	sal_uInt32 n = 0;
1308 
1309 	if( rSeq.getValueTypeClass() != TypeClass_SEQUENCE )
1310         throw IllegalArgumentException(
1311             OUSTR("[automation bridge]UnoConversionUtilities<T>::createUnoSequenceWrapper\n"
1312                   "The UNO argument is not a sequence"), 0, -1);
1313 
1314     uno_Sequence * punoSeq= *(uno_Sequence**) rSeq.getValue();
1315 
1316     typelib_TypeDescriptionReference* pSeqTypeRef= rSeq.getValueTypeRef();
1317     typelib_TypeDescription* pSeqType= NULL;
1318     TYPELIB_DANGER_GET( &pSeqType, pSeqTypeRef);
1319     typelib_IndirectTypeDescription * pSeqIndDec=	(typelib_IndirectTypeDescription*) pSeqType;
1320 
1321 
1322     typelib_TypeDescriptionReference * pSeqElementTypeRef= pSeqIndDec->pType;
1323     TYPELIB_DANGER_RELEASE( pSeqType);
1324 
1325     typelib_TypeDescription* pSeqElementDesc= NULL;
1326     TYPELIB_DANGER_GET( &pSeqElementDesc, pSeqElementTypeRef);
1327 
1328     // try to find VARIANT type that is related to the UNO type of the sequence elements
1329     // the sequence as a sequence element should be handled in a special way
1330     VARTYPE eTargetElementType = VT_EMPTY;
1331     if ( pSeqElementDesc->eTypeClass != TypeClass_SEQUENCE )
1332         eTargetElementType = mapTypeClassToVartype( static_cast< TypeClass >( pSeqElementDesc->eTypeClass ) );
1333 
1334     if ( eTargetElementType != VT_EMPTY )
1335         pArray = createUnoSequenceWrapper( rSeq, eTargetElementType );
1336 
1337     if ( !pArray )
1338     {
1339         sal_Int32 nElementSize= pSeqElementDesc->nSize;
1340         n= punoSeq->nElements;
1341 
1342         SAFEARRAYBOUND rgsabound[1];
1343         rgsabound[0].lLbound = 0;
1344         rgsabound[0].cElements = n;
1345         VARIANT oleElement;
1346         long safeI[1];
1347 
1348         pArray = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
1349 
1350         Any unoElement;
1351         //		sal_uInt8 * pSeqData= (sal_uInt8*) punoSeq->pElements;
1352         sal_uInt8 * pSeqData= (sal_uInt8*) punoSeq->elements;
1353 
1354         for (sal_uInt32 i = 0; i < n; i++)
1355         {
1356             unoElement.setValue( pSeqData + i * nElementSize, pSeqElementDesc);
1357             VariantInit(&oleElement);
1358 
1359             anyToVariant(&oleElement, unoElement);
1360 
1361             safeI[0] = i;
1362             SafeArrayPutElement(pArray, safeI, &oleElement);
1363 
1364             VariantClear(&oleElement);
1365         }
1366     }
1367 
1368     TYPELIB_DANGER_RELEASE( pSeqElementDesc);
1369 
1370     return pArray;
1371 }
1372 
1373 /* The argument rObj can contain
1374 - UNO struct
1375 - UNO interface
1376 - UNO interface created by this bridge (adapter factory)
1377 - UNO interface created by this bridge ( COM Wrapper)
1378 
1379 pVar must be initialized.
1380 */
1381 template<class T>
1382 void UnoConversionUtilities<T>::createUnoObjectWrapper(const Any & rObj, VARIANT * pVar)
1383 {
1384 	MutexGuard guard(getBridgeMutex());
1385 
1386 	Reference<XInterface> xInt;
1387 
1388     TypeClass tc = rObj.getValueTypeClass();
1389     if (tc != TypeClass_INTERFACE && tc != TypeClass_STRUCT)
1390         throw IllegalArgumentException(
1391             OUSTR("[automation bridge]UnoConversionUtilities<T>::createUnoObjectWrapper \n"
1392                   "Cannot create an Automation interface for a UNO type which is not "
1393                   "a struct or interface!"), 0, -1);
1394 
1395     if (rObj.getValueTypeClass() == TypeClass_INTERFACE)
1396     {
1397         if (! (rObj >>= xInt))
1398             throw IllegalArgumentException(
1399                 OUSTR("[automation bridge] UnoConversionUtilities<T>::createUnoObjectWrapper\n "
1400                   "Could not create wrapper object for UNO object!"), 0, -1);
1401         //If XInterface is NULL, which is a valid value, then simply return NULL.
1402         if ( ! xInt.is())
1403         {
1404             pVar->vt = VT_UNKNOWN;
1405             pVar->punkVal = NULL;
1406             return;
1407         }
1408         //make sure we have the main XInterface which is used with a map
1409         xInt = Reference<XInterface>(xInt, UNO_QUERY);
1410         //If there is already a wrapper for the UNO object then use it
1411 
1412         Reference<XInterface> xIntWrapper;
1413         // Does a UNO wrapper exist already ?
1414         IT_Uno it_uno = UnoObjToWrapperMap.find( (sal_uInt32) xInt.get());
1415         if(it_uno != UnoObjToWrapperMap.end())
1416         {
1417             xIntWrapper =  it_uno->second;
1418             if (xIntWrapper.is())
1419             {
1420                 convertSelfToCom(xIntWrapper, pVar);
1421                 return;
1422             }
1423         }
1424         // Is the object a COM wrapper ( either XInvocation, or Adapter object)
1425         // or does it suppy an IDispatch by its own ?
1426         else
1427         {
1428             Reference<XInterface> xIntComWrapper = xInt;
1429             typedef hash_map<sal_uInt32,sal_uInt32>::iterator _IT;
1430             // Adapter? then get the COM wrapper to which the adapter delegates its calls
1431             _IT it= AdapterToWrapperMap.find( (sal_uInt32) xInt.get());
1432             if( it != AdapterToWrapperMap.end() )
1433                 xIntComWrapper= reinterpret_cast<XInterface*>(it->second);
1434 
1435             if (convertSelfToCom(xIntComWrapper, pVar))
1436                 return;
1437         }
1438     }
1439     // If we have no UNO wrapper nor the IDispatch yet then we have to create
1440     // a wrapper. For that we need an XInvocation from the UNO object.
1441 
1442     // get an XInvocation or create one using the invocation service
1443     Reference<XInvocation> xInv(xInt, UNO_QUERY);
1444     if ( ! xInv.is())
1445     {
1446         Reference<XSingleServiceFactory> xInvFactory= getInvocationFactory(rObj);
1447         if (xInvFactory.is())
1448         {
1449             Sequence<Any> params(1);
1450             params.getArray()[0] = rObj;
1451             Reference<XInterface> xInt = xInvFactory->createInstanceWithArguments(params);
1452             xInv= Reference<XInvocation>(xInt, UNO_QUERY);
1453         }
1454     }
1455 
1456     if (xInv.is())
1457     {
1458         Reference<XInterface> xNewWrapper = createUnoWrapperInstance();
1459         Reference<XInitialization> xInitWrapper(xNewWrapper, UNO_QUERY);
1460         if (xInitWrapper.is())
1461         {
1462             VARTYPE vartype= getVarType( rObj);
1463 
1464             if (xInt.is())
1465             {
1466                 Any params[3];
1467                 params[0] <<= xInv;
1468                 params[1] <<= xInt;
1469                 params[2] <<= vartype;
1470                 xInitWrapper->initialize( Sequence<Any>(params, 3));
1471             }
1472             else
1473             {
1474                 Any params[2];
1475                 params[0] <<= xInv;
1476                 params[1] <<= vartype;
1477                 xInitWrapper->initialize( Sequence<Any>(params, 2));
1478             }
1479 
1480             // put the newly created object into a map. If the same object will
1481             // be mapped again and there is already a wrapper then the old wrapper
1482             // will be used.
1483             if(xInt.is()) // only interfaces
1484                 UnoObjToWrapperMap[(sal_uInt32) xInt.get()]= xNewWrapper;
1485             convertSelfToCom(xNewWrapper, pVar);
1486             return;
1487         }
1488     }
1489 }
1490 
1491 template<class T>
1492 void UnoConversionUtilities<T>::variantToAny( const VARIANT* pVariant, Any& rAny,
1493 												  sal_Bool bReduceValueRange /* = sal_True */)
1494 {
1495     HRESULT hr = S_OK;
1496     try
1497     {
1498         CComVariant var;
1499 
1500         // There is no need to support indirect values, since they're not supported by UNO
1501         if( FAILED(hr= VariantCopyInd( &var, const_cast<VARIANTARG*>(pVariant)))) // remove VT_BYREF
1502             throw BridgeRuntimeError(
1503                 OUSTR("[automation bridge] UnoConversionUtilities<T>::variantToAny \n"
1504                       "VariantCopyInd failed for reason : ") + OUString::valueOf(hr));
1505 
1506         if ( ! convertValueObject( & var, rAny))
1507         {
1508             if ((var.vt & VT_ARRAY) > 0)
1509             {
1510                 VARTYPE oleTypeFlags = ::sal::static_int_cast< VARTYPE, int >( var.vt ^ VT_ARRAY );
1511 
1512                 Sequence<Any> unoSeq = createOleArrayWrapper(var.parray, oleTypeFlags);
1513                 rAny.setValue( &unoSeq, getCppuType( &unoSeq));
1514             }
1515             else
1516             {
1517                 switch (var.vt)
1518                 {
1519 				case VT_EMPTY:
1520 					rAny.setValue(NULL, Type());
1521 					break;
1522 				case VT_NULL:
1523 					rAny.setValue(NULL, Type());
1524 					break;
1525 				case VT_I2:
1526 					rAny.setValue( & var.iVal, getCppuType( (sal_Int16*)0));
1527 					break;
1528 				case VT_I4:
1529 					rAny.setValue( & var.lVal, getCppuType( (sal_Int32*)0));
1530 					// necessary for use in JavaScript ( see "reduceRange")
1531 					if( bReduceValueRange)
1532 						reduceRange(rAny);
1533 					break;
1534 				case VT_R4:
1535 					rAny.setValue( & var.fltVal, getCppuType( (float*)0));
1536 					break;
1537 				case VT_R8:
1538 					rAny.setValue(& var.dblVal, getCppuType( (double*)0));
1539 					break;
1540 				case VT_CY:
1541                 {
1542                     Currency cy(var.cyVal.int64);
1543                     rAny <<= cy;
1544 					break;
1545                 }
1546 				case VT_DATE:
1547                 {
1548                     Date d(var.date);
1549                     rAny <<= d;
1550 					break;
1551                 }
1552 				case VT_BSTR:
1553 				{
1554 					OUString b(reinterpret_cast<const sal_Unicode*>(var.bstrVal));
1555 					rAny.setValue( &b, getCppuType( &b));
1556 					break;
1557 				}
1558                 case VT_UNKNOWN:
1559 				case VT_DISPATCH:
1560 				{
1561                     //check if it is a UNO type
1562 #ifdef __MINGW32__
1563                     CComQIPtr<IUnoTypeWrapper, &__uuidof(IUnoTypeWrapper)> spType((IUnknown*) var.byref);
1564 #else
1565                     CComQIPtr<IUnoTypeWrapper> spType((IUnknown*) var.byref);
1566 #endif
1567                     if (spType)
1568                     {
1569                         CComBSTR sName;
1570                         if (FAILED(spType->get_Name(&sName)))
1571                             throw BridgeRuntimeError(
1572                                 OUSTR("[automation bridge]UnoConversionUtilities<T>::variantToAny \n"
1573                                     "Failed to get the type name from a UnoTypeWrapper!"));
1574                         Type type;
1575                         if (getType(sName, type) == false)
1576                         {
1577                             throw CannotConvertException(
1578                                 OUSTR("[automation bridge]UnoConversionUtilities<T>::variantToAny \n"
1579                                       "A UNO type with the name: ") + OUString(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName))) +
1580                                 OUSTR("does not exist!"),
1581                                 0, TypeClass_UNKNOWN, FailReason::TYPE_NOT_SUPPORTED,0);
1582                         }
1583                         rAny <<= type;
1584                     }
1585                     else
1586                     {
1587                         rAny = createOleObjectWrapper( & var);
1588                     }
1589 					break;
1590 				}
1591 				case VT_ERROR:
1592                 {
1593                     SCode scode(var.scode);
1594                     rAny <<= scode;
1595 					break;
1596                 }
1597 				case VT_BOOL:
1598 				{
1599 					sal_Bool b= var.boolVal == VARIANT_TRUE;
1600 					rAny.setValue( &b, getCppuType( &b));
1601 					break;
1602 				}
1603 				case VT_I1:
1604 					rAny.setValue( & var.cVal, getCppuType((sal_Int8*)0));
1605 					break;
1606 				case VT_UI1: // there is no unsigned char in UNO
1607 					rAny.setValue( & var.bVal, getCppuType( (sal_Int8*)0));
1608 					break;
1609 				case VT_UI2:
1610 					rAny.setValue( & var.uiVal, getCppuType( (sal_uInt16*)0));
1611 					break;
1612 				case VT_UI4:
1613 					rAny.setValue( & var.ulVal, getCppuType( (sal_uInt32*)0));
1614 					break;
1615 				case VT_INT:
1616 					rAny.setValue( & var.intVal, getCppuType( (sal_Int32*)0));
1617 					break;
1618 				case VT_UINT:
1619 					rAny.setValue( & var.uintVal, getCppuType( (sal_uInt32*)0));
1620 					break;
1621 				case VT_VOID:
1622 					rAny.setValue( NULL, Type());
1623 					break;
1624                 case VT_DECIMAL:
1625                 {
1626                     Decimal dec;
1627                     dec.Scale = var.decVal.scale;
1628                     dec.Sign = var.decVal.sign;
1629                     dec.LowValue = var.decVal.Lo32;
1630                     dec.MiddleValue = var.decVal.Mid32;
1631                     dec.HighValue = var.decVal.Hi32;
1632                     rAny <<= dec;
1633                     break;
1634                 }
1635 
1636 				default:
1637 					break;
1638                 }
1639             }
1640         }
1641     }
1642     catch (IllegalArgumentException & )
1643     {
1644         throw;
1645     }
1646     catch (CannotConvertException &)
1647     {
1648         throw;
1649     }
1650     catch (BridgeRuntimeError & )
1651     {
1652          throw;
1653     }
1654     catch (Exception & e)
1655     {
1656         throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in "
1657                                        "UnoConversionUtilities<T>::variantToAny ! Message : \n") +
1658                                e.Message);
1659     }
1660     catch(...)
1661     {
1662         throw BridgeRuntimeError(
1663             OUSTR("[automation bridge] unexpected exception in "
1664                   "UnoConversionUtilities<T>::variantToAny !"));
1665     }
1666 
1667 }
1668 // The function converts an IUnknown* into an UNO interface or struct. The
1669 // IUnknown pointer can constitute different kind of objects:
1670 // 1. a wrapper of an UNO struct (the wrapper was created by this bridge)
1671 // 2. a wrapper of an UNO interface (created by this bridge)
1672 // 3. a dispatch object that implements UNO interfaces
1673 // 4. a dispatch object.
1674 
1675 // If the parameter "aType" has a value then the COM object ( pUnknown) is supposed to
1676 // implement the interface described by "aType". Moreover it ( pUnknown) can implement
1677 // several other
1678 // UNO interfaces in which case it has to support the SUPPORTED_INTERFACES_PROP (see
1679 // #define) property. That property contains all names of interfaces.
1680 // "pUnknown" is wrapped by a COM wrapper object that implements XInvocation, e.g.
1681 // IUnknownWrapper_Impl. Additionally an object of type "aType" is created by help
1682 // of the INTERFACE_ADAPTER_FACTORY (see #define) service. The implementation of
1683 // "aType" calls on the COM wrapper's XInvocation::invoke. If the COM object supports
1684 // more then one UNO interfaces, as can be determined by the property
1685 // SUPPORTED_INTERFACES_PROP, then the INTERFACE_ADAPTER_FACTORY creates an object that
1686 // implements all these interfaces.
1687 // This is only done if "pUnknown" is not already a UNO wrapper,
1688 // that is it is actually NOT an UNO object that was converted to a COM object. If it is an
1689 // UNO wrapper than the original UNO object is being extracted, queried for "aType" (if
1690 // it is no struct) and returned.
1691 template<class T>
1692 #ifdef __MINGW32__
1693 Any UnoConversionUtilities<T>::createOleObjectWrapper(VARIANT* pVar, const Type& aType)
1694 #else
1695 Any UnoConversionUtilities<T>::createOleObjectWrapper(VARIANT* pVar, const Type& aType= Type())
1696 #endif
1697 {
1698     //To allow passing "Nothing" in VS 2008 we need to accept VT_EMPTY
1699     if (pVar->vt != VT_UNKNOWN && pVar->vt != VT_DISPATCH && pVar->vt != VT_EMPTY)
1700         throw IllegalArgumentException(
1701             OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n"
1702                   "The VARIANT does not contain an object type! "), 0, -1);
1703 
1704     MutexGuard guard( getBridgeMutex());
1705 
1706     CComPtr<IUnknown>  spUnknown;
1707 	CComPtr<IDispatch> spDispatch;
1708 
1709     if (pVar->vt == VT_UNKNOWN)
1710     {
1711         spUnknown = pVar->punkVal;
1712         if (spUnknown)
1713 #ifdef __MINGW32__
1714             spUnknown->QueryInterface( IID_IDispatch, reinterpret_cast<LPVOID*>( & spDispatch.p));
1715 #else
1716             spUnknown.QueryInterface( & spDispatch.p);
1717 #endif
1718     }
1719     else if (pVar->vt == VT_DISPATCH && pVar->pdispVal != NULL)
1720     {
1721         CComPtr<IDispatch> spDispatch(pVar->pdispVal);
1722         if (spDispatch)
1723 #ifdef __MINGW32__
1724             spDispatch->QueryInterface( IID_IUnknown, reinterpret_cast<LPVOID*>( & spUnknown.p));
1725 #else
1726             spDispatch.QueryInterface( & spUnknown.p);
1727 #endif
1728     }
1729 
1730     static Type VOID_TYPE= Type();
1731     Any ret;
1732     //If no Type is provided and pVar contains IUnknown then we return a XInterface.
1733     //If pVar contains an IDispatch then we return a XInvocation.
1734     Type desiredType = aType;
1735 
1736     if (aType == VOID_TYPE)
1737     {
1738         switch (pVar->vt)
1739         {
1740         case VT_EMPTY:
1741         case VT_UNKNOWN:
1742             desiredType = getCppuType((Reference<XInterface>*) 0);
1743             break;
1744         case VT_DISPATCH:
1745             desiredType = getCppuType((Reference<XInvocation>*) 0);
1746             break;
1747         default:
1748             desiredType = aType;
1749         }
1750     }
1751 
1752     // COM pointer are NULL, no wrapper required
1753  	if (spUnknown == NULL)
1754 	{
1755         Reference<XInterface> xInt;
1756 		if( aType.getTypeClass() == TypeClass_INTERFACE)
1757 			ret.setValue( &xInt, aType);
1758 		else if( aType.getTypeClass() == TypeClass_STRUCT)
1759 			ret.setValue( NULL, aType);
1760 		else
1761 			ret <<= xInt;
1762         return ret;
1763 	}
1764 
1765 
1766 	// Check if "spUnknown" is a UNO wrapper, that is an UNO object that has been
1767 	// passed to COM. Then it supports IUnoObjectWrapper
1768 	// and we extract the original UNO object.
1769 #ifdef __MINGW32__
1770 	CComQIPtr<IUnoObjectWrapper, &__uuidof(IUnoObjectWrapper)> spUno( spUnknown);
1771 #else
1772 	CComQIPtr<IUnoObjectWrapper> spUno( spUnknown);
1773 #endif
1774 	if( spUno)
1775 	{   // it is a wrapper
1776  		Reference<XInterface> xInt;
1777 		if( SUCCEEDED( spUno->getOriginalUnoObject( &xInt)))
1778 		{
1779 			ret <<= xInt;
1780 		}
1781 		else
1782 		{
1783 			Any any;
1784 			if( SUCCEEDED( spUno->getOriginalUnoStruct(&any)))
1785 				ret= any;
1786 		}
1787         return ret;
1788 	}
1789 
1790 	// "spUnknown" is a real COM object.
1791     // Before we create a new wrapper object we check if there is an existing wrapper
1792     // There can be two kinds of wrappers, those who wrap dispatch - UNO objects, and those who
1793     // wrap ordinary dispatch objects. The dispatch-UNO objects usually are adapted to represent
1794     // particular UNO interfaces.
1795     Reference<XInterface> xIntWrapper;
1796     CIT_Com cit_currWrapper= ComPtrToWrapperMap.find( reinterpret_cast<sal_uInt32>(spUnknown.p));
1797     if(cit_currWrapper != ComPtrToWrapperMap.end())
1798             xIntWrapper = cit_currWrapper->second;
1799     if (xIntWrapper.is())
1800     {
1801         //Try to find an adapter for the wrapper
1802         //find the proper Adapter. The pointer in the WrapperToAdapterMap are valid as long as
1803         //we get a pointer to the wrapper from ComPtrToWrapperMap, because the Adapter hold references
1804         //to the wrapper.
1805         CIT_Wrap it = WrapperToAdapterMap.find((sal_uInt32) xIntWrapper.get());
1806         if (it == WrapperToAdapterMap.end())
1807         {
1808             // No adapter available.
1809             //The COM component could be a UNO object. Then we need to provide
1810             // a proxy  that implements all interfaces
1811             Sequence<Type> seqTypes= getImplementedInterfaces(spUnknown);
1812             Reference<XInterface> xIntAdapter;
1813             if (seqTypes.getLength() > 0)
1814             {
1815                 //It is a COM UNO object
1816                 xIntAdapter = createAdapter(seqTypes, xIntWrapper);
1817             }
1818             else
1819             {
1820                 // Some ordinary COM object
1821                 xIntAdapter = xIntWrapper;
1822             }
1823             // return the wrapper directly, return XInterface or XInvocation
1824             ret = xIntWrapper->queryInterface(desiredType);
1825             if ( ! ret.hasValue())
1826                 throw IllegalArgumentException(
1827                     OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n"
1828                           "The COM object is not suitable for the UNO type: ") +
1829                     desiredType.getTypeName(), 0, -1);
1830         }
1831         else
1832         {
1833             //There is an adapter available
1834             Reference<XInterface> xIntAdapter((XInterface*) it->second);
1835             ret = xIntAdapter->queryInterface( desiredType);
1836             if ( ! ret.hasValue())
1837                 throw IllegalArgumentException(
1838                     OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n"
1839                           "The COM object is not suitable for the UNO type: ") +
1840                     desiredType.getTypeName(), 0, -1);
1841         }
1842 
1843         return ret;
1844     }
1845     // No existing wrapper. Therefore create a new proxy.
1846     // If the object implements UNO interfaces then get the types.
1847     Sequence<Type> seqTypes = getImplementedInterfaces(spUnknown);
1848     if (seqTypes.getLength() == 0 &&
1849         aType != VOID_TYPE && aType != getCppuType((Reference<XInvocation>*)0))
1850     {
1851         seqTypes = Sequence<Type>( & aType, 1);
1852     }
1853 
1854     //There is no existing wrapper, therefore we create one for the real COM object
1855     Reference<XInterface> xIntNewProxy= createComWrapperInstance();
1856     if ( ! xIntNewProxy.is())
1857         throw BridgeRuntimeError(
1858             OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n"
1859                   "Could not create proxy object for COM object!"));
1860 
1861     // initialize the COM wrapper
1862     Reference<XInitialization> xInit( xIntNewProxy, UNO_QUERY);
1863     OSL_ASSERT( xInit.is());
1864 
1865     Any  params[3];
1866 #ifdef __MINGW32__
1867     params[0] <<= reinterpret_cast<sal_uInt32>( spUnknown.p );
1868 #else
1869     params[0] <<= (sal_uInt32) spUnknown.p;
1870 #endif
1871     sal_Bool bDisp = pVar->vt == VT_DISPATCH ? sal_True : sal_False;
1872     params[1].setValue( & bDisp, getBooleanCppuType());
1873     params[2] <<= seqTypes;
1874 
1875     xInit->initialize( Sequence<Any>( params, 3));
1876 #ifdef __MINGW32__
1877     ComPtrToWrapperMap[reinterpret_cast<sal_uInt32>( spUnknown.p )]= xIntNewProxy;
1878 #else
1879     ComPtrToWrapperMap[reinterpret_cast<sal_uInt32>(spUnknown.p)]= xIntNewProxy;
1880 #endif
1881 
1882     // we have a wrapper object
1883     //The wrapper implements already XInvocation and XInterface. If
1884     //param aType is void then the object is supposed to have XInvocation.
1885      if (aType == getCppuType((Reference<XInvocation>*)0) ||
1886          (aType == VOID_TYPE && seqTypes.getLength() == 0 ))
1887      {
1888          ret = xIntNewProxy->queryInterface(desiredType);
1889      }
1890      else
1891      {
1892          Reference<XInterface> xIntAdapter =
1893              createAdapter(seqTypes, xIntNewProxy);
1894          ret = xIntAdapter->queryInterface(desiredType);
1895      }
1896 	return ret;
1897 }
1898 template<class T>
1899 Reference<XInterface> UnoConversionUtilities<T>::createAdapter(const Sequence<Type>& seqTypes,
1900                                     const Reference<XInterface>& receiver)
1901 {
1902     Reference< XInterface> xIntAdapterFac;
1903     xIntAdapterFac= m_smgr->createInstance(INTERFACE_ADAPTER_FACTORY);
1904     // We create an adapter object that does not only implement the required type but also
1905     // all types that the COM object pretends to implement. An COM object must therefore
1906     // support the property "_implementedInterfaces".
1907     Reference<XInterface> xIntAdapted;
1908     Reference<XInvocation> xInv(receiver, UNO_QUERY);
1909     Reference<XInvocationAdapterFactory2> xAdapterFac( xIntAdapterFac, UNO_QUERY);
1910     if( xAdapterFac.is())
1911         xIntAdapted= xAdapterFac->createAdapter( xInv, seqTypes);
1912 
1913     if( xIntAdapted.is())
1914     {
1915         // Put the pointer to the wrapper object and the interface pointer of the adapted interface
1916         // in a global map. Thus we can determine in a call to createUnoObjectWrapper whether the UNO
1917         // object is a wrapped COM object. In that case we extract the original COM object rather than
1918         // creating a wrapper around the UNO object.
1919         typedef hash_map<sal_uInt32,sal_uInt32>::value_type VALUE;
1920         AdapterToWrapperMap.insert( VALUE( (sal_uInt32) xIntAdapted.get(), (sal_uInt32) receiver.get()));
1921         WrapperToAdapterMap.insert( VALUE( (sal_uInt32) receiver.get(), (sal_uInt32) xIntAdapted.get()));
1922     }
1923     else
1924     {
1925         throw BridgeRuntimeError(
1926             OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n"
1927                   "Could not create a proxy for COM object! Creation of adapter failed."));
1928     }
1929     return xIntAdapted;
1930 }
1931 // "convertValueObject" converts a JScriptValue object contained in "var" into
1932 // an any. The type contained in the any is stipulated by a "type value" thas
1933 // was set within the JScript script on the value object ( see JScriptValue).
1934 template<class T>
1935 bool UnoConversionUtilities<T>::convertValueObject( const VARIANTARG *var, Any& any)
1936 {
1937     bool ret = false;
1938     try
1939     {
1940         bool bFail = false;
1941         HRESULT hr= S_OK;
1942         CComVariant varDisp;
1943 
1944         if(SUCCEEDED(hr = varDisp.ChangeType( VT_DISPATCH, var)))
1945         {
1946             CComPtr <IJScriptValueObject> spValue;
1947             VARIANT_BOOL varBool;
1948             CComBSTR bstrType;
1949             CComVariant varValue;
1950             CComPtr<IDispatch> spDisp( varDisp.pdispVal);
1951             if(spDisp)
1952             {
1953                 if(SUCCEEDED( spDisp->QueryInterface( __uuidof( IJScriptValueObject),
1954                                                        reinterpret_cast<void**> (&spValue))))
1955                 {
1956                     ret = true; // is is a ValueObject
1957                     //If it is an out - param then it does not need to be converted. In/out and
1958                     // in params does so.
1959                     if (SUCCEEDED(hr= spValue->IsOutParam( &varBool)))
1960                     {
1961                         // if varBool == true then no conversion needed because out param
1962                         if (varBool == VARIANT_FALSE)
1963                         {
1964                             if(SUCCEEDED(hr = spValue->GetValue( & bstrType, & varValue)))
1965                             {
1966                                 Type type;
1967                                 if (getType(bstrType, type))
1968                                     variantToAny( & varValue, any, type);
1969                                 else
1970                                     bFail = true;
1971                             }
1972                             else
1973                                 bFail = true;
1974                         }
1975                     }
1976                     else
1977                         bFail = true;;
1978                 }
1979             }
1980         }
1981         else if( hr != DISP_E_TYPEMISMATCH && hr != E_NOINTERFACE)
1982             bFail = true;
1983 
1984         if (bFail)
1985             throw BridgeRuntimeError(
1986                 OUSTR("[automation bridge] Conversion of ValueObject failed "));
1987     }
1988     catch (BridgeRuntimeError &)
1989     {
1990          throw;
1991     }
1992     catch (Exception & e)
1993     {
1994         throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in "
1995                                        "UnoConversionUtilities<T>::convertValueObject ! Message : \n") +
1996                                e.Message);
1997     }
1998     catch(...)
1999     {
2000         throw BridgeRuntimeError(
2001             OUSTR("[automation bridge] unexpected exception in "
2002                   "UnoConversionUtilities<T>::convertValueObject !"));
2003     }
2004     return ret;
2005 }
2006 
2007 template<class T>
2008 void UnoConversionUtilities<T>::dispatchExObject2Sequence( const VARIANTARG* pvar, Any& anySeq, const Type& type)
2009 {
2010     try
2011     {
2012         bool bFail = false;
2013         if( pvar->vt != VT_DISPATCH)
2014             throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
2015                                            "Conversion of dispatch object to Sequence failed!"));
2016         IDispatchEx* pdispEx;
2017         HRESULT hr;
2018         if( FAILED( hr= pvar->pdispVal->QueryInterface( IID_IDispatchEx,
2019                                                         reinterpret_cast<void**>( &pdispEx))))
2020             throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
2021                                            "Conversion of dispatch object to Sequence failed!"));
2022 
2023         DISPID dispid;
2024         OUString sindex;
2025         DISPPARAMS param= {0,0,0,0};
2026         CComVariant result;
2027 
2028         OLECHAR* sLength= L"length";
2029 
2030         // Get the length of the array. Can also be obtained throu GetNextDispID. The
2031         // method only returns DISPIDs of the array data. Their names are like "0", "1" etc.
2032         if( FAILED( hr= pdispEx->GetIDsOfNames(IID_NULL, &sLength , 1, LOCALE_USER_DEFAULT, &dispid)))
2033             throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
2034                                            "Conversion of dispatch object to Sequence failed!"));
2035         if( FAILED( hr= pdispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
2036                                           &param, &result, NULL, NULL)))
2037             throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
2038                                            "Conversion of dispatch object to Sequence failed!"));
2039         if( FAILED( VariantChangeType( &result, &result, 0, VT_I4)))
2040             throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
2041                                            "Conversion of dispatch object to Sequence failed!"));
2042         long length= result.lVal;
2043 
2044         result.Clear();
2045 
2046         // get a few basic facts about the sequence, and reallocate:
2047         // create the Sequences
2048         // get the size of the elements
2049         typelib_TypeDescription *pDesc= NULL;
2050         type.getDescription( &pDesc);
2051 
2052         typelib_IndirectTypeDescription *pSeqDesc= reinterpret_cast<typelib_IndirectTypeDescription*>(pDesc);
2053         typelib_TypeDescriptionReference *pSeqElemDescRef= pSeqDesc->pType; // type of the Sequence' elements
2054         Type elemType( pSeqElemDescRef);
2055         _typelib_TypeDescription* pSeqElemDesc=NULL;
2056         TYPELIB_DANGER_GET( &pSeqElemDesc, pSeqElemDescRef)
2057             sal_uInt32 nelementSize= pSeqElemDesc->nSize;
2058         TYPELIB_DANGER_RELEASE( pSeqElemDesc)
2059 
2060             uno_Sequence *p_uno_Seq;
2061         uno_sequence_construct( &p_uno_Seq, pDesc, NULL, length, cpp_acquire);
2062 
2063         typelib_TypeClass typeElement= pSeqDesc->pType->eTypeClass;
2064         char *pArray= p_uno_Seq->elements;
2065 
2066         // Get All properties in the object, convert their values to the expected type and
2067         // put them into the passed in sequence
2068         for( sal_Int32 i= 0; i< length; i++)
2069         {
2070             OUString ousIndex=OUString::valueOf( i);
2071             OLECHAR* sindex =  (OLECHAR*)ousIndex.getStr();
2072 
2073             if( FAILED( hr= pdispEx->GetIDsOfNames(IID_NULL, &sindex , 1, LOCALE_USER_DEFAULT, &dispid)))
2074             {
2075                 throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
2076                                                "Conversion of dispatch object to Sequence failed!"));
2077             }
2078             if( FAILED( hr= pdispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
2079                                               &param, &result, NULL, NULL)))
2080             {
2081                 throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n"
2082                                                "Conversion of dispatch object to Sequence failed!"));
2083             }
2084 
2085             // If the result is VT_DISPATCH than the Sequence's element type could be Sequence
2086             // Look that up in the CoreReflection to make clear.
2087             // That requires a recursiv conversion
2088             Any any;
2089             // Destination address within the out-Sequence "anySeq" where to copy the next converted element
2090             void* pDest= (void*)(pArray + (i * nelementSize));
2091 
2092             if( result.vt & VT_DISPATCH && typeElement == typelib_TypeClass_SEQUENCE)
2093             {
2094                 variantToAny( &result, any, elemType, sal_False);
2095                 // copy the converted VARIANT, that is a Sequence to the Sequence
2096                 uno_Sequence * p_unoSeq= *(uno_Sequence**)any.getValue();
2097                 // just copy the pointer of the uno_Sequence
2098                 // nelementSize should be 4 !!!!
2099                 memcpy( pDest, &p_unoSeq, nelementSize);
2100                 osl_incrementInterlockedCount( &p_unoSeq->nRefCount);
2101             }
2102             else // Element type is no Sequence -> do one conversion
2103             {
2104                 variantToAny( &result, any, elemType, sal_False);
2105                 if( typeElement == typelib_TypeClass_ANY)
2106                 {
2107                     // copy the converted VARIANT to the Sequence
2108                     uno_type_assignData( pDest, pSeqElemDescRef , &any, pSeqElemDescRef,cpp_queryInterface,
2109                                          cpp_acquire, cpp_release);
2110                 }
2111                 else
2112                 {
2113                     // type after conversion must be the element type of the sequence
2114                     OSL_ENSURE( (any.getValueTypeClass() == typeElement), "wrong conversion");
2115                     uno_type_assignData( pDest, pSeqElemDescRef,const_cast<void*>( any.getValue()), any.getValueTypeRef(),
2116                                          cpp_queryInterface, cpp_acquire, cpp_release);
2117                 }
2118             }
2119         } // else
2120         result.Clear();
2121         anySeq.setValue( &p_uno_Seq, pDesc);
2122         uno_destructData( &p_uno_Seq, pDesc, cpp_release);
2123         typelib_typedescription_release( pDesc);
2124 
2125         if (bFail)
2126             throw BridgeRuntimeError(
2127                 OUSTR("[automation bridge] Conversion of ValueObject failed "));
2128     }
2129     catch (BridgeRuntimeError & )
2130     {
2131         throw;
2132     }
2133     catch (Exception & e)
2134     {
2135         throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in "
2136                                        "UnoConversionUtilities<T>::convertValueObject ! Message : \n") +
2137                                  e.Message);
2138     }
2139     catch(...)
2140     {
2141         throw BridgeRuntimeError(
2142             OUSTR("[automation bridge] unexpected exception in "
2143                   "UnoConversionUtilities<T>::convertValueObject !"));
2144     }
2145 }
2146 
2147 /* The argument unotype is the type that is expected by the currently called UNO function.
2148    For example: []long, [][]long. If the function calls itself recursively then the element type
2149    is passed on. For example a two dimensional SAFEARRAY of type VT_I4 is to be converted. Then
2150    unotype has to be either void or [][]long. When the function calls itself recursivly then
2151    it passes the element type which is []long.
2152 */
2153 template<class T>
2154 Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* pArray,
2155               unsigned int dimCount, unsigned int actDim, long* index, VARTYPE type, const Type& unotype)
2156 {
2157 	HRESULT hr= S_OK;
2158 	long lBound;
2159 	long uBound;
2160 	long nCountElements;
2161 
2162 	SafeArrayGetLBound(pArray, actDim, &lBound);
2163 	SafeArrayGetUBound(pArray, actDim, &uBound);
2164 	nCountElements= uBound - lBound +1;
2165 
2166 	Sequence<Any> 	anySeq(nCountElements);
2167 	Any* 			pUnoArray = anySeq.getArray();
2168 
2169 	for (index[actDim - 1] = lBound; index[actDim - 1] <= uBound; index[actDim - 1]++)
2170 	{
2171 		if (actDim > 1 )
2172 		{
2173 			Sequence<Any> element = createOleArrayWrapperOfDim(pArray, dimCount,
2174 				actDim - 1, index, type, getElementTypeOfSequence(unotype));
2175 
2176 			pUnoArray[index[actDim - 1] - lBound].setValue(&element, getCppuType(&element));
2177 		}
2178 		else
2179 		{
2180 			VARIANT variant;
2181 
2182 			VariantInit(&variant);
2183 
2184 			V_VT(&variant) = type;
2185 
2186 			switch (type)
2187 			{
2188 				case VT_I2:
2189 					SafeArrayGetElement(pArray, index, &V_I2(&variant));
2190 					break;
2191 				case VT_I4:
2192 					SafeArrayGetElement(pArray, index, &V_I4(&variant));
2193 					break;
2194 				case VT_R4:
2195 					SafeArrayGetElement(pArray, index, &V_R4(&variant));
2196 					break;
2197 				case VT_R8:
2198 					SafeArrayGetElement(pArray, index, &V_R8(&variant));
2199 					break;
2200 				case VT_CY:
2201 					SafeArrayGetElement(pArray, index, &V_CY(&variant));
2202 					break;
2203 				case VT_DATE:
2204 					SafeArrayGetElement(pArray, index, &V_DATE(&variant));
2205 					break;
2206 				case VT_BSTR:
2207 					hr= SafeArrayGetElement(pArray, index, &V_BSTR(&variant));
2208 					break;
2209 				case VT_DISPATCH:
2210 					SafeArrayGetElement(pArray, index, &V_DISPATCH(&variant));
2211 					break;
2212 				case VT_ERROR:
2213 					SafeArrayGetElement(pArray, index, &V_ERROR(&variant));
2214 					break;
2215 				case VT_BOOL:
2216 					SafeArrayGetElement(pArray, index, &V_BOOL(&variant));
2217 					break;
2218 				case VT_VARIANT:
2219 					SafeArrayGetElement(pArray, index, &variant);
2220 					break;
2221 				case VT_UNKNOWN:
2222 					SafeArrayGetElement(pArray, index, &V_UNKNOWN(&variant));
2223 					break;
2224 				case VT_I1:
2225 					SafeArrayGetElement(pArray, index, &V_I1(&variant));
2226 					break;
2227 				case VT_UI1:
2228 					SafeArrayGetElement(pArray, index, &V_UI1(&variant));
2229 					break;
2230 				case VT_UI2:
2231 					SafeArrayGetElement(pArray, index, &V_UI2(&variant));
2232 					break;
2233 				case VT_UI4:
2234 					SafeArrayGetElement(pArray, index, &V_UI4(&variant));
2235 					break;
2236 				default:
2237 					break;
2238 			}
2239 
2240             if( unotype.getTypeClass() == TypeClass_VOID)
2241                 // the function was called without specifying the destination type
2242                 variantToAny(&variant, pUnoArray[index[actDim - 1] - lBound], sal_False);
2243             else
2244                 variantToAny(&variant, pUnoArray[index[actDim - 1] - lBound],
2245 					getElementTypeOfSequence(unotype), sal_False);
2246 
2247             VariantClear(&variant);
2248 		}
2249 	}
2250 	return anySeq;
2251 }
2252 
2253 template<class T>
2254 Type UnoConversionUtilities<T>::getElementTypeOfSequence( const Type& seqType)
2255 {
2256     Type retValue;
2257 	if( seqType.getTypeClass() != TypeClass_VOID)
2258 	{
2259 		OSL_ASSERT( seqType.getTypeClass() == TypeClass_SEQUENCE);
2260 		typelib_IndirectTypeDescription* pDescSeq= NULL;
2261 		seqType.getDescription((typelib_TypeDescription** ) & pDescSeq);
2262 		retValue = Type(pDescSeq->pType);
2263 		typelib_typedescription_release( (typelib_TypeDescription*) pDescSeq);
2264 	}
2265 	return retValue;
2266 }
2267 template<class T>
2268 Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapper(SAFEARRAY* pArray, VARTYPE type, const Type& unoType)
2269 {
2270 	sal_uInt32 dim = SafeArrayGetDim(pArray);
2271 
2272 	Sequence<Any> ret;
2273 
2274 	if (dim > 0)
2275 	{
2276         scoped_array<long> sarIndex(new long[dim]);
2277 		long * index =  sarIndex.get();
2278 
2279 		for (unsigned int i = 0; i < dim; i++)
2280 		{
2281 			index[i] = 0;
2282 		}
2283 
2284 		ret	= createOleArrayWrapperOfDim(pArray, dim, dim, index, type, unoType);
2285 	}
2286 
2287 	return ret;
2288 }
2289 
2290 // If an VARIANT has the type VT_DISPATCH it can either be an JScript Array
2291 // or some other object. This function finds out if it is such an array or
2292 // not. Currently there's no way to make sure it's an array
2293 // so we assume that when the object has a property "0" then it is an Array.
2294 // An JScript has property like "0", "1", "2" etc. which represent the
2295 // value at the corresponding index of the array
2296 template<class T>
2297 sal_Bool UnoConversionUtilities<T>::isJScriptArray(const VARIANT* rvar)
2298 {
2299 	OSL_ENSURE( rvar->vt == VT_DISPATCH, "param is not a VT_DISPATCH");
2300 	HRESULT hr;
2301 	OLECHAR* sindex= L"0";
2302 	DISPID id;
2303 	if ( rvar->vt == VT_DISPATCH && rvar->pdispVal )
2304 	{
2305 		hr= rvar->pdispVal->GetIDsOfNames( IID_NULL, &sindex, 1,
2306 			LOCALE_USER_DEFAULT, &id);
2307 
2308 		if( SUCCEEDED ( hr) )
2309 			return sal_True;
2310 	}
2311 
2312 	return sal_False;
2313 }
2314 
2315 template<class T>
2316 VARTYPE UnoConversionUtilities<T>::mapTypeClassToVartype( TypeClass type)
2317 {
2318 	VARTYPE ret;
2319 	switch( type)
2320 	{
2321 	case TypeClass_INTERFACE: ret= VT_DISPATCH;
2322 		break;
2323 	case TypeClass_STRUCT: ret= VT_DISPATCH;
2324 		break;
2325 	case TypeClass_ENUM: ret= VT_I4;
2326 		break;
2327 	case TypeClass_SEQUENCE: ret= VT_ARRAY;
2328 		break;
2329 	case TypeClass_ANY: ret= VT_VARIANT;
2330 		break;
2331 	case TypeClass_BOOLEAN: ret= VT_BOOL;
2332 		break;
2333 	case TypeClass_CHAR: ret= VT_I2;
2334 		break;
2335 	case TypeClass_STRING: ret= VT_BSTR;
2336 		break;
2337 	case TypeClass_FLOAT: ret= VT_R4;
2338 		break;
2339 	case TypeClass_DOUBLE: ret= VT_R8;
2340 		break;
2341 	case TypeClass_BYTE: ret= VT_UI1;
2342 		break;
2343 	case TypeClass_SHORT: ret= VT_I2;
2344 		break;
2345 	case TypeClass_LONG: ret= VT_I4;
2346 		break;
2347 	case TypeClass_UNSIGNED_SHORT: ret= VT_UI2;
2348 		 break;
2349 	case TypeClass_UNSIGNED_LONG: ret= VT_UI4;
2350 		break;
2351 	default:
2352 		ret= VT_EMPTY;
2353 	}
2354 	return ret;
2355 }
2356 
2357 template<class T>
2358 Sequence<Type> UnoConversionUtilities<T>::getImplementedInterfaces(IUnknown* pUnk)
2359 {
2360     Sequence<Type> seqTypes;
2361     CComDispatchDriver disp( pUnk);
2362     if( disp)
2363     {
2364         CComVariant var;
2365         HRESULT hr= S_OK;
2366         // There are two different property names possible.
2367         if(	FAILED( hr= disp.GetPropertyByName( SUPPORTED_INTERFACES_PROP, &var)))
2368         {
2369             hr= disp.GetPropertyByName( SUPPORTED_INTERFACES_PROP2, &var);
2370         }
2371         if (SUCCEEDED( hr))
2372         {
2373             // we exspect an array( SafeArray or IDispatch) of Strings.
2374             Any anyNames;
2375             variantToAny( &var, anyNames, getCppuType( (Sequence<Any>*) 0));
2376             Sequence<Any> seqAny;
2377             if( anyNames >>= seqAny)
2378             {
2379                 seqTypes.realloc( seqAny.getLength());
2380                 for( sal_Int32 i=0; i < seqAny.getLength(); i++)
2381                 {
2382                     OUString typeName;
2383                     seqAny[i] >>= typeName;
2384                     seqTypes[i]= Type( TypeClass_INTERFACE, typeName);
2385                 }
2386             }
2387         }
2388     }
2389     return seqTypes;
2390 }
2391 template<class T>
2392 Reference<XTypeConverter> UnoConversionUtilities<T>::getTypeConverter()
2393 {
2394     if ( ! m_typeConverter.is())
2395     {
2396         MutexGuard guard(getBridgeMutex());
2397         if ( ! m_typeConverter.is())
2398         {
2399             Reference<XInterface> xIntConverter =
2400                 m_smgr->createInstance(OUSTR("com.sun.star.script.Converter"));
2401             if (xIntConverter.is())
2402                 m_typeConverter = Reference<XTypeConverter>(xIntConverter, UNO_QUERY);
2403         }
2404     }
2405     return m_typeConverter;
2406 }
2407 
2408 // This function tries to the change the type of a value (contained in the Any)
2409 // to the smallest possible that can hold the value. This is actually done only
2410 // for types of VT_I4 (see o2u_variantToAny). The reason is the following:
2411 // JavaScript passes integer values always as VT_I4. If there is a parameter or
2412 // property of type any then the bridge converts the any's content according
2413 // to "o2u_variantToAny". Because the VARTYPE is VT_I4 the value would be converted
2414 // to TypeClass_LONG. Say the method XPropertySet::setPropertyValue( string name, any value)
2415 // would be called on an object and the property actually is of TypeClass_SHORT.
2416 // After conversion of the VARIANT parameter the Any would contain type
2417 // TypeClass_LONG. Because the corereflection does not cast from long to short
2418 // the "setPropertValue" would fail as the value has not the right type.
2419 
2420 // The corereflection does convert small integer types to bigger types.
2421 // Therefore we can reduce the type if possible and avoid the above mentioned
2422 // problem.
2423 
2424 // The function is not used when elements are to be converted for Sequences.
2425 
2426 #ifndef _REDUCE_RANGE
2427 #define _REDUCE_RANGE
2428 inline void reduceRange( Any& any)
2429 {
2430 	OSL_ASSERT( any.getValueTypeClass() == TypeClass_LONG);
2431 
2432 	sal_Int32 value= *(sal_Int32*)any.getValue();
2433 	if( value <= 0x7f &&  value >= -0x80)
2434 	{// -128 bis 127
2435 		sal_Int8 charVal= static_cast<sal_Int8>( value);
2436 		any.setValue( &charVal, getCppuType( (sal_Int8*)0));
2437 	}
2438 	else if( value <= 0x7fff && value >= -0x8000)
2439 	{// -32768 bis 32767
2440 		sal_Int16 shortVal= static_cast<sal_Int16>( value);
2441 		any.setValue( &shortVal, getCppuType( (sal_Int16*)0));
2442 	}
2443 }
2444 #endif
2445 
2446 
2447 
2448 } // end namespace
2449 #endif
2450 
2451