summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2018-04-24 01:29:58 +0300
committerTor Lillqvist <tml@collabora.com>2018-05-31 21:55:20 +0300
commit363df7b4462d484c41cb25d96346e2b89cad208a (patch)
tree6e2b2b41c23b946f1c7b943cb927e0e69de15b32 /extensions
parentMake SAL_INFO logging style more useful (diff)
downloadcore-363df7b4462d484c41cb25d96346e2b89cad208a.tar.gz
core-363df7b4462d484c41cb25d96346e2b89cad208a.zip
Implement EnumConnections, and fix handling of mismatched parameter number
If we have too few parameters, fill with empty ones, as before. If we have more paramters than the called method expects, but the extra ones are empty anyway, ignore them. Do all of this in convertDispparamsArgs(). This improves interoperability with typical Automation clients. Change-Id: I47376993dc10b401e4c349e19b2bbe4be9f8f444
Diffstat (limited to 'extensions')
-rw-r--r--extensions/source/ole/unoobjw.cxx195
1 files changed, 159 insertions, 36 deletions
diff --git a/extensions/source/ole/unoobjw.cxx b/extensions/source/ole/unoobjw.cxx
index 9d5110e05c15..5f8f305c61fb 100644
--- a/extensions/source/ole/unoobjw.cxx
+++ b/extensions/source/ole/unoobjw.cxx
@@ -1253,15 +1253,8 @@ STDMETHODIMP InterfaceOleWrapper::GetIDsOfNames(REFIID /*riid*/,
void InterfaceOleWrapper::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;
+ HRESULT hr = S_OK;
+ const int countArgs = pdispparams->cArgs;
//Get type information for the current call
InvocationInfo info;
@@ -1270,17 +1263,42 @@ void InterfaceOleWrapper::convertDispparamsArgs(DISPID id,
"[automation bridge]InterfaceOleWrapper::convertDispparamsArgs \n"
"Could not obtain type information for current call.");
- for (int i = 0; i < countArgs; i++)
+ // 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();
+ rSeq.realloc( expectedArgs );
+ Any* pParams = rSeq.getArray();
+
+ Any anyParam;
+
+ for (int i = 0; i < std::max(countArgs, expectedArgs); i++)
{
+ // Ignore too many parameters if they are VT_EMPTY anyway
+ if ( i < countArgs && i >= expectedArgs && pdispparams->rgvarg[i].vt == VT_EMPTY )
+ continue;
+
+ // But otherwise too many parameters is an error
+ if ( i < countArgs && i >= expectedArgs )
+ throw BridgeRuntimeError( "[automation bridge] Too many parameters" );
+
if (info.eMemberType == MemberType_METHOD &&
- info.aParamModes[ countArgs - i -1 ] == ParamMode_OUT)
+ info.aParamModes[ expectedArgs - 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 (i < countArgs)
+ {
+ if(convertValueObject( & pdispparams->rgvarg[i], anyParam))
+ { //a param is a ValueObject and could be converted
+ pParams[ expectedArgs - i - 1 ] = anyParam;
+ continue;
+ }
+ }
+ else
+ {
+ // 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.
+ continue;
+ }
// If the param is an out, in/out parameter in
// JScript (Array object, with value at index 0) then we
@@ -1293,7 +1311,7 @@ void InterfaceOleWrapper::convertDispparamsArgs(DISPID id,
// 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)
+ if( info.eMemberType == MemberType_METHOD && info.aParamModes[ expectedArgs - i - 1 ] == ParamMode_INOUT)
{
// INOUT-param
// Index ( property) "0" contains the actual IN-param. The object is a JScript
@@ -1318,17 +1336,17 @@ void InterfaceOleWrapper::convertDispparamsArgs(DISPID id,
}
if( varParam.vt == VT_EMPTY) // then it was no in/out parameter
- varParam= pdispparams->rgvarg[i];
+ varParam= pdispparams->rgvarg[i];
if(info.eMemberType == MemberType_METHOD)
variantToAny( & varParam, anyParam,
- info.aParamTypes[ countArgs - i - 1]);
+ info.aParamTypes[ expectedArgs - i - 1 ]);
else if(info.eMemberType == MemberType_PROPERTY)
variantToAny( & varParam, anyParam, info.aType);
else
OSL_ASSERT(false);
- pParams[countArgs - (i + 1)]= anyParam;
+ pParams[ expectedArgs - i - 1 ]= anyParam;
}// end for / iterating over all parameters
}
@@ -1748,17 +1766,6 @@ STDMETHODIMP InterfaceOleWrapper::Invoke(DISPID dispidMember,
convertDispparamsArgs(dispidMember, wFlags, pdispparams , params );
- // Pass missing (hopefully optional) parameters as Any().
- InvocationInfo aInvocationInfo;
- getInvocationInfoForCall(dispidMember, aInvocationInfo);
- if (pdispparams->cArgs < (UINT)aInvocationInfo.aParamTypes.getLength())
- {
- params.realloc(aInvocationInfo.aParamTypes.getLength());
- Any* pParams = params.getArray();
- for (int i = pdispparams->cArgs; i < aInvocationInfo.aParamTypes.getLength(); ++i)
- pParams[i] = Any();
- }
-
ret= doInvoke(pdispparams, pvarResult,
pexcepinfo, puArgErr, d.name, params);
}
@@ -2261,6 +2268,99 @@ Sink::Call( const OUString& Method, Sequence< Any >& Arguments )
SAL_WARN("extensions.olebridge", "Sink::Call: Uknown method '" << Method << "'");
}
+class CXEnumConnections : public IEnumConnections,
+ public CComObjectRoot
+{
+public:
+ CXEnumConnections()
+ {
+ }
+
+ ~CXEnumConnections()
+ {
+ }
+
+ BEGIN_COM_MAP(CXEnumConnections)
+ COM_INTERFACE_ENTRY(IEnumConnections)
+ END_COM_MAP()
+
+ DECLARE_NOT_AGGREGATABLE(CXEnumConnections)
+
+ void Init(std::vector<IUnknown*>& rUnknowns, std::vector<DWORD>& rCookies)
+ {
+ SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Init");
+ SAL_WARN_IF(rUnknowns.size() != rCookies.size(), "extensions.olebridge", "Vectors of different size");
+ mvUnknowns = rUnknowns;
+ mvCookies = rCookies;
+ mnIndex = 0;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Next(ULONG cConnections,
+ LPCONNECTDATA rgcd,
+ ULONG *pcFetched) override
+ {
+ if (!rgcd)
+ {
+ SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections << "): E_POINTER");
+ return E_POINTER;
+ }
+
+ if (pcFetched && cConnections != 1)
+ {
+ SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections << "): E_INVALIDARG");
+ return E_POINTER;
+ }
+
+ ULONG nFetched = 0;
+ while (nFetched < cConnections && mnIndex < mvUnknowns.size())
+ {
+ rgcd[nFetched].pUnk = mvUnknowns[mnIndex];
+ rgcd[nFetched].pUnk->AddRef();
+ rgcd[nFetched].dwCookie = mvCookies[mnIndex];
+ ++nFetched;
+ ++mnIndex;
+ }
+ if (nFetched != cConnections)
+ {
+ SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections << "): S_FALSE");
+ if (pcFetched)
+ *pcFetched = nFetched;
+ return S_FALSE;
+ }
+ SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Next(" << cConnections << "): S_OK");
+ if (pcFetched)
+ *pcFetched = nFetched;
+
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Skip(ULONG cConnections) override
+ {
+ SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Skip(" << cConnections << "): E_NOTIMPL");
+
+ return E_NOTIMPL;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Reset() override
+ {
+ SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Reset: E_NOTIMPL");
+
+ return E_NOTIMPL;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Clone(IEnumConnections** /* ppEnum */) override
+ {
+ SAL_INFO("extensions.olebridge", this << "@CXEnumConnections::Clone: E_NOTIMPL");
+
+ return E_NOTIMPL;
+ }
+
+private:
+ std::vector<IUnknown*> mvUnknowns;
+ std::vector<DWORD> mvCookies;
+ ULONG mnIndex;
+};
+
class CXConnectionPoint : public IConnectionPoint,
public CComObjectRoot
{
@@ -2350,16 +2450,39 @@ public:
virtual HRESULT STDMETHODCALLTYPE EnumConnections(IEnumConnections **ppEnum) override
{
- (void) ppEnum;
- SAL_WARN("extensions.olebridge", this << "@CXConnectionPoint::EnumConnections: E_NOTIMPL");
- return E_NOTIMPL;
+ HRESULT nResult;
+
+ SAL_INFO("extensions.olebridge", this << "@CXConnectionPoint::EnumConnections...");
+
+ if (!ppEnum)
+ {
+ SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: E_POINTER");
+ return E_POINTER;
+ }
+
+ CComObject<CXEnumConnections>* pEnumConnections;
+
+ nResult = CComObject<CXEnumConnections>::CreateInstance(&pEnumConnections);
+ if (FAILED(nResult))
+ {
+ SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: " << WindowsErrorStringFromHRESULT(nResult));
+ return nResult;
+ }
+
+ pEnumConnections->AddRef();
+
+ pEnumConnections->Init(mvISinks, mvCookies);
+ *ppEnum = pEnumConnections;
+
+ SAL_INFO("extensions.olebridge", "..." << this << "@CXConnectionPoint::EnumConnections: S_OK");
+
+ return S_OK;
}
-private:
InterfaceOleWrapper* mpInterfaceOleWrapper;
std::vector<IUnknown*> mvISinks;
std::vector<Reference<ooo::vba::XSink>> mvXSinks;
- std::vector<sal_uInt32> mvCookies;
+ std::vector<DWORD> mvCookies;
Reference<XMultiServiceFactory> mxMSF;
Reference<ooo::vba::XConnectionPoint> mxCP;
ooo::vba::TypeAndIID maTypeAndIID;