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
86*2d95c451SJohn Bampton // UNO interface is mapped again to COM then the IDispatch 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:
UnoConversionUtilities(const Reference<XMultiServiceFactory> & smgr)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
UnoConversionUtilities(const Reference<XMultiServiceFactory> & xFactory,sal_uInt8 unoWrapperClass,sal_uInt8 comWrapperClass)114cdf0e10cSrcweir UnoConversionUtilities( const Reference<XMultiServiceFactory> & xFactory, sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass )
115cdf0e10cSrcweir : m_smgr( xFactory), m_nComWrapperClass( comWrapperClass), m_nUnoWrapperClass( unoWrapperClass)
116cdf0e10cSrcweir {}
117cdf0e10cSrcweir
~UnoConversionUtilities()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 >
convertSelfToCom(T & unoInterface,VARIANT * pVar)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>
getInvocationFactory(const Any & anyObject)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>
variantToAny(const VARIANTARG * pArg,Any & rAny,const Type & ptype,sal_Bool bReduceValueRange)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
32830acf5e8Spfg // type in JavaScript and the script engine determines the type being 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>
370*2d95c451SJohn Bampton // 3. VBScript 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) +
585*2d95c451SJohn Bampton OUSTR("\" is inappropriate 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>
anyToVariant(VARIANT * pVariant,const Any & rAny,VARTYPE type)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>
anyToVariant(VARIANT * pVariant,const Any & rAny)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() +
998*2d95c451SJohn Bampton OUSTR("\" is inappropriate 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
102907a3d7f1SPedro Giffuni // creates a SAFEARRAY with multiple dimensions.
1030cdf0e10cSrcweir // Used by sal_Bool anyToVariant(VARIANT* pVariant, const Any& rAny, VARTYPE type);
1031cdf0e10cSrcweir template<class T>
createUnoSequenceWrapper(const Any & rSeq,VARTYPE elemtype)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>
incrementMultidimensionalIndex(sal_Int32 dimensions,const sal_Int32 * parDimensionLengths,sal_Int32 * parMultidimensionalIndex)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>
getOleElementSize(VARTYPE type)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.
125807a3d7f1SPedro Giffuni // param seqElementCounts - contains 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>
getElementCountAndTypeOfSequence(const Any & rSeq,sal_Int32 dim,Sequence<sal_Int32> & seqElementCounts,TypeDescription & typeDesc)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>
createUnoSequenceWrapper(const Any & rSeq)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>
createUnoObjectWrapper(const Any & rObj,VARIANT * pVar)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)
140607a3d7f1SPedro Giffuni // or does it supply 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>
variantToAny(const VARIANT * pVariant,Any & rAny,sal_Bool bReduceValueRange)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__
createOleObjectWrapper(VARIANT * pVar,const Type & aType)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>
createAdapter(const Sequence<Type> & seqTypes,const Reference<XInterface> & receiver)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>
convertValueObject(const VARIANTARG * var,Any & any)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>
dispatchExObject2Sequence(const VARIANTARG * pvar,Any & anySeq,const Type & type)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;
2037ad7e1cc0SAriel Constenla-Haile TYPELIB_DANGER_GET( &pSeqElemDesc, pSeqElemDescRef);
2038cdf0e10cSrcweir sal_uInt32 nelementSize= pSeqElemDesc->nSize;
2039ad7e1cc0SAriel 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>
createOleArrayWrapperOfDim(SAFEARRAY * pArray,unsigned int dimCount,unsigned int actDim,long * index,VARTYPE type,const Type & unotype)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>
getElementTypeOfSequence(const Type & seqType)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>
createOleArrayWrapper(SAFEARRAY * pArray,VARTYPE type,const Type & unoType)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>
isJScriptArray(const VARIANT * rvar)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>
mapTypeClassToVartype(TypeClass type)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>
getImplementedInterfaces(IUnknown * pUnk)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>
getTypeConverter()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
reduceRange(Any & any)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
2431