diff options
Diffstat (limited to 'extensions/source/ole/unoobjw.cxx')
-rw-r--r-- | extensions/source/ole/unoobjw.cxx | 1688 |
1 files changed, 1688 insertions, 0 deletions
diff --git a/extensions/source/ole/unoobjw.cxx b/extensions/source/ole/unoobjw.cxx new file mode 100644 index 000000000000..5452a95129ff --- /dev/null +++ b/extensions/source/ole/unoobjw.cxx @@ -0,0 +1,1688 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#include "ole2uno.hxx" +#include <stdio.h> +#include <tools/presys.h> +#include <olectl.h> +#include <vector> +#include <list> +#include <hash_map> +#include "comifaces.hxx" +#include <tools/postsys.h> + + +#include <vos/diagnose.hxx> +#include <vos/refernce.hxx> +#include <tools/debug.hxx> +#include <rtl/ustring.hxx> +#include <com/sun/star/beans/MethodConcept.hpp> +#include <com/sun/star/beans/PropertyConcept.hpp> +#include <com/sun/star/script/FailReason.hpp> +#include <com/sun/star/reflection/ParamInfo.hpp> +#include <com/sun/star/beans/XExactName.hpp> +#include <com/sun/star/container/NoSuchElementException.hpp> + +#include <com/sun/star/beans/XMaterialHolder.hpp> +#include <com/sun/star/script/XInvocation2.hpp> +#include <com/sun/star/script/MemberType.hpp> +#include <com/sun/star/reflection/XIdlReflection.hpp> +#include <osl/interlck.h> +#include <com/sun/star/uno/genfunc.h> +#include <cppuhelper/implbase1.hxx> + +#include "comifaces.hxx" +#include "jscriptclasses.hxx" +#include "unotypewrapper.hxx" +#include "oleobjw.hxx" +#include "unoobjw.hxx" +#include "servprov.hxx" + +using namespace vos; +using namespace std; +using namespace rtl; +using namespace osl; +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::container; +using namespace com::sun::star::script; +using namespace com::sun::star::lang; +using namespace com::sun::star::bridge::ModelDependent; +using namespace com::sun::star::reflection; + + + +#if _MSC_VER < 1200 +extern "C" const GUID IID_IDispatchEx; +#endif + +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); + + +/* Does not throw any exceptions. + Param pInfo can be NULL. + */ +static void writeExcepinfo(EXCEPINFO * pInfo, const OUString& message) +{ + if (pInfo != NULL) + { + pInfo->wCode = UNO_2_OLE_EXCEPTIONCODE; + pInfo->bstrSource = SysAllocString(L"[automation bridge] "); + pInfo->bstrDescription = SysAllocString(reinterpret_cast<LPCOLESTR>(message.getStr())); + } +} + +/***************************************************************************** + + class implementation: InterfaceOleWrapper_Impl + +*****************************************************************************/ +InterfaceOleWrapper_Impl::InterfaceOleWrapper_Impl( Reference<XMultiServiceFactory>& xFactory, + sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass): + m_defaultValueType( 0), + UnoConversionUtilities<InterfaceOleWrapper_Impl>( xFactory, unoWrapperClass, comWrapperClass) +{ +} + +InterfaceOleWrapper_Impl::~InterfaceOleWrapper_Impl() +{ + MutexGuard guard(getBridgeMutex()); + // remove entries in global map + IT_Uno it= UnoObjToWrapperMap.find( (sal_uInt32) m_xOrigin.get()); + if(it != UnoObjToWrapperMap.end()) + UnoObjToWrapperMap.erase(it); +#if OSL_DEBUG_LEVEL > 0 + fprintf(stderr,"[automation bridge] UnoObjToWrapperMap contains: %i \n", + UnoObjToWrapperMap.size()); +#endif + +} + +STDMETHODIMP InterfaceOleWrapper_Impl::QueryInterface(REFIID riid, LPVOID FAR * ppv) +{ + HRESULT ret= S_OK; + + if( !ppv) + return E_POINTER; + + if(IsEqualIID(riid, IID_IUnknown)) + { + AddRef(); + *ppv = (IUnknown*) (IDispatch*) this; + } + else if (IsEqualIID(riid, IID_IDispatch)) + { + AddRef(); + *ppv = (IDispatch*) this; + } + else if( IsEqualIID( riid, __uuidof( IUnoObjectWrapper))) + { + AddRef(); + *ppv= (IUnoObjectWrapper*) this; + } + else + ret= E_NOINTERFACE; + return ret; +} + +STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::AddRef() +{ + acquire(); + // does not need to guard because one should not rely on the return value of + // AddRef anyway + return m_refCount; +} + +STDMETHODIMP_(ULONG) InterfaceOleWrapper_Impl::Release() +{ + ULONG n= m_refCount; + release(); + return n - 1; +} + +// IUnoObjectWrapper -------------------------------------------------------- +STDMETHODIMP InterfaceOleWrapper_Impl::getWrapperXInterface( Reference<XInterface>* pXInt) +{ + *pXInt= Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY); + return pXInt->is() ? S_OK : E_FAIL; +} +STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoObject( Reference<XInterface>* pXInt) +{ + *pXInt= m_xOrigin; + return m_xOrigin.is() ? S_OK : E_FAIL; +} +STDMETHODIMP InterfaceOleWrapper_Impl::getOriginalUnoStruct( Any * pStruct) +{ + HRESULT ret= E_FAIL; + if( !m_xOrigin.is()) + { + Reference<XMaterialHolder> xMatHolder( m_xInvocation, UNO_QUERY); + if( xMatHolder.is()) + { + Any any = xMatHolder->getMaterial(); + if( any.getValueTypeClass() == TypeClass_STRUCT) + { + *pStruct= any; + ret= S_OK; + } + } + } + return ret; +} + +STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfoCount( unsigned int * /*pctinfo*/ ) +{ + return E_NOTIMPL ; +} + +STDMETHODIMP InterfaceOleWrapper_Impl::GetTypeInfo(unsigned int /*itinfo*/, LCID /*lcid*/, ITypeInfo ** /*pptinfo*/) +{ + return E_NOTIMPL; +} + +STDMETHODIMP InterfaceOleWrapper_Impl::GetIDsOfNames(REFIID /*riid*/, + OLECHAR ** rgszNames, + unsigned int cNames, + LCID /*lcid*/, + DISPID * rgdispid ) +{ + HRESULT ret = DISP_E_UNKNOWNNAME; + try + { + MutexGuard guard( getBridgeMutex()); + if( ! rgdispid) + return E_POINTER; + + // ---------------------------------------- + if( ! _wcsicmp( *rgszNames, JSCRIPT_VALUE_FUNC) || + ! _wcsicmp( *rgszNames, BRIDGE_VALUE_FUNC)) + { + *rgdispid= DISPID_JSCRIPT_VALUE_FUNC; + return S_OK; + } + else if( ! _wcsicmp( *rgszNames, GET_STRUCT_FUNC) || + ! _wcsicmp( *rgszNames, BRIDGE_GET_STRUCT_FUNC)) + { + *rgdispid= DISPID_GET_STRUCT_FUNC; + return S_OK; + } + else if( ! _wcsicmp( *rgszNames, BRIDGE_CREATE_TYPE_FUNC)) + { + *rgdispid= DISPID_CREATE_TYPE_FUNC; + return S_OK; + } + + // ---------------------------------------- + if (m_xInvocation.is() && (cNames > 0)) + { + OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0])); + NameToIdMap::iterator iter = m_nameToDispIdMap.find(name); + + if (iter == m_nameToDispIdMap.end()) + { + OUString exactName; + + if (m_xExactName.is()) + { + exactName = m_xExactName->getExactName(name); + } + else + { + exactName = name; + } + + MemberInfo d(0, exactName); + + if (m_xInvocation->hasProperty(exactName)) + { + d.flags |= DISPATCH_PROPERTYGET; + d.flags |= DISPATCH_PROPERTYPUT; + d.flags |= DISPATCH_PROPERTYPUTREF; + } + + if (m_xInvocation->hasMethod(exactName)) + { + d.flags |= DISPATCH_METHOD; + } + + if (d.flags != 0) + { + m_MemberInfos.push_back(d); + iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(exactName, (DISPID)m_MemberInfos.size())).first; + + if (exactName != name) + { + iter = m_nameToDispIdMap.insert(NameToIdMap::value_type(name, (DISPID)m_MemberInfos.size())).first; + } + } + } + + if (iter == m_nameToDispIdMap.end()) + { + ret = DISP_E_UNKNOWNNAME; + } + else + { + *rgdispid = (*iter).second; + ret = S_OK; + } + } + } + catch(BridgeRuntimeError& ) + { + OSL_ASSERT(0); + } + catch(Exception& ) + { + OSL_ASSERT(0); + } + catch(...) + { + OSL_ASSERT(0); + } + + return ret; +} + +// "convertDispparamsArgs" converts VARIANTS to their respecting Any counterparts +// The parameters "id", "wFlags" and "pdispparams" equal those as used in +// IDispatch::Invoke. The function handles special JavaScript +// cases where a VARIANT of type VT_DISPATCH is ambiguous and could represent +// an object, array ( JavaScript Array object), out parameter and in/out ( JavaScript Array object) +// parameter (JavaScript Array object) +// Because all those VT_DISPATCH objects need a different conversion +// we have to find out what the object is supposed to be. The function does this +// by either using type information or by help of a specialized ValueObject object. + +// A. Type Information +// ----------------------------------------------------------------------------- +// With the help of type information the kind of parameter can be exactly determined +// and an appropriate conversion can be choosen. A problem arises if a method expects +// an Any. Then the type info does not tell what the type of the value, that is kept +// by the any, should be. In this situation the decision wheter the param is a +// sequence or an object is made upon the fact if the object has a property "0" +// ( see function "isJScriptArray"). Since this is unsafe it is recommended to use +// the JScript value objects within a JScript script on such an occasion. + +// B. JavaScript Value Object ( class JScriptValue ) +// ----------------------------------------------------------------------------- +// A JScriptValue (ValueObject) object is a COM object in that it implements IDispatch and the +// IJScriptValue object interface. Such objects are provided by all UNO wrapper +// objects used within a JScript script. To obtain an instance one has to call +// "_GetValueObject() or Bridge_GetValueObject()" on an UNO wrapper object (class InterfaceOleWrapper_Impl). +// A value object is appropriately initialized within the script and passed as +// parameter to an UNO object method or property. The convertDispparamsArgs function +// can easily find out that a param is such an object by queriing for the +// IJScriptValue interface. By this interface one the type and kind ( out, in/out) +// can be determined and the right conversion can be applied. +// Using ValueObjects we spare us the effort of aquiring and examining type information +// in order to figure out what the an IDispatch parameter is meant for. + +// Normal JScript object parameter can be mixed with JScriptValue object. If an +// VARIANT contains an VT_DISPATCH that is no JScriptValue than the type information +// is used to find out about the reqired type. +void InterfaceOleWrapper_Impl::convertDispparamsArgs(DISPID id, + unsigned short /*wFlags*/, DISPPARAMS* pdispparams, Sequence<Any>& rSeq) +{ + HRESULT hr= S_OK; + sal_Int32 countArgs= pdispparams->cArgs; + if( countArgs == 0) + return; + + rSeq.realloc( countArgs); + Any* pParams = rSeq.getArray(); + + Any anyParam; + + //Get type information for the current call + InvocationInfo info; + if( ! getInvocationInfoForCall( id, info)) + throw BridgeRuntimeError( + OUSTR("[automation bridge]InterfaceOleWrapper_Impl::convertDispparamsArgs \n" + "Could not obtain type information for current call.")); + + for (int i = 0; i < countArgs; i++) + { + if (info.eMemberType == MemberType_METHOD && + info.aParamModes[ countArgs - i -1 ] == ParamMode_OUT) + continue; + + if(convertValueObject( & pdispparams->rgvarg[i], anyParam)) + { //a param is a ValueObject and could be converted + pParams[countArgs - (i + 1)] = anyParam; + continue; + } + + // 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 + // is converted if it contains a value otherwise the VARIANT from + // DISPPARAMS is converted. + CComVariant varParam; + + // Check for JScript out and in/out paramsobjects (VT_DISPATCH). + // To find them out we use typeinformation of the function being called. + if( pdispparams->rgvarg[i].vt == VT_DISPATCH ) + { + if( info.eMemberType == MemberType_METHOD && info.aParamModes[ countArgs - i -1 ] == ParamMode_INOUT) + { + // INOUT-param + // Index ( property) "0" contains the actual IN-param. The object is a JScript + // Array object. + // Get the IN-param at index "0" + IDispatch* pdisp= pdispparams->rgvarg[i].pdispVal; + + OLECHAR* sindex= L"0"; + DISPID id; + DISPPARAMS noParams= {0,0,0,0}; + if(SUCCEEDED( hr= pdisp->GetIDsOfNames( IID_NULL, &sindex, 1, LOCALE_USER_DEFAULT, &id))) + hr= pdisp->Invoke( id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, + & noParams, & varParam, NULL, NULL); + if( FAILED( hr)) + { + throw BridgeRuntimeError( + OUSTR("[automation bridge] Could not determine " + "if the object has a member \"0\". Error: ") + + OUString::valueOf(hr)); + } + } + } + + if( varParam.vt == VT_EMPTY) // then it was no in/out parameter + varParam= pdispparams->rgvarg[i]; + + if(info.eMemberType == MemberType_METHOD) + variantToAny( & varParam, anyParam, + info.aParamTypes[ countArgs - i - 1]); + else if(info.eMemberType == MemberType_PROPERTY) + variantToAny( & varParam, anyParam, info.aType); + else + OSL_ASSERT(0); + + pParams[countArgs - (i + 1)]= anyParam; + }// end for / iterating over all parameters +} + +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 +// can bridged to IDispatch ( if destModelType == OLE). The IDispatch is +// implemented by this class. +Any SAL_CALL InterfaceOleWrapper_Impl::createBridge(const Any& modelDepObject, + const Sequence<sal_Int8>& /*ProcessId*/, + sal_Int16 sourceModelType, + sal_Int16 destModelType) + throw (IllegalArgumentException, RuntimeException) +{ + + Any retAny; + if( sourceModelType == UNO && destModelType == OLE && + modelDepObject.getValueTypeClass() == TypeClass_INTERFACE ) + { + Reference<XInterface> xInt; + if( modelDepObject >>= xInt ) + { + if( xInt == Reference<XInterface>( static_cast<XWeak*>( this), UNO_QUERY)) + { + VARIANT *pVar= (VARIANT*)CoTaskMemAlloc( sizeof( VARIANT)); + if( pVar) + { + pVar->vt= VT_DISPATCH; + pVar->pdispVal= static_cast<IDispatch*>( this); + AddRef(); + + retAny<<= reinterpret_cast< sal_uInt32 >( pVar); + } + } + } + } + + return retAny; +} + + +// XInitialization -------------------------------------------------- +void SAL_CALL InterfaceOleWrapper_Impl::initialize( const Sequence< Any >& aArguments ) + throw(Exception, RuntimeException) +{ + switch( aArguments.getLength() ) + { + case 2: // the object wraps an UNO struct + aArguments[0] >>= m_xInvocation; + aArguments[1] >>= m_defaultValueType; + break; + case 3: // the object wraps an UNO interface + aArguments[0] >>= m_xInvocation; + aArguments[1] >>= m_xOrigin; + aArguments[2] >>= m_defaultValueType; + break; + } + + m_xExactName= Reference<XExactName>( m_xInvocation, UNO_QUERY); +} + +Reference< XInterface > InterfaceOleWrapper_Impl::createUnoWrapperInstance() +{ + Reference<XWeak> xWeak= static_cast<XWeak*>( new InterfaceOleWrapper_Impl( + m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); + return Reference<XInterface>( xWeak, UNO_QUERY); +} + +Reference<XInterface> InterfaceOleWrapper_Impl::createComWrapperInstance() +{ + Reference<XWeak> xWeak= static_cast<XWeak*>( new IUnknownWrapper_Impl( + m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); + return Reference<XInterface>( xWeak, UNO_QUERY); +} + + + +// "getType" is used in convertValueObject to map the string denoting the type +// to an actual Type object. +bool getType( const BSTR name, Type & type) +{ + Type retType; + bool ret = false; + typelib_TypeDescription * pDesc= NULL; + OUString str( reinterpret_cast<const sal_Unicode*>(name)); + typelib_typedescription_getByName( &pDesc, str.pData ); + if( pDesc) + { + type = Type( pDesc->pWeakRef ); + typelib_typedescription_release( pDesc); + ret = true; + } + return ret; +} + +static sal_Bool writeBackOutParameter2( VARIANTARG* pDest, VARIANT* pSource) +{ + sal_Bool ret = sal_False; + HRESULT hr; + + // Handle JScriptValue objects and JScript out params ( Array object ) + CComVariant varDest( *pDest); + + if( SUCCEEDED( varDest.ChangeType(VT_DISPATCH))) + { + CComPtr<IDispatch> spDispDest(varDest.pdispVal); + + // special Handling for a JScriptValue object +#ifdef __MINGW32__ + CComQIPtr<IJScriptValueObject, &__uuidof(IJScriptValueObject)> spValueDest(spDispDest); +#else + CComQIPtr<IJScriptValueObject> spValueDest(spDispDest); +#endif + if (spValueDest) + { + VARIANT_BOOL varBool= VARIANT_FALSE; + if( SUCCEEDED( hr= spValueDest->IsOutParam( &varBool) ) + && varBool == VARIANT_TRUE || + SUCCEEDED(hr= spValueDest->IsInOutParam( &varBool) ) + && varBool == VARIANT_TRUE ) + { + if( SUCCEEDED( spValueDest->Set( CComVariant(), *pSource))) + ret= sal_True; + } + } + else if (pDest->vt == VT_DISPATCH)// VT_DISPATCH -> JScript out param + { + // We use IDispatchEx because its GetDispID function causes the creation + // of a property if it does not exist already. This is convenient for + // out parameters in JScript. Then the user must not specify propery "0" + // explicitly +#ifdef __MINGW32__ + CComQIPtr<IDispatchEx, &__uuidof(IDispatchEx)> spDispEx( spDispDest); +#else + CComQIPtr<IDispatchEx> spDispEx( spDispDest); +#endif + if( spDispEx) + { + CComBSTR nullProp(L"0"); + DISPID dwDispID; + if( SUCCEEDED( spDispEx->GetDispID( nullProp, fdexNameEnsure, &dwDispID))) + { + DISPPARAMS dispparams = {NULL, NULL, 1, 1}; + dispparams.rgvarg = pSource; + DISPID dispidPut = DISPID_PROPERTYPUT; + dispparams.rgdispidNamedArgs = &dispidPut; + + if (pSource->vt == VT_UNKNOWN || pSource->vt == VT_DISPATCH || + (pSource->vt & VT_ARRAY) || (pSource->vt & VT_BYREF)) + hr = spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, + &dispparams, NULL, NULL, NULL); + else + hr= spDispEx->InvokeEx(dwDispID, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, + &dispparams, NULL, NULL, NULL); + if( SUCCEEDED(hr)) + ret= sal_True; + } + } + } + else + ret= writeBackOutParameter( pDest, pSource); + } + else // The param can't be a JScript out-parameter ( an Array object), it could be a VBScript + { // param. The function checks itself for correct VBScript params + ret= writeBackOutParameter( pDest, pSource); + } + return ret; +} +// VisualBasic Script passes arguments as VT_VARIANT | VT_BYREF be it in or out parameter. +// Thus we are in charge of freeing an eventual value contained by the inner VARIANT +// Please note: VariantCopy doesn't free a VT_BYREF value +// The out parameters are expected to have always a valid type +static sal_Bool writeBackOutParameter(VARIANTARG* pDest, VARIANT* pSource) +{ + HRESULT hr; + sal_Bool ret = FALSE; + // Out parameter must be VT_BYREF + if ((V_VT(pDest) & VT_BYREF) != 0 ) + { + VARTYPE oleTypeFlags = V_VT(pSource); + + // if caller accept VARIANT as out parameter, any value must be converted + if (V_VT(pDest) == (VT_VARIANT | VT_BYREF)) + { + // When the user provides a VARIANT rather then a concrete type + // we just copy the source to the out, in/out parameter + // VT_DISPATCH, VT_UNKNOWN, VT_ARRAY, VT_BSTR in the VARIANT that + // is contained in pDest are released by VariantCopy + VariantCopy(V_VARIANTREF(pDest), pSource); + ret = sal_True; + } + else + { + // variantarg and variant must have same type + if ((V_VT(pDest) & oleTypeFlags) == oleTypeFlags) + { + if ((oleTypeFlags & VT_ARRAY) != 0) + { + // In / Out Param + if( *V_ARRAYREF(pDest) != NULL) + hr= SafeArrayCopyData( V_ARRAY(pSource), *V_ARRAYREF(pDest)); + else + // Out Param + hr= SafeArrayCopy(V_ARRAY(pSource), V_ARRAYREF(pDest)) == NOERROR; + if( SUCCEEDED( hr)) + ret = sal_True; + } + else + { + // copy base type + switch (V_VT(pSource)) + { + case VT_I2: + { + *V_I2REF(pDest) = V_I2(pSource); + ret = sal_True; + break; + } + case VT_I4: + *V_I4REF(pDest) = V_I4(pSource); + ret = sal_True; + break; + case VT_R4: + *V_R4REF(pDest) = V_R4(pSource); + ret = sal_True; + break; + case VT_R8: + *V_R8REF(pDest) = V_R8(pSource); + ret = sal_True; + break; + case VT_CY: + *V_CYREF(pDest) = V_CY(pSource); + ret = sal_True; + break; + case VT_DATE: + *V_DATEREF(pDest) = V_DATE(pSource); + ret = sal_True; + break; + case VT_BSTR: + SysFreeString( *pDest->pbstrVal); + + *V_BSTRREF(pDest) = SysAllocString(V_BSTR(pSource)); + ret = sal_True; + break; + case VT_DISPATCH: + if (*V_DISPATCHREF(pDest) != NULL) + (*V_DISPATCHREF(pDest))->Release(); + + *V_DISPATCHREF(pDest) = V_DISPATCH(pSource); + + if (*V_DISPATCHREF(pDest) != NULL) + (*V_DISPATCHREF(pDest))->AddRef(); + + ret = sal_True; + break; + case VT_ERROR: + *V_ERRORREF(pDest) = V_ERROR(pSource); + ret = sal_True; + break; + case VT_BOOL: + *V_BOOLREF(pDest) = V_BOOL(pSource); + ret = sal_True; + break; + case VT_UNKNOWN: + if (*V_UNKNOWNREF(pDest) != NULL) + (*V_UNKNOWNREF(pDest))->Release(); + + *V_UNKNOWNREF(pDest) = V_UNKNOWN(pSource); + + if (*V_UNKNOWNREF(pDest) != NULL) + (*V_UNKNOWNREF(pDest))->AddRef(); + + ret = sal_True; + break; + case VT_I1: + *V_I1REF(pDest) = V_I1(pSource); + ret = sal_True; + break; + case VT_UI1: + *V_UI1REF(pDest) = V_UI1(pSource); + ret = sal_True; + break; + case VT_UI2: + *V_UI2REF(pDest) = V_UI2(pSource); + ret = sal_True; + break; + case VT_UI4: + *V_UI4REF(pDest) = V_UI4(pSource); + ret = sal_True; + break; + case VT_INT: + *V_INTREF(pDest) = V_INT(pSource); + ret = sal_True; + break; + case VT_UINT: + *V_UINTREF(pDest) = V_UINT(pSource); + ret = sal_True; + break; + case VT_DECIMAL: + memcpy(pDest->pdecVal, pSource, sizeof(DECIMAL)); + ret = sal_True; + break; + default: + break; + } + } + } + else + { + // Handling of special cases + // Destination and source types are different + if( pDest->vt == (VT_BSTR | VT_BYREF) + && pSource->vt == VT_I2) + { + // When the user provides a String as out our in/out parameter + // and the type is char (TypeClass_CHAR) then we convert to a BSTR + // instead of VT_I2 as is done otherwise + OLECHAR buff[]= {0,0}; + buff[0]= pSource->iVal; + + SysFreeString( *pDest->pbstrVal); + *pDest->pbstrVal= SysAllocString( buff); + ret = sal_True; + } + } + } + } + return ret; +} + +STDMETHODIMP InterfaceOleWrapper_Impl::Invoke(DISPID dispidMember, + REFIID /*riid*/, + LCID /*lcid*/, + unsigned short wFlags, + DISPPARAMS * pdispparams, + VARIANT * pvarResult, + EXCEPINFO * pexcepinfo, + unsigned int * puArgErr ) +{ + HRESULT ret = S_OK; + + try + { + sal_Bool bHandled= sal_False; + ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, + puArgErr, bHandled); + if( bHandled) + return ret; + + if ((dispidMember > 0) && ((size_t)dispidMember <= m_MemberInfos.size()) && m_xInvocation.is()) + { + MemberInfo d = m_MemberInfos[dispidMember - 1]; + DWORD flags = wFlags & d.flags; + + if (flags != 0) + { + if ((flags & DISPATCH_METHOD) != 0) + { + if (pdispparams->cNamedArgs > 0) + ret = DISP_E_NONAMEDARGS; + else + { + Sequence<Any> params; + + convertDispparamsArgs(dispidMember, wFlags, pdispparams , params ); + + ret= doInvoke(pdispparams, pvarResult, + pexcepinfo, puArgErr, d.name, params); + } + } + else if ((flags & DISPATCH_PROPERTYGET) != 0) + { + ret= doGetProperty( pdispparams, pvarResult, + pexcepinfo, d.name); + } + else if ((flags & DISPATCH_PROPERTYPUT || flags & DISPATCH_PROPERTYPUTREF) != 0) + { + if (pdispparams->cArgs != 1) + ret = DISP_E_BADPARAMCOUNT; + else + { + Sequence<Any> params; + convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); + if(params.getLength() > 0) + ret= doSetProperty( pdispparams, pvarResult, pexcepinfo, puArgErr, d.name, params); + else + ret = DISP_E_BADVARTYPE; + } + } + } + else + ret= DISP_E_MEMBERNOTFOUND; + } + else + ret = DISP_E_MEMBERNOTFOUND; + } + catch(BridgeRuntimeError& e) + { + writeExcepinfo(pexcepinfo, e.message); + ret = DISP_E_EXCEPTION; + } + catch(Exception& e) + { + OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n") + + e.Message; + writeExcepinfo(pexcepinfo, message); + ret = DISP_E_EXCEPTION; + } + catch(...) + { + OUString message= OUSTR("InterfaceOleWrapper_Impl::Invoke : \n" + "Unexpected exception"); + writeExcepinfo(pexcepinfo, message); + ret = DISP_E_EXCEPTION; + } + + return ret; +} + +HRESULT InterfaceOleWrapper_Impl::doInvoke( DISPPARAMS * pdispparams, VARIANT * pvarResult, + EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any>& params) +{ + + + HRESULT ret= S_OK; + try + { + Sequence<INT16> outIndex; + Sequence<Any> outParams; + Any returnValue; + + if (pdispparams->cNamedArgs > 0) + return DISP_E_NONAMEDARGS; + + // invoke method and take care of exceptions + returnValue = m_xInvocation->invoke(name, + params, + outIndex, + outParams); + + // try to write back out parameter + if (outIndex.getLength() > 0) + { + const INT16* pOutIndex = outIndex.getConstArray(); + const Any* pOutParams = outParams.getConstArray(); + + for (sal_Int32 i = 0; i < outIndex.getLength(); i++) + { + CComVariant variant; + // Currently a Sequence is converted to an SafeArray of VARIANTs. + anyToVariant( &variant, pOutParams[i]); + + // out parameter need special handling if they are VT_DISPATCH + // and used in JScript + int outindex= pOutIndex[i]; + writeBackOutParameter2(&(pdispparams->rgvarg[pdispparams->cArgs - 1 - outindex]), + &variant ); + } + } + + // write back return value + if (pvarResult != NULL) + anyToVariant(pvarResult, returnValue); + } + catch(IllegalArgumentException & e) //XInvocation::invoke + { + writeExcepinfo(pexcepinfo, e.Message); + ret = DISP_E_TYPEMISMATCH; + } + catch(CannotConvertException & e) //XInvocation::invoke + { + writeExcepinfo(pexcepinfo, e.Message); + ret = mapCannotConvertException( e, puArgErr); + } + catch(InvocationTargetException & e) //XInvocation::invoke + { + const Any& org = e.TargetException; + Exception excTarget; + org >>= excTarget; + OUString message= + org.getValueType().getTypeName() + OUSTR(": ") + excTarget.Message; + writeExcepinfo(pexcepinfo, message); + ret = DISP_E_EXCEPTION; + } + catch(NoSuchMethodException & e) //XInvocation::invoke + { + writeExcepinfo(pexcepinfo, e.Message); + ret = DISP_E_MEMBERNOTFOUND; + } + catch(BridgeRuntimeError & e) + { + writeExcepinfo(pexcepinfo, e.message); + ret = DISP_E_EXCEPTION; + } + catch(Exception & e) + { + OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n") + + e.Message; + writeExcepinfo(pexcepinfo, message); + ret = DISP_E_EXCEPTION; + } + catch( ... ) + { + OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n" + "Unexpected exception"); + writeExcepinfo(pexcepinfo, message); + ret = DISP_E_EXCEPTION; + } + return ret; +} + +HRESULT InterfaceOleWrapper_Impl::doGetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * pvarResult, + EXCEPINFO * pexcepinfo, OUString& name) +{ + HRESULT ret= S_OK; + + Any value; + try + { + Any returnValue = m_xInvocation->getValue( name); + // write back return value + if (pvarResult) + anyToVariant(pvarResult, returnValue); + } + catch(UnknownPropertyException e) //XInvocation::getValue + { + writeExcepinfo(pexcepinfo, e.Message); + ret = DISP_E_MEMBERNOTFOUND; + } + catch(BridgeRuntimeError& e) + { + writeExcepinfo(pexcepinfo, e.message); + ret = DISP_E_EXCEPTION; + } + catch(Exception& e) + { + OUString message= OUSTR("InterfaceOleWrapper_Impl::doGetProperty : \n") + + e.Message; + writeExcepinfo(pexcepinfo, message); + } + catch( ... ) + { + OUString message= OUSTR("InterfaceOleWrapper_Impl::doInvoke : \n" + "Unexpected exception"); + writeExcepinfo(pexcepinfo, message); + ret = DISP_E_EXCEPTION; + } + return ret; +} + +HRESULT InterfaceOleWrapper_Impl::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/, + EXCEPINFO * pexcepinfo, unsigned int * puArgErr, OUString& name, Sequence<Any> params) +{ + HRESULT ret= S_OK; + + try + { + m_xInvocation->setValue( name, params.getConstArray()[0]); + } + catch(UnknownPropertyException ) + { + ret = DISP_E_MEMBERNOTFOUND; + } + catch(CannotConvertException e) + { + ret= mapCannotConvertException( e, puArgErr); + } + catch(InvocationTargetException e) + { + if (pexcepinfo != NULL) + { + Any org = e.TargetException; + + pexcepinfo->wCode = UNO_2_OLE_EXCEPTIONCODE; + pexcepinfo->bstrSource = SysAllocString(L"any ONE component"); + pexcepinfo->bstrDescription = SysAllocString( + reinterpret_cast<LPCOLESTR>(org.getValueType().getTypeName().getStr())); + } + ret = DISP_E_EXCEPTION; + } + catch( ... ) + { + ret= DISP_E_EXCEPTION; + } + return ret; +} + +HRESULT InterfaceOleWrapper_Impl::InvokeGeneral( DISPID dispidMember, unsigned short wFlags, + DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, + unsigned int * /*puArgErr*/, sal_Bool& bHandled) +{ + HRESULT ret= S_OK; + try + { +// DISPID_VALUE | The DEFAULT Value is required in JScript when the situation +// is that we put an object into an Array object ( out parameter). We have to return +// IDispatch otherwise the object cannot be accessed from the Script. + if( dispidMember == DISPID_VALUE && wFlags == DISPATCH_PROPERTYGET + && m_defaultValueType != VT_EMPTY && pvarResult != NULL) + { + bHandled= sal_True; + if( m_defaultValueType == VT_DISPATCH) + { + pvarResult->vt= VT_DISPATCH; + pvarResult->pdispVal= static_cast<IDispatch*>( this); + AddRef(); + ret= S_OK; + } + } +// --------- + // function: _GetValueObject + else if( dispidMember == DISPID_JSCRIPT_VALUE_FUNC) + { + bHandled= sal_True; + if( !pvarResult) + ret= E_POINTER; + CComObject< JScriptValue>* pValue; + if( SUCCEEDED( CComObject<JScriptValue>::CreateInstance( &pValue))) + { + pValue->AddRef(); + pvarResult->vt= VT_DISPATCH; +#ifdef __MINGW32__ + pvarResult->pdispVal= CComQIPtr<IDispatch, &__uuidof(IDispatch)>(pValue->GetUnknown()); +#else + pvarResult->pdispVal= CComQIPtr<IDispatch>(pValue->GetUnknown()); +#endif + ret= S_OK; + } + else + ret= DISP_E_EXCEPTION; + } + else if( dispidMember == DISPID_GET_STRUCT_FUNC) + { + bHandled= sal_True; + sal_Bool bStruct= sal_False; + + + Reference<XInterface> xIntCore= m_smgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection")); + Reference<XIdlReflection> xRefl( xIntCore, UNO_QUERY); + if( xRefl.is() ) + { + // the first parameter is in DISPPARAMS rgvargs contains the name of the struct. + CComVariant arg; + if( pdispparams->cArgs == 1 && SUCCEEDED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0])) ) + { + Reference<XIdlClass> classStruct= xRefl->forName( reinterpret_cast<const sal_Unicode*>(arg.bstrVal)); + if( classStruct.is()) + { + Any anyStruct; + classStruct->createObject( anyStruct); + CComVariant var; + anyToVariant( &var, anyStruct ); + + if( var.vt == VT_DISPATCH) + { + VariantCopy( pvarResult, & var); + bStruct= sal_True; + } + } + } + } + ret= bStruct == sal_True ? S_OK : DISP_E_EXCEPTION; + } + else if (dispidMember == DISPID_CREATE_TYPE_FUNC) + { + bHandled= sal_True; + if( !pvarResult) + ret= E_POINTER; + // the first parameter is in DISPPARAMS rgvargs contains the name of the struct. + CComVariant arg; + if( pdispparams->cArgs != 1) + return DISP_E_BADPARAMCOUNT; + if (FAILED( arg.ChangeType( VT_BSTR, &pdispparams->rgvarg[0]))) + return DISP_E_BADVARTYPE; + + //check if the provided name represents a valid type + Type type; + if (getType(arg.bstrVal, type) == false) + { + writeExcepinfo(pexcepinfo,OUString( + OUSTR("[automation bridge] A UNO type with the name ") + + OUString(reinterpret_cast<const sal_Unicode*>(arg.bstrVal)) + OUSTR(" does not exist!"))); + return DISP_E_EXCEPTION; + } + + if (createUnoTypeWrapper(arg.bstrVal, pvarResult) == false) + { + writeExcepinfo(pexcepinfo,OUSTR("[automation bridge] InterfaceOleWrapper_Impl::InvokeGeneral\n" + "Could not initialize UnoTypeWrapper object!")); + return DISP_E_EXCEPTION; + } + } + } + catch(BridgeRuntimeError & e) + { + writeExcepinfo(pexcepinfo, e.message); + ret = DISP_E_EXCEPTION; + } + catch(Exception & e) + { + OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n") + + e.Message; + writeExcepinfo(pexcepinfo, message); + ret = DISP_E_EXCEPTION; + } + catch( ... ) + { + OUString message= OUSTR("InterfaceOleWrapper_Impl::InvokeGeneral : \n" + "Unexpected exception"); + writeExcepinfo(pexcepinfo, message); + ret = DISP_E_EXCEPTION; + } + return ret; +} + + + + +STDMETHODIMP InterfaceOleWrapper_Impl::GetDispID(BSTR /*bstrName*/, DWORD /*grfdex*/, DISPID __RPC_FAR* /*pid*/) +{ + HRESULT ret = ResultFromScode(E_NOTIMPL); + + return ret; +} + +STDMETHODIMP InterfaceOleWrapper_Impl::InvokeEx( + /* [in] */ DISPID /*id*/, + /* [in] */ LCID /*lcid*/, + /* [in] */ WORD /*wFlags*/, + /* [in] */ DISPPARAMS __RPC_FAR* /*pdp*/, + /* [out] */ VARIANT __RPC_FAR* /*pvarRes*/, + /* [out] */ EXCEPINFO __RPC_FAR* /*pei*/, + /* [unique][in] */ IServiceProvider __RPC_FAR* /*pspCaller*/) +{ + HRESULT ret = ResultFromScode(E_NOTIMPL); + + return ret; +} + + +STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByName( + /* [in] */ BSTR /*bstr*/, + /* [in] */ DWORD /*grfdex*/) +{ + HRESULT ret = ResultFromScode(E_NOTIMPL); + + return ret; +} + +STDMETHODIMP InterfaceOleWrapper_Impl::DeleteMemberByDispID(DISPID /*id*/) +{ + HRESULT ret = ResultFromScode(E_NOTIMPL); + + return ret; +} + +STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberProperties( + /* [in] */ DISPID /*id*/, + /* [in] */ DWORD /*grfdexFetch*/, + /* [out] */ DWORD __RPC_FAR* /*pgrfdex*/) +{ + HRESULT ret = ResultFromScode(E_NOTIMPL); + + return ret; +} + +STDMETHODIMP InterfaceOleWrapper_Impl::GetMemberName( + /* [in] */ DISPID /*id*/, + /* [out] */ BSTR __RPC_FAR* /*pbstrName*/) +{ + HRESULT ret = ResultFromScode(E_NOTIMPL); + + return ret; +} + +STDMETHODIMP InterfaceOleWrapper_Impl::GetNextDispID( + /* [in] */ DWORD /*grfdex*/, + /* [in] */ DISPID /*id*/, + /* [out] */ DISPID __RPC_FAR* /*pid*/) +{ + HRESULT ret = ResultFromScode(E_NOTIMPL); + + return ret; +} + +STDMETHODIMP InterfaceOleWrapper_Impl::GetNameSpaceParent( + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR* /*ppunk*/) +{ + HRESULT ret = ResultFromScode(E_NOTIMPL); + + return ret; +} + + +/************************************************************************* + + UnoObjectWrapperRemoteOpt + +*************************************************************************/ +UnoObjectWrapperRemoteOpt::UnoObjectWrapperRemoteOpt( Reference<XMultiServiceFactory>& aFactory, + sal_uInt8 unoWrapperClass, sal_uInt8 comWrapperClass): +InterfaceOleWrapper_Impl( aFactory, unoWrapperClass, comWrapperClass), +m_currentId(1) + +{ +} +UnoObjectWrapperRemoteOpt::~UnoObjectWrapperRemoteOpt() +{ +} + +// UnoConversionUtilities +Reference< XInterface > UnoObjectWrapperRemoteOpt::createUnoWrapperInstance() +{ + Reference<XWeak> xWeak= static_cast<XWeak*>( new UnoObjectWrapperRemoteOpt( + m_smgr, m_nUnoWrapperClass, m_nComWrapperClass)); + return Reference<XInterface>( xWeak, UNO_QUERY); +} + +STDMETHODIMP UnoObjectWrapperRemoteOpt::GetIDsOfNames ( REFIID /*riid*/, OLECHAR ** rgszNames, unsigned int cNames, + LCID /*lcid*/, DISPID * rgdispid ) +{ + MutexGuard guard( getBridgeMutex()); + + if( ! rgdispid) + return E_POINTER; + HRESULT ret = E_UNEXPECTED; + // ---------------------------------------- + // _GetValueObject + if( ! wcscmp( *rgszNames, JSCRIPT_VALUE_FUNC)) + { + *rgdispid= DISPID_JSCRIPT_VALUE_FUNC; + return S_OK; + } + else if( ! wcscmp( *rgszNames, GET_STRUCT_FUNC)) + { + *rgdispid= DISPID_GET_STRUCT_FUNC; + return S_OK; + } + + // ---------------------------------------- + if (m_xInvocation.is() && (cNames > 0)) + { + OUString name(reinterpret_cast<const sal_Unicode*>(rgszNames[0])); + // has this name been determined as "bad" + BadNameMap::iterator badIter= m_badNameMap.find( name); + if( badIter == m_badNameMap.end() ) + { + // name has not been bad before( member exists + typedef NameToIdMap::iterator ITnames; + pair< ITnames, bool > pair_id= m_nameToDispIdMap.insert( NameToIdMap::value_type(name, m_currentId++)); + // new ID inserted ? + if( pair_id.second ) + {// yes, now create MemberInfo and ad to IdToMemberInfoMap + MemberInfo d(0, name); + m_idToMemberInfoMap.insert( IdToMemberInfoMap::value_type( m_currentId - 1, d)); + } + + *rgdispid = pair_id.first->second; + ret = S_OK; + } + else + ret= DISP_E_UNKNOWNNAME; + } + return ret; +} + +STDMETHODIMP UnoObjectWrapperRemoteOpt::Invoke ( DISPID dispidMember, REFIID /*riid*/, LCID /*lcid*/, unsigned short wFlags, + DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, + unsigned int * puArgErr ) +{ + HRESULT ret = S_OK; + try + { + sal_Bool bHandled= sal_False; + ret= InvokeGeneral( dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, + puArgErr, bHandled); + if( bHandled) + return ret; + + if ( dispidMember > 0 && m_xInvocation.is()) + { + + IdToMemberInfoMap::iterator it_MemberInfo= m_idToMemberInfoMap.find( dispidMember); + if( it_MemberInfo != m_idToMemberInfoMap.end() ) + { + MemberInfo& info= it_MemberInfo->second; + + Sequence<Any> params; // holds converted any s + if( ! info.flags ) + { // DISPID called for the first time + if( wFlags == DISPATCH_METHOD ) + { + convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); + + if( FAILED( ret= doInvoke( pdispparams, pvarResult, + pexcepinfo, puArgErr, info.name, params)) + && ret == DISP_E_MEMBERNOTFOUND) + { + // try to get the exact name + OUString exactName; + if (m_xExactName.is()) + { + exactName = m_xExactName->getExactName( info.name); + // invoke again + if( exactName.getLength() != 0) + { + if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult, + pexcepinfo, puArgErr, exactName, params))) + info.name= exactName; + } + } + } + if( SUCCEEDED( ret ) ) + info.flags= DISPATCH_METHOD; + } //if( wFlags == DISPATCH_METHOD ) + + else if( wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_PROPERTYPUTREF) + { + convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); + if( FAILED( ret= doSetProperty( pdispparams, pvarResult, + pexcepinfo, puArgErr, info.name, params)) + && ret == DISP_E_MEMBERNOTFOUND) + { + // try to get the exact name + OUString exactName; + if (m_xExactName.is()) + { + exactName = m_xExactName->getExactName( info.name); + // invoke again + if( exactName.getLength() != 0) + { + if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult, + pexcepinfo, puArgErr, exactName, params))) + info.name= exactName; + } + } + } + if( SUCCEEDED( ret ) ) + info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET; + } + + else if( wFlags == DISPATCH_PROPERTYGET) + { + if( FAILED( ret= doGetProperty( pdispparams, pvarResult, + pexcepinfo, info.name)) + && ret == DISP_E_MEMBERNOTFOUND) + { + // try to get the exact name + OUString exactName; + if (m_xExactName.is()) + { + exactName = m_xExactName->getExactName( info.name); + // invoke again + if( exactName.getLength() != 0) + { + if( SUCCEEDED( ret= doGetProperty( pdispparams, pvarResult, + pexcepinfo, exactName))) + info.name= exactName; + } + } + } + if( SUCCEEDED( ret ) ) + info.flags= DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT; + } + else if( wFlags & DISPATCH_METHOD && + (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF)) + { + + OUString exactName; + // convert params for DISPATCH_METHOD or DISPATCH_PROPERTYPUT + convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); + // try first as method + if( FAILED( ret= doInvoke( pdispparams, pvarResult, + pexcepinfo, puArgErr, info.name, params)) + && ret == DISP_E_MEMBERNOTFOUND) + { + // try to get the exact name + if (m_xExactName.is()) + { + exactName = m_xExactName->getExactName( info.name); + // invoke again + if( exactName.getLength() != 0) + { + if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult, + pexcepinfo, puArgErr, exactName, params))) + info.name= exactName; + } + } + } + if( SUCCEEDED( ret ) ) + info.flags= DISPATCH_METHOD; + + // try as property + if( FAILED( ret) && pdispparams->cArgs == 1) + { + if( FAILED( ret= doSetProperty( pdispparams, pvarResult, + pexcepinfo, puArgErr, info.name, params)) + && ret == DISP_E_MEMBERNOTFOUND) + { + // try to get the exact name + if( exactName.getLength() != 0) + { + if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult, + pexcepinfo, puArgErr, exactName, params))) + info.name= exactName; + } + } + if( SUCCEEDED( ret ) ) + info.flags= DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYGET; + } + } + else if( wFlags & DISPATCH_METHOD && wFlags & DISPATCH_PROPERTYGET) + { + OUString exactName; + convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); + + if( FAILED( ret= doInvoke( pdispparams, pvarResult, + pexcepinfo, puArgErr, info.name, params)) + && ret == DISP_E_MEMBERNOTFOUND) + { + // try to get the exact name + if (m_xExactName.is()) + { + exactName = m_xExactName->getExactName( info.name); + // invoke again + if( exactName.getLength() != 0) + { + if( SUCCEEDED( ret= doInvoke( pdispparams, pvarResult, + pexcepinfo, puArgErr, exactName, params))) + info.name= exactName; + } + } + } + if( SUCCEEDED( ret ) ) + info.flags= DISPATCH_METHOD; + + // try as property + if( FAILED( ret) && pdispparams->cArgs == 1) + { + if( FAILED( ret= doGetProperty( pdispparams, pvarResult, + pexcepinfo, info.name)) + && ret == DISP_E_MEMBERNOTFOUND) + { + if( exactName.getLength() != 0) + { + if( SUCCEEDED( ret= doSetProperty( pdispparams, pvarResult, + pexcepinfo, puArgErr, exactName, params))) + info.name= exactName; + } + } + if( SUCCEEDED( ret ) ) + info.flags= DISPATCH_PROPERTYGET; + } + } + + // update nformation about this member + if( ret == DISP_E_MEMBERNOTFOUND) + { + // Remember the name as not existing + // and remove the MemberInfo + m_badNameMap[info.name]= sal_False; + m_idToMemberInfoMap.erase( it_MemberInfo); + } + } // if( ! info.flags ) + else // IdToMemberInfoMap contains a MemberInfo + { + if( wFlags & DISPATCH_METHOD && info.flags == DISPATCH_METHOD) + { + convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); + ret= doInvoke( pdispparams, pvarResult, + pexcepinfo, puArgErr, info.name, params); + } + else if( (wFlags & DISPATCH_PROPERTYPUT || wFlags & DISPATCH_PROPERTYPUTREF ) && + info.flags & DISPATCH_PROPERTYPUT) + { + convertDispparamsArgs(dispidMember, wFlags, pdispparams, params ); + ret= doSetProperty( pdispparams, pvarResult, + pexcepinfo, puArgErr, info.name, params); + } + else if( (wFlags & DISPATCH_PROPERTYGET) && ( info.flags & DISPATCH_PROPERTYGET)) + { + ret= doGetProperty( pdispparams, pvarResult, + pexcepinfo, info.name); + } + else + { + ret= DISP_E_MEMBERNOTFOUND; + } + } + }// if( it_MemberInfo != m_idToMemberInfoMap.end() ) + else + ret= DISP_E_MEMBERNOTFOUND; + } + } + catch(BridgeRuntimeError& e) + { + writeExcepinfo(pexcepinfo, e.message); + ret = DISP_E_EXCEPTION; + } + catch(Exception& e) + { + OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n") + + e.Message; + writeExcepinfo(pexcepinfo, message); + ret = DISP_E_EXCEPTION; + } + catch(...) + { + OUString message= OUSTR("UnoObjectWrapperRemoteOpt::Invoke : \n" + "Unexpected exception"); + writeExcepinfo(pexcepinfo, message); + ret = DISP_E_EXCEPTION; + } + + return ret; +} + +HRESULT UnoObjectWrapperRemoteOpt::methodInvoke( DISPID /*dispidMember*/, DISPPARAMS * /*pdispparams*/, VARIANT * /*pvarResult*/, + EXCEPINFO * /*pexcepinfo*/, unsigned int * /*puArgErr*/, Sequence<Any> params) +{ + return S_OK; +} + + +// The returned HRESULT is only appropriate for IDispatch::Invoke +static HRESULT mapCannotConvertException( CannotConvertException e, unsigned int * puArgErr) +{ + HRESULT ret; + sal_Bool bWriteIndex= sal_True; + + switch ( e.Reason) + { + case FailReason::OUT_OF_RANGE: + ret = DISP_E_OVERFLOW; + break; + case FailReason::IS_NOT_NUMBER: + ret = DISP_E_TYPEMISMATCH; + break; + case FailReason::IS_NOT_ENUM: + ret = DISP_E_TYPEMISMATCH; + break; + case FailReason::IS_NOT_BOOL: + ret = DISP_E_TYPEMISMATCH; + break; + case FailReason::NO_SUCH_INTERFACE: + ret = DISP_E_TYPEMISMATCH; + break; + case FailReason::SOURCE_IS_NO_DERIVED_TYPE: + ret = DISP_E_TYPEMISMATCH; + break; + case FailReason::TYPE_NOT_SUPPORTED: + ret = DISP_E_TYPEMISMATCH; + break; + case FailReason::INVALID: + ret = DISP_E_TYPEMISMATCH; + break; + case FailReason::NO_DEFAULT_AVAILABLE: + ret = DISP_E_BADPARAMCOUNT; + break; + case FailReason::UNKNOWN: + ret = E_UNEXPECTED; + break; + default: + ret = E_UNEXPECTED; + bWriteIndex= sal_False; + break; + } + + if( bWriteIndex && puArgErr != NULL) + *puArgErr = e.ArgumentIndex; + return ret; +} + +// The function maps the TypeClass of the any to VARTYPE: If +// the Any contains STRUCT or INTERFACE then the return value +// is VT_DISPATCH. The function is used from o2u_createUnoObjectWrapper +// and the result is put into the constructor of the uno - wrapper +// object. If a client asks the object for DISPID_VALUE and this +// funtion returned VT_DISPATCH then the IDispatch of the same +// object is being returned. +// See InterfaceOleWrapper_Impl::Invoke, InterfaceOleWrapper_Impl::m_defaultValueType +const VARTYPE getVarType( const Any& value) +{ + VARTYPE ret= VT_EMPTY; + + switch ( value.getValueTypeClass()) + { + case TypeClass_STRUCT: ret= VT_DISPATCH; break; + case TypeClass_INTERFACE: ret= VT_DISPATCH; break; + default: break; + } + return ret; +} + + + + +} // end namespace |