diff options
Diffstat (limited to 'extensions')
-rwxr-xr-x | extensions/source/ole/oleobjw.cxx | 275 | ||||
-rw-r--r-- | extensions/source/ole/oleobjw.hxx | 15 |
2 files changed, 284 insertions, 6 deletions
diff --git a/extensions/source/ole/oleobjw.cxx b/extensions/source/ole/oleobjw.cxx index 89cb5625bca3..4ec4287754b8 100755 --- a/extensions/source/ole/oleobjw.cxx +++ b/extensions/source/ole/oleobjw.cxx @@ -74,6 +74,7 @@ using namespace com::sun::star::lang; using namespace com::sun::star::bridge; using namespace com::sun::star::bridge::oleautomation; using namespace com::sun::star::bridge::ModelDependent; +using namespace ::com::sun::star; #define JSCRIPT_ID_PROPERTY L"_environment" #define JSCRIPT_ID L"jscript" @@ -155,8 +156,8 @@ Any IUnknownWrapper_Impl::queryInterface(const Type& t) if (t == getCppuType(static_cast<Reference<XInvocation>*>( 0)) && !m_spDispatch) return Any(); - return WeakImplHelper6<XInvocation, XBridgeSupplier2, - XInitialization, XAutomationObject, XDefaultProperty, XDefaultMethod>::queryInterface(t); + return WeakImplHelper7<XInvocation, XBridgeSupplier2, + XInitialization, XAutomationObject, XDefaultProperty, XDefaultMethod, XDirectInvocation>::queryInterface(t); } Reference<XIntrospectionAccess> SAL_CALL IUnknownWrapper_Impl::getIntrospection(void) @@ -1174,7 +1175,7 @@ Any IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString& sFunctionName, - // -------------------------- +// -------------------------- // XInitialization void SAL_CALL IUnknownWrapper_Impl::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException) { @@ -1257,6 +1258,274 @@ void SAL_CALL IUnknownWrapper_Impl::initialize( const Sequence< Any >& aArgument } } +// -------------------------- +// XDirectInvocation +uno::Any SAL_CALL IUnknownWrapper_Impl::directInvoke( const ::rtl::OUString& aName, const uno::Sequence< uno::Any >& aParams ) + throw (lang::IllegalArgumentException, script::CannotConvertException, reflection::InvocationTargetException, uno::RuntimeException) +{ + Any aResult; + + if ( !m_spDispatch ) + { + throw RuntimeException( + OUSTR("[automation bridge] The object does not have an IDispatch interface"), + Reference<XInterface>()); + } + + o2u_attachCurrentThread(); + DISPID dispid; + if ( !getDispid( aName, &dispid ) ) + throw IllegalArgumentException( + OUSTR( "[automation bridge] The object does not have a function or property " ) + + aName, Reference<XInterface>(), 0); + + CComVariant varResult; + ExcepInfo excepinfo; + unsigned int uArgErr = 0; + INVOKEKIND pInvkinds[2]; + pInvkinds[0] = INVOKE_FUNC; + pInvkinds[1] = aParams.getLength() ? INVOKE_PROPERTYPUT : INVOKE_PROPERTYGET; + HRESULT hInvRes = E_FAIL; + + // try Invoke first, if it does not work, try put/get property + for ( sal_Int32 nStep = 0; FAILED( hInvRes ) && nStep < 2; nStep++ ) + { + DISPPARAMS dispparams = {NULL, NULL, 0, 0}; + + DISPID idPropertyPut = DISPID_PROPERTYPUT; + scoped_array<DISPID> arDispidNamedArgs; + scoped_array<CComVariant> ptrArgs; + scoped_array<CComVariant> ptrRefArgs; // referenced arguments + CComVariant * arArgs = NULL; + CComVariant * arRefArgs = NULL; + bool bVarargParam = false; + + dispparams.cArgs = aParams.getLength(); + + // Determine the number of named arguments + for ( sal_Int32 nInd = 0; nInd < aParams.getLength(); nInd++ ) + if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0) ) + dispparams.cNamedArgs ++; + + // fill the named arguments + if ( dispparams.cNamedArgs > 0 + && !( dispparams.cNamedArgs == 1 && pInvkinds[nStep] == INVOKE_PROPERTYPUT ) ) + { + int nSizeAr = dispparams.cNamedArgs + 1; + if ( pInvkinds[nStep] == INVOKE_PROPERTYPUT ) + nSizeAr = dispparams.cNamedArgs; + + scoped_array<OLECHAR*> saNames(new OLECHAR*[nSizeAr]); + OLECHAR ** pNames = saNames.get(); + pNames[0] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(aName.getStr())); + + int cNamedArg = 0; + for ( size_t nInd = 0; nInd < dispparams.cArgs; nInd++ ) + { + if ( aParams[nInd].getValueType() == getCppuType((NamedArgument*) 0)) + { + const NamedArgument& arg = *(NamedArgument const*)aParams[nInd].getValue(); + + //We put the parameter names in reverse order into the array, + //so we can use the DISPID array for DISPPARAMS::rgdispidNamedArgs + //The first name in the array is the method name + pNames[nSizeAr - 1 - cNamedArg++] = const_cast<OLECHAR*>(reinterpret_cast<LPCOLESTR>(arg.Name.getStr())); + } + } + + arDispidNamedArgs.reset( new DISPID[nSizeAr] ); + HRESULT hr = getTypeInfo()->GetIDsOfNames( pNames, nSizeAr, arDispidNamedArgs.get() ); + if ( hr == E_NOTIMPL ) + hr = m_spDispatch->GetIDsOfNames(IID_NULL, pNames, nSizeAr, LOCALE_USER_DEFAULT, arDispidNamedArgs.get() ); + + if ( SUCCEEDED( hr ) ) + { + if ( pInvkinds[nStep] == DISPATCH_PROPERTYPUT ) + { + DISPID* arIDs = arDispidNamedArgs.get(); + arIDs[0] = DISPID_PROPERTYPUT; + dispparams.rgdispidNamedArgs = arIDs; + } + else + { + DISPID* arIDs = arDispidNamedArgs.get(); + dispparams.rgdispidNamedArgs = & arIDs[1]; + } + } + else if (hr == DISP_E_UNKNOWNNAME) + { + throw IllegalArgumentException( + OUSTR("[automation bridge]One of the named arguments is wrong!"), + Reference<XInterface>(), 0); + } + else + { + throw InvocationTargetException( + OUSTR("[automation bridge] ITypeInfo::GetIDsOfNames returned error ") + + OUString::valueOf((sal_Int32) hr, 16), Reference<XInterface>(), Any()); + } + } + + //Convert arguments + ptrArgs.reset(new CComVariant[dispparams.cArgs]); + ptrRefArgs.reset(new CComVariant[dispparams.cArgs]); + arArgs = ptrArgs.get(); + arRefArgs = ptrRefArgs.get(); + + size_t nInd = 0; + try + { + sal_Int32 revIndex = 0; + for ( nInd = 0; nInd < dispparams.cArgs; nInd++) + { + revIndex = dispparams.cArgs - nInd - 1; + arRefArgs[revIndex].byref = 0; + Any anyArg; + if ( nInd < aParams.getLength() ) + anyArg = aParams.getConstArray()[nInd]; + + // Property Put arguments + if ( anyArg.getValueType() == getCppuType((PropertyPutArgument*)0) ) + { + PropertyPutArgument arg; + anyArg >>= arg; + anyArg <<= arg.Value; + } + // named argument + if (anyArg.getValueType() == getCppuType((NamedArgument*) 0)) + { + NamedArgument aNamedArgument; + anyArg >>= aNamedArgument; + anyArg <<= aNamedArgument.Value; + } + + if ( nInd < aParams.getLength() && anyArg.getValueTypeClass() != TypeClass_VOID ) + { + anyToVariant( &arArgs[revIndex], anyArg, VT_VARIANT ); + } + else + { + arArgs[revIndex].vt = VT_ERROR; + arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND; + } + } + } + catch (IllegalArgumentException & e) + { + e.ArgumentPosition = ::sal::static_int_cast< sal_Int16, sal_Int32 >( nInd ); + throw; + } + catch (CannotConvertException & e) + { + e.ArgumentIndex = nInd; + throw; + } + + dispparams.rgvarg = arArgs; + // invoking OLE method + DWORD localeId = LOCALE_USER_DEFAULT; + hInvRes = m_spDispatch->Invoke( dispid, + IID_NULL, + localeId, + ::sal::static_int_cast< WORD, INVOKEKIND >( pInvkinds[nStep] ), + &dispparams, + &varResult, + &excepinfo, + &uArgErr); + } + + // converting return value and out parameter back to UNO + if ( SUCCEEDED( hInvRes ) ) + variantToAny( &varResult, aResult, sal_False ); + else + { + // map error codes to exceptions + OUString message; + switch ( hInvRes ) + { + case S_OK: + break; + case DISP_E_BADPARAMCOUNT: + throw IllegalArgumentException(OUSTR("[automation bridge] Wrong " + "number of arguments. Object returned DISP_E_BADPARAMCOUNT."), + 0, 0); + break; + case DISP_E_BADVARTYPE: + throw RuntimeException(OUSTR("[automation bridge] One or more " + "arguments have the wrong type. Object returned " + "DISP_E_BADVARTYPE."), 0); + break; + case DISP_E_EXCEPTION: + message = OUSTR("[automation bridge]: "); + message += OUString(reinterpret_cast<const sal_Unicode*>(excepinfo.bstrDescription), + ::SysStringLen(excepinfo.bstrDescription)); + throw InvocationTargetException(message, Reference<XInterface>(), Any()); + break; + case DISP_E_MEMBERNOTFOUND: + message = OUSTR("[automation bridge]: A function with the name \"") + + aName + OUSTR("\" is not supported. Object returned " + "DISP_E_MEMBERNOTFOUND."); + throw IllegalArgumentException(message, 0, 0); + break; + case DISP_E_NONAMEDARGS: + throw IllegalArgumentException(OUSTR("[automation bridge] Object " + "returned DISP_E_NONAMEDARGS"),0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); + break; + case DISP_E_OVERFLOW: + throw CannotConvertException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[automation bridge] Call failed.")), + static_cast<XInterface*>( + static_cast<XWeak*>(this)), TypeClass_UNKNOWN, FailReason::OUT_OF_RANGE, uArgErr); + break; + case DISP_E_PARAMNOTFOUND: + throw IllegalArgumentException(OUSTR("[automation bridge]Call failed." + "Object returned DISP_E_PARAMNOTFOUND."), + 0, ::sal::static_int_cast< sal_Int16, unsigned int >( uArgErr )); + break; + case DISP_E_TYPEMISMATCH: + throw CannotConvertException(OUSTR("[automation bridge] Call failed. " + "Object returned DISP_E_TYPEMISMATCH"), + static_cast<XInterface*>( + static_cast<XWeak*>(this)) , TypeClass_UNKNOWN, FailReason::UNKNOWN, uArgErr); + break; + case DISP_E_UNKNOWNINTERFACE: + throw RuntimeException(OUSTR("[automation bridge] Call failed. " + "Object returned DISP_E_UNKNOWNINTERFACE."),0); + break; + case DISP_E_UNKNOWNLCID: + throw RuntimeException(OUSTR("[automation bridge] Call failed. " + "Object returned DISP_E_UNKNOWNLCID."),0); + break; + case DISP_E_PARAMNOTOPTIONAL: + throw CannotConvertException(OUSTR("[automation bridge] Call failed." + "Object returned DISP_E_PARAMNOTOPTIONAL"), + static_cast<XInterface*>(static_cast<XWeak*>(this)), + TypeClass_UNKNOWN, FailReason::NO_DEFAULT_AVAILABLE, uArgErr); + break; + default: + throw RuntimeException(); + break; + } + } + + return aResult; +} + +::sal_Bool SAL_CALL IUnknownWrapper_Impl::hasMember( const ::rtl::OUString& aName ) + throw (uno::RuntimeException) +{ + if ( ! m_spDispatch ) + { + throw RuntimeException( + OUSTR("[automation bridge] The object does not have an IDispatch interface"), + Reference<XInterface>()); + } + + o2u_attachCurrentThread(); + DISPID dispid; + return getDispid( aName, &dispid ); +} + + // UnoConversionUtilities -------------------------------------------------------------------------------- Reference< XInterface > IUnknownWrapper_Impl::createUnoWrapperInstance() { diff --git a/extensions/source/ole/oleobjw.hxx b/extensions/source/ole/oleobjw.hxx index b990ac3af17d..fa796013946e 100644 --- a/extensions/source/ole/oleobjw.hxx +++ b/extensions/source/ole/oleobjw.hxx @@ -50,7 +50,7 @@ #endif #include <cppuhelper/implbase3.hxx> #include <cppuhelper/implbase4.hxx> -#include <cppuhelper/implbase6.hxx> +#include <cppuhelper/implbase7.hxx> #include <com/sun/star/lang/XInitialization.hpp> #include <com/sun/star/bridge/oleautomation/XAutomationObject.hpp> @@ -58,6 +58,7 @@ #include <com/sun/star/script/XDefaultProperty.hpp> #include <com/sun/star/script/XDefaultMethod.hpp> +#include <com/sun/star/script/XDirectInvocation.hpp> #include <typelib/typedescription.hxx> #include "unoconversionutilities.hxx" @@ -81,7 +82,7 @@ typedef hash_multimap<OUString, unsigned int, hashOUString_Impl, equalOUString_I // This class wraps an IDispatch and maps XInvocation calls to IDispatch calls on the wrapped object. // If m_TypeDescription is set then this class represents an UNO interface implemented in a COM component. // The interface is not a real interface in terms of an abstract class but is realized through IDispatch. -class IUnknownWrapper_Impl : public WeakImplHelper6<XInvocation, XBridgeSupplier2, XInitialization, XAutomationObject, XDefaultProperty, XDefaultMethod>, +class IUnknownWrapper_Impl : public WeakImplHelper7< XInvocation, XBridgeSupplier2, XInitialization, XAutomationObject, XDefaultProperty, XDefaultMethod, XDirectInvocation >, public UnoConversionUtilities<IUnknownWrapper_Impl> @@ -130,10 +131,18 @@ public: // XInitialization virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException); + + // XDefaultProperty virtual ::rtl::OUString SAL_CALL getDefaultPropertyName( ) throw (::com::sun::star::uno::RuntimeException) { return m_sDefaultMember; } -protected: + + // XDefaultMethod virtual ::rtl::OUString SAL_CALL getDefaultMethodName( ) throw (::com::sun::star::uno::RuntimeException) { return m_sDefaultMember; } + // XDirectInvocation + virtual ::com::sun::star::uno::Any SAL_CALL directInvoke( const ::rtl::OUString& aName, const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aParams ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::script::CannotConvertException, ::com::sun::star::reflection::InvocationTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL hasMember( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException); + +protected: // ---------------------------------------------------------------------------- virtual Any invokeWithDispIdUnoTlb(const OUString& sFunctionName, const Sequence< Any >& Params, |