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 1324 // try to find VARIANT type that is related to the UNO type of the sequence elements 1325 // the sequence as a sequence element should be handled in a special way 1326 VARTYPE eTargetElementType = VT_EMPTY; 1327 if ( pSeqElementDesc->eTypeClass != TypeClass_SEQUENCE ) 1328 eTargetElementType = mapTypeClassToVartype( static_cast< TypeClass >( pSeqElementDesc->eTypeClass ) ); 1329 1330 if ( eTargetElementType != VT_EMPTY ) 1331 pArray = createUnoSequenceWrapper( rSeq, eTargetElementType ); 1332 1333 if ( !pArray ) 1334 { 1335 sal_Int32 nElementSize= pSeqElementDesc->nSize; 1336 n= punoSeq->nElements; 1337 1338 SAFEARRAYBOUND rgsabound[1]; 1339 rgsabound[0].lLbound = 0; 1340 rgsabound[0].cElements = n; 1341 VARIANT oleElement; 1342 long safeI[1]; 1343 1344 pArray = SafeArrayCreate(VT_VARIANT, 1, rgsabound); 1345 1346 Any unoElement; 1347 // sal_uInt8 * pSeqData= (sal_uInt8*) punoSeq->pElements; 1348 sal_uInt8 * pSeqData= (sal_uInt8*) punoSeq->elements; 1349 1350 for (sal_uInt32 i = 0; i < n; i++) 1351 { 1352 unoElement.setValue( pSeqData + i * nElementSize, pSeqElementDesc); 1353 VariantInit(&oleElement); 1354 1355 anyToVariant(&oleElement, unoElement); 1356 1357 safeI[0] = i; 1358 SafeArrayPutElement(pArray, safeI, &oleElement); 1359 1360 VariantClear(&oleElement); 1361 } 1362 } 1363 1364 TYPELIB_DANGER_RELEASE( pSeqElementDesc); 1365 1366 return pArray; 1367 } 1368 1369 /* The argument rObj can contain 1370 - UNO struct 1371 - UNO interface 1372 - UNO interface created by this bridge (adapter factory) 1373 - UNO interface created by this bridge ( COM Wrapper) 1374 1375 pVar must be initialized. 1376 */ 1377 template<class T> 1378 void UnoConversionUtilities<T>::createUnoObjectWrapper(const Any & rObj, VARIANT * pVar) 1379 { 1380 MutexGuard guard(getBridgeMutex()); 1381 1382 Reference<XInterface> xInt; 1383 1384 TypeClass tc = rObj.getValueTypeClass(); 1385 if (tc != TypeClass_INTERFACE && tc != TypeClass_STRUCT) 1386 throw IllegalArgumentException( 1387 OUSTR("[automation bridge]UnoConversionUtilities<T>::createUnoObjectWrapper \n" 1388 "Cannot create an Automation interface for a UNO type which is not " 1389 "a struct or interface!"), 0, -1); 1390 1391 if (rObj.getValueTypeClass() == TypeClass_INTERFACE) 1392 { 1393 if (! (rObj >>= xInt)) 1394 throw IllegalArgumentException( 1395 OUSTR("[automation bridge] UnoConversionUtilities<T>::createUnoObjectWrapper\n " 1396 "Could not create wrapper object for UNO object!"), 0, -1); 1397 //If XInterface is NULL, which is a valid value, then simply return NULL. 1398 if ( ! xInt.is()) 1399 { 1400 pVar->vt = VT_UNKNOWN; 1401 pVar->punkVal = NULL; 1402 return; 1403 } 1404 //make sure we have the main XInterface which is used with a map 1405 xInt = Reference<XInterface>(xInt, UNO_QUERY); 1406 //If there is already a wrapper for the UNO object then use it 1407 1408 Reference<XInterface> xIntWrapper; 1409 // Does a UNO wrapper exist already ? 1410 IT_Uno it_uno = UnoObjToWrapperMap.find( (sal_uInt32) xInt.get()); 1411 if(it_uno != UnoObjToWrapperMap.end()) 1412 { 1413 xIntWrapper = it_uno->second; 1414 if (xIntWrapper.is()) 1415 { 1416 convertSelfToCom(xIntWrapper, pVar); 1417 return; 1418 } 1419 } 1420 // Is the object a COM wrapper ( either XInvocation, or Adapter object) 1421 // or does it suppy an IDispatch by its own ? 1422 else 1423 { 1424 Reference<XInterface> xIntComWrapper = xInt; 1425 typedef hash_map<sal_uInt32,sal_uInt32>::iterator _IT; 1426 // Adapter? then get the COM wrapper to which the adapter delegates its calls 1427 _IT it= AdapterToWrapperMap.find( (sal_uInt32) xInt.get()); 1428 if( it != AdapterToWrapperMap.end() ) 1429 xIntComWrapper= reinterpret_cast<XInterface*>(it->second); 1430 1431 if (convertSelfToCom(xIntComWrapper, pVar)) 1432 return; 1433 } 1434 } 1435 // If we have no UNO wrapper nor the IDispatch yet then we have to create 1436 // a wrapper. For that we need an XInvocation from the UNO object. 1437 1438 // get an XInvocation or create one using the invocation service 1439 Reference<XInvocation> xInv(xInt, UNO_QUERY); 1440 if ( ! xInv.is()) 1441 { 1442 Reference<XSingleServiceFactory> xInvFactory= getInvocationFactory(rObj); 1443 if (xInvFactory.is()) 1444 { 1445 Sequence<Any> params(1); 1446 params.getArray()[0] = rObj; 1447 Reference<XInterface> xInt = xInvFactory->createInstanceWithArguments(params); 1448 xInv= Reference<XInvocation>(xInt, UNO_QUERY); 1449 } 1450 } 1451 1452 if (xInv.is()) 1453 { 1454 Reference<XInterface> xNewWrapper = createUnoWrapperInstance(); 1455 Reference<XInitialization> xInitWrapper(xNewWrapper, UNO_QUERY); 1456 if (xInitWrapper.is()) 1457 { 1458 VARTYPE vartype= getVarType( rObj); 1459 1460 if (xInt.is()) 1461 { 1462 Any params[3]; 1463 params[0] <<= xInv; 1464 params[1] <<= xInt; 1465 params[2] <<= vartype; 1466 xInitWrapper->initialize( Sequence<Any>(params, 3)); 1467 } 1468 else 1469 { 1470 Any params[2]; 1471 params[0] <<= xInv; 1472 params[1] <<= vartype; 1473 xInitWrapper->initialize( Sequence<Any>(params, 2)); 1474 } 1475 1476 // put the newly created object into a map. If the same object will 1477 // be mapped again and there is already a wrapper then the old wrapper 1478 // will be used. 1479 if(xInt.is()) // only interfaces 1480 UnoObjToWrapperMap[(sal_uInt32) xInt.get()]= xNewWrapper; 1481 convertSelfToCom(xNewWrapper, pVar); 1482 return; 1483 } 1484 } 1485 } 1486 1487 template<class T> 1488 void UnoConversionUtilities<T>::variantToAny( const VARIANT* pVariant, Any& rAny, 1489 sal_Bool bReduceValueRange /* = sal_True */) 1490 { 1491 HRESULT hr = S_OK; 1492 try 1493 { 1494 CComVariant var; 1495 1496 // There is no need to support indirect values, since they're not supported by UNO 1497 if( FAILED(hr= VariantCopyInd( &var, const_cast<VARIANTARG*>(pVariant)))) // remove VT_BYREF 1498 throw BridgeRuntimeError( 1499 OUSTR("[automation bridge] UnoConversionUtilities<T>::variantToAny \n" 1500 "VariantCopyInd failed for reason : ") + OUString::valueOf(hr)); 1501 1502 if ( ! convertValueObject( & var, rAny)) 1503 { 1504 if ((var.vt & VT_ARRAY) > 0) 1505 { 1506 VARTYPE oleTypeFlags = ::sal::static_int_cast< VARTYPE, int >( var.vt ^ VT_ARRAY ); 1507 1508 Sequence<Any> unoSeq = createOleArrayWrapper(var.parray, oleTypeFlags); 1509 rAny.setValue( &unoSeq, getCppuType( &unoSeq)); 1510 } 1511 else 1512 { 1513 switch (var.vt) 1514 { 1515 case VT_EMPTY: 1516 rAny.setValue(NULL, Type()); 1517 break; 1518 case VT_NULL: 1519 rAny.setValue(NULL, Type()); 1520 break; 1521 case VT_I2: 1522 rAny.setValue( & var.iVal, getCppuType( (sal_Int16*)0)); 1523 break; 1524 case VT_I4: 1525 rAny.setValue( & var.lVal, getCppuType( (sal_Int32*)0)); 1526 // necessary for use in JavaScript ( see "reduceRange") 1527 if( bReduceValueRange) 1528 reduceRange(rAny); 1529 break; 1530 case VT_R4: 1531 rAny.setValue( & var.fltVal, getCppuType( (float*)0)); 1532 break; 1533 case VT_R8: 1534 rAny.setValue(& var.dblVal, getCppuType( (double*)0)); 1535 break; 1536 case VT_CY: 1537 { 1538 Currency cy(var.cyVal.int64); 1539 rAny <<= cy; 1540 break; 1541 } 1542 case VT_DATE: 1543 { 1544 Date d(var.date); 1545 rAny <<= d; 1546 break; 1547 } 1548 case VT_BSTR: 1549 { 1550 OUString b(reinterpret_cast<const sal_Unicode*>(var.bstrVal)); 1551 rAny.setValue( &b, getCppuType( &b)); 1552 break; 1553 } 1554 case VT_UNKNOWN: 1555 case VT_DISPATCH: 1556 { 1557 //check if it is a UNO type 1558 #ifdef __MINGW32__ 1559 CComQIPtr<IUnoTypeWrapper, &__uuidof(IUnoTypeWrapper)> spType((IUnknown*) var.byref); 1560 #else 1561 CComQIPtr<IUnoTypeWrapper> spType((IUnknown*) var.byref); 1562 #endif 1563 if (spType) 1564 { 1565 CComBSTR sName; 1566 if (FAILED(spType->get_Name(&sName))) 1567 throw BridgeRuntimeError( 1568 OUSTR("[automation bridge]UnoConversionUtilities<T>::variantToAny \n" 1569 "Failed to get the type name from a UnoTypeWrapper!")); 1570 Type type; 1571 if (getType(sName, type) == false) 1572 { 1573 throw CannotConvertException( 1574 OUSTR("[automation bridge]UnoConversionUtilities<T>::variantToAny \n" 1575 "A UNO type with the name: ") + OUString(reinterpret_cast<const sal_Unicode*>(LPCOLESTR(sName))) + 1576 OUSTR("does not exist!"), 1577 0, TypeClass_UNKNOWN, FailReason::TYPE_NOT_SUPPORTED,0); 1578 } 1579 rAny <<= type; 1580 } 1581 else 1582 { 1583 rAny = createOleObjectWrapper( & var); 1584 } 1585 break; 1586 } 1587 case VT_ERROR: 1588 { 1589 SCode scode(var.scode); 1590 rAny <<= scode; 1591 break; 1592 } 1593 case VT_BOOL: 1594 { 1595 sal_Bool b= var.boolVal == VARIANT_TRUE; 1596 rAny.setValue( &b, getCppuType( &b)); 1597 break; 1598 } 1599 case VT_I1: 1600 rAny.setValue( & var.cVal, getCppuType((sal_Int8*)0)); 1601 break; 1602 case VT_UI1: // there is no unsigned char in UNO 1603 rAny.setValue( & var.bVal, getCppuType( (sal_Int8*)0)); 1604 break; 1605 case VT_UI2: 1606 rAny.setValue( & var.uiVal, getCppuType( (sal_uInt16*)0)); 1607 break; 1608 case VT_UI4: 1609 rAny.setValue( & var.ulVal, getCppuType( (sal_uInt32*)0)); 1610 break; 1611 case VT_INT: 1612 rAny.setValue( & var.intVal, getCppuType( (sal_Int32*)0)); 1613 break; 1614 case VT_UINT: 1615 rAny.setValue( & var.uintVal, getCppuType( (sal_uInt32*)0)); 1616 break; 1617 case VT_VOID: 1618 rAny.setValue( NULL, Type()); 1619 break; 1620 case VT_DECIMAL: 1621 { 1622 Decimal dec; 1623 dec.Scale = var.decVal.scale; 1624 dec.Sign = var.decVal.sign; 1625 dec.LowValue = var.decVal.Lo32; 1626 dec.MiddleValue = var.decVal.Mid32; 1627 dec.HighValue = var.decVal.Hi32; 1628 rAny <<= dec; 1629 break; 1630 } 1631 1632 default: 1633 break; 1634 } 1635 } 1636 } 1637 } 1638 catch (IllegalArgumentException & ) 1639 { 1640 throw; 1641 } 1642 catch (CannotConvertException &) 1643 { 1644 throw; 1645 } 1646 catch (BridgeRuntimeError & ) 1647 { 1648 throw; 1649 } 1650 catch (Exception & e) 1651 { 1652 throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in " 1653 "UnoConversionUtilities<T>::variantToAny ! Message : \n") + 1654 e.Message); 1655 } 1656 catch(...) 1657 { 1658 throw BridgeRuntimeError( 1659 OUSTR("[automation bridge] unexpected exception in " 1660 "UnoConversionUtilities<T>::variantToAny !")); 1661 } 1662 1663 } 1664 // The function converts an IUnknown* into an UNO interface or struct. The 1665 // IUnknown pointer can constitute different kind of objects: 1666 // 1. a wrapper of an UNO struct (the wrapper was created by this bridge) 1667 // 2. a wrapper of an UNO interface (created by this bridge) 1668 // 3. a dispatch object that implements UNO interfaces 1669 // 4. a dispatch object. 1670 1671 // If the parameter "aType" has a value then the COM object ( pUnknown) is supposed to 1672 // implement the interface described by "aType". Moreover it ( pUnknown) can implement 1673 // several other 1674 // UNO interfaces in which case it has to support the SUPPORTED_INTERFACES_PROP (see 1675 // #define) property. That property contains all names of interfaces. 1676 // "pUnknown" is wrapped by a COM wrapper object that implements XInvocation, e.g. 1677 // IUnknownWrapper_Impl. Additionally an object of type "aType" is created by help 1678 // of the INTERFACE_ADAPTER_FACTORY (see #define) service. The implementation of 1679 // "aType" calls on the COM wrapper's XInvocation::invoke. If the COM object supports 1680 // more then one UNO interfaces, as can be determined by the property 1681 // SUPPORTED_INTERFACES_PROP, then the INTERFACE_ADAPTER_FACTORY creates an object that 1682 // implements all these interfaces. 1683 // This is only done if "pUnknown" is not already a UNO wrapper, 1684 // that is it is actually NOT an UNO object that was converted to a COM object. If it is an 1685 // UNO wrapper than the original UNO object is being extracted, queried for "aType" (if 1686 // it is no struct) and returned. 1687 template<class T> 1688 #ifdef __MINGW32__ 1689 Any UnoConversionUtilities<T>::createOleObjectWrapper(VARIANT* pVar, const Type& aType) 1690 #else 1691 Any UnoConversionUtilities<T>::createOleObjectWrapper(VARIANT* pVar, const Type& aType= Type()) 1692 #endif 1693 { 1694 //To allow passing "Nothing" in VS 2008 we need to accept VT_EMPTY 1695 if (pVar->vt != VT_UNKNOWN && pVar->vt != VT_DISPATCH && pVar->vt != VT_EMPTY) 1696 throw IllegalArgumentException( 1697 OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n" 1698 "The VARIANT does not contain an object type! "), 0, -1); 1699 1700 MutexGuard guard( getBridgeMutex()); 1701 1702 CComPtr<IUnknown> spUnknown; 1703 CComPtr<IDispatch> spDispatch; 1704 1705 if (pVar->vt == VT_UNKNOWN) 1706 { 1707 spUnknown = pVar->punkVal; 1708 if (spUnknown) 1709 #ifdef __MINGW32__ 1710 spUnknown->QueryInterface( IID_IDispatch, reinterpret_cast<LPVOID*>( & spDispatch.p)); 1711 #else 1712 spUnknown.QueryInterface( & spDispatch.p); 1713 #endif 1714 } 1715 else if (pVar->vt == VT_DISPATCH && pVar->pdispVal != NULL) 1716 { 1717 CComPtr<IDispatch> spDispatch(pVar->pdispVal); 1718 if (spDispatch) 1719 #ifdef __MINGW32__ 1720 spDispatch->QueryInterface( IID_IUnknown, reinterpret_cast<LPVOID*>( & spUnknown.p)); 1721 #else 1722 spDispatch.QueryInterface( & spUnknown.p); 1723 #endif 1724 } 1725 1726 static Type VOID_TYPE= Type(); 1727 Any ret; 1728 //If no Type is provided and pVar contains IUnknown then we return a XInterface. 1729 //If pVar contains an IDispatch then we return a XInvocation. 1730 Type desiredType = aType; 1731 1732 if (aType == VOID_TYPE) 1733 { 1734 switch (pVar->vt) 1735 { 1736 case VT_EMPTY: 1737 case VT_UNKNOWN: 1738 desiredType = getCppuType((Reference<XInterface>*) 0); 1739 break; 1740 case VT_DISPATCH: 1741 desiredType = getCppuType((Reference<XInvocation>*) 0); 1742 break; 1743 default: 1744 desiredType = aType; 1745 } 1746 } 1747 1748 // COM pointer are NULL, no wrapper required 1749 if (spUnknown == NULL) 1750 { 1751 Reference<XInterface> xInt; 1752 if( aType.getTypeClass() == TypeClass_INTERFACE) 1753 ret.setValue( &xInt, aType); 1754 else if( aType.getTypeClass() == TypeClass_STRUCT) 1755 ret.setValue( NULL, aType); 1756 else 1757 ret <<= xInt; 1758 return ret; 1759 } 1760 1761 1762 // Check if "spUnknown" is a UNO wrapper, that is an UNO object that has been 1763 // passed to COM. Then it supports IUnoObjectWrapper 1764 // and we extract the original UNO object. 1765 #ifdef __MINGW32__ 1766 CComQIPtr<IUnoObjectWrapper, &__uuidof(IUnoObjectWrapper)> spUno( spUnknown); 1767 #else 1768 CComQIPtr<IUnoObjectWrapper> spUno( spUnknown); 1769 #endif 1770 if( spUno) 1771 { // it is a wrapper 1772 Reference<XInterface> xInt; 1773 if( SUCCEEDED( spUno->getOriginalUnoObject( &xInt))) 1774 { 1775 ret <<= xInt; 1776 } 1777 else 1778 { 1779 Any any; 1780 if( SUCCEEDED( spUno->getOriginalUnoStruct(&any))) 1781 ret= any; 1782 } 1783 return ret; 1784 } 1785 1786 // "spUnknown" is a real COM object. 1787 // Before we create a new wrapper object we check if there is an existing wrapper 1788 // There can be two kinds of wrappers, those who wrap dispatch - UNO objects, and those who 1789 // wrap ordinary dispatch objects. The dispatch-UNO objects usually are adapted to represent 1790 // particular UNO interfaces. 1791 Reference<XInterface> xIntWrapper; 1792 CIT_Com cit_currWrapper= ComPtrToWrapperMap.find( reinterpret_cast<sal_uInt32>(spUnknown.p)); 1793 if(cit_currWrapper != ComPtrToWrapperMap.end()) 1794 xIntWrapper = cit_currWrapper->second; 1795 if (xIntWrapper.is()) 1796 { 1797 //Try to find an adapter for the wrapper 1798 //find the proper Adapter. The pointer in the WrapperToAdapterMap are valid as long as 1799 //we get a pointer to the wrapper from ComPtrToWrapperMap, because the Adapter hold references 1800 //to the wrapper. 1801 CIT_Wrap it = WrapperToAdapterMap.find((sal_uInt32) xIntWrapper.get()); 1802 if (it == WrapperToAdapterMap.end()) 1803 { 1804 // No adapter available. 1805 //The COM component could be a UNO object. Then we need to provide 1806 // a proxy that implements all interfaces 1807 Sequence<Type> seqTypes= getImplementedInterfaces(spUnknown); 1808 Reference<XInterface> xIntAdapter; 1809 if (seqTypes.getLength() > 0) 1810 { 1811 //It is a COM UNO object 1812 xIntAdapter = createAdapter(seqTypes, xIntWrapper); 1813 } 1814 else 1815 { 1816 // Some ordinary COM object 1817 xIntAdapter = xIntWrapper; 1818 } 1819 // return the wrapper directly, return XInterface or XInvocation 1820 ret = xIntWrapper->queryInterface(desiredType); 1821 if ( ! ret.hasValue()) 1822 throw IllegalArgumentException( 1823 OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n" 1824 "The COM object is not suitable for the UNO type: ") + 1825 desiredType.getTypeName(), 0, -1); 1826 } 1827 else 1828 { 1829 //There is an adapter available 1830 Reference<XInterface> xIntAdapter((XInterface*) it->second); 1831 ret = xIntAdapter->queryInterface( desiredType); 1832 if ( ! ret.hasValue()) 1833 throw IllegalArgumentException( 1834 OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n" 1835 "The COM object is not suitable for the UNO type: ") + 1836 desiredType.getTypeName(), 0, -1); 1837 } 1838 1839 return ret; 1840 } 1841 // No existing wrapper. Therefore create a new proxy. 1842 // If the object implements UNO interfaces then get the types. 1843 Sequence<Type> seqTypes = getImplementedInterfaces(spUnknown); 1844 if (seqTypes.getLength() == 0 && 1845 aType != VOID_TYPE && aType != getCppuType((Reference<XInvocation>*)0)) 1846 { 1847 seqTypes = Sequence<Type>( & aType, 1); 1848 } 1849 1850 //There is no existing wrapper, therefore we create one for the real COM object 1851 Reference<XInterface> xIntNewProxy= createComWrapperInstance(); 1852 if ( ! xIntNewProxy.is()) 1853 throw BridgeRuntimeError( 1854 OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n" 1855 "Could not create proxy object for COM object!")); 1856 1857 // initialize the COM wrapper 1858 Reference<XInitialization> xInit( xIntNewProxy, UNO_QUERY); 1859 OSL_ASSERT( xInit.is()); 1860 1861 Any params[3]; 1862 #ifdef __MINGW32__ 1863 params[0] <<= reinterpret_cast<sal_uInt32>( spUnknown.p ); 1864 #else 1865 params[0] <<= (sal_uInt32) spUnknown.p; 1866 #endif 1867 sal_Bool bDisp = pVar->vt == VT_DISPATCH ? sal_True : sal_False; 1868 params[1].setValue( & bDisp, getBooleanCppuType()); 1869 params[2] <<= seqTypes; 1870 1871 xInit->initialize( Sequence<Any>( params, 3)); 1872 #ifdef __MINGW32__ 1873 ComPtrToWrapperMap[reinterpret_cast<sal_uInt32>( spUnknown.p )]= xIntNewProxy; 1874 #else 1875 ComPtrToWrapperMap[reinterpret_cast<sal_uInt32>(spUnknown.p)]= xIntNewProxy; 1876 #endif 1877 1878 // we have a wrapper object 1879 //The wrapper implements already XInvocation and XInterface. If 1880 //param aType is void then the object is supposed to have XInvocation. 1881 if (aType == getCppuType((Reference<XInvocation>*)0) || 1882 (aType == VOID_TYPE && seqTypes.getLength() == 0 )) 1883 { 1884 ret = xIntNewProxy->queryInterface(desiredType); 1885 } 1886 else 1887 { 1888 Reference<XInterface> xIntAdapter = 1889 createAdapter(seqTypes, xIntNewProxy); 1890 ret = xIntAdapter->queryInterface(desiredType); 1891 } 1892 return ret; 1893 } 1894 template<class T> 1895 Reference<XInterface> UnoConversionUtilities<T>::createAdapter(const Sequence<Type>& seqTypes, 1896 const Reference<XInterface>& receiver) 1897 { 1898 Reference< XInterface> xIntAdapterFac; 1899 xIntAdapterFac= m_smgr->createInstance(INTERFACE_ADAPTER_FACTORY); 1900 // We create an adapter object that does not only implement the required type but also 1901 // all types that the COM object pretends to implement. An COM object must therefore 1902 // support the property "_implementedInterfaces". 1903 Reference<XInterface> xIntAdapted; 1904 Reference<XInvocation> xInv(receiver, UNO_QUERY); 1905 Reference<XInvocationAdapterFactory2> xAdapterFac( xIntAdapterFac, UNO_QUERY); 1906 if( xAdapterFac.is()) 1907 xIntAdapted= xAdapterFac->createAdapter( xInv, seqTypes); 1908 1909 if( xIntAdapted.is()) 1910 { 1911 // Put the pointer to the wrapper object and the interface pointer of the adapted interface 1912 // in a global map. Thus we can determine in a call to createUnoObjectWrapper whether the UNO 1913 // object is a wrapped COM object. In that case we extract the original COM object rather than 1914 // creating a wrapper around the UNO object. 1915 typedef hash_map<sal_uInt32,sal_uInt32>::value_type VALUE; 1916 AdapterToWrapperMap.insert( VALUE( (sal_uInt32) xIntAdapted.get(), (sal_uInt32) receiver.get())); 1917 WrapperToAdapterMap.insert( VALUE( (sal_uInt32) receiver.get(), (sal_uInt32) xIntAdapted.get())); 1918 } 1919 else 1920 { 1921 throw BridgeRuntimeError( 1922 OUSTR("[automation bridge]UnoConversionUtilities<T>::createOleObjectWrapper \n" 1923 "Could not create a proxy for COM object! Creation of adapter failed.")); 1924 } 1925 return xIntAdapted; 1926 } 1927 // "convertValueObject" converts a JScriptValue object contained in "var" into 1928 // an any. The type contained in the any is stipulated by a "type value" thas 1929 // was set within the JScript script on the value object ( see JScriptValue). 1930 template<class T> 1931 bool UnoConversionUtilities<T>::convertValueObject( const VARIANTARG *var, Any& any) 1932 { 1933 bool ret = false; 1934 try 1935 { 1936 bool bFail = false; 1937 HRESULT hr= S_OK; 1938 CComVariant varDisp; 1939 1940 if(SUCCEEDED(hr = varDisp.ChangeType( VT_DISPATCH, var))) 1941 { 1942 CComPtr <IJScriptValueObject> spValue; 1943 VARIANT_BOOL varBool; 1944 CComBSTR bstrType; 1945 CComVariant varValue; 1946 CComPtr<IDispatch> spDisp( varDisp.pdispVal); 1947 if(spDisp) 1948 { 1949 if(SUCCEEDED( spDisp->QueryInterface( __uuidof( IJScriptValueObject), 1950 reinterpret_cast<void**> (&spValue)))) 1951 { 1952 ret = true; // is is a ValueObject 1953 //If it is an out - param then it does not need to be converted. In/out and 1954 // in params does so. 1955 if (SUCCEEDED(hr= spValue->IsOutParam( &varBool))) 1956 { 1957 // if varBool == true then no conversion needed because out param 1958 if (varBool == VARIANT_FALSE) 1959 { 1960 if(SUCCEEDED(hr = spValue->GetValue( & bstrType, & varValue))) 1961 { 1962 Type type; 1963 if (getType(bstrType, type)) 1964 variantToAny( & varValue, any, type); 1965 else 1966 bFail = true; 1967 } 1968 else 1969 bFail = true; 1970 } 1971 } 1972 else 1973 bFail = true;; 1974 } 1975 } 1976 } 1977 else if( hr != DISP_E_TYPEMISMATCH && hr != E_NOINTERFACE) 1978 bFail = true; 1979 1980 if (bFail) 1981 throw BridgeRuntimeError( 1982 OUSTR("[automation bridge] Conversion of ValueObject failed ")); 1983 } 1984 catch (BridgeRuntimeError &) 1985 { 1986 throw; 1987 } 1988 catch (Exception & e) 1989 { 1990 throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in " 1991 "UnoConversionUtilities<T>::convertValueObject ! Message : \n") + 1992 e.Message); 1993 } 1994 catch(...) 1995 { 1996 throw BridgeRuntimeError( 1997 OUSTR("[automation bridge] unexpected exception in " 1998 "UnoConversionUtilities<T>::convertValueObject !")); 1999 } 2000 return ret; 2001 } 2002 2003 template<class T> 2004 void UnoConversionUtilities<T>::dispatchExObject2Sequence( const VARIANTARG* pvar, Any& anySeq, const Type& type) 2005 { 2006 try 2007 { 2008 bool bFail = false; 2009 if( pvar->vt != VT_DISPATCH) 2010 throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n" 2011 "Conversion of dispatch object to Sequence failed!")); 2012 IDispatchEx* pdispEx; 2013 HRESULT hr; 2014 if( FAILED( hr= pvar->pdispVal->QueryInterface( IID_IDispatchEx, 2015 reinterpret_cast<void**>( &pdispEx)))) 2016 throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n" 2017 "Conversion of dispatch object to Sequence failed!")); 2018 2019 DISPID dispid; 2020 OUString sindex; 2021 DISPPARAMS param= {0,0,0,0}; 2022 CComVariant result; 2023 2024 OLECHAR* sLength= L"length"; 2025 2026 // Get the length of the array. Can also be obtained throu GetNextDispID. The 2027 // method only returns DISPIDs of the array data. Their names are like "0", "1" etc. 2028 if( FAILED( hr= pdispEx->GetIDsOfNames(IID_NULL, &sLength , 1, LOCALE_USER_DEFAULT, &dispid))) 2029 throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n" 2030 "Conversion of dispatch object to Sequence failed!")); 2031 if( FAILED( hr= pdispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, 2032 ¶m, &result, NULL, NULL))) 2033 throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n" 2034 "Conversion of dispatch object to Sequence failed!")); 2035 if( FAILED( VariantChangeType( &result, &result, 0, VT_I4))) 2036 throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n" 2037 "Conversion of dispatch object to Sequence failed!")); 2038 long length= result.lVal; 2039 2040 result.Clear(); 2041 2042 // get a few basic facts about the sequence, and reallocate: 2043 // create the Sequences 2044 // get the size of the elements 2045 typelib_TypeDescription *pDesc= NULL; 2046 type.getDescription( &pDesc); 2047 2048 typelib_IndirectTypeDescription *pSeqDesc= reinterpret_cast<typelib_IndirectTypeDescription*>(pDesc); 2049 typelib_TypeDescriptionReference *pSeqElemDescRef= pSeqDesc->pType; // type of the Sequence' elements 2050 Type elemType( pSeqElemDescRef); 2051 _typelib_TypeDescription* pSeqElemDesc=NULL; 2052 TYPELIB_DANGER_GET( &pSeqElemDesc, pSeqElemDescRef) 2053 sal_uInt32 nelementSize= pSeqElemDesc->nSize; 2054 TYPELIB_DANGER_RELEASE( pSeqElemDesc) 2055 2056 uno_Sequence *p_uno_Seq; 2057 uno_sequence_construct( &p_uno_Seq, pDesc, NULL, length, cpp_acquire); 2058 2059 typelib_TypeClass typeElement= pSeqDesc->pType->eTypeClass; 2060 char *pArray= p_uno_Seq->elements; 2061 2062 // Get All properties in the object, convert their values to the expected type and 2063 // put them into the passed in sequence 2064 for( sal_Int32 i= 0; i< length; i++) 2065 { 2066 OUString ousIndex=OUString::valueOf( i); 2067 OLECHAR* sindex = (OLECHAR*)ousIndex.getStr(); 2068 2069 if( FAILED( hr= pdispEx->GetIDsOfNames(IID_NULL, &sindex , 1, LOCALE_USER_DEFAULT, &dispid))) 2070 { 2071 throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n" 2072 "Conversion of dispatch object to Sequence failed!")); 2073 } 2074 if( FAILED( hr= pdispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, 2075 ¶m, &result, NULL, NULL))) 2076 { 2077 throw BridgeRuntimeError(OUSTR("[automation bridge] UnoConversionUtilities<T>::dispatchExObject2Sequence \n" 2078 "Conversion of dispatch object to Sequence failed!")); 2079 } 2080 2081 // If the result is VT_DISPATCH than the Sequence's element type could be Sequence 2082 // Look that up in the CoreReflection to make clear. 2083 // That requires a recursiv conversion 2084 Any any; 2085 // Destination address within the out-Sequence "anySeq" where to copy the next converted element 2086 void* pDest= (void*)(pArray + (i * nelementSize)); 2087 2088 if( result.vt & VT_DISPATCH && typeElement == typelib_TypeClass_SEQUENCE) 2089 { 2090 variantToAny( &result, any, elemType, sal_False); 2091 // copy the converted VARIANT, that is a Sequence to the Sequence 2092 uno_Sequence * p_unoSeq= *(uno_Sequence**)any.getValue(); 2093 // just copy the pointer of the uno_Sequence 2094 // nelementSize should be 4 !!!! 2095 memcpy( pDest, &p_unoSeq, nelementSize); 2096 osl_incrementInterlockedCount( &p_unoSeq->nRefCount); 2097 } 2098 else // Element type is no Sequence -> do one conversion 2099 { 2100 variantToAny( &result, any, elemType, sal_False); 2101 if( typeElement == typelib_TypeClass_ANY) 2102 { 2103 // copy the converted VARIANT to the Sequence 2104 uno_type_assignData( pDest, pSeqElemDescRef , &any, pSeqElemDescRef,cpp_queryInterface, 2105 cpp_acquire, cpp_release); 2106 } 2107 else 2108 { 2109 // type after conversion must be the element type of the sequence 2110 OSL_ENSURE( (any.getValueTypeClass() == typeElement), "wrong conversion"); 2111 uno_type_assignData( pDest, pSeqElemDescRef,const_cast<void*>( any.getValue()), any.getValueTypeRef(), 2112 cpp_queryInterface, cpp_acquire, cpp_release); 2113 } 2114 } 2115 } // else 2116 result.Clear(); 2117 anySeq.setValue( &p_uno_Seq, pDesc); 2118 uno_destructData( &p_uno_Seq, pDesc, cpp_release); 2119 typelib_typedescription_release( pDesc); 2120 2121 if (bFail) 2122 throw BridgeRuntimeError( 2123 OUSTR("[automation bridge] Conversion of ValueObject failed ")); 2124 } 2125 catch (BridgeRuntimeError & ) 2126 { 2127 throw; 2128 } 2129 catch (Exception & e) 2130 { 2131 throw BridgeRuntimeError(OUSTR("[automation bridge] unexpected exception in " 2132 "UnoConversionUtilities<T>::convertValueObject ! Message : \n") + 2133 e.Message); 2134 } 2135 catch(...) 2136 { 2137 throw BridgeRuntimeError( 2138 OUSTR("[automation bridge] unexpected exception in " 2139 "UnoConversionUtilities<T>::convertValueObject !")); 2140 } 2141 } 2142 2143 /* The argument unotype is the type that is expected by the currently called UNO function. 2144 For example: []long, [][]long. If the function calls itself recursively then the element type 2145 is passed on. For example a two dimensional SAFEARRAY of type VT_I4 is to be converted. Then 2146 unotype has to be either void or [][]long. When the function calls itself recursivly then 2147 it passes the element type which is []long. 2148 */ 2149 template<class T> 2150 Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* pArray, 2151 unsigned int dimCount, unsigned int actDim, long* index, VARTYPE type, const Type& unotype) 2152 { 2153 HRESULT hr= S_OK; 2154 long lBound; 2155 long uBound; 2156 long nCountElements; 2157 2158 SafeArrayGetLBound(pArray, actDim, &lBound); 2159 SafeArrayGetUBound(pArray, actDim, &uBound); 2160 nCountElements= uBound - lBound +1; 2161 2162 Sequence<Any> anySeq(nCountElements); 2163 Any* pUnoArray = anySeq.getArray(); 2164 2165 for (index[actDim - 1] = lBound; index[actDim - 1] <= uBound; index[actDim - 1]++) 2166 { 2167 if (actDim > 1 ) 2168 { 2169 Sequence<Any> element = createOleArrayWrapperOfDim(pArray, dimCount, 2170 actDim - 1, index, type, getElementTypeOfSequence(unotype)); 2171 2172 pUnoArray[index[actDim - 1] - lBound].setValue(&element, getCppuType(&element)); 2173 } 2174 else 2175 { 2176 VARIANT variant; 2177 2178 VariantInit(&variant); 2179 2180 V_VT(&variant) = type; 2181 2182 switch (type) 2183 { 2184 case VT_I2: 2185 SafeArrayGetElement(pArray, index, &V_I2(&variant)); 2186 break; 2187 case VT_I4: 2188 SafeArrayGetElement(pArray, index, &V_I4(&variant)); 2189 break; 2190 case VT_R4: 2191 SafeArrayGetElement(pArray, index, &V_R4(&variant)); 2192 break; 2193 case VT_R8: 2194 SafeArrayGetElement(pArray, index, &V_R8(&variant)); 2195 break; 2196 case VT_CY: 2197 SafeArrayGetElement(pArray, index, &V_CY(&variant)); 2198 break; 2199 case VT_DATE: 2200 SafeArrayGetElement(pArray, index, &V_DATE(&variant)); 2201 break; 2202 case VT_BSTR: 2203 hr= SafeArrayGetElement(pArray, index, &V_BSTR(&variant)); 2204 break; 2205 case VT_DISPATCH: 2206 SafeArrayGetElement(pArray, index, &V_DISPATCH(&variant)); 2207 break; 2208 case VT_ERROR: 2209 SafeArrayGetElement(pArray, index, &V_ERROR(&variant)); 2210 break; 2211 case VT_BOOL: 2212 SafeArrayGetElement(pArray, index, &V_BOOL(&variant)); 2213 break; 2214 case VT_VARIANT: 2215 SafeArrayGetElement(pArray, index, &variant); 2216 break; 2217 case VT_UNKNOWN: 2218 SafeArrayGetElement(pArray, index, &V_UNKNOWN(&variant)); 2219 break; 2220 case VT_I1: 2221 SafeArrayGetElement(pArray, index, &V_I1(&variant)); 2222 break; 2223 case VT_UI1: 2224 SafeArrayGetElement(pArray, index, &V_UI1(&variant)); 2225 break; 2226 case VT_UI2: 2227 SafeArrayGetElement(pArray, index, &V_UI2(&variant)); 2228 break; 2229 case VT_UI4: 2230 SafeArrayGetElement(pArray, index, &V_UI4(&variant)); 2231 break; 2232 default: 2233 break; 2234 } 2235 2236 if( unotype.getTypeClass() == TypeClass_VOID) 2237 // the function was called without specifying the destination type 2238 variantToAny(&variant, pUnoArray[index[actDim - 1] - lBound], sal_False); 2239 else 2240 variantToAny(&variant, pUnoArray[index[actDim - 1] - lBound], 2241 getElementTypeOfSequence(unotype), sal_False); 2242 2243 VariantClear(&variant); 2244 } 2245 } 2246 return anySeq; 2247 } 2248 2249 template<class T> 2250 Type UnoConversionUtilities<T>::getElementTypeOfSequence( const Type& seqType) 2251 { 2252 Type retValue; 2253 if( seqType.getTypeClass() != TypeClass_VOID) 2254 { 2255 OSL_ASSERT( seqType.getTypeClass() == TypeClass_SEQUENCE); 2256 typelib_IndirectTypeDescription* pDescSeq= NULL; 2257 seqType.getDescription((typelib_TypeDescription** ) & pDescSeq); 2258 retValue = Type(pDescSeq->pType); 2259 typelib_typedescription_release( (typelib_TypeDescription*) pDescSeq); 2260 } 2261 return retValue; 2262 } 2263 template<class T> 2264 Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapper(SAFEARRAY* pArray, VARTYPE type, const Type& unoType) 2265 { 2266 sal_uInt32 dim = SafeArrayGetDim(pArray); 2267 2268 Sequence<Any> ret; 2269 2270 if (dim > 0) 2271 { 2272 scoped_array<long> sarIndex(new long[dim]); 2273 long * index = sarIndex.get(); 2274 2275 for (unsigned int i = 0; i < dim; i++) 2276 { 2277 index[i] = 0; 2278 } 2279 2280 ret = createOleArrayWrapperOfDim(pArray, dim, dim, index, type, unoType); 2281 } 2282 2283 return ret; 2284 } 2285 2286 // If an VARIANT has the type VT_DISPATCH it can either be an JScript Array 2287 // or some other object. This function finds out if it is such an array or 2288 // not. Currently there's no way to make sure it's an array 2289 // so we assume that when the object has a property "0" then it is an Array. 2290 // An JScript has property like "0", "1", "2" etc. which represent the 2291 // value at the corresponding index of the array 2292 template<class T> 2293 sal_Bool UnoConversionUtilities<T>::isJScriptArray(const VARIANT* rvar) 2294 { 2295 OSL_ENSURE( rvar->vt == VT_DISPATCH, "param is not a VT_DISPATCH"); 2296 HRESULT hr; 2297 OLECHAR* sindex= L"0"; 2298 DISPID id; 2299 if ( rvar->vt == VT_DISPATCH && rvar->pdispVal ) 2300 { 2301 hr= rvar->pdispVal->GetIDsOfNames( IID_NULL, &sindex, 1, 2302 LOCALE_USER_DEFAULT, &id); 2303 2304 if( SUCCEEDED ( hr) ) 2305 return sal_True; 2306 } 2307 2308 return sal_False; 2309 } 2310 2311 template<class T> 2312 VARTYPE UnoConversionUtilities<T>::mapTypeClassToVartype( TypeClass type) 2313 { 2314 VARTYPE ret; 2315 switch( type) 2316 { 2317 case TypeClass_INTERFACE: ret= VT_DISPATCH; 2318 break; 2319 case TypeClass_STRUCT: ret= VT_DISPATCH; 2320 break; 2321 case TypeClass_ENUM: ret= VT_I4; 2322 break; 2323 case TypeClass_SEQUENCE: ret= VT_ARRAY; 2324 break; 2325 case TypeClass_ANY: ret= VT_VARIANT; 2326 break; 2327 case TypeClass_BOOLEAN: ret= VT_BOOL; 2328 break; 2329 case TypeClass_CHAR: ret= VT_I2; 2330 break; 2331 case TypeClass_STRING: ret= VT_BSTR; 2332 break; 2333 case TypeClass_FLOAT: ret= VT_R4; 2334 break; 2335 case TypeClass_DOUBLE: ret= VT_R8; 2336 break; 2337 case TypeClass_BYTE: ret= VT_UI1; 2338 break; 2339 case TypeClass_SHORT: ret= VT_I2; 2340 break; 2341 case TypeClass_LONG: ret= VT_I4; 2342 break; 2343 case TypeClass_UNSIGNED_SHORT: ret= VT_UI2; 2344 break; 2345 case TypeClass_UNSIGNED_LONG: ret= VT_UI4; 2346 break; 2347 default: 2348 ret= VT_EMPTY; 2349 } 2350 return ret; 2351 } 2352 2353 template<class T> 2354 Sequence<Type> UnoConversionUtilities<T>::getImplementedInterfaces(IUnknown* pUnk) 2355 { 2356 Sequence<Type> seqTypes; 2357 CComDispatchDriver disp( pUnk); 2358 if( disp) 2359 { 2360 CComVariant var; 2361 HRESULT hr= S_OK; 2362 // There are two different property names possible. 2363 if( FAILED( hr= disp.GetPropertyByName( SUPPORTED_INTERFACES_PROP, &var))) 2364 { 2365 hr= disp.GetPropertyByName( SUPPORTED_INTERFACES_PROP2, &var); 2366 } 2367 if (SUCCEEDED( hr)) 2368 { 2369 // we exspect an array( SafeArray or IDispatch) of Strings. 2370 Any anyNames; 2371 variantToAny( &var, anyNames, getCppuType( (Sequence<Any>*) 0)); 2372 Sequence<Any> seqAny; 2373 if( anyNames >>= seqAny) 2374 { 2375 seqTypes.realloc( seqAny.getLength()); 2376 for( sal_Int32 i=0; i < seqAny.getLength(); i++) 2377 { 2378 OUString typeName; 2379 seqAny[i] >>= typeName; 2380 seqTypes[i]= Type( TypeClass_INTERFACE, typeName); 2381 } 2382 } 2383 } 2384 } 2385 return seqTypes; 2386 } 2387 template<class T> 2388 Reference<XTypeConverter> UnoConversionUtilities<T>::getTypeConverter() 2389 { 2390 if ( ! m_typeConverter.is()) 2391 { 2392 MutexGuard guard(getBridgeMutex()); 2393 if ( ! m_typeConverter.is()) 2394 { 2395 Reference<XInterface> xIntConverter = 2396 m_smgr->createInstance(OUSTR("com.sun.star.script.Converter")); 2397 if (xIntConverter.is()) 2398 m_typeConverter = Reference<XTypeConverter>(xIntConverter, UNO_QUERY); 2399 } 2400 } 2401 return m_typeConverter; 2402 } 2403 2404 // This function tries to the change the type of a value (contained in the Any) 2405 // to the smallest possible that can hold the value. This is actually done only 2406 // for types of VT_I4 (see o2u_variantToAny). The reason is the following: 2407 // JavaScript passes integer values always as VT_I4. If there is a parameter or 2408 // property of type any then the bridge converts the any's content according 2409 // to "o2u_variantToAny". Because the VARTYPE is VT_I4 the value would be converted 2410 // to TypeClass_LONG. Say the method XPropertySet::setPropertyValue( string name, any value) 2411 // would be called on an object and the property actually is of TypeClass_SHORT. 2412 // After conversion of the VARIANT parameter the Any would contain type 2413 // TypeClass_LONG. Because the corereflection does not cast from long to short 2414 // the "setPropertValue" would fail as the value has not the right type. 2415 2416 // The corereflection does convert small integer types to bigger types. 2417 // Therefore we can reduce the type if possible and avoid the above mentioned 2418 // problem. 2419 2420 // The function is not used when elements are to be converted for Sequences. 2421 2422 #ifndef _REDUCE_RANGE 2423 #define _REDUCE_RANGE 2424 inline void reduceRange( Any& any) 2425 { 2426 OSL_ASSERT( any.getValueTypeClass() == TypeClass_LONG); 2427 2428 sal_Int32 value= *(sal_Int32*)any.getValue(); 2429 if( value <= 0x7f && value >= -0x80) 2430 {// -128 bis 127 2431 sal_Int8 charVal= static_cast<sal_Int8>( value); 2432 any.setValue( &charVal, getCppuType( (sal_Int8*)0)); 2433 } 2434 else if( value <= 0x7fff && value >= -0x8000) 2435 {// -32768 bis 32767 2436 sal_Int16 shortVal= static_cast<sal_Int16>( value); 2437 any.setValue( &shortVal, getCppuType( (sal_Int16*)0)); 2438 } 2439 } 2440 #endif 2441 2442 2443 2444 } // end namespace 2445 #endif 2446 2447