xref: /trunk/main/extensions/source/ole/unoconversionutilities.hxx (revision 914d351e5f5b84e4342a86d6ab8d4aca7308b9bd)
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                                           &param, &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                                               &param, &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