summaryrefslogtreecommitdiff
path: root/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'extensions')
-rw-r--r--extensions/source/ole/unoobjw.cxx66
1 files changed, 53 insertions, 13 deletions
diff --git a/extensions/source/ole/unoobjw.cxx b/extensions/source/ole/unoobjw.cxx
index 35a70c5aa8d8..083688683e0b 100644
--- a/extensions/source/ole/unoobjw.cxx
+++ b/extensions/source/ole/unoobjw.cxx
@@ -1253,8 +1253,35 @@ STDMETHODIMP InterfaceOleWrapper::GetIDsOfNames(REFIID /*riid*/,
void InterfaceOleWrapper::convertDispparamsArgs(DISPID id,
unsigned short /*wFlags*/, DISPPARAMS* pdispparams, Sequence<Any>& rSeq)
{
+ // Parameters come in in reverse order in pdispparams. There might be less parameters than
+ // expected. In that case, assume they are "optional" (but can't be marked as such in UNO IDL),
+ // and fill in the rest with empty Anys. There might also be more than expected. In that case,
+ // assume the oovbaapi UNO IDL hasn't kept up with added optional parameters in MSO, and just
+ // ignore the extra ones, as long as they are empty.
+
+ // An example: incoming parameters: <12, 13, "foo/bar.tem">
+ //
+ // Expected paramters: (string filename, int something, int somethingElse, Any whatever, Any
+ // whateverElse)
+ //
+ // Here the existing incoming parameters are placed in reverse order in the first three outgoing
+ // parameters, and the rest of the outgoing paramters are kept as empty Anys.
+ //
+ // Another example: incoming parameters: <EMPTY, TRUE>
+ //
+ // Expected parameters: (bool flag)
+ //
+ // Here the TRUE is passed as the sole outgoing parameter, and the incoming EMPTY is ignored.
+ //
+ // Still an example: incoming parameters: <"foo.doc", TRUE>
+ //
+ // Expected parameters: (bool flag)
+ //
+ // This throws an error as the incoming string parameter presumably should do something important,
+ // but there is no corresponding outgoing parameter.
+
HRESULT hr = S_OK;
- const int countArgs = pdispparams->cArgs;
+ const int countIncomingArgs = pdispparams->cArgs;
//Get type information for the current call
InvocationInfo info;
@@ -1263,33 +1290,39 @@ void InterfaceOleWrapper::convertDispparamsArgs(DISPID id,
"[automation bridge]InterfaceOleWrapper::convertDispparamsArgs \n"
"Could not obtain type information for current call.");
- // We accept less or even more parameters (on certain conditions) than expected. So size rSeq
- // according to the number of expected parameters.
- const int expectedArgs = info.aParamTypes.getLength();
+ // Size rSeq according to the number of expected parameters.
+ const int expectedArgs = info.aParamTypes.getLength() + (info.eMemberType == MemberType_PROPERTY ? 1 : 0);
rSeq.realloc( expectedArgs );
Any* pParams = rSeq.getArray();
Any anyParam;
- for (int i = 0; i < std::max(countArgs, expectedArgs); i++)
+ int outgoingArgIndex = 0;
+
+ // Go through incoming parameters in reverse order, i.e. in the order as declared in IDL
+ for (int i = std::max(countIncomingArgs, expectedArgs) - 1; i >= 0; i--)
{
// Ignore too many parameters if they are VT_EMPTY anyway
- if ( i < countArgs && i >= expectedArgs && pdispparams->rgvarg[i].vt == VT_EMPTY )
+ if ( outgoingArgIndex >= expectedArgs && pdispparams->rgvarg[i].vt == VT_EMPTY )
continue;
// But otherwise too many parameters is an error
- if ( i < countArgs && i >= expectedArgs )
+ if ( outgoingArgIndex >= expectedArgs )
throw BridgeRuntimeError( "[automation bridge] Too many parameters" );
if (info.eMemberType == MemberType_METHOD &&
- info.aParamModes[ expectedArgs - i - 1 ] == ParamMode_OUT)
+ info.aParamModes[ outgoingArgIndex ] == ParamMode_OUT)
+ {
+ outgoingArgIndex++;
continue;
+ }
- if (i < countArgs)
+ if (i < countIncomingArgs)
{
if(convertValueObject( & pdispparams->rgvarg[i], anyParam))
{ //a param is a ValueObject and could be converted
- pParams[ expectedArgs - i - 1 ] = anyParam;
+ pParams[ outgoingArgIndex ] = anyParam;
+ outgoingArgIndex++;
continue;
}
}
@@ -1297,6 +1330,7 @@ void InterfaceOleWrapper::convertDispparamsArgs(DISPID id,
{
// A missing arg. Let's hope it is de facto optional (there is no way in UNO IDL to mark
// a parameter as optional). The corresponding slot in pParams is already a void Any.
+ // Here we don't increase outgoingArgIndex!
continue;
}
@@ -1309,9 +1343,13 @@ void InterfaceOleWrapper::convertDispparamsArgs(DISPID id,
// Check for JScript out and in/out paramsobjects (VT_DISPATCH).
// To find them out we use typeinformation of the function being called.
+
+ // No idea how this stuff, originally written for JScript, works for other Automation
+ // clients.
+
if( pdispparams->rgvarg[i].vt == VT_DISPATCH )
{
- if( info.eMemberType == MemberType_METHOD && info.aParamModes[ expectedArgs - i - 1 ] == ParamMode_INOUT)
+ if( info.eMemberType == MemberType_METHOD && info.aParamModes[ outgoingArgIndex ] == ParamMode_INOUT)
{
// INOUT-param
// Index ( property) "0" contains the actual IN-param. The object is a JScript
@@ -1340,13 +1378,15 @@ void InterfaceOleWrapper::convertDispparamsArgs(DISPID id,
if(info.eMemberType == MemberType_METHOD)
variantToAny( & varParam, anyParam,
- info.aParamTypes[ expectedArgs - i - 1 ]);
+ info.aParamTypes[ outgoingArgIndex ]);
else if(info.eMemberType == MemberType_PROPERTY)
variantToAny( & varParam, anyParam, info.aType);
else
OSL_ASSERT(false);
- pParams[ expectedArgs - i - 1 ]= anyParam;
+ if (outgoingArgIndex < expectedArgs)
+ pParams[ outgoingArgIndex ]= anyParam;
+ outgoingArgIndex++;
}// end for / iterating over all parameters
}