Aaro Altonen : msado15: Implement IConnectionPoint::Advise/Unadvise.

Alexandre Julliard julliard at winehq.org
Tue Nov 10 13:46:22 CST 2020


Module: wine
Branch: stable
Commit: e6c8bd73b4a60b7eb61c9b6acd85a4b46f0135b4
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e6c8bd73b4a60b7eb61c9b6acd85a4b46f0135b4

Author: Aaro Altonen <a.altonen at hotmail.com>
Date:   Wed Jun 17 15:36:15 2020 +0300

msado15: Implement IConnectionPoint::Advise/Unadvise.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49388
Signed-off-by: Aaro Altonen <a.altonen at hotmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit b852f777d979f83e9f94fba6484762245bfffbc1)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>

---

 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 9e8c05522ef..b90486b7cd9 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 );
     }
@@ -530,15 +539,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,
@@ -577,6 +632,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 4f4ebde9d2f..27e917ce626 100644
--- a/dlls/msado15/tests/msado15.c
+++ b/dlls/msado15/tests/msado15.c
@@ -959,7 +959,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 );
@@ -973,10 +972,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 );
@@ -1005,7 +1002,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 );
 




More information about the wine-cvs mailing list