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 ¶m, &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 ¶m, &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