summaryrefslogtreecommitdiff
path: root/extensions/source/ole/unoconversionutilities.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/source/ole/unoconversionutilities.hxx')
-rw-r--r--extensions/source/ole/unoconversionutilities.hxx1574
1 files changed, 1574 insertions, 0 deletions
diff --git a/extensions/source/ole/unoconversionutilities.hxx b/extensions/source/ole/unoconversionutilities.hxx
new file mode 100644
index 000000000000..11be00a3000d
--- /dev/null
+++ b/extensions/source/ole/unoconversionutilities.hxx
@@ -0,0 +1,1574 @@
+/*************************************************************************
+ *
+ * $RCSfile: unoconversionutilities.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:16:41 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#ifndef _UNO_CONVERSION_UTILITIES
+#define _UNO_CONVERSION_UTILITIES
+
+#include <com/sun/star/script/XInvocationAdapterFactory.hpp>
+#include <com/sun/star/script/XInvocationAdapterFactory2.hpp>
+
+#include <vos/mutex.hxx>
+#include "ole2uno.hxx"
+
+// classes for wrapping uno objects
+#define INTERFACE_OLE_WRAPPER_IMPL 1
+#define UNO_OBJECT_WRAPPER_REMOTE_OPT 2
+
+#define INVOCATION_SERVICE L"com.sun.star.script.Invocation"
+
+
+// classes for wrapping ole objects
+#define IUNKNOWN_WRAPPER_IMPL 1
+
+#define INTERFACE_ADAPTER_FACTORY L"com.sun.star.script.InvocationAdapterFactory"
+// COM or JScript objects implementing UNO interfaces have to implement this interface as well
+#define SUPPORTED_INTERFACES_PROP L"_implementedInterfaces"
+
+using namespace com::sun::star::script;
+using namespace com::sun::star::beans;
+using namespace vos;
+
+namespace ole_adapter
+{
+extern OMutex globalWrapperMutex;
+extern hash_map<sal_uInt32, sal_uInt32> AdapterToWrapperMap;
+extern hash_map<sal_uInt32, sal_uInt32> WrapperToAdapterMap;
+
+ // createUnoObjectWrapper gets a wrapper instance by calling createUnoWrapperInstance
+ // and initializes it via XInitialization. The wrapper object is required to implement
+ // XBridgeSupplier so that it can convert itself to IDispatch.
+ // class T: Deriving class ( must implement XInterface )
+template< class >
+class UnoConversionUtilities
+{
+public:
+ UnoConversionUtilities(): m_nUnoWrapperClass( INTERFACE_OLE_WRAPPER_IMPL),
+ m_nComWrapperClass( IUNKNOWN_WRAPPER_IMPL)
+ {}
+ UnoConversionUtilities( sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass )
+ : m_nUnoWrapperClass( unoWrapperClass), m_nComWrapperClass( comWrapperClass)
+ {}
+ UnoConversionUtilities( Reference<XMultiServiceFactory> xFactory, sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass )
+ : m_xMultiServiceFactory( xFactory), m_nComWrapperClass( comWrapperClass), m_nUnoWrapperClass( unoWrapperClass)
+ {}
+ // converts only into oleautomation types, that is there is no VT_I1, VT_UI2, VT_UI4
+ // a sal_Unicode character is converted into a BSTR
+ sal_Bool anyToVariant(VARIANT* pVariant, const Any& rAny);
+ SAFEARRAY* createUnoSequenceWrapper(const Any& rSeq);
+ IDispatch* createUnoObjectWrapper(const Any& rObj);
+
+ sal_Bool variantToAny(const VARIANT* pVariant, Any& rAny, sal_Bool bReduceValueRange = sal_True);
+ sal_Bool variantToAny2( const VARIANTARG* pArg, Any& rAny, const Type& ptype, sal_Bool bReduceValueRange = sal_True);
+ Any createOleObjectWrapper(IUnknown* pUnknown);
+ Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType);
+
+
+ sal_Bool convertValueObject( const VARIANTARG *var, Any& any, sal_Bool& bHandled);
+ sal_Bool dispatchExObject2Sequence( const VARIANTARG* pvar, Any& anySeq, const Type& type);
+
+ Sequence<Any> createOleArrayWrapperOfDim(SAFEARRAY* pArray, unsigned int dimCount, unsigned int actDim, long* index, VARTYPE type);
+ Sequence<Any> createOleArrayWrapper(SAFEARRAY* pArray, VARTYPE type);
+
+// SAFEARRAY* createUnoSequenceWrapper(const Any& rSeq);
+
+ VARTYPE mapTypeClassToVartype( TypeClass type);
+
+ Reference< XSingleServiceFactory > getInvocationFactory();
+
+ virtual Reference< XInterface > createUnoWrapperInstance()=0;
+ virtual Reference< XInterface > createComWrapperInstance()=0;
+
+ static sal_Bool isJScriptArray(const VARIANT* pvar);
+
+
+
+// Attributes:
+protected:
+ // This member determines what class is used to convert a UNO object
+ // or struct to a COM object. It is passed along to the o2u_anyToVariant
+ // function in the createBridge function implementation
+ sal_uInt8 m_nUnoWrapperClass;
+ sal_uInt8 m_nComWrapperClass;
+
+ // This factory is set by calling XInitialization::initialize.
+ // If this ServiceManager is supplied then it is used to create all
+ // necessary services.
+ Reference<XMultiServiceFactory> m_xMultiServiceFactory;
+ Reference<XSingleServiceFactory> m_xInvocationFactory;
+
+
+};
+
+template<class T>
+Reference< XSingleServiceFactory > UnoConversionUtilities<T>::getInvocationFactory()
+{
+ if( m_xInvocationFactory.is() )
+ return Reference< XSingleServiceFactory >( m_xInvocationFactory );
+
+ if( m_xMultiServiceFactory.is() )
+ m_xInvocationFactory= Reference<XSingleServiceFactory >( m_xMultiServiceFactory->createInstance( INVOCATION_SERVICE), UNO_QUERY);
+ else
+ m_xInvocationFactory= Reference<XSingleServiceFactory>( o2u_getMultiServiceFactory()->createInstance(INVOCATION_SERVICE ), UNO_QUERY);
+
+ return m_xInvocationFactory;
+}
+
+template<class T>
+sal_Bool UnoConversionUtilities<T>::variantToAny2( const VARIANTARG* pArg, Any& rAny, const Type& ptype, sal_Bool bReduceValueRange /* = sal_True */)
+{
+ HRESULT hr;
+ sal_Bool retVal= sal_True;
+
+ VARIANT var;
+ VariantInit( &var);
+ // There is no need to support indirect values, since they're not supported by UNO
+ if( FAILED(hr= VariantCopyInd( &var, const_cast<VARIANTARG*>(pArg)))) // remove VT_BYREF
+ return sal_False;
+
+ sal_Bool bHandled= sal_False;
+ if( pArg->vt == VT_DISPATCH )
+ {
+ convertValueObject( &var, rAny, bHandled);
+ if( bHandled)
+ OSL_ENSURE( rAny.getValueType() == ptype, "type in Value Object must tally with the type parameter");
+ }
+
+
+ if( ! bHandled)
+ {
+ // convert into a variant type that is the equivalent to the type
+ // the sequence expects. Thus variantToAny produces the correct type
+ // E.g. An Array object contains VT_I4 and the sequence expects shorts
+ // than the vartype must be changed. The reason is, you can't specify the
+ // type in JavaScript and the script engine determines the type beeing used.
+ switch( ptype.getTypeClass())
+ {
+ case TypeClass_CHAR: // could be: new Array( 12, 'w', "w")
+ if( pArg->vt == VT_BSTR)
+ {
+ if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_BSTR)))
+ rAny.setValue( (void*)V_BSTR( &var), ptype);
+ else
+ retVal= sal_False;
+ }
+ else if( pArg->vt == VT_I4 ||
+ pArg->vt == VT_UI4 ||
+ pArg->vt == VT_I2 ||
+ pArg->vt == VT_UI2 ||
+ pArg->vt == VT_I1 ||
+ pArg->vt == VT_UI1)
+ {
+ if( SUCCEEDED( hr= VariantChangeType( &var, & var, 0, VT_UI2)))
+ rAny.setValue(& V_UI2( &var), ptype);
+ else
+ retVal= sal_False;
+ }
+ break;
+ case TypeClass_INTERFACE: // could also be an IUnknown
+ // if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_DISPATCH)))
+ // retVal= variantToAny(&var, rAny);
+ {
+ CComVariant varUnk;
+ if( SUCCEEDED( hr= VariantChangeType( &varUnk, &var, 0, VT_UNKNOWN)))
+ {
+ rAny = createOleObjectWrapper( varUnk.punkVal, ptype);
+ retVal = sal_True;
+ }
+ else
+ retVal= sal_False;
+ break;
+ }
+ case TypeClass_SERVICE: break; // meta construct
+ case TypeClass_STRUCT:
+ {// dispatch
+ CComVariant varUnk;
+ if( SUCCEEDED( hr= VariantChangeType( &varUnk, &var, 0, VT_UNKNOWN)))
+ {
+ rAny= createOleObjectWrapper( varUnk.punkVal, ptype);
+ retVal= sal_True;
+ }
+ else
+ retVal= sal_False;
+ break;
+ }
+ case TypeClass_TYPEDEF: break;
+ case TypeClass_UNION: break;
+ case TypeClass_ENUM:
+ if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_I4)))
+ {
+ rAny.setValue( (void*)&var.lVal, ptype);
+ retVal= sal_True;
+ }
+ else
+ retVal= sal_False;
+ break;
+ case TypeClass_EXCEPTION: break;
+ case TypeClass_ARRAY: break; // there's no Array at the moment
+ case TypeClass_SEQUENCE:
+ // There are different ways of receiving a sequence:
+ // 1: JScript, VARTYPE: VT_DISPATCH
+ // 2. VBScript simple arraysVT_VARIANT|VT_BYREF the referenced VARIANT contains
+ // a VT_ARRAY| <type>
+ // 3. VBSrcript multi dimensional arrays: VT_ARRAY|VT_BYREF
+ if( pArg->vt == VT_DISPATCH)
+ {
+ retVal= dispatchExObject2Sequence( pArg, rAny, ptype);
+ }
+ else
+ retVal= variantToAny(&var, rAny);
+ break; // maybe later ( convert to VT_ARRAY| ??? )
+ case TypeClass_VOID:
+ rAny.setValue(NULL,Type());
+ break;
+
+ case TypeClass_ANY: // Any
+ // There could be a JScript Array that needs special handling
+ // If an Any is expected and this Any must contain a Sequence
+ // then we cannot figure out what element type is required.
+ // Therefore we convert to Sequence< Any >
+ if( pArg->vt == VT_DISPATCH && isJScriptArray( pArg))
+ {
+ Sequence<Any> s;
+ retVal= dispatchExObject2Sequence( pArg, rAny, getCppuType(&s));
+ }
+ else
+ retVal= variantToAny( &var, rAny);
+ break;
+ case TypeClass_UNKNOWN: break;
+ case TypeClass_BOOLEAN: // VARIANT could be VARIANT_BOOL or other
+ if(SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_BOOL)))
+ retVal= variantToAny(&var, rAny);
+ else
+ retVal= sal_False;
+ break;
+ case TypeClass_STRING: // UString
+ if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_BSTR)))
+ retVal= variantToAny(&var, rAny);
+ else
+ retVal= sal_False;
+ break;
+ case TypeClass_FLOAT: // float
+ if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_R4)))
+ retVal= variantToAny(&var, rAny);
+ else
+ retVal= sal_False;
+ break;
+ case TypeClass_DOUBLE: // double
+ if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_R8)))
+ retVal= variantToAny(&var, rAny );
+ else
+ retVal= sal_False;
+ break;
+ case TypeClass_BYTE: // BYTE
+ if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_I1)))
+ retVal= variantToAny(&var, rAny);
+ else
+ retVal= sal_False;
+ break;
+ case TypeClass_SHORT: // INT16
+ if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_I2)))
+ retVal= variantToAny(&var, rAny);
+ else
+ retVal= sal_False;
+ break;
+ case TypeClass_LONG: // INT32
+ if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_I4)))
+ retVal= variantToAny(&var, rAny, bReduceValueRange);
+ else
+ retVal= sal_False;
+ break;
+ case TypeClass_HYPER: break; // INT64
+ case TypeClass_UNSIGNED_SHORT: // UINT16
+ if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_UI2)))
+ retVal= variantToAny(&var, rAny);
+ else
+ retVal= sal_False;
+ break;
+ case TypeClass_UNSIGNED_LONG: // UINT32
+ if( SUCCEEDED( hr= VariantChangeType( &var, &var, 0, VT_UI4)))
+ retVal= variantToAny(&var, rAny, bReduceValueRange);
+ else
+ retVal= sal_False;
+ break;
+ case TypeClass_UNSIGNED_HYPER: break;// UINT64
+ case TypeClass_MODULE: break; // module
+
+ default:
+ retVal= variantToAny(pArg, rAny); // hopfully delegating ;-)
+ break;
+
+ }
+ }
+ return retVal;
+}
+
+
+template<class T>
+sal_Bool UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& rAny)
+{
+ sal_Bool ret = sal_False;
+
+ switch (rAny.getValueTypeClass())
+ {
+ case TypeClass_INTERFACE: // XInterfaceRef
+ {
+ Reference<XInterface> xInt( *(XInterface**)rAny.getValue());
+
+ V_VT(pVariant) = VT_DISPATCH;
+ V_DISPATCH(pVariant) = NULL;
+
+ if (xInt.is())
+ {
+ // check, wether the object provides OLE bridging or not
+ Reference<XBridgeSupplier2> XBridgeSup(xInt, UNO_QUERY);
+ sal_Bool bOwnService= sal_False;
+ if (XBridgeSup.is())
+ {
+ // check if we try to convert our own OleConverter2 service
+ // If so we would run into a recursion!!!
+ T* pT= static_cast< T* >( this);
+
+ Any anyXInt= pT->queryInterface( getCppuType( static_cast<Reference<XInterface>* >( 0) ));
+ Reference< XInterface > xIntThis;
+
+ if( (anyXInt >>= xIntThis) && xInt != xIntThis)
+ { // not our own OleConverter_Impl2
+ sal_uInt8 arId[16];
+ rtl_getGlobalProcessId( arId);
+ Any oleAny = XBridgeSup->createBridge(
+ rAny,
+ Sequence<sal_Int8>( (sal_Int8*)arId, 16),
+ UNO,
+ OLE);
+
+ if( oleAny.getValueType() == getCppuType( (sal_uInt32*)0))
+ {
+ VARIANT* pTmpVariant = *(VARIANT**)oleAny.getValue();
+
+ VariantCopy(pVariant, pTmpVariant);
+ VariantClear(pTmpVariant);
+ CoTaskMemFree(pTmpVariant);
+ }
+ else
+ {
+ XBridgeSup = Reference<XBridgeSupplier2>();
+ }
+ }
+ else
+ {// The object is our OleConverter_Impl2 !!
+ bOwnService= sal_True;
+ }
+ }
+
+ if (!XBridgeSup.is() || bOwnService )
+ {
+ V_DISPATCH(pVariant)= createUnoObjectWrapper( rAny);
+ }
+ }
+ ret = sal_True;
+
+ break;
+ }
+ case TypeClass_SERVICE: // meta construct
+ break;
+ case TypeClass_STRUCT: // struct
+ V_VT(pVariant) = VT_DISPATCH;
+ V_DISPATCH(pVariant) = createUnoObjectWrapper(rAny);
+ ret = sal_True;
+ break;
+ case TypeClass_TYPEDEF: // typedef compiler construct ???
+ break;
+ case TypeClass_UNION: // union
+ break;
+ case TypeClass_ENUM: // enumeration
+ V_VT(pVariant) = VT_I4;
+ V_I4(pVariant) = *(sal_Int32*)rAny.getValue();
+ ret = sal_True;
+ break;
+ case TypeClass_EXCEPTION: // exception
+ break;
+ case TypeClass_ARRAY: // array not implemented
+ break;
+ case TypeClass_SEQUENCE: // sequence ??? SafeArray descriptor
+ {
+ SAFEARRAY* pArray = createUnoSequenceWrapper(rAny);
+ if (pArray)
+ {
+ V_VT(pVariant) = VT_ARRAY | VT_VARIANT;
+ V_ARRAY(pVariant) = pArray;
+ ret = sal_True;
+ }
+ break;
+ }
+ case TypeClass_VOID: // void
+ VariantClear(pVariant);
+ ret = sal_True;
+ break;
+ case TypeClass_ANY: // Any
+ break;
+ case TypeClass_UNKNOWN: // unknown type
+ break;
+ case TypeClass_BOOLEAN: // BOOL
+ {
+ V_VT(pVariant) = VT_BOOL;
+ V_BOOL( pVariant)= *(sal_Bool*) rAny.getValue() == sal_True? VARIANT_TRUE: VARIANT_FALSE;
+ ret = sal_True;
+ break;
+ }
+ case TypeClass_CHAR:// char
+ {
+ // Because VT_UI2 does not conform to oleautomation we convert into VT_I2 instead
+// V_VT(pVariant) = VT_BSTR;
+// sal_uInt16 _c = *(sal_uInt16*)rAny.getValue();
+// pVariant->bstrVal= SysAllocStringLen( &_c, 1);
+// ret= pVariant->bstrVal ? sal_True : sal_False;
+ V_VT(pVariant) = VT_I2;
+ V_I2(pVariant) = *(sal_Int16*)rAny.getValue();
+ ret = sal_True;
+ break;
+ }
+ case TypeClass_STRING: // UString
+ V_VT(pVariant) = VT_BSTR;
+ V_BSTR(pVariant) = SysAllocString( OUString(*(rtl_uString**)rAny.getValue()));
+ ret = sal_True;
+ break;
+ case TypeClass_FLOAT: // float
+ V_VT(pVariant) = VT_R4;
+ V_R4(pVariant) = *(float*)rAny.getValue();
+ ret = sal_True;
+ break;
+ case TypeClass_DOUBLE: // double
+ V_VT(pVariant) = VT_R8;
+ V_R8(pVariant) = *(double*)rAny.getValue();
+ ret = sal_True;
+ break;
+ case TypeClass_BYTE: // BYTE
+ // ole automation does not know a signed char but only unsigned char
+ V_VT(pVariant) = VT_UI1;
+ V_UI1(pVariant) = *(sal_uInt8*)rAny.getValue();
+ ret= sal_False;
+ break;
+ case TypeClass_SHORT: // INT16
+ V_VT(pVariant) = VT_I2;
+ V_I2(pVariant) = *(sal_Int16*)rAny.getValue();
+ ret = sal_True;
+ break;
+ case TypeClass_LONG: // INT32
+ V_VT(pVariant) = VT_I4;
+ V_I4(pVariant) = *(sal_Int32*)rAny.getValue();
+ ret = sal_True;
+ break;
+ case TypeClass_HYPER: // INT64
+ // V_VT(pVariant) = VT_CY;
+ // V_CY(pVariant).Lo = rAny.getINT64().p.loPart;
+ // V_CY(pVariant).Lo = rAny.getINT64().p.hiPart;
+ // ret = sal_True;
+ break;
+ //case TypeClass_UNSIGNED_OCTET: // ??? not implemented
+ // V_VT(pVariant) = VT_UI1;
+ // V_UI1(pVariant) = rAny.getBYTE();
+ // ret = sal_True;
+ // break;
+ case TypeClass_UNSIGNED_SHORT: // UINT16
+ V_VT(pVariant) = VT_I2;
+ V_I2(pVariant) = *(sal_Int16*)rAny.getValue();
+ ret = sal_False;
+ break;
+ case TypeClass_UNSIGNED_LONG: // UINT32
+ V_VT(pVariant) = VT_I4;
+ V_I4(pVariant) = *(sal_Int32*)rAny.getValue();
+ ret = sal_False;
+ break;
+ case TypeClass_UNSIGNED_HYPER: // UINT64
+ // V_VT(pVariant) = VT_UI8;
+ // V_UI8(pVariant) = rAny.getUINT64();
+ // ret = sal_True;
+ break;
+ // case TypeClass_UNSIGNED_INT: // int not implemented
+ // break;
+ //case TypeClass_UNSIGNED_BYTE:
+ // V_VT(pVariant) = VT_UI1;
+ // V_UI1(pVariant) = rAny.getBYTE();
+ // ret = sal_True;
+ // break;
+ case TypeClass_MODULE: // module
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+template<class T>
+SAFEARRAY* UnoConversionUtilities<T>::createUnoSequenceWrapper(const Any& rSeq)
+{
+ SAFEARRAY* pArray = NULL;
+ sal_uInt32 n = 0;
+
+ if( rSeq.getValueTypeClass() == TypeClass_SEQUENCE )
+ {
+ uno_Sequence * punoSeq= *(uno_Sequence**) rSeq.getValue();
+
+ typelib_TypeDescriptionReference* pSeqTypeRef= rSeq.getValueTypeRef();
+ typelib_TypeDescription* pSeqType= NULL;
+ TYPELIB_DANGER_GET( &pSeqType, pSeqTypeRef)
+ typelib_IndirectTypeDescription * pSeqIndDec= (typelib_IndirectTypeDescription*) pSeqType;
+// typelib_IndirectTypeDescription * pSeqDec= (typelib_IndirectTypeDescription*)rSeq.getValueTypeDescriptionRef();
+
+ typelib_TypeDescriptionReference * pSeqElementTypeRef= pSeqIndDec->pType;
+ TYPELIB_DANGER_RELEASE( pSeqType)
+
+
+
+ typelib_TypeDescription* pSeqElementDesc= NULL;
+ TYPELIB_DANGER_GET( &pSeqElementDesc, pSeqElementTypeRef)
+ sal_Int32 nElementSize= pSeqElementDesc->nSize;
+ n= punoSeq->nElements;
+
+ SAFEARRAYBOUND rgsabound[1];
+ rgsabound[0].lLbound = 0;
+ rgsabound[0].cElements = n;
+ VARIANT oleElement;
+ long safeI[1];
+
+ pArray = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
+
+ Any unoElement;
+ // sal_uInt8 * pSeqData= (sal_uInt8*) punoSeq->pElements;
+ sal_uInt8 * pSeqData= (sal_uInt8*) punoSeq->elements;
+
+ for (sal_uInt32 i = 0; i < n; i++)
+ {
+ unoElement.setValue( pSeqData + i * nElementSize, pSeqElementDesc);
+ VariantInit(&oleElement);
+
+ if (anyToVariant(&oleElement, unoElement))
+ {
+ safeI[0] = i;
+ SafeArrayPutElement(pArray, safeI, &oleElement);
+ }
+
+ VariantClear(&oleElement);
+ }
+ TYPELIB_DANGER_RELEASE( pSeqElementDesc)
+ }
+
+ return pArray;
+}
+
+template<class T>
+IDispatch* UnoConversionUtilities<T>::createUnoObjectWrapper(const Any& rObj)
+{
+ OGuard guard(globalWrapperMutex);
+
+ IDispatch* pDispatch = NULL;
+ Reference<XInvocation> xInv;
+ Reference<XInterface> xInt;
+
+
+ // If the UNO object is already a wrapped COM object then
+ // of course the original IDispatch is returned.
+ if( rObj.getValueTypeClass() == TypeClass_INTERFACE)
+ {
+ if( rObj >>= xInt)
+ {
+ // can the object provide a Wrapper on its own
+ if( ! convertSelfToIDispatch( xInt, &pDispatch) )
+ {
+ // figure out if the UNO object is a Wrapper through global maps
+ typedef hash_map<sal_uInt32,sal_uInt32>::iterator _IT;
+ _IT it= AdapterToWrapperMap.find( (sal_uInt32) xInt.get());
+ if( it != AdapterToWrapperMap.end() )
+ {
+ Reference<XInterface> xIntWrapper( (XInterface*)it->second);
+ convertSelfToIDispatch( xIntWrapper, &pDispatch); // should always work on the objects in the map
+ }
+ else
+ xInv= Reference<XInvocation>( xInt, UNO_QUERY);
+ }
+ }
+ }
+
+ if (! pDispatch && !xInv.is())
+ {
+ // static Reference<XSingleServiceFactory> xInvFactory(o2u_getMultiServiceFactory()->createInstance(INVOCATION_SERVICE),UNO_QUERY);
+ Reference<XSingleServiceFactory> xInvFactory= getInvocationFactory();
+ if( xInvFactory.is())
+ {
+ Sequence<Any> params(1);
+ params.getArray()[0] = rObj;
+ Reference<XInterface> xInt = xInvFactory->createInstanceWithArguments(params);
+ xInv= Reference<XInvocation>(xInt, UNO_QUERY);
+ }
+ }
+
+ OSL_ENSURE(xInv.is() || pDispatch, "no invocation interface");
+ if( !pDispatch)
+ {
+ Reference< XInterface > xIntWrapper= createUnoWrapperInstance();
+ if( xIntWrapper.is())
+ {
+ Reference< XInitialization > xInitWrapper( xIntWrapper, UNO_QUERY);
+ if( xInitWrapper.is() )
+ {
+ VARTYPE vartype= getVarType( rObj);
+
+ if( xInt.is())
+ {
+ Any params[3];
+ params[0] <<= xInv;
+ params[1] <<= xInt;
+ params[2] <<= vartype;
+ xInitWrapper->initialize( Sequence<Any>(params, 3));
+ }
+ else
+ {
+ Any params[2];
+ params[0] <<= xInv;
+ params[1] <<= vartype;
+ xInitWrapper->initialize( Sequence<Any>(params, 2));
+ }
+
+ // Get the IDispatch
+ // A wrapper is expected to implement XBridgeSupplier in order to
+ // convert itself to an IDispatch:
+ IDispatch* pDisp;
+ if( convertSelfToIDispatch( xIntWrapper, &pDisp))
+ pDispatch= pDisp;
+ }
+ }
+ }
+
+ return pDispatch;
+}
+
+template<class T>
+sal_Bool UnoConversionUtilities<T>::variantToAny( const VARIANT* pVariant, Any& rAny,
+ sal_Bool bReduceValueRange /* = sal_True */)
+{
+ sal_Bool ret = sal_False;
+ VARTYPE oleTypeFlags = V_VT(pVariant);
+
+ if ((oleTypeFlags & VT_BYREF) != 0)
+ {
+ oleTypeFlags ^= VT_BYREF;
+
+ if ((oleTypeFlags & VT_ARRAY) != 0)
+ {
+ oleTypeFlags ^= VT_ARRAY;
+
+ Sequence<Any> unoSeq = createOleArrayWrapper(*V_ARRAYREF(pVariant), oleTypeFlags);
+ rAny.setValue( &unoSeq, getCppuType( &unoSeq));
+
+ ret = sal_True;
+ }
+ else
+ {
+ switch (oleTypeFlags) // conversion by reference
+ {
+ case VT_EMPTY: // jo
+ rAny.setValue(NULL, Type());
+ ret= sal_True;
+ break;
+ case VT_NULL:
+ rAny.setValue(NULL, Type());
+ ret = sal_True;
+ break;
+ case VT_I2:
+ rAny.setValue(V_I2REF(pVariant), getCppuType((sal_Int16*)0));
+ ret = sal_True;
+ break;
+ case VT_I4:
+ rAny.setValue(V_I4REF(pVariant), getCppuType((sal_Int32*)0));
+ ret = sal_True;
+ break;
+ case VT_R4:
+ rAny.setValue(V_R4REF(pVariant), getCppuType( (float*)0));
+ ret = sal_True;
+ break;
+ case VT_R8:
+ rAny.setValue(V_R8REF(pVariant), getCppuType( (double*)0));
+ ret = sal_True;
+ break;
+ case VT_CY:
+ // rAny.setHyper(*V_CYREF(pVariant));
+ // ret = sal_True;
+ break;
+ case VT_DATE:
+ break;
+ case VT_BSTR:
+ {
+ OUString s(*V_BSTRREF(pVariant));
+ rAny.setValue( &s, getCppuType( &s));
+ ret = sal_True;
+ break;
+ }
+ case VT_DISPATCH:
+ {
+ IUnknown* pUnknown = NULL;
+
+ if ((*V_DISPATCHREF(pVariant)) != NULL)
+ {
+ (*V_DISPATCHREF(pVariant))->QueryInterface(IID_IUnknown, (void**)&pUnknown);
+ }
+
+ rAny = createOleObjectWrapper(pUnknown);
+
+ if (pUnknown != NULL)
+ {
+ pUnknown->Release();
+ }
+
+ ret = sal_True;
+ break;
+ }
+ case VT_ERROR:
+ rAny.setValue(V_ERRORREF(pVariant), getCppuType( (sal_uInt32*)0));
+ ret = sal_True;
+ break;
+ case VT_BOOL:
+ {
+ sal_Bool b= (*V_BOOLREF(pVariant)) == VARIANT_TRUE;
+ rAny.setValue( &b, getCppuType( &b));
+ ret = sal_True;
+ break;
+ }
+ case VT_VARIANT:
+ {
+ if (V_VT(V_VARIANTREF(pVariant)) == VT_EMPTY)
+ {
+ rAny.setValue(NULL, Type());
+ ret = sal_True;
+ }
+ else
+ {
+ ret = variantToAny(V_VARIANTREF(pVariant), rAny);
+ }
+ }
+ break;
+ case VT_UNKNOWN:
+ rAny = createOleObjectWrapper(*V_UNKNOWNREF(pVariant));
+ ret = sal_True;
+ break;
+ case VT_I1:
+ rAny.setValue(V_I1REF(pVariant), getCppuType( (sal_Int8*)0));
+ ret = sal_True;
+ break;
+ case VT_UI1:
+ // convert to sal_Int8 because there is no Type for sal_uInt8
+ rAny.setValue(V_UI1REF(pVariant), getCppuType( (sal_Int8*)0));
+ ret = sal_True;
+ break;
+ case VT_UI2:
+ rAny.setValue(V_UI2REF(pVariant), getCppuType( (sal_uInt16*)0));
+ ret = sal_True;
+ break;
+ case VT_UI4:
+ rAny.setValue(V_UI4REF(pVariant), getCppuType( (sal_uInt32*)0));
+ ret = sal_True;
+ break;
+ case VT_INT:
+ rAny.setValue(V_INTREF(pVariant), getCppuType( (sal_Int32*)0));
+ ret = sal_True;
+ break;
+ case VT_UINT:
+ rAny.setValue(V_UINTREF(pVariant), getCppuType((sal_uInt32*)0));
+ ret = sal_True;
+ break;
+ case VT_VOID:
+ rAny.setValue( NULL, Type());
+ ret = sal_True;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ if ((oleTypeFlags & VT_ARRAY) > 0)
+ {
+ oleTypeFlags ^= VT_ARRAY;
+
+ Sequence<Any> unoSeq = createOleArrayWrapper(V_ARRAY(pVariant), oleTypeFlags);
+ rAny.setValue( &unoSeq, getCppuType( &unoSeq));
+
+ ret = sal_True;
+ }
+ else
+ {
+ switch (oleTypeFlags) // conversion by value
+ {
+ case VT_EMPTY: // jo
+ rAny.setValue(NULL, Type());
+ ret= sal_True;
+ break;
+
+ case VT_NULL:
+ rAny.setValue(NULL, Type());
+ ret = sal_True;
+ break;
+ case VT_I2:
+ rAny.setValue(&V_I2(pVariant), getCppuType( (sal_Int16*)0));
+ ret = sal_True;
+ break;
+ case VT_I4:
+ rAny.setValue(&V_I4(pVariant), getCppuType( (sal_Int32*)0));
+ // necessary for use in JavaScript ( see "reduceRange")
+ if( bReduceValueRange)
+ reduceRange( rAny);
+ ret = sal_True;
+ break;
+ case VT_R4:
+ rAny.setValue(&V_R4(pVariant), getCppuType( (float*)0));
+ ret = sal_True;
+ break;
+ case VT_R8:
+ rAny.setValue(&V_R8(pVariant), getCppuType( (double*)0));
+ ret = sal_True;
+ break;
+ case VT_CY:
+ // rAny.setHyper(V_CY(pVariant));
+ // ret = sal_True;
+ break;
+ case VT_DATE:
+ break;
+ case VT_BSTR:
+ {
+ OUString b( V_BSTR(pVariant));
+ rAny.setValue( &b, getCppuType( &b));
+ ret = sal_True;
+ break;
+ }
+ case VT_DISPATCH:
+ {
+ IUnknown* pUnknown = NULL;
+
+ if (V_DISPATCH(pVariant) != NULL)
+ {
+ V_DISPATCH(pVariant)->QueryInterface(IID_IUnknown, (void**)&pUnknown);
+ }
+
+ rAny = createOleObjectWrapper(pUnknown);
+
+ if (pUnknown != NULL)
+ {
+ pUnknown->Release();
+ }
+
+ ret = sal_True;
+
+ break;
+ }
+ case VT_ERROR:
+ rAny.setValue(&V_ERROR(pVariant), getCppuType( (sal_uInt32*)0));
+ ret = sal_True;
+ break;
+ case VT_BOOL:
+ {
+ sal_Bool b= V_BOOL(pVariant) == VARIANT_TRUE;
+ rAny.setValue( &b, getCppuType( &b));
+ ret = sal_True;
+ break;
+ }
+ case VT_UNKNOWN:
+ rAny = createOleObjectWrapper(V_UNKNOWN(pVariant));
+ ret = sal_True;
+ break;
+ case VT_I1:
+ rAny.setValue(&V_I1(pVariant), getCppuType((sal_Int8*)0));
+ ret = sal_True;
+ break;
+ case VT_UI1: // there is no unsigned char in UNO
+ rAny.setValue((char*)&V_UI1(pVariant), getCppuType( (sal_Int8*)0));
+ ret = sal_True;
+ break;
+ case VT_UI2:
+ rAny.setValue(&V_UI2(pVariant), getCppuType( (sal_uInt16*)0));
+ ret = sal_True;
+ break;
+ case VT_UI4:
+ rAny.setValue(&V_UI4(pVariant), getCppuType( (sal_uInt32*)0));
+ ret = sal_True;
+ break;
+ case VT_INT:
+ rAny.setValue(&V_INT(pVariant), getCppuType( (sal_Int32*)0));
+ ret = sal_True;
+ break;
+ case VT_UINT:
+ rAny.setValue(&V_UINT(pVariant), getCppuType( (sal_uInt32*)0));
+ ret = sal_True;
+ break;
+ case VT_VOID:
+ rAny.setValue( NULL, Type());
+ ret = sal_True;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+template<class T>
+Any UnoConversionUtilities<T>::createOleObjectWrapper(IUnknown* pUnknown)
+{
+ Any ret;
+
+ Reference<XInterface> xInt;
+
+ if (pUnknown == NULL)
+ {
+ ret <<= xInt;
+ }
+ else
+ {
+ CComQIPtr<IUnoObjectWrapper> spUno( pUnknown);
+ if( spUno)
+ {
+ Reference<XInterface> xInt;
+ spUno->getOriginalUnoObject( &xInt);
+ ret <<= xInt;
+ }
+ else
+ {
+ Reference<XInterface> xInt= createComWrapperInstance();
+ if( xInt.is())
+ {
+ Reference<XInitialization> xInit( xInt, UNO_QUERY);
+ if( xInit.is())
+ {
+ Any param;
+ param <<= (sal_uInt32) pUnknown;
+ xInit->initialize( Sequence<Any>(&param, 1));
+ }
+ }
+ ret<<= Reference<XInvocation>( xInt, UNO_QUERY);
+ }
+ }
+
+ return ret;
+}
+
+// if the object supports only one type then it does not have to implement the property
+// SUPPORTER_INTERFACES_PROP ( define)
+template<class T>
+Any UnoConversionUtilities<T>::createOleObjectWrapper(IUnknown* pUnknown, const Type& aType)
+{
+ OGuard guard( globalWrapperMutex);
+ Any ret;
+
+ Reference<XInterface> xInt;
+
+ if (pUnknown == NULL)
+ {
+ if( aType.getTypeClass() == TypeClass_INTERFACE)
+ ret.setValue( &xInt, aType);
+ else if( aType.getTypeClass() == TypeClass_STRUCT)
+ ret.setValue( NULL, aType);
+ }
+ else
+ {
+ CComQIPtr<IUnoObjectWrapper> spUno( pUnknown);
+ if( spUno)
+ {
+ if( aType.getTypeClass() == TypeClass_INTERFACE)
+ {
+ Reference<XInterface> xInt;
+ spUno->getOriginalUnoObject( &xInt);
+ if( xInt.is())
+ {
+ ret= xInt->queryInterface( aType);
+ }
+
+ }
+ else if( aType.getTypeClass() == TypeClass_STRUCT)
+ {
+ Any any;
+ if( SUCCEEDED( spUno->getOriginalUnoStruct(&any)))
+ ret= any;
+ }
+ }
+ else
+ {
+ Reference<XInterface> xInt= createComWrapperInstance();
+ if( xInt.is())
+ {
+// Reference<XInitialization> xInit( xInt, UNO_QUERY);
+// if( xInit.is())
+// {
+// Any params[2];
+// params[0] <<= (sal_uInt32) pUnknown;
+// params[1] <<= aType;
+// xInit->initialize( Sequence<Any>( params, 2));
+// }
+
+ Reference<XInvocation> xInv( xInt, UNO_QUERY);
+
+ Sequence<Type> seqTypes;
+
+ // create the actual Interface of type "Type"
+ // If the type is XInvocation than we use the COM wrapper directly.
+ if( aType.getTypeName() == OUString::createFromAscii("com.sun.star.script.XInvocation"))
+ {
+ ret <<= xInv;
+ }
+ else
+ {
+ Reference< XInterface> xIntAdapterFac;
+ if( m_xMultiServiceFactory.is())
+ {
+ xIntAdapterFac= m_xMultiServiceFactory->createInstance( INTERFACE_ADAPTER_FACTORY);
+
+ }
+ else
+ {
+ xIntAdapterFac= o2u_getMultiServiceFactory()->createInstance( INTERFACE_ADAPTER_FACTORY);
+ }
+
+ // We create an adapter object that does not only implement the required type but also
+ // all types that the COM object pretends to implement. An COM object must therefore
+ // support the property "_implementedInterfaces". If it does not an Adapter of param
+ // type
+// Sequence<Type> seqTypes;
+ CComDispatchDriver disp( pUnknown);
+ if( disp)
+ {
+ CComVariant var;
+ if( SUCCEEDED( disp.GetPropertyByName( SUPPORTED_INTERFACES_PROP, &var)))
+ {// we exspect an array( SafeArray or IDispatch) of Strings.
+ Any anyNames;
+ if( variantToAny2( &var, anyNames, getCppuType( (Sequence<Any>*) 0)))
+ {
+ Sequence<Any> seqAny;
+ if( anyNames >>= seqAny)
+ {
+ seqTypes.realloc( seqAny.getLength());
+ for( sal_Int32 i=0; i < seqAny.getLength(); i++)
+ {
+ OUString typeName;
+ seqAny[i] >>= typeName;
+ seqTypes[i]= Type( TypeClass_INTERFACE, typeName);
+ }
+ }
+ }
+ }
+ }
+
+ Reference<XInterface> xIntAdapted;
+ if( seqTypes.getLength() >0)
+ {
+ Reference< XInvocationAdapterFactory2> xAdapterFac( xIntAdapterFac, UNO_QUERY);
+ if( xAdapterFac.is())
+ xIntAdapted= xAdapterFac->createAdapter( xInv, seqTypes);
+ }
+ else
+ {
+ Reference<XInvocationAdapterFactory> xAdapterFac( xIntAdapterFac, UNO_QUERY);
+ if( xAdapterFac.is())
+ xIntAdapted= xAdapterFac->createAdapter( xInv, aType);
+ }
+ if( xIntAdapted.is())
+ {
+ ret= xIntAdapted->queryInterface( aType);
+ // Put the pointer to the wrapper object and the interface pointer of the adapted interface
+ // in a global map. Thus we can determine in a call to createUnoObjectWrapper whether the UNO
+ // object is a wrapped COM object. In that case we extract the original COM object rather than
+ // creating a wrapper around the UNO object.
+ typedef hash_map<sal_uInt32,sal_uInt32>::value_type VALUE;
+ AdapterToWrapperMap.insert( VALUE( (sal_uInt32) xIntAdapted.get(), (sal_uInt32) xInt.get()));
+ WrapperToAdapterMap.insert( VALUE( (sal_uInt32) xInt.get(), (sal_uInt32) xIntAdapted.get()));
+
+ }
+ }
+
+ // initialize the COM wrapper ( IUnknown + Type s)
+ Reference<XInitialization> xInit( xInt, UNO_QUERY);
+ if( xInit.is())
+ {
+ Any params[2];
+ params[0] <<= (sal_uInt32) pUnknown;
+ if( ! seqTypes.getLength() )
+ {
+ params[1] <<= Sequence<Type>( &aType, 1);
+ }
+ else
+ {
+ params[1] <<= seqTypes;
+ }
+
+ xInit->initialize( Sequence<Any>( params, 2));
+ }
+
+ }
+ }
+ }
+
+ return ret;
+}
+// "convertValueObject" converts a JScriptValue object contained in "var" into
+// an any. The type contained in the any is stipulated by a "type value" thas
+// was set within the JScript script on the value object ( see JScriptValue).
+template<class T>
+sal_Bool UnoConversionUtilities<T>::convertValueObject( const VARIANTARG *var, Any& any, sal_Bool& bHandled)
+{
+ sal_Bool ret= sal_True;
+ bHandled= sal_False;
+ HRESULT hr= S_OK;
+
+ if( var->vt == VT_DISPATCH)
+ {
+ CComPtr <IJScriptValueObject> spValue;
+ VARIANT_BOOL varBool;
+ CComBSTR bstrType;
+ CComVariant varValue;
+
+ if( SUCCEEDED( var->pdispVal->QueryInterface( __uuidof( IJScriptValueObject),
+ reinterpret_cast<void**> (&spValue))))
+ {
+ // Out Parameter --------------------------------------------------
+ if( SUCCEEDED( hr= spValue->IsOutParam( &varBool) )
+ && varBool == VARIANT_TRUE )
+ {// no conversion necessary
+ bHandled= sal_True;
+ }
+ // In / Out Parameter ---------------------------------------------
+ else if( SUCCEEDED( hr= spValue->IsInOutParam( &varBool) )
+ && varBool == VARIANT_TRUE)
+ {
+ if( SUCCEEDED( hr= spValue->GetValue( &bstrType, &varValue)))
+ {
+ if( variantToAny2( &varValue, any, getType( bstrType)))
+ {
+ bHandled= sal_True;
+ }
+ } //IJScriptValueObject::GetValue()
+ } // in/out parameter
+ // In Parameter
+ else
+ {
+ if( SUCCEEDED( hr= spValue->GetValue( &bstrType, &varValue)))
+ {
+ if( variantToAny2(&varValue, any, getType( bstrType)))
+ {
+ bHandled= sal_True;
+ }
+ }
+ }
+
+ }// if IJScriptValueObject
+ }// if IDispatch
+ if( FAILED( hr) )
+ ret= sal_False;
+ return ret;
+}
+template<class T>
+sal_Bool UnoConversionUtilities<T>::dispatchExObject2Sequence( const VARIANTARG* pvar, Any& anySeq, const Type& type)
+{
+ sal_Bool retVal= TRUE;
+
+ if( pvar->vt != VT_DISPATCH) return FALSE;
+ IDispatchEx* pdispEx;
+ HRESULT hr;
+ if( FAILED( hr= pvar->pdispVal->QueryInterface( IID_IDispatchEx,
+ reinterpret_cast<void**>( &pdispEx)))) return FALSE;
+
+ DISPID dispid;
+ OUString sindex;
+ DISPPARAMS param= {0,0,0,0};
+ VARIANT result;
+ VariantInit( & result);
+ OLECHAR* sLength= L"length";
+
+ // Get the length of the array. Can also be obtained throu GetNextDispID. The
+ // method only returns DISPIDs of the array data. Their names are like "0", "1" etc.
+ if( FAILED( hr= pdispEx->GetIDsOfNames(IID_NULL, &sLength , 1, LOCALE_USER_DEFAULT, &dispid)))
+ return FALSE;
+ if( FAILED( hr= pdispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
+ &param, &result, NULL, NULL)))
+ return FALSE;
+ if( FAILED( VariantChangeType( &result, &result, 0, VT_I4)))
+ return FALSE;
+ long length= result.lVal;
+ VariantClear( &result);
+
+ // get a few basic facts about the sequence, and reallocate:
+ // create the Sequences
+ // get the size of the elements
+ typelib_TypeDescription *pDesc= NULL;
+ type.getDescription( &pDesc);
+
+ typelib_IndirectTypeDescription *pSeqDesc= reinterpret_cast<typelib_IndirectTypeDescription*>(pDesc);
+ typelib_TypeDescriptionReference *pSeqElemDescRef= pSeqDesc->pType; // type of the Sequence' elements
+ Type elemType( pSeqElemDescRef);
+ _typelib_TypeDescription* pSeqElemDesc=NULL;
+ TYPELIB_DANGER_GET( &pSeqElemDesc, pSeqElemDescRef)
+ sal_uInt32 nelementSize= pSeqElemDesc->nSize;
+ TYPELIB_DANGER_RELEASE( pSeqElemDesc)
+
+ uno_Sequence *p_uno_Seq;
+ uno_sequence_construct( &p_uno_Seq, pDesc, NULL, length, cpp_acquire);
+
+ typelib_TypeClass typeElement= pSeqDesc->pType->eTypeClass;
+ char *pArray= p_uno_Seq->elements;
+
+ // Get All properties in the object, convert their values to the expected type and
+ // put them into the passed in sequence
+ for( sal_Int32 i= 0; i< length; i++)
+ {
+ OLECHAR* sindex = (sal_Unicode*)(const sal_Unicode*)OUString::valueOf( i);
+
+ if( FAILED( hr= pdispEx->GetIDsOfNames(IID_NULL, &sindex , 1, LOCALE_USER_DEFAULT, &dispid)))
+ {
+ retVal= FALSE;
+ break;
+ }
+ if( FAILED( hr= pdispEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
+ &param, &result, NULL, NULL)))
+ {
+ retVal= FALSE;
+ break;
+ }
+
+ // If the result is VT_DISPATCH than the Sequence's element type could be Sequence
+ // Look that up in the CoreReflection to make clear.
+ // That requires a recursiv conversion
+ Any any;
+ // Destination address within the out-Sequence "anySeq" where to copy the next converted element
+ void* pDest= (void*)(pArray + (i * nelementSize));
+
+ if( result.vt & VT_DISPATCH && typeElement == typelib_TypeClass_SEQUENCE)
+ {
+ if( variantToAny2( &result, any, elemType, sal_False) )
+ {
+ // copy the converted VARIANT, that is a Sequence to the Sequence
+ uno_Sequence * p_unoSeq= *(uno_Sequence**)any.getValue();
+ // just copy the pointer of the uno_Sequence
+ // nelementSize should be 4 !!!!
+ memcpy( pDest, &p_unoSeq, nelementSize);
+ osl_incrementInterlockedCount( &p_unoSeq->nRefCount);
+ }
+ else
+ {
+ retVal= FALSE;
+ break;
+ }
+ }
+ else // Element type is no Sequence -> do one conversion
+ {
+ if( variantToAny2( &result, any, elemType, sal_False) )
+ {
+
+ if( typeElement == typelib_TypeClass_ANY)
+ {
+ // copy the converted VARIANT to the Sequence
+ uno_type_assignData( pDest, pSeqElemDescRef , &any, pSeqElemDescRef,cpp_queryInterface,
+ cpp_acquire, cpp_release);
+ }
+ else
+ {
+ // type after conversion must be the element type of the sequence
+ OSL_ENSURE( (any.getValueTypeClass() == typeElement), "wrong conversion");
+ uno_type_assignData( pDest, pSeqElemDescRef,const_cast<void*>( any.getValue()), any.getValueTypeRef(),
+ cpp_queryInterface, cpp_acquire, cpp_release);
+ }
+ } // if
+ else
+ {
+ retVal= FALSE;
+ break;
+ }
+ } // else
+ VariantClear(&result);
+ if( retVal == FALSE)
+ break;
+ } // for
+ VariantClear(&result);
+ uno_Sequence **pps= &p_uno_Seq;
+ anySeq.setValue( &p_uno_Seq, pDesc);
+ uno_destructData( &p_uno_Seq, pDesc, cpp_release);
+ typelib_typedescription_release( pDesc);
+ return retVal;
+}
+template<class T>
+Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* pArray, unsigned int dimCount, unsigned int actDim, long* index, VARTYPE type)
+{
+ HRESULT hr= S_OK;
+ long lBound;
+ long uBound;
+ long nCountElements;
+
+ SafeArrayGetLBound(pArray, actDim + 1, &lBound);
+ SafeArrayGetUBound(pArray, actDim + 1, &uBound);
+ nCountElements= uBound - lBound +1;
+
+
+ Sequence<Any> anySeq(nCountElements);
+ Any* pUnoArray = anySeq.getArray();
+
+ for (index[actDim] = lBound; index[actDim] < nCountElements; index[actDim]++)
+ {
+ if (actDim < (dimCount - 1))
+ {
+ Sequence<Any> element = createOleArrayWrapperOfDim(pArray, dimCount, actDim + 1, index, type);
+
+ pUnoArray[index[actDim] - lBound].setValue(&element, getCppuType(&element));
+ }
+ else
+ {
+ VARIANT variant;
+
+ VariantInit(&variant);
+
+ V_VT(&variant) = type;
+
+ switch (type)
+ {
+ case VT_I2:
+ SafeArrayGetElement(pArray, index, &V_I2(&variant));
+ break;
+ case VT_I4:
+ SafeArrayGetElement(pArray, index, &V_I4(&variant));
+ break;
+ case VT_R4:
+ SafeArrayGetElement(pArray, index, &V_R4(&variant));
+ break;
+ case VT_R8:
+ SafeArrayGetElement(pArray, index, &V_R8(&variant));
+ break;
+ case VT_CY:
+ SafeArrayGetElement(pArray, index, &V_CY(&variant));
+ break;
+ case VT_DATE:
+ SafeArrayGetElement(pArray, index, &V_DATE(&variant));
+ break;
+ case VT_BSTR:
+ hr= SafeArrayGetElement(pArray, index, &V_BSTR(&variant));
+ break;
+ case VT_DISPATCH:
+ SafeArrayGetElement(pArray, index, &V_DISPATCH(&variant));
+ break;
+ case VT_ERROR:
+ SafeArrayGetElement(pArray, index, &V_ERROR(&variant));
+ break;
+ case VT_BOOL:
+ SafeArrayGetElement(pArray, index, &V_BOOL(&variant));
+ break;
+ case VT_VARIANT:
+ SafeArrayGetElement(pArray, index, &variant);
+ break;
+ case VT_UNKNOWN:
+ SafeArrayGetElement(pArray, index, &V_UNKNOWN(&variant));
+ break;
+ case VT_I1:
+ SafeArrayGetElement(pArray, index, &V_I1(&variant));
+ break;
+ case VT_UI1:
+ SafeArrayGetElement(pArray, index, &V_UI1(&variant));
+ break;
+ case VT_UI2:
+ SafeArrayGetElement(pArray, index, &V_UI2(&variant));
+ break;
+ case VT_UI4:
+ SafeArrayGetElement(pArray, index, &V_UI4(&variant));
+ break;
+ default:
+ break;
+ }
+
+ variantToAny(&variant, pUnoArray[index[actDim] - lBound], sal_False);
+
+ VariantClear(&variant);
+ }
+ }
+
+ return anySeq;
+}
+template<class T>
+Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapper(SAFEARRAY* pArray, VARTYPE type)
+{
+ sal_uInt32 dim = SafeArrayGetDim(pArray);
+
+ Sequence<Any> ret;
+
+ if (dim > 0)
+ {
+ long * index = new long[dim];
+
+ for (unsigned int i = 0; i < dim; i++)
+ {
+ index[i] = 0;
+ }
+
+ ret = createOleArrayWrapperOfDim(pArray, dim, 0, index, type);
+
+ delete[] index;
+ }
+
+ return ret;
+}
+
+// If an VARIANT has the type VT_DISPATCH it can either be an JScript Array
+// or some other object. This function finds out if it is such an array or
+// not. Currently there's no way to make sure it's an array
+// so we assume that when the object has a property "0" then it is an Array.
+// An JScript has property like "0", "1", "2" etc. which represent the
+// value at the corresponding index of the array
+template<class T>
+sal_Bool UnoConversionUtilities<T>::isJScriptArray(const VARIANT* rvar)
+{
+ OSL_ENSURE( rvar->vt == VT_DISPATCH, "param is not a VT_DISPATCH");
+ HRESULT hr;
+ OLECHAR* sindex= L"0";
+ DISPID id;
+ hr= rvar->pdispVal->GetIDsOfNames( IID_NULL, &sindex, 1,
+ LOCALE_USER_DEFAULT, &id);
+
+ if( SUCCEEDED ( hr) )
+ return sal_True;
+ return sal_False;
+}
+
+template<class T>
+VARTYPE UnoConversionUtilities<T>::mapTypeClassToVartype( TypeClass type)
+{
+ VARTYPE ret;
+ switch( type)
+ {
+ case TypeClass_INTERFACE: ret= VT_DISPATCH;
+ break;
+ case TypeClass_STRUCT: ret= VT_DISPATCH;
+ break;
+ case TypeClass_ENUM: ret= VT_I4;
+ break;
+ case TypeClass_SEQUENCE: ret= VT_ARRAY;
+ break;
+ case TypeClass_ANY: ret= VT_VARIANT;
+ break;
+ case TypeClass_BOOLEAN: ret= VT_BOOL;
+ break;
+ case TypeClass_CHAR: ret= VT_UI2;
+ break;
+ case TypeClass_STRING: ret= VT_BSTR;
+ break;
+ case TypeClass_FLOAT: ret= VT_R4;
+ break;
+ case TypeClass_DOUBLE: ret= VT_R8;
+ break;
+ case TypeClass_BYTE: ret= VT_I1;
+ break;
+ case TypeClass_SHORT: ret= VT_I2;
+ break;
+ case TypeClass_LONG: ret= VT_I4;
+ break;
+ case TypeClass_UNSIGNED_SHORT: ret= VT_UI2;
+ break;
+ case TypeClass_UNSIGNED_LONG: ret= VT_UI4;
+ break;
+ default:
+ ret= VT_EMPTY;
+ }
+ return ret;
+}
+
+
+// This function tries to the change the type of a value (contained in the Any)
+// to the smallest possible that can hold the value. This is actually done only
+// for types of VT_I4 (see o2u_variantToAny). The reason is the following:
+// JavaScript passes integer values always as VT_I4. If there is a parameter or
+// property of type any then the bridge converts the any's content according
+// to "o2u_variantToAny". Because the VARTYPE is VT_I4 the value would be converted
+// to TypeClass_LONG. Say the method XPropertySet::setPropertyValue( string name, any value)
+// would be called on an object and the property actually is of TypeClass_SHORT.
+// After conversion of the VARIANT parameter the Any would contain type
+// TypeClass_LONG. Because the corereflection does not cast from long to short
+// the "setPropertValue" would fail as the value has not the right type.
+
+// The corereflection does convert small integer types to bigger types.
+// Therefore we can reduce the type if possible and avoid the above mentioned
+// problem.
+
+// The function is not used when elements are to be converted for Sequences.
+
+#ifndef _REDUCE_RANGE
+#define _REDUCE_RANGE
+inline void reduceRange( Any& any)
+{
+ OSL_ASSERT( any.getValueTypeClass() == TypeClass_LONG);
+
+ sal_Int32 value= *(sal_Int32*)any.getValue();
+ if( value <= 0x7f && value >= -0x80)
+ {// -128 bis 127
+ sal_Int8 charVal= static_cast<sal_Int8>( value);
+ any.setValue( &charVal, getCppuType( (sal_Int8*)0));
+ }
+ else if( value <= 0x7fff && value >= -0x8000)
+ {// -32768 bis 32767
+ sal_Int16 shortVal= static_cast<sal_Int16>( value);
+ any.setValue( &shortVal, getCppuType( (sal_Int16*)0));
+ }
+}
+#endif
+} // end namespace
+#endif
+