[Libreoffice-commits] core.git: extensions/source
Tor Lillqvist
tml at collabora.com
Tue May 29 12:52:03 UTC 2018
extensions/source/ole/unoobjw.cxx | 124 ++++++++++++++++++++++++++++++++++++++
1 file changed, 124 insertions(+)
New commits:
commit 52eb78c8d2c9954733d95326922462a820d9f0dd
Author: Tor Lillqvist <tml at collabora.com>
Date: Tue Feb 13 18:37:28 2018 +0200
Handle DISPID_NEWENUM
We get that when an Automation client wants to enumerate an object
that is a collection. We need to create an IEnumVARIANT object and
return it (as an IUnknown).
I wasted days on trying to implement this IEnumVARIANT object using
the same twisty maze of helpers, wrappers, UNO conversion utilities,
etc as used for the other stuff here. The other objects have both UNO
and OLE personalities. Could not figure out how to do it.
Then I decided to just do it brute force, following some sample code,
not bothering with any UNO personality at all for the IEnumVARIANT
thing, and it worked right away.
Change-Id: I6a175ea80b75d48d2f0b793f143f3a84715522c1
Reviewed-on: https://gerrit.libreoffice.org/54994
Tested-by: Jenkins <ci at libreoffice.org>
Reviewed-by: Tor Lillqvist <tml at collabora.com>
diff --git a/extensions/source/ole/unoobjw.cxx b/extensions/source/ole/unoobjw.cxx
index 0d012daa2bed..376496e005c8 100644
--- a/extensions/source/ole/unoobjw.cxx
+++ b/extensions/source/ole/unoobjw.cxx
@@ -24,6 +24,10 @@
#include <unordered_map>
#include <vector>
+#include <atlbase.h>
+#include <atlcom.h>
+#include <comdef.h>
+
#include <osl/diagnose.h>
#include <salhelper/simplereferenceobject.hxx>
#include <rtl/ustring.hxx>
@@ -36,6 +40,8 @@
#include <com/sun/star/reflection/ParamInfo.hpp>
#include <com/sun/star/beans/XExactName.hpp>
#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/beans/XMaterialHolder.hpp>
#include <com/sun/star/script/XInvocation2.hpp>
@@ -1040,6 +1046,92 @@ HRESULT InterfaceOleWrapper::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIAN
return ret;
}
+class CXEnumVariant : public IEnumVARIANT,
+ public CComObjectRoot
+{
+public:
+ CXEnumVariant()
+ {
+ }
+
+ ~CXEnumVariant()
+ {
+ }
+
+ BEGIN_COM_MAP(CXEnumVariant)
+ COM_INTERFACE_ENTRY(IEnumVARIANT)
+ END_COM_MAP()
+
+ DECLARE_NOT_AGGREGATABLE(CXEnumVariant)
+
+ // Creates and intializes the enumerator
+ void Init(InterfaceOleWrapper* pInterfaceOleWrapper,
+ const Reference< XEnumeration > xEnumeration)
+ {
+ mpInterfaceOleWrapper = pInterfaceOleWrapper;
+ mxEnumeration = xEnumeration;
+ }
+
+ // IEnumVARIANT
+ virtual HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum) override
+ {
+ (void) ppEnum;
+ return E_NOTIMPL;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt,
+ VARIANT *rgVar,
+ ULONG *pCeltFetched) override
+ {
+ if (pCeltFetched)
+ *pCeltFetched = 0;
+
+ if (celt == 0)
+ return E_INVALIDARG;
+
+ if (rgVar == NULL || (celt != 1 && pCeltFetched == NULL))
+ return E_FAIL;
+
+ for (ULONG i = 0; i < celt; i++)
+ VariantInit(&rgVar[i]);
+
+ while (celt > 0)
+ {
+ if (!mxEnumeration->hasMoreElements())
+ return S_FALSE;
+ Any aElement = mxEnumeration->nextElement();
+ mpInterfaceOleWrapper->anyToVariant(rgVar, aElement);
+ // rgVar->pdispVal->AddRef(); ??
+ if (pCeltFetched)
+ (*pCeltFetched)++;
+ rgVar++;
+ celt--;
+ }
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Reset() override
+ {
+ return E_NOTIMPL;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE Skip(ULONG celt) override
+ {
+ while (celt > 0)
+ {
+ if (!mxEnumeration->hasMoreElements())
+ return S_FALSE;
+ mxEnumeration->nextElement();
+ celt--;
+ }
+ return S_OK;
+ }
+
+private:
+ InterfaceOleWrapper* mpInterfaceOleWrapper;
+ Reference<XEnumeration> mxEnumeration;
+};
+
HRESULT InterfaceOleWrapper::InvokeGeneral( DISPID dispidMember, unsigned short wFlags,
DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
unsigned int * /*puArgErr*/, bool& bHandled)
@@ -1136,6 +1228,38 @@ HRESULT InterfaceOleWrapper::InvokeGeneral( DISPID dispidMember, unsigned short
return DISP_E_EXCEPTION;
}
}
+ else if (dispidMember == DISPID_NEWENUM)
+ {
+ bHandled = true;
+ if( !pvarResult)
+ return E_POINTER;
+
+ Reference< XEnumerationAccess > xEnumerationAccess(m_xOrigin, UNO_QUERY_THROW);
+ if (!xEnumerationAccess.is())
+ return DISP_E_MEMBERNOTFOUND;
+
+ Reference< XEnumeration > xEnumeration = xEnumerationAccess->createEnumeration();
+
+ CComObject<CXEnumVariant>* pEnumVar;
+
+ ret = CComObject<CXEnumVariant>::CreateInstance(&pEnumVar);
+ if (FAILED(ret))
+ return ret;
+
+ pEnumVar->AddRef();
+
+ pEnumVar->Init(this, xEnumeration);
+
+ pvarResult->vt = VT_UNKNOWN;
+ pvarResult->punkVal = NULL;
+
+ ret = pEnumVar->QueryInterface(IID_IUnknown, (void**)&pvarResult->punkVal);
+ if (FAILED(ret))
+ {
+ pEnumVar->Release();
+ return ret;
+ }
+ }
}
catch(const BridgeRuntimeError & e)
{
More information about the Libreoffice-commits
mailing list