summaryrefslogtreecommitdiff
path: root/extensions
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2018-02-13 18:37:28 +0200
committerTor Lillqvist <tml@collabora.com>2018-05-31 21:37:42 +0300
commited6234c0ab6b04f95847f6ee40d77934b9b5f03f (patch)
tree0eb501ceac6ae1b919447786bc58e4f7d58d81e3 /extensions
parent28d5b049e74f29214e97444c5c0d6d160cfd6b22 (diff)
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@libreoffice.org> Reviewed-by: Tor Lillqvist <tml@collabora.com> (cherry picked from commit 52eb78c8d2c9954733d95326922462a820d9f0dd)
Diffstat (limited to 'extensions')
-rw-r--r--extensions/source/ole/unoobjw.cxx124
1 files changed, 124 insertions, 0 deletions
diff --git a/extensions/source/ole/unoobjw.cxx b/extensions/source/ole/unoobjw.cxx
index 9b9a86a83c52..44ceeee791ef 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)
{