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