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