From b852f777d979f83e9f94fba6484762245bfffbc1 Mon Sep 17 00:00:00 2001 From: Aaro Altonen Date: Wed, 17 Jun 2020 15:36:15 +0300 Subject: [PATCH] msado15: Implement IConnectionPoint::Advise/Unadvise. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49388 Signed-off-by: Aaro Altonen Signed-off-by: Alexandre Julliard --- dlls/msado15/connection.c | 65 +++++++++++++++++++++++++++++++++--- dlls/msado15/tests/msado15.c | 5 +-- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/dlls/msado15/connection.c b/dlls/msado15/connection.c index 35202d14aaa..5d8f78f53e8 100644 --- a/dlls/msado15/connection.c +++ b/dlls/msado15/connection.c @@ -40,6 +40,8 @@ struct connection_point IConnectionPoint IConnectionPoint_iface; struct connection *conn; const IID *riid; + IUnknown **sinks; + ULONG sinks_size; }; struct connection @@ -84,9 +86,16 @@ static ULONG WINAPI connection_Release( _Connection *iface ) { struct connection *connection = impl_from_Connection( iface ); LONG refs = InterlockedDecrement( &connection->refs ); + ULONG i; if (!refs) { TRACE( "destroying %p\n", connection ); + for (i = 0; i < connection->cp_connev.sinks_size; ++i) + { + if (connection->cp_connev.sinks[i]) + IUnknown_Release( connection->cp_connev.sinks[i] ); + } + heap_free( connection->cp_connev.sinks ); heap_free( connection->datasource ); heap_free( connection ); } @@ -548,15 +557,61 @@ static HRESULT WINAPI connpoint_Advise( IConnectionPoint *iface, IUnknown *unk_s DWORD *cookie ) { struct connection_point *connpoint = impl_from_IConnectionPoint( iface ); - FIXME( "%p, %p, %p\n", connpoint, unk_sink, cookie ); - return E_NOTIMPL; + IUnknown *sink, **tmp; + ULONG new_size; + HRESULT hr; + DWORD i; + + TRACE( "%p, %p, %p\n", iface, unk_sink, cookie ); + + if (!unk_sink || !cookie) return E_FAIL; + + if (FAILED(hr = IUnknown_QueryInterface( unk_sink, &IID_ConnectionEventsVt, (void**)&sink ))) + { + *cookie = 0; + return E_FAIL; + } + + if (connpoint->sinks) + { + for (i = 0; i < connpoint->sinks_size; ++i) + { + if (!connpoint->sinks[i]) + break; + } + + if (i == connpoint->sinks_size) + { + new_size = connpoint->sinks_size * 2; + if (!(tmp = heap_realloc_zero( connpoint->sinks, new_size * sizeof(*connpoint->sinks) ))) + return E_OUTOFMEMORY; + connpoint->sinks = tmp; + connpoint->sinks_size = new_size; + } + } + else + { + if (!(connpoint->sinks = heap_alloc_zero( sizeof(*connpoint->sinks) ))) return E_OUTOFMEMORY; + connpoint->sinks_size = 1; + i = 0; + } + + connpoint->sinks[i] = sink; + *cookie = i + 1; + return S_OK; } static HRESULT WINAPI connpoint_Unadvise( IConnectionPoint *iface, DWORD cookie ) { struct connection_point *connpoint = impl_from_IConnectionPoint( iface ); - FIXME( "%p, %d\n", connpoint, cookie ); - return E_NOTIMPL; + TRACE( "%p, %u\n", connpoint, cookie ); + + if (!cookie || cookie > connpoint->sinks_size || !connpoint->sinks || !connpoint->sinks[cookie - 1]) + return E_FAIL; + + IUnknown_Release( connpoint->sinks[cookie - 1] ); + connpoint->sinks[cookie - 1] = NULL; + return S_OK; } static HRESULT WINAPI connpoint_EnumConnections( IConnectionPoint *iface, @@ -595,6 +650,8 @@ HRESULT Connection_create( void **obj ) connection->cp_connev.conn = connection; connection->cp_connev.riid = &DIID_ConnectionEvents; connection->cp_connev.IConnectionPoint_iface.lpVtbl = &connpoint_vtbl; + connection->cp_connev.sinks = NULL; + connection->cp_connev.sinks_size = 0; *obj = &connection->Connection_iface; TRACE( "returning iface %p\n", *obj ); diff --git a/dlls/msado15/tests/msado15.c b/dlls/msado15/tests/msado15.c index e072ed022f4..1629fe15bed 100644 --- a/dlls/msado15/tests/msado15.c +++ b/dlls/msado15/tests/msado15.c @@ -996,7 +996,6 @@ static void test_ConnectionPoint(void) hr = IConnectionPointContainer_FindConnectionPoint( pointcontainer, &DIID_ConnectionEvents, &point ); ok( hr == S_OK, "got %08x\n", hr ); -todo_wine { /* nothing advised yet */ hr = IConnectionPoint_Unadvise( point, 3 ); ok( hr == E_FAIL, "got %08x\n", hr ); @@ -1010,10 +1009,8 @@ todo_wine { cookie = 0xdeadbeef; hr = IConnectionPoint_Advise( point, NULL, &cookie ); ok( hr == E_FAIL, "got %08x\n", hr ); -} ok( cookie == 0xdeadbeef, "got %08x\n", cookie ); -todo_wine { /* unsupported sink */ cookie = 0xdeadbeef; hr = IConnectionPoint_Advise( point, (void*)&support_err_sink, &cookie ); @@ -1042,7 +1039,7 @@ todo_wine { ok( hr == S_OK, "got %08x\n", hr ); ok( cookie, "got %08x\n", cookie ); ok( conn_event.refs == 1, "got %d\n", conn_event.refs ); -} + refs = IConnectionPoint_Release( point ); ok( refs == 1, "got %u", refs );