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: 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 114 UnoConversionUtilities( const Reference<XMultiServiceFactory> & xFactory, sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass ) 115 : m_smgr( xFactory), m_nComWrapperClass( comWrapperClass), m_nUnoWrapperClass( unoWrapperClass) 116 {} 117 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 > 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> 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> 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 beeing 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> 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> 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 whith multiple dimensions. 1030 // Used by sal_Bool anyToVariant(VARIANT* pVariant, const Any& rAny, VARTYPE type); 1031 template<class T> 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> 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> 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 - countains 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> 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> 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> 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 suppy 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> 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__ 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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 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