Module: wine Branch: master Commit: e9ac8e568bc9685cff16a69c2be392255912804d URL: http://source.winehq.org/git/wine.git/?a=commit;h=e9ac8e568bc9685cff16a69c2b...
Author: Jacek Caban jacek@codeweavers.com Date: Thu Apr 24 13:27:14 2014 +0200
mshtml: Added IConnectionPoint::EnumConnections implementation.
---
dlls/mshtml/conpoint.c | 133 ++++++++++++++++++++++++++++++++++++++++++- dlls/mshtml/tests/htmldoc.c | 21 +++++++ 2 files changed, 152 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/conpoint.c b/dlls/mshtml/conpoint.c index de501b4..8912eab 100644 --- a/dlls/mshtml/conpoint.c +++ b/dlls/mshtml/conpoint.c @@ -48,6 +48,120 @@ static const char *debugstr_cp_guid(REFIID riid) return debugstr_guid(riid); }
+typedef struct { + IEnumConnections IEnumConnections_iface; + + LONG ref; + + unsigned iter; + ConnectionPoint *cp; +} EnumConnections; + +static inline EnumConnections *impl_from_IEnumConnections(IEnumConnections *iface) +{ + return CONTAINING_RECORD(iface, EnumConnections, IEnumConnections_iface); +} + +static HRESULT WINAPI EnumConnections_QueryInterface(IEnumConnections *iface, REFIID riid, void **ppv) +{ + EnumConnections *This = impl_from_IEnumConnections(iface); + + if(IsEqualGUID(riid, &IID_IUnknown)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = &This->IEnumConnections_iface; + }else if(IsEqualGUID(riid, &IID_IEnumConnections)) { + TRACE("(%p)->(IID_IEnumConnections %p)\n", This, ppv); + *ppv = &This->IEnumConnections_iface; + }else { + WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI EnumConnections_AddRef(IEnumConnections *iface) +{ + EnumConnections *This = impl_from_IEnumConnections(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI EnumConnections_Release(IEnumConnections *iface) +{ + EnumConnections *This = impl_from_IEnumConnections(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) { + IConnectionPoint_Release(&This->cp->IConnectionPoint_iface); + heap_free(This); + } + + return ref; +} + +static HRESULT WINAPI EnumConnections_Next(IEnumConnections *iface, ULONG cConnections, CONNECTDATA *rgcd, ULONG *pcFetched) +{ + EnumConnections *This = impl_from_IEnumConnections(iface); + ULONG fetched = 0; + + TRACE("(%p)->(%d %p %p)\n", This, cConnections, rgcd, pcFetched); + + while(fetched < cConnections && This->iter < This->cp->sinks_size) { + if(!This->cp->sinks[This->iter].unk) { + This->iter++; + continue; + } + + rgcd[fetched].pUnk = This->cp->sinks[This->iter].unk; + rgcd[fetched].dwCookie = ++This->iter; + IUnknown_AddRef(rgcd[fetched].pUnk); + fetched++; + } + + if(pcFetched) + *pcFetched = fetched; + return fetched == cConnections ? S_OK : S_FALSE; +} + +static HRESULT WINAPI EnumConnections_Skip(IEnumConnections *iface, ULONG cConnections) +{ + EnumConnections *This = impl_from_IEnumConnections(iface); + FIXME("(%p)->(%d)\n", This, cConnections); + return E_NOTIMPL; +} + +static HRESULT WINAPI EnumConnections_Reset(IEnumConnections *iface) +{ + EnumConnections *This = impl_from_IEnumConnections(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI EnumConnections_Clone(IEnumConnections *iface, IEnumConnections **ppEnum) +{ + EnumConnections *This = impl_from_IEnumConnections(iface); + FIXME("(%p)->(%p)\n", This, ppEnum); + return E_NOTIMPL; +} + +static const IEnumConnectionsVtbl EnumConnectionsVtbl = { + EnumConnections_QueryInterface, + EnumConnections_AddRef, + EnumConnections_Release, + EnumConnections_Next, + EnumConnections_Skip, + EnumConnections_Reset, + EnumConnections_Clone +}; + static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface) { return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface); @@ -175,8 +289,23 @@ static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface, IEnumConnections **ppEnum) { ConnectionPoint *This = impl_from_IConnectionPoint(iface); - FIXME("(%p)->(%p)\n", This, ppEnum); - return E_NOTIMPL; + EnumConnections *ret; + + TRACE("(%p)->(%p)\n", This, ppEnum); + + ret = heap_alloc(sizeof(*ret)); + if(!ret) + return E_OUTOFMEMORY; + + ret->IEnumConnections_iface.lpVtbl = &EnumConnectionsVtbl; + ret->ref = 1; + ret->iter = 0; + + IConnectionPoint_AddRef(&This->IConnectionPoint_iface); + ret->cp = This; + + *ppEnum = &ret->IEnumConnections_iface; + return S_OK; }
static const IConnectionPointVtbl ConnectionPointVtbl = diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c index bad7291..24c6cac 100644 --- a/dlls/mshtml/tests/htmldoc.c +++ b/dlls/mshtml/tests/htmldoc.c @@ -5453,8 +5453,29 @@ static void test_ConnectionPoint(IConnectionPointContainer *container, REFIID ri hres = IConnectionPoint_Advise(cp, (IUnknown*)&PropertyNotifySink, NULL); ok(hres == S_OK, "Advise failed: %08x\n", hres); } else if(IsEqualGUID(&IID_IDispatch, riid)) { + IEnumConnections *enum_conn; + CONNECTDATA conn_data; + ULONG fetched; + hres = IConnectionPoint_Advise(cp, (IUnknown*)&EventDispatch, &cookie); ok(hres == S_OK, "Advise failed: %08x\n", hres); + + hres = IConnectionPoint_EnumConnections(cp, &enum_conn); + ok(hres == S_OK, "EnumConnections failed: %08x\n", hres); + + fetched = 0; + hres = IEnumConnections_Next(enum_conn, 1, &conn_data, &fetched); + ok(hres == S_OK, "Next failed: %08x\n", hres); + ok(conn_data.pUnk == (IUnknown*)&EventDispatch, "conn_data.pUnk == EventDispatch\n"); + ok(conn_data.dwCookie == cookie, "conn_data.dwCookie != cookie\n"); + IUnknown_Release(conn_data.pUnk); + + fetched = 0xdeadbeef; + hres = IEnumConnections_Next(enum_conn, 1, &conn_data, &fetched); + ok(hres == S_FALSE, "Next failed: %08x\n", hres); + ok(!fetched, "fetched = %d\n", fetched); + + IEnumConnections_Release(enum_conn); }
IConnectionPoint_Release(cp);