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