[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