Kaydet (Commit) 52eb78c8 authored tarafından Tor Lillqvist's avatar Tor Lillqvist

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/54994Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarTor Lillqvist <tml@collabora.com>
üst eb754cf5
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <atlbase.h>
#include <atlcom.h>
#include <comdef.h>
#include <osl/diagnose.h> #include <osl/diagnose.h>
#include <salhelper/simplereferenceobject.hxx> #include <salhelper/simplereferenceobject.hxx>
#include <rtl/ustring.hxx> #include <rtl/ustring.hxx>
...@@ -36,6 +40,8 @@ ...@@ -36,6 +40,8 @@
#include <com/sun/star/reflection/ParamInfo.hpp> #include <com/sun/star/reflection/ParamInfo.hpp>
#include <com/sun/star/beans/XExactName.hpp> #include <com/sun/star/beans/XExactName.hpp>
#include <com/sun/star/container/NoSuchElementException.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/beans/XMaterialHolder.hpp>
#include <com/sun/star/script/XInvocation2.hpp> #include <com/sun/star/script/XInvocation2.hpp>
...@@ -1040,6 +1046,92 @@ HRESULT InterfaceOleWrapper::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIAN ...@@ -1040,6 +1046,92 @@ HRESULT InterfaceOleWrapper::doSetProperty( DISPPARAMS * /*pdispparams*/, VARIAN
return ret; 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, HRESULT InterfaceOleWrapper::InvokeGeneral( DISPID dispidMember, unsigned short wFlags,
DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
unsigned int * /*puArgErr*/, bool& bHandled) unsigned int * /*puArgErr*/, bool& bHandled)
...@@ -1136,6 +1228,38 @@ HRESULT InterfaceOleWrapper::InvokeGeneral( DISPID dispidMember, unsigned short ...@@ -1136,6 +1228,38 @@ HRESULT InterfaceOleWrapper::InvokeGeneral( DISPID dispidMember, unsigned short
return DISP_E_EXCEPTION; 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) catch(const BridgeRuntimeError & e)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment