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