summaryrefslogtreecommitdiff
path: root/extensions/source/ole/oleobjw.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/source/ole/oleobjw.cxx')
-rw-r--r--extensions/source/ole/oleobjw.cxx299
1 files changed, 278 insertions, 21 deletions
diff --git a/extensions/source/ole/oleobjw.cxx b/extensions/source/ole/oleobjw.cxx
index a8f0f5b45092..6648d1773560 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;
+ }
}
}
}