diff options
-rw-r--r-- | extensions/source/ole/makefile.mk | 8 | ||||
-rw-r--r-- | extensions/source/ole/ole2uno.cxx | 25 | ||||
-rw-r--r-- | extensions/source/ole/ole2uno.hxx | 14 | ||||
-rw-r--r-- | extensions/source/ole/oleobjw.cxx | 30 | ||||
-rw-r--r-- | extensions/source/ole/servprov.cxx | 17 | ||||
-rw-r--r-- | extensions/source/ole/unoconversionutilities.hxx | 436 | ||||
-rw-r--r-- | extensions/source/ole/unoobjw.cxx | 175 | ||||
-rw-r--r-- | extensions/source/ole/unoobjw.hxx | 8 |
8 files changed, 403 insertions, 310 deletions
diff --git a/extensions/source/ole/makefile.mk b/extensions/source/ole/makefile.mk index 0aa96d8127fa..c83d92daff8e 100644 --- a/extensions/source/ole/makefile.mk +++ b/extensions/source/ole/makefile.mk @@ -2,9 +2,9 @@ # # $RCSfile: makefile.mk,v $ # -# $Revision: 1.5 $ +# $Revision: 1.6 $ # -# last change: $Author: kz $ $Date: 2001-10-23 15:35:23 $ +# last change: $Author: jl $ $Date: 2002-06-05 13:21:38 $ # # The Contents of this file are made available subject to the terms of # either of the following licenses @@ -151,7 +151,9 @@ SLOFILES= \ $(SLO)$/oleobjw.obj \ $(SLO)$/olethread.obj \ $(SLO)$/oledll.obj \ - $(SLO)$/jscriptclasses.obj + $(SLO)$/jscriptclasses.obj \ + $(SLO)$/ole2uno.obj + SHL1TARGET=$(TARGET) diff --git a/extensions/source/ole/ole2uno.cxx b/extensions/source/ole/ole2uno.cxx new file mode 100644 index 000000000000..7f7ebda9b196 --- /dev/null +++ b/extensions/source/ole/ole2uno.cxx @@ -0,0 +1,25 @@ + +#include <osl/mutex.hxx> +#include "ole2uno.hxx" + +using namespace osl; +namespace ole_adapter +{ + +Mutex* getBridgeMutex() +{ + static Mutex* pMutex= NULL; + + if( ! pMutex) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pMutex) + { + static Mutex aMutex; + pMutex= &aMutex; + } + } + return pMutex; +} + +} diff --git a/extensions/source/ole/ole2uno.hxx b/extensions/source/ole/ole2uno.hxx index 2656278228e2..603ef955e14d 100644 --- a/extensions/source/ole/ole2uno.hxx +++ b/extensions/source/ole/ole2uno.hxx @@ -2,9 +2,9 @@ * * $RCSfile: ole2uno.hxx,v $ * - * $Revision: 1.3 $ + * $Revision: 1.4 $ * - * last change: $Author: jl $ $Date: 2001-06-27 10:56:03 $ + * last change: $Author: jl $ $Date: 2002-06-05 13:21:38 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -158,7 +158,7 @@ #endif #define UNO_2_OLE_EXCEPTIONCODE 1001 - +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) using namespace com::sun::star::uno; using namespace com::sun::star::lang; using namespace com::sun::star::script; @@ -173,13 +173,6 @@ using namespace std; namespace ole_adapter { -// function shared in this component -// Reference<XSingleServiceFactory> o2u_getConverterProvider2(const Reference<XMultiServiceFactory>& xMan, const Reference<XRegistryKey>& xKey); -// Reference<XSingleServiceFactory> o2u_getConverterProviderVar1(const Reference<XMultiServiceFactory>& xMan, const Reference<XRegistryKey>& xKey); -// Reference<XSingleServiceFactory> o2u_getClientProvider(const Reference<XMultiServiceFactory>& xMan, const Reference<XRegistryKey>& xKey); -// Reference<XSingleServiceFactory> o2u_getServerProvider(const Reference<XMultiServiceFactory>& xMan, const Reference<XRegistryKey>& xKey); - -//Reference<XMultiServiceFactory> o2u_getMultiServiceFactory(); Reference<XRegistryKey> o2u_getRegistryKey(); const VARTYPE getVarType( const Any& val); Type getType( BSTR type); @@ -244,6 +237,7 @@ sal_Bool convertSelfToIDispatch( T& unoInterface, IDispatch** ppDisp) } +Mutex* getBridgeMutex(); inline sal_Bool operator == (const Uik & uik1, const Uik & uik2) diff --git a/extensions/source/ole/oleobjw.cxx b/extensions/source/ole/oleobjw.cxx index a1d733768863..3528cee4b2ed 100644 --- a/extensions/source/ole/oleobjw.cxx +++ b/extensions/source/ole/oleobjw.cxx @@ -2,9 +2,9 @@ * * $RCSfile: oleobjw.cxx,v $ * - * $Revision: 1.8 $ + * $Revision: 1.9 $ * - * last change: $Author: jl $ $Date: 2001-12-03 18:28:51 $ + * last change: $Author: jl $ $Date: 2002-06-05 13:21:38 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -108,10 +108,6 @@ #ifndef _COM_SUN_STAR_BRIDGE_XBRIDGESUPPLIER_HPP_ #include <com/sun/star/bridge/XBridgeSupplier.hpp> #endif -//#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_ -//#include <com/sun/star/lang/XUnoTunnel.hpp> -//#endif - #ifndef _COM_SUN_STAR_BRIDGE_MODELDEPENDENT_HPP_ #include <com/sun/star/bridge/ModelDependent.hpp> #endif @@ -145,9 +141,6 @@ namespace ole_adapter { - - - // key: XInterface pointer created by Invocation Adapter Factory // value: XInterface pointer to the wrapper class. // Entries to the map are made within @@ -165,7 +158,7 @@ hash_map<sal_uInt32,sal_uInt32> AdapterToWrapperMap; // adapted interface which is then used to locate the entry in AdapterToWrapperMap. hash_map<sal_uInt32,sal_uInt32> WrapperToAdapterMap; - +//hash_map<sal_uInt32, WeakReference<XInterface> > ComPtrToWrapperMap; /***************************************************************************** class implementation IUnknownWrapper_Impl @@ -182,7 +175,7 @@ IUnknownWrapper_Impl::IUnknownWrapper_Impl( Reference<XMultiServiceFactory>& xFa IUnknownWrapper_Impl::~IUnknownWrapper_Impl() { - OGuard guard( globalWrapperMutex); + MutexGuard guard(getBridgeMutex()); acquire(); // make sure we don't delete us twice Reference<XInterface> xInt( static_cast<XWeak*>(this), UNO_QUERY); @@ -197,6 +190,10 @@ IUnknownWrapper_Impl::~IUnknownWrapper_Impl() WrapperToAdapterMap.erase( it); } +// IT_Com it_c= ComPtrToWrapperMap.find( (sal_uInt32) m_pUnknown); +// if(it_c != ComPtrToWrapperMap.end()) +// ComPtrToWrapperMap.erase(it_c); + o2u_attachCurrentThread(); m_pUnknown->Release(); @@ -292,9 +289,12 @@ Any SAL_CALL IUnknownWrapper_Impl::invoke( const OUString& aFunctionName, throw(IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException) { + + Any ret; + setCurrentInvokeCall( aFunctionName); - Any ret; + DispIdMap::iterator iter = getDispIdEntry(aFunctionName); @@ -318,9 +318,8 @@ Any SAL_CALL IUnknownWrapper_Impl::invoke( const OUString& aFunctionName, { OUString message= OUString(RTL_CONSTASCII_USTRINGPARAM( "OleBridge: coult not get DISPID for ")) + aFunctionName; - throw RuntimeException( message, Reference<XInterface>()); - -// throw IllegalArgumentException(); + //throw RuntimeException( message, Reference<XInterface>()); + throw InvocationTargetException(); } return ret; @@ -1514,5 +1513,6 @@ ITypeInfo* IUnknownWrapper_Impl::getTypeInfo() } return m_spTypeInfo; } + } // end namespace diff --git a/extensions/source/ole/servprov.cxx b/extensions/source/ole/servprov.cxx index d4c8553c99a4..750086a1aa22 100644 --- a/extensions/source/ole/servprov.cxx +++ b/extensions/source/ole/servprov.cxx @@ -2,9 +2,9 @@ * * $RCSfile: servprov.cxx,v $ * - * $Revision: 1.8 $ + * $Revision: 1.9 $ * - * last change: $Author: jl $ $Date: 2002-02-26 08:49:02 $ + * last change: $Author: jl $ $Date: 2002-06-05 13:21:38 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -58,7 +58,6 @@ * * ************************************************************************/ -#include <vos/mutex.hxx> #include "ole2uno.hxx" #include "unoconversionutilities.hxx" @@ -67,11 +66,18 @@ #include "oleobjw.hxx" #include <rtl/unload.h> +#include <tools/presys.h> +#define _WIN32_WINNT 0x0400 +#include <atlbase.h> +extern CComModule _Module; +#include <atlcom.h> +#include <tools/postsys.h> + + using namespace std; using namespace cppu; using namespace rtl; using namespace osl; -using namespace vos; using namespace com::sun::star::lang; using namespace com::sun::star::uno; using namespace com::sun::star::bridge; @@ -93,9 +99,6 @@ DEFINE_GUID(OID_ServiceManager, 0x82154420, 0xfbf, 0x11d4, 0x83, 0x13, 0x0, 0x50 extern rtl_StandardModuleCount globalModuleCount; - -extern OMutex globalWrapperMutex; - /***************************************************************************** class implementation ProviderOleWrapper_Impl diff --git a/extensions/source/ole/unoconversionutilities.hxx b/extensions/source/ole/unoconversionutilities.hxx index a5d03e35a1d1..ea3ca23ca8a0 100644 --- a/extensions/source/ole/unoconversionutilities.hxx +++ b/extensions/source/ole/unoconversionutilities.hxx @@ -2,9 +2,9 @@ * * $RCSfile: unoconversionutilities.hxx,v $ * - * $Revision: 1.10 $ + * $Revision: 1.11 $ * - * last change: $Author: jl $ $Date: 2001-12-03 18:28:51 $ + * last change: $Author: jl $ $Date: 2002-06-05 13:21:38 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -64,10 +64,12 @@ #include <com/sun/star/script/XInvocationAdapterFactory.hpp> #include <com/sun/star/script/XInvocationAdapterFactory2.hpp> -#include <vos/mutex.hxx> #include <typelib/typedescription.hxx> #include "ole2uno.hxx" +// Test ------------------- +#include <com/sun/star/lang/XEventListener.hpp> +// ------------------------ // classes for wrapping uno objects #define INTERFACE_OLE_WRAPPER_IMPL 1 #define UNO_OBJECT_WRAPPER_REMOTE_OPT 2 @@ -87,15 +89,31 @@ using namespace com::sun::star::script; using namespace com::sun::star::beans; using namespace com::sun::star::uno; -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 +typedef hash_map<sal_uInt32, sal_uInt32>::iterator IT_Wrap; +typedef hash_map<sal_uInt32, sal_uInt32>::iterator CIT_Wrap; +//Maps IUnknown pointers to a weak reference of the respective wrapper class (e.g. +// IUnknownWrapperImpl. It is the responsibility of the wrapper to remove the entry when +// it is being destroyed. +// Used to ensure that an Automation object is always mapped to the same UNO objects. +// extern hash_map<sal_uInt32, WeakReference<XInterface> > ComPtrToWrapperMap; +// typedef hash_map<sal_uInt32, WeakReference<XInterface> >::iterator IT_Com; +// typedef hash_map<sal_uInt32, WeakReference<XInterface> >::const_iterator CIT_Com; + +// Maps XInterface pointers to a weak reference of its wrapper class (i.e. +// InterfaceOleWrapper_Impl). It is the responsibility of the wrapper to remove the entry when +// it is being destroyed. It is used to ensure the identity of objects. That is, an UNO interface +// is mapped to IDispatch which is kept alive in the COM environment. If the same +// UNO interface is mapped again to COM then the IDispach of the first mapped instance +// must be returned. +extern hash_map<sal_uInt32, WeakReference<XInterface> > UnoObjToWrapperMap; +typedef hash_map<sal_uInt32, WeakReference<XInterface> >::iterator IT_Uno; +typedef hash_map<sal_uInt32, WeakReference<XInterface> >::const_iterator CIT_Uno; +// 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 ) @@ -123,15 +141,15 @@ public: 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); + Any createOleObjectWrapper(IUnknown* pUnknown, const Type& aType= Type()); 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); + Sequence<Any> createOleArrayWrapperOfDim(SAFEARRAY* pArray, unsigned int dimCount, unsigned int actDim, long* index, + VARTYPE type, const Type& unotype); + Sequence<Any> createOleArrayWrapper(SAFEARRAY* pArray, VARTYPE type, const Type& unotype= Type()); VARTYPE mapTypeClassToVartype( TypeClass type); @@ -154,6 +172,8 @@ protected: // helper function for Sequence conversion size_t getOleElementSize( VARTYPE type); + Type getElementTypeOfSequence( const Type& seqType); + // 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 @@ -190,7 +210,7 @@ template<class T> Reference< XSingleServiceFactory > UnoConversionUtilities<T>::getInvocationFactory(const Any& anyObject) { Reference< XSingleServiceFactory > retVal; - OGuard guard( globalWrapperMutex); + MutexGuard guard( getBridgeMutex()); if( anyObject.getValueTypeClass() != TypeClass_STRUCT && m_smgrRemote.is() ) { @@ -222,14 +242,11 @@ sal_Bool UnoConversionUtilities<T>::variantToAny2( const VARIANTARG* pArg, Any& return sal_False; sal_Bool bHandled= sal_False; -// if( pArg->vt == VT_DISPATCH ) -// { + if( !convertValueObject( &var, rAny, bHandled)) return sal_False; if( bHandled) OSL_ENSURE( rAny.getValueType() == ptype, "type in Value Object must match the type parameter"); -// } - if( ! bHandled) { @@ -310,8 +327,16 @@ sal_Bool UnoConversionUtilities<T>::variantToAny2( const VARIANTARG* pArg, Any& retVal= dispatchExObject2Sequence( pArg, rAny, ptype); } else - retVal= variantToAny(&var, rAny); - break; // maybe later ( convert to VT_ARRAY| ??? ) + { + if ((var.vt & VT_ARRAY) != 0) + { + VARTYPE oleType = var.vt ^ VT_ARRAY; + Sequence<Any> unoSeq = createOleArrayWrapper( var.parray, oleType, ptype); + rAny.setValue( &unoSeq, getCppuType( &unoSeq)); + retVal = sal_True; + } + } + break; case TypeClass_VOID: rAny.setValue(NULL,Type()); break; @@ -403,6 +428,7 @@ sal_Bool UnoConversionUtilities<T>::variantToAny2( const VARIANTARG* pArg, Any& template<class T> sal_Bool UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& rAny, VARTYPE type) { + HRESULT hr= S_OK; sal_Bool ret= sal_False; type &= 0xffff ^ VT_BYREF; // remove VT_BYREF if set if( type & VT_ARRAY) @@ -418,8 +444,22 @@ sal_Bool UnoConversionUtilities<T>::anyToVariant(VARIANT* pVariant, const Any& r } } + else if(type == VT_VARIANT) + { + ret= anyToVariant(pVariant, rAny); + } else - ret= anyToVariant( pVariant, rAny); + { + CComVariant var; + if(anyToVariant( &var, rAny)) + { + if(SUCCEEDED(hr= VariantChangeType(&var, &var, 0, type))) + { + if( SUCCEEDED(VariantCopy(pVariant, &var))) + ret= sal_True; + } + } + } return ret; } @@ -942,19 +982,24 @@ SAFEARRAY* UnoConversionUtilities<T>::createUnoSequenceWrapper(const Any& rSeq) template<class T> IDispatch* UnoConversionUtilities<T>::createUnoObjectWrapper(const Any& rObj) { - OGuard guard(globalWrapperMutex); + MutexGuard guard(getBridgeMutex()); 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) + rObj >>= xInt; + //If there is already a wrapper for the UNO object then use it + if(xInt.is()) { - if( rObj >>= xInt) + IT_Uno it_uno= UnoObjToWrapperMap.find( (sal_uInt32) xInt.get()); + if(it_uno != UnoObjToWrapperMap.end()) { + Reference<XInterface> wrapper( it_uno->second); + } + } + + if(xInt.is()) + { // can the object provide a Wrapper on its own if( ! convertSelfToIDispatch( xInt, &pDispatch) ) { @@ -969,13 +1014,11 @@ IDispatch* UnoConversionUtilities<T>::createUnoObjectWrapper(const Any& rObj) else xInv= Reference<XInvocation>( xInt, UNO_QUERY); } - } } if (! pDispatch && !xInv.is()) { - - + // create a XInvocation object for the uno interface or struct Reference<XSingleServiceFactory> xInvFactory= getInvocationFactory(rObj); if( xInvFactory.is()) { @@ -1019,6 +1062,12 @@ IDispatch* UnoConversionUtilities<T>::createUnoObjectWrapper(const Any& rObj) IDispatch* pDisp; if( convertSelfToIDispatch( xIntWrapper, &pDisp)) pDispatch= pDisp; + + // put the newly created object into a map. If the same object will + // be mapped again and there is already a wrapper then the old wrapper + // will be used. + if(xInt.is()) // only interfaces + UnoObjToWrapperMap[(sal_uInt32) xInt.get()]= WeakReference<XInterface>(xIntWrapper); } } } @@ -1295,57 +1344,12 @@ sal_Bool UnoConversionUtilities<T>::variantToAny( const VARIANT* pVariant, Any& 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) - { - // The wrapped UNO object can either be a struct that has been converted to XInvocation - // or another interface - // try first for an interface - Reference<XInterface> xInt; - if( SUCCEEDED( spUno->getOriginalUnoObject( &xInt))) - { - ret <<= xInt; - } - else - { - 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 param; - param <<= (sal_uInt32) pUnknown; - xInit->initialize( Sequence<Any>(¶m, 1)); - } - } - ret<<= Reference<XInvocation>( xInt, UNO_QUERY); - } - } - - return ret; -} +// The function converts an IUnknown* into an UNO interface or struct. The +// IUnknown pointer can constitute different kind of objects: +// 1. a wrapper of an UNO struct (the wrapper was created by this bridge) +// 2. a wrapper of an UNO interface (created by this bridge) +// 3. a dispatch object that implements UNO interfaces +// 4. a dispatch object. // If the parameter "aType" has a value then the COM object ( pUnknown) is supposed to // implement the interface described by "aType". Moreover it ( pUnknown) can implement @@ -1364,14 +1368,16 @@ Any UnoConversionUtilities<T>::createOleObjectWrapper(IUnknown* pUnknown) // UNO wrapper than the original UNO object is being extracted, queried for "aType" (if // it is no struct) and returned. template<class T> -Any UnoConversionUtilities<T>::createOleObjectWrapper(IUnknown* pUnknown, const Type& aType) +Any UnoConversionUtilities<T>::createOleObjectWrapper(IUnknown* pUnknown, const Type& aType= Type()) { - OGuard guard( globalWrapperMutex); + MutexGuard guard( getBridgeMutex()); + static Type VOID_TYPE= Type(); Any ret; - Reference<XInterface> xInt; + Type desiredType= aType == VOID_TYPE ? getCppuType((Reference<XInvocation>*) 0) : aType; + Reference<XInterface> xInt; - if (pUnknown == NULL) + if (pUnknown == NULL) { if( aType.getTypeClass() == TypeClass_INTERFACE) ret.setValue( &xInt, aType); @@ -1385,17 +1391,12 @@ Any UnoConversionUtilities<T>::createOleObjectWrapper(IUnknown* pUnknown, const CComQIPtr<IUnoObjectWrapper> spUno( pUnknown); if( spUno) { - if( aType.getTypeClass() == TypeClass_INTERFACE) + Reference<XInterface> xInt; + if( SUCCEEDED( spUno->getOriginalUnoObject( &xInt))) { - Reference<XInterface> xInt; - spUno->getOriginalUnoObject( &xInt); - if( xInt.is()) - { - ret= xInt->queryInterface( aType); - } - + ret <<= xInt; } - else if( aType.getTypeClass() == TypeClass_STRUCT) + else { Any any; if( SUCCEEDED( spUno->getOriginalUnoStruct(&any))) @@ -1405,105 +1406,138 @@ Any UnoConversionUtilities<T>::createOleObjectWrapper(IUnknown* pUnknown, const else { // "pUnknown" is a real COM object. - Reference<XInterface> xInt= createComWrapperInstance(); - if( xInt.is()) - { - Reference<XInvocation> xInv( xInt, UNO_QUERY); + // Before we create a new wrapper object we check if there is an existing wrapper + // CIT_Com cit_currWrapper= ComPtrToWrapperMap.find( reinterpret_cast<sal_uInt32>(pUnknown)); +// sal_Bool bSuccess= sal_False; +// if(cit_currWrapper != ComPtrToWrapperMap.end()) +// { +// WeakReference<XInterface> xweak= cit_currWrapper->second; +// Reference<XInterface> xint= xweak; +// // get the Adapter from the WrapperToAdapterMap. This is dangerous since the stored pointer +// // might be invalid already. We should store the adapter in a map with a weak reference. The +// // invocation adapter factory does not support adapter which can be kept weekly. +// CIT_Wrap cit_w= WrapperToAdapterMap.find((sal_uInt32) xint.get()); +// if( cit_w != WrapperToAdapterMap.end()) +// { +// Reference<XInterface> xIntAdapt(reinterpret_cast<XInterface*>( cit_w->second)); +// if(xIntAdapt.is()) +// { +// ret= xIntAdapt->queryInterface(desiredType); +// bSuccess= sal_True; +// } +// } +// else +// { +// ret= xint->queryInterface(desiredType); +// bSuccess= sal_True; +// } +// } +// if(bSuccess == sal_False) +// { + //There is no existing wrapper, therefore we create one for the real COM object + Reference<XInterface> xInt= createComWrapperInstance(); + if( xInt.is()) + { + Reference<XInvocation> xInv( xInt, UNO_QUERY); - Sequence<Type> seqTypes; + Sequence<Type> seqTypes; + //The wrapper implements already XInvocation and XInterface. Therefore if the + //param aType is one of those we can use the wrapper object directly otherwise + //we have to create an Adapter interface. + //If aType is void then we assume the type to be XInterface - // 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; - xIntAdapterFac= m_smgr->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". - CComDispatchDriver disp( pUnknown); - if( disp) + if( desiredType == getCppuType((Reference<XInvocation>*) 0)) { - CComVariant var; - HRESULT hr= S_OK; - // There are two different property names possible. - if( FAILED( hr= disp.GetPropertyByName( SUPPORTED_INTERFACES_PROP, &var))) - { - hr= disp.GetPropertyByName( SUPPORTED_INTERFACES_PROP2, &var); - } - if (SUCCEEDED( hr)) + ret <<= xInt; +// ComPtrToWrapperMap[reinterpret_cast<sal_uInt32>(pUnknown)]= xInt; + } + else + { + Reference< XInterface> xIntAdapterFac; + xIntAdapterFac= m_smgr->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". + CComDispatchDriver disp( pUnknown); + if( disp) { - // we exspect an array( SafeArray or IDispatch) of Strings. - Any anyNames; - if( variantToAny2( &var, anyNames, getCppuType( (Sequence<Any>*) 0))) + CComVariant var; + HRESULT hr= S_OK; + // There are two different property names possible. + if( FAILED( hr= disp.GetPropertyByName( SUPPORTED_INTERFACES_PROP, &var))) + { + hr= disp.GetPropertyByName( SUPPORTED_INTERFACES_PROP2, &var); + } + if (SUCCEEDED( hr)) { - Sequence<Any> seqAny; - if( anyNames >>= seqAny) + // we exspect an array( SafeArray or IDispatch) of Strings. + Any anyNames; + if( variantToAny2( &var, anyNames, getCppuType( (Sequence<Any>*) 0))) { - seqTypes.realloc( seqAny.getLength()); - for( sal_Int32 i=0; i < seqAny.getLength(); i++) + Sequence<Any> seqAny; + if( anyNames >>= seqAny) { - OUString typeName; - seqAny[i] >>= typeName; - seqTypes[i]= Type( TypeClass_INTERFACE, typeName); + 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())); - } - } + Reference<XInterface> xIntAdapted; + sal_Int32 seqTypesLen = seqTypes.getLength(); - // 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 + if( seqTypesLen > 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, desiredType); + } + if( xIntAdapted.is()) + { + ret= xIntAdapted->queryInterface( desiredType); + // 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())); +// ComPtrToWrapperMap[reinterpret_cast<sal_uInt32>(pUnknown)]= xInt; + } + } + // initialize the COM wrapper ( IUnknown + Type s) + Reference<XInitialization> xInit( xInt, UNO_QUERY); + if( xInit.is()) { - params[1] <<= seqTypes; - } + 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)); + xInit->initialize( Sequence<Any>( params, 2)); + } } - - } - } - } +// } + } + } return ret; } @@ -1686,9 +1720,13 @@ sal_Bool UnoConversionUtilities<T>::dispatchExObject2Sequence( const VARIANTARG* return retVal; } - +/* The argument unotype is the type that is expected by the currently called UNO function. + For example: []long, [][]long. If the function calls itself recursively then unotype is + just passed on. It is only used to determine the element type (e.g. long here). +*/ template<class T> -Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* pArray, unsigned int dimCount, unsigned int actDim, long* index, VARTYPE type) +Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* pArray, + unsigned int dimCount, unsigned int actDim, long* index, VARTYPE type, const Type& unotype) { HRESULT hr= S_OK; long lBound; @@ -1699,6 +1737,7 @@ Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* p SafeArrayGetUBound(pArray, actDim, &uBound); nCountElements= uBound - lBound +1; + Type elementType; Sequence<Any> anySeq(nCountElements); Any* pUnoArray = anySeq.getArray(); @@ -1707,7 +1746,7 @@ Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* p { if (actDim > 1 ) { - Sequence<Any> element = createOleArrayWrapperOfDim(pArray, dimCount, actDim - 1, index, type); + Sequence<Any> element = createOleArrayWrapperOfDim(pArray, dimCount, actDim - 1, index, type, unotype); pUnoArray[index[actDim - 1] - lBound].setValue(&element, getCppuType(&element)); } @@ -1773,16 +1812,47 @@ Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapperOfDim(SAFEARRAY* p break; } - variantToAny(&variant, pUnoArray[index[actDim - 1] - lBound], sal_False); + // obtain the element type of the sequence. In case the sequence contains a sequence, then + // get the element type of that sequence and so on. For example, element type of + // Sequence<Sequence<long> > is long + if( elementType.getTypeClass() == TypeClass_VOID) + elementType= getElementTypeOfSequence( unotype); + + if( unotype.getTypeClass() == TypeClass_VOID) + // the function was called without specifying the destination type + variantToAny(&variant, pUnoArray[index[actDim - 1] - lBound], sal_False); + else if( variant.vt & VT_ARRAY) + variantToAny2(&variant, pUnoArray[index[actDim - 1] - lBound], unotype, sal_False); + else + variantToAny2(&variant, pUnoArray[index[actDim - 1] - lBound], elementType, sal_False); VariantClear(&variant); } } - return anySeq; } + +template<class T> +Type UnoConversionUtilities<T>::getElementTypeOfSequence( const Type& seqType) +{ + Type retValue; + if( seqType.getTypeClass() != TypeClass_VOID) + { + OSL_ASSERT( seqType.getTypeClass() == TypeClass_SEQUENCE); + + typelib_IndirectTypeDescription* pDescSeq= NULL; + seqType.getDescription( (typelib_TypeDescription** ) & pDescSeq); + if( pDescSeq->pType->eTypeClass == TypeClass_SEQUENCE) + retValue= getElementTypeOfSequence( Type( pDescSeq->pType)); + else + retValue= Type( pDescSeq->pType); + + typelib_typedescription_release( (typelib_TypeDescription*) pDescSeq); + } + return retValue; +} template<class T> -Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapper(SAFEARRAY* pArray, VARTYPE type) +Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapper(SAFEARRAY* pArray, VARTYPE type, const Type& unoType) { sal_uInt32 dim = SafeArrayGetDim(pArray); @@ -1797,7 +1867,7 @@ Sequence<Any> UnoConversionUtilities<T>::createOleArrayWrapper(SAFEARRAY* pArray index[i] = 0; } - ret = createOleArrayWrapperOfDim(pArray, dim, dim, index, type); + ret = createOleArrayWrapperOfDim(pArray, dim, dim, index, type, unoType); delete[] index; } diff --git a/extensions/source/ole/unoobjw.cxx b/extensions/source/ole/unoobjw.cxx index 8217ebfd5051..e9e7c2073e39 100644 --- a/extensions/source/ole/unoobjw.cxx +++ b/extensions/source/ole/unoobjw.cxx @@ -2,9 +2,9 @@ * * $RCSfile: unoobjw.cxx,v $ * - * $Revision: 1.11 $ + * $Revision: 1.12 $ * - * last change: $Author: jl $ $Date: 2001-12-06 08:12:40 $ + * last change: $Author: jl $ $Date: 2002-06-05 13:21:38 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -71,7 +71,6 @@ #include <vos/diagnose.hxx> -#include <vos/mutex.hxx> #include <vos/refernce.hxx> #include <tools/debug.hxx> @@ -144,20 +143,11 @@ extern "C" const GUID IID_IDispatchEx; namespace ole_adapter { +hash_map<sal_uInt32, WeakReference<XInterface> > UnoObjToWrapperMap; static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource); static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource); static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr); - - -/***************************************************************************** - - static objects - -*****************************************************************************/ - -OMutex globalWrapperMutex; - /***************************************************************************** class implementation: InterfaceOleWrapper_Impl @@ -172,6 +162,7 @@ InterfaceOleWrapper_Impl::InterfaceOleWrapper_Impl( Reference<XMultiServiceFacto InterfaceOleWrapper_Impl::~InterfaceOleWrapper_Impl() { + UnoObjToWrapperMap.erase( (unsigned long) m_xOrigin.get()); } STDMETHODIMP InterfaceOleWrapper_Impl::QueryInterface(REFIID riid, LPVOID FAR * ppv) @@ -211,7 +202,7 @@ STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::Release() ULONG n; { - OGuard guard(globalWrapperMutex); + MutexGuard guard(getBridgeMutex()); n = m_refCount.release(); } @@ -271,7 +262,7 @@ STDMETHODIMP InterfaceOleWrapper_Impl::GetIDsOfNames(REFIID riid, DISPID * rgdispid ) { - OGuard guard( globalWrapperMutex); + MutexGuard guard( getBridgeMutex()); if( ! rgdispid) return E_POINTER; HRESULT ret = E_UNEXPECTED; @@ -402,12 +393,15 @@ HRESULT InterfaceOleWrapper_Impl::convertDispparamsArgs( DISPID id, unsigned sh rSeq.realloc( countArgs); Any* pParams = rSeq.getArray(); - sal_Bool allDispHandled= sal_True; + sal_Bool bTypeInfoNeeded= sal_False; Any anyParam; sal_Bool bHandled= sal_False; - // iterate over all parameter and check for special JScriptValue objects that originated in this bridge. - // Those can be converted straight away. The index in the sequence "seqConvertedParams" matches the index in the + // Iterate over all parameters. The aim is to find out if we need to obtain + // type information for the parameter, which is the case when we receive an + // VT_DISPATCH or VT_ARRAY argument. Also, ValuObjects are converted in this loop. + // An VT_DISPATCH can be a ValueObject (class JScriptValue) objects that originated in this bridge. + // The index in the sequence "seqConvertedParams" matches the index in the // DISPPARAMS.rgvarg array. If the value is true then the corresponding VARIANT has been converted // and the any has been written to the Sequence that holds the converted values. for( int i= 0; i < countArgs; i++) @@ -423,79 +417,29 @@ HRESULT InterfaceOleWrapper_Impl::convertDispparamsArgs( DISPID id, unsigned sh else { // if the param is no ValueObject although it is an IDispatch then we must - // set a flag that indicates that we have to examine those objects further + // set a flag that indicates that we have to examine those objects further. + // This is also true if the argument is an array CComVariant var; - if( SUCCEEDED( var.ChangeType(VT_DISPATCH, &pdispparams->rgvarg[i]))) - allDispHandled= sal_False; + if( SUCCEEDED( var.ChangeType(VT_DISPATCH, &pdispparams->rgvarg[i])) + || (pdispparams->rgvarg[i].vt & VT_ARRAY) + || ( pdispparams->rgvarg[i].vt == (VT_VARIANT | VT_BYREF) && + pdispparams->rgvarg[i].pvarVal->vt & VT_ARRAY)) + { + bTypeInfoNeeded= sal_True; + } } } - // If there is a VT_DISPATCH and if it is no JScriptValue object then - // we need to know if it represents a Sequence, out or in/out parameter - // or an actual object. Therefore we obtain type information try{ - sal_Bool bTypesAvailable= sal_False; + // If there is a VT_DISPATCH and if it is no JScriptValue object then + // we need to know if it represents a Sequence, out or in/out parameter + // or an actual object. Therefore we obtain type information. InvocationInfo info; - - //only aquire type information if at least one of the parameter is IDispatch - // and has not been converted yet because it is no JScriptValue object - if( ! allDispHandled) + sal_Bool bTypesAvailable= sal_False; + if( bTypeInfoNeeded) { - if( !m_xInvocation.is() )return DISP_E_EXCEPTION; - Reference<XInvocation2> inv2( m_xInvocation, UNO_QUERY); - if( inv2.is()) - { - - // We need the name of the property or method to get its type information. - // The name can be identified through the param "id" - // that is kept als value in the map m_nameToDispIdMap. - // Proplem: the Windows JScript engine sometimes changes small letters to capital - // letters as happens in xidlclass_obj.createObject( var) // in JScript. - // IDispatch::GetIdsOfNames is then called with "CreateObject" !!! - // m_nameToDispIdMap can contain several names for one DISPID but only one is - // the exact one. If there's no m_xExactName and therfore no exact name then - // there's only one entry in the map. - typedef NameToIdMap::const_iterator cit; - OUString sMemberName; - - for(cit ci1= m_nameToDispIdMap.begin(); ci1 != m_nameToDispIdMap.end(); ci1++) - { - if( (*ci1).second == id) // iterator is a pair< OUString, DISPID> - { - sMemberName= (*ci1).first; - break; - } - } - - // Get information for the current call ( property or method). - // There could be similar names which only differ in the cases - // of letters. First we assume that the name which was passed into - // GetIDsOfNames is correct. If we won't get information with that - // name then we have the invocation service use the XExactName interface. - sal_Bool validInfo= sal_True; - try{ - info= inv2->getInfoForName( sMemberName, sal_False); - } - catch( IllegalArgumentException ) - { - validInfo= sal_False; - } - - if( ! validInfo) - { - info= inv2->getInfoForName( sMemberName, sal_True); - } - - // If the current call is being dispatched to a method, - // make sure that the number of arguments in DISPPARAMS::cArgs is equal - // to the one in InvocationInfo::aParamTypes.getLength(); - if( info.eMemberType == MemberType_METHOD && - countArgs != info.aParamTypes.getLength() ) - hr= DISP_E_BADPARAMCOUNT; - - bTypesAvailable= sal_True; - } + if( ! (bTypesAvailable= getInvocationInfoForCall( id, info))) + return DISP_E_EXCEPTION; } - // Used within the following "for" loop. If the param is an out, in/out parameter in // JScript (Array object, with value at index 0) then we // extract Array[0] and put the value into varParam. At the end of the loop varParam @@ -578,6 +522,61 @@ HRESULT InterfaceOleWrapper_Impl::convertDispparamsArgs( DISPID id, unsigned sh return hr; } +sal_Bool InterfaceOleWrapper_Impl::getInvocationInfoForCall( DISPID id, InvocationInfo& info) +{ + sal_Bool bTypesAvailable= sal_False; + + if( !m_xInvocation.is() )return false; + Reference<XInvocation2> inv2( m_xInvocation, UNO_QUERY); + if( inv2.is()) + { + // We need the name of the property or method to get its type information. + // The name can be identified through the param "id" + // that is kept as value in the map m_nameToDispIdMap. + // Proplem: the Windows JScript engine sometimes changes small letters to capital + // letters as happens in xidlclass_obj.createObject( var) // in JScript. + // IDispatch::GetIdsOfNames is then called with "CreateObject" !!! + // m_nameToDispIdMap can contain several names for one DISPID but only one is + // the exact one. If there's no m_xExactName and therefore no exact name then + // there's only one entry in the map. + typedef NameToIdMap::const_iterator cit; + OUString sMemberName; + + for(cit ci1= m_nameToDispIdMap.begin(); ci1 != m_nameToDispIdMap.end(); ci1++) + { + if( (*ci1).second == id) // iterator is a pair< OUString, DISPID> + { + sMemberName= (*ci1).first; + break; + } + } + // Get information for the current call ( property or method). + // There could be similar names which only differ in the cases + // of letters. First we assume that the name which was passed into + // GetIDsOfNames is correct. If we won't get information with that + // name then we have the invocation service use the XExactName interface. + sal_Bool validInfo= sal_True; + InvocationInfo invInfo; + try{ + invInfo= inv2->getInfoForName( sMemberName, sal_False); + } + catch( IllegalArgumentException ) + { + validInfo= sal_False; + } + + if( ! validInfo) + { + invInfo= inv2->getInfoForName( sMemberName, sal_True); + } + if( invInfo.aName.pData) + { + bTypesAvailable= sal_True; + info= invInfo; + } + } + return bTypesAvailable; +} // XBridgeSupplier2 --------------------------------------------------- // only bridges itself ( this instance of InterfaceOleWrapper_Impl)from UNO to IDispatch // If sourceModelType is UNO than any UNO interface implemented by InterfaceOleWrapper_Impl @@ -1035,12 +1034,8 @@ HRESULT InterfaceOleWrapper_Impl::doInvoke( DISPPARAMS * pdispparams, VARIANT * { ret = DISP_E_BADVARTYPE; } -// else -// { -// ret = NOERROR; -// } } - catch(IllegalArgumentException ) + catch(IllegalArgumentException e) { ret = DISP_E_TYPEMISMATCH; } @@ -1315,7 +1310,7 @@ Reference< XInterface > UnoObjectWrapperRemoteOpt::createUnoWrapperInstance() STDMETHODIMP UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID riid, OLECHAR ** rgszNames, unsigned int cNames, LCID lcid, DISPID * rgdispid ) { - OGuard guard( globalWrapperMutex); + MutexGuard guard( getBridgeMutex()); if( ! rgdispid) return E_POINTER; diff --git a/extensions/source/ole/unoobjw.hxx b/extensions/source/ole/unoobjw.hxx index 8cd38baaf9a5..42c0edea6e3c 100644 --- a/extensions/source/ole/unoobjw.hxx +++ b/extensions/source/ole/unoobjw.hxx @@ -2,9 +2,9 @@ * * $RCSfile: unoobjw.hxx,v $ * - * $Revision: 1.5 $ + * $Revision: 1.6 $ * - * last change: $Author: jl $ $Date: 2001-09-17 14:15:46 $ + * last change: $Author: jl $ $Date: 2002-06-05 13:21:38 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -65,6 +65,7 @@ #include <com/sun/star/bridge/XBridgeSupplier2.hpp> #include <com/sun/star/beans/XExactName.hpp> #include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/script/InvocationInfo.hpp> #include <vos/refernce.hxx> #include <tools/presys.h> @@ -86,6 +87,7 @@ using namespace std; using namespace cppu; using namespace com::sun::star::bridge; +using namespace com::sun::star::script; namespace ole_adapter { @@ -252,6 +254,8 @@ protected: HRESULT convertDispparamsArgs( DISPID id, unsigned short wFlags, DISPPARAMS* pdispparams, Sequence<Any>& rSeq); + sal_Bool getInvocationInfoForCall(DISPID id, InvocationInfo& info); + vos::ORefCount m_refCount; Reference<XInvocation> m_xInvocation; Reference<XExactName> m_xExactName; |