diff options
Diffstat (limited to 'extensions/source/ole/oleobjw.cxx')
-rw-r--r-- | extensions/source/ole/oleobjw.cxx | 299 |
1 files changed, 278 insertions, 21 deletions
diff --git a/extensions/source/ole/oleobjw.cxx b/extensions/source/ole/oleobjw.cxx index 4c772288fe16..80517c680e01 100644 --- a/extensions/source/ole/oleobjw.cxx +++ b/extensions/source/ole/oleobjw.cxx @@ -75,6 +75,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; using ::rtl::OUString; using ::rtl::OString; @@ -160,8 +161,8 @@ Any IUnknownWrapper_Impl::queryInterface(const Type& t) if ( ( t == getCppuType(static_cast<Reference<XInvocation>*>( 0)) || t == getCppuType(static_cast<Reference<XAutomationInvocation>*>( 0)) ) && !m_spDispatch) return Any(); - return WeakImplHelper6<XAutomationInvocation, 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) @@ -1242,7 +1243,7 @@ Any IUnknownWrapper_Impl::invokeWithDispIdUnoTlb(const OUString& sFunctionName, - // -------------------------- +// -------------------------- // XInitialization void SAL_CALL IUnknownWrapper_Impl::initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException) { @@ -1325,6 +1326,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(); + + sal_Int32 nInd = 0; + try + { + sal_Int32 revIndex = 0; + for ( nInd = 0; nInd < sal_Int32(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() { @@ -1668,22 +1937,6 @@ Any IUnknownWrapper_Impl::invokeWithDispIdComTlb(FuncDesc& aFuncDesc, throw IllegalArgumentException( buf.makeStringAndClear(), Reference<XInterface>(), (sal_Int16) i); } - //make sure we get no void any for an in parameter. In StarBasic - //this may be caused by - // Dim arg - // obj.func(arg) - //A void any is allowed if the parameter is optional - if ( ! (aFuncDesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOPT) - && (i < nUnoArgs) && (paramFlags & PARAMFLAG_FIN) && - Params.getConstArray()[i].getValueTypeClass() == TypeClass_VOID) - { - OUStringBuffer buf(256); - buf.appendAscii("ole automation bridge: The argument at position: "); - buf.append(OUString::valueOf((sal_Int32) i)); - buf.appendAscii(" (index starts with 0) is uninitialized."); - throw IllegalArgumentException( buf.makeStringAndClear(), - Reference<XInterface>(), (sal_Int16) i); - } // Property Put arguments if (anyArg.getValueType() == getCppuType((PropertyPutArgument*)0)) @@ -1796,12 +2049,16 @@ Any IUnknownWrapper_Impl::invokeWithDispIdComTlb(FuncDesc& aFuncDesc, & aFuncDesc->lprgelemdescParam[i].paramdesc. pparamdescex->varDefaultValue); } - else + else if (paramFlags & PARAMFLAG_FOPT) { - OSL_ASSERT(paramFlags & PARAMFLAG_FOPT); arArgs[revIndex].vt = VT_ERROR; arArgs[revIndex].scode = DISP_E_PARAMNOTFOUND; } + else + { + arArgs[revIndex].vt = VT_EMPTY; + arArgs[revIndex].lVal = 0; + } } } } |