[PATCH v3] wmp: Implement IConnectionPoint[Container] and add _WMPOCXEvents

Anton Romanov theli.ua at gmail.com
Mon Feb 12 15:26:08 CST 2018


Signed-off-by: Anton Romanov <theli.ua at gmail.com>
---
 dlls/wmp/Makefile.in    |   3 +-
 dlls/wmp/events.c       | 404 ++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/wmp/oleobj.c       |  52 +------
 dlls/wmp/tests/oleobj.c |  70 ++++++++-
 dlls/wmp/wmp_private.h  |  16 ++
 5 files changed, 493 insertions(+), 52 deletions(-)
 create mode 100644 dlls/wmp/events.c

diff --git a/dlls/wmp/Makefile.in b/dlls/wmp/Makefile.in
index 71ca0e5c7a..8789de59d9 100644
--- a/dlls/wmp/Makefile.in
+++ b/dlls/wmp/Makefile.in
@@ -1,9 +1,10 @@
 MODULE    = wmp.dll
-IMPORTS   = user32 gdi32 oleaut32
+IMPORTS   = user32 gdi32 oleaut32 ole32
 
 C_SRCS = \
 	oleobj.c \
 	player.c \
+	events.c \
 	wmp_main.c
 
 RC_SRCS = rsrc.rc
diff --git a/dlls/wmp/events.c b/dlls/wmp/events.c
new file mode 100644
index 0000000000..f5f693bd4f
--- /dev/null
+++ b/dlls/wmp/events.c
@@ -0,0 +1,404 @@
+/*
+ * This is for the most part a copy of dlls/ieframe/events.c
+ *
+ * Implementation of event-related interfaces for WMP control:
+ *
+ *  - IConnectionPointContainer
+ *  - IConnectionPoint
+ *
+ * Copyright 2001 John R. Sheets (for CodeWeavers)
+ * Copyright 2006 Jacek Caban for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "wmp_private.h"
+#include "olectl.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wmp);
+
+static inline WindowsMediaPlayer *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
+{
+    return CONTAINING_RECORD(iface, WindowsMediaPlayer, IConnectionPointContainer_iface);
+}
+
+static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
+        REFIID riid, LPVOID *ppv)
+{
+    WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
+    return IOleObject_QueryInterface(&This->IOleObject_iface, riid, ppv);
+}
+
+static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
+{
+    WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
+    return IOleObject_AddRef(&This->IOleObject_iface);
+}
+
+static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
+{
+    WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
+    return IOleObject_Release(&This->IOleObject_iface);
+}
+
+static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
+        IEnumConnectionPoints **ppEnum)
+{
+    WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
+    FIXME("(%p)->(%p)\n", This, ppEnum);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
+        REFIID riid, IConnectionPoint **ppCP){
+    WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
+
+    if(!ppCP) {
+        WARN("ppCP == NULL\n");
+        return E_POINTER;
+    }
+
+    *ppCP = NULL;
+
+    if(IsEqualGUID(&IID__WMPOCXEvents, riid)) {
+        TRACE("(%p)->(IID__WMPOCXEvents %p)\n", This, ppCP);
+        *ppCP = &This->wmpocx->IConnectionPoint_iface;
+    }
+
+    if(*ppCP) {
+        IConnectionPoint_AddRef(*ppCP);
+        return S_OK;
+    }
+
+    WARN("Unsupported IID %s\n", debugstr_guid(riid));
+    return CONNECT_E_NOCONNECTION;
+}
+
+static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
+{
+    ConnectionPointContainer_QueryInterface,
+    ConnectionPointContainer_AddRef,
+    ConnectionPointContainer_Release,
+    ConnectionPointContainer_EnumConnectionPoints,
+    ConnectionPointContainer_FindConnectionPoint
+};
+
+static inline ConnectionPoint *impl_from_IConnectionPoint(IConnectionPoint *iface)
+{
+    return CONTAINING_RECORD(iface, ConnectionPoint, IConnectionPoint_iface);
+}
+
+typedef struct {
+    IEnumConnections IEnumConnections_iface;
+
+    LONG ref;
+
+    ConnectionPoint *cp;
+    DWORD iter;
+} 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(&IID_IUnknown, riid)) {
+        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+        *ppv = &This->IEnumConnections_iface;
+    }else if(IsEqualGUID(&IID_IEnumConnections, riid)) {
+        TRACE("(%p)->(IID_IEnumConnections %p)\n", This, ppv);
+        *ppv = &This->IEnumConnections_iface;
+    }else {
+        WARN("Unsupported interface %s\n", debugstr_guid(riid));
+        *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);
+    LONG 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);
+    LONG 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 *pgcd, ULONG *pcFetched)
+{
+    EnumConnections *This = impl_from_IEnumConnections(iface);
+    ULONG cnt = 0;
+
+    TRACE("(%p)->(%u %p %p)\n", This, cConnections, pgcd, pcFetched);
+
+    while(cConnections--) {
+        while(This->iter < This->cp->sinks_size && !This->cp->sinks[This->iter])
+            This->iter++;
+        if(This->iter == This->cp->sinks_size)
+            break;
+
+        pgcd[cnt].pUnk = (IUnknown*)This->cp->sinks[This->iter];
+        pgcd[cnt].dwCookie = cnt+1;
+        This->iter++;
+        cnt++;
+        IUnknown_AddRef(pgcd[cnt].pUnk);
+    }
+
+    if(pcFetched)
+        *pcFetched = cnt;
+    return cnt ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI EnumConnections_Skip(IEnumConnections *iface, ULONG cConnections)
+{
+    EnumConnections *This = impl_from_IEnumConnections(iface);
+    FIXME("(%p)->(%u)\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 HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface,
+                                                     REFIID riid, LPVOID *ppv)
+{
+    ConnectionPoint *This = impl_from_IConnectionPoint(iface);
+
+    *ppv = NULL;
+
+    if(IsEqualGUID(&IID_IUnknown, riid)) {
+        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+        *ppv = &This->IConnectionPoint_iface;
+    }else if(IsEqualGUID(&IID_IConnectionPoint, riid)) {
+        TRACE("(%p)->(IID_IConnectionPoint %p)\n", This, ppv);
+        *ppv = &This->IConnectionPoint_iface;
+    }
+
+    if(*ppv) {
+        IConnectionPointContainer_AddRef(This->container);
+        return S_OK;
+    }
+
+    WARN("Unsupported interface %s\n", debugstr_guid(riid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface)
+{
+    ConnectionPoint *This = impl_from_IConnectionPoint(iface);
+    return IConnectionPointContainer_AddRef(This->container);
+}
+
+static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface)
+{
+    ConnectionPoint *This = impl_from_IConnectionPoint(iface);
+    return IConnectionPointContainer_Release(This->container);
+}
+
+static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *pIID)
+{
+    ConnectionPoint *This = impl_from_IConnectionPoint(iface);
+
+    TRACE("(%p)->(%p)\n", This, pIID);
+
+    *pIID = This->iid;
+    return S_OK;
+}
+
+static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoint *iface,
+        IConnectionPointContainer **ppCPC)
+{
+    ConnectionPoint *This = impl_from_IConnectionPoint(iface);
+
+    TRACE("(%p)->(%p)\n", This, ppCPC);
+
+    *ppCPC = This->container;
+    IConnectionPointContainer_AddRef(This->container);
+    return S_OK;
+}
+
+static HRESULT WINAPI ConnectionPoint_Advise(IConnectionPoint *iface, IUnknown *pUnkSink,
+                                             DWORD *pdwCookie)
+{
+    ConnectionPoint *This = impl_from_IConnectionPoint(iface);
+    IDispatch *disp;
+    DWORD i;
+    HRESULT hres;
+
+    TRACE("(%p)->(%p %p)\n", This, pUnkSink, pdwCookie);
+
+    hres = IUnknown_QueryInterface(pUnkSink, &This->iid, (void**)&disp);
+    if(FAILED(hres)) {
+        hres = IUnknown_QueryInterface(pUnkSink, &IID_IDispatch, (void**)&disp);
+        if(FAILED(hres))
+            return CONNECT_E_CANNOTCONNECT;
+    }
+
+    if(This->sinks) {
+        for(i=0; i<This->sinks_size; i++) {
+            if(!This->sinks[i])
+                break;
+        }
+
+        if(i == This->sinks_size)
+            This->sinks = heap_realloc(This->sinks,
+                    (++This->sinks_size)*sizeof(*This->sinks));
+    }else {
+        This->sinks = heap_alloc(sizeof(*This->sinks));
+        This->sinks_size = 1;
+        i = 0;
+    }
+
+    This->sinks[i] = disp;
+    *pdwCookie = i+1;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI ConnectionPoint_Unadvise(IConnectionPoint *iface, DWORD dwCookie)
+{
+    ConnectionPoint *This = impl_from_IConnectionPoint(iface);
+
+    TRACE("(%p)->(%d)\n", This, dwCookie);
+
+    if(!dwCookie || dwCookie > This->sinks_size || !This->sinks[dwCookie-1])
+        return CONNECT_E_NOCONNECTION;
+
+    IDispatch_Release(This->sinks[dwCookie-1]);
+    This->sinks[dwCookie-1] = NULL;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI ConnectionPoint_EnumConnections(IConnectionPoint *iface,
+                                                      IEnumConnections **ppEnum)
+{
+    ConnectionPoint *This = impl_from_IConnectionPoint(iface);
+    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 =
+{
+    ConnectionPoint_QueryInterface,
+    ConnectionPoint_AddRef,
+    ConnectionPoint_Release,
+    ConnectionPoint_GetConnectionInterface,
+    ConnectionPoint_GetConnectionPointContainer,
+    ConnectionPoint_Advise,
+    ConnectionPoint_Unadvise,
+    ConnectionPoint_EnumConnections
+};
+
+static void ConnectionPoint_Destroy(ConnectionPoint *This)
+{
+    DWORD i;
+
+    for(i=0; i<This->sinks_size; i++) {
+        if(This->sinks[i])
+            IDispatch_Release(This->sinks[i]);
+    }
+
+    heap_free(This->sinks);
+    heap_free(This);
+}
+
+static void ConnectionPoint_Create(REFIID riid, ConnectionPoint **cp,
+                                   IConnectionPointContainer *container)
+{
+    ConnectionPoint *ret = heap_alloc(sizeof(ConnectionPoint));
+
+    ret->IConnectionPoint_iface.lpVtbl = &ConnectionPointVtbl;
+
+    ret->sinks = NULL;
+    ret->sinks_size = 0;
+    ret->container = container;
+
+    ret->iid = *riid;
+
+    *cp = ret;
+}
+
+void ConnectionPointContainer_Init(WindowsMediaPlayer *wmp)
+{
+    wmp->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
+    ConnectionPoint_Create(&IID__WMPOCXEvents, &wmp->wmpocx, &wmp->IConnectionPointContainer_iface);
+}
+
+void ConnectionPointContainer_Destroy(WindowsMediaPlayer *wmp)
+{
+    ConnectionPoint_Destroy(wmp->wmpocx);
+}
diff --git a/dlls/wmp/oleobj.c b/dlls/wmp/oleobj.c
index 167b893206..1baf45a439 100644
--- a/dlls/wmp/oleobj.c
+++ b/dlls/wmp/oleobj.c
@@ -307,6 +307,7 @@ static ULONG WINAPI OleObject_Release(IOleObject *iface)
 
     if(!ref) {
         release_client_site(This);
+        ConnectionPointContainer_Destroy(This);
         heap_free(This);
     }
 
@@ -875,55 +876,6 @@ static const IPersistStreamInitVtbl PersistStreamInitVtbl = {
     PersistStreamInit_InitNew
 };
 
-static inline WindowsMediaPlayer *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
-{
-    return CONTAINING_RECORD(iface, WindowsMediaPlayer, IConnectionPointContainer_iface);
-}
-
-static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface,
-        REFIID riid, LPVOID *ppv)
-{
-    WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
-    return IOleObject_QueryInterface(&This->IOleObject_iface, riid, ppv);
-}
-
-static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface)
-{
-    WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
-    return IOleObject_AddRef(&This->IOleObject_iface);
-}
-
-static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface)
-{
-    WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
-    return IOleObject_Release(&This->IOleObject_iface);
-}
-
-static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface,
-        IEnumConnectionPoints **ppEnum)
-{
-    WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
-    FIXME("(%p)->(%p)\n", This, ppEnum);
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface,
-        REFIID riid, IConnectionPoint **ppCP)
-{
-    WindowsMediaPlayer *This = impl_from_IConnectionPointContainer(iface);
-    FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppCP);
-    return CONNECT_E_NOCONNECTION;
-}
-
-static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl =
-{
-    ConnectionPointContainer_QueryInterface,
-    ConnectionPointContainer_AddRef,
-    ConnectionPointContainer_Release,
-    ConnectionPointContainer_EnumConnectionPoints,
-    ConnectionPointContainer_FindConnectionPoint
-};
-
 HRESULT WINAPI WMPFactory_CreateInstance(IClassFactory *iface, IUnknown *outer,
         REFIID riid, void **ppv)
 {
@@ -942,13 +894,13 @@ HRESULT WINAPI WMPFactory_CreateInstance(IClassFactory *iface, IUnknown *outer,
     wmp->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl;
     wmp->IPersistStreamInit_iface.lpVtbl = &PersistStreamInitVtbl;
     wmp->IOleInPlaceObjectWindowless_iface.lpVtbl = &OleInPlaceObjectWindowlessVtbl;
-    wmp->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
     wmp->IOleControl_iface.lpVtbl = &OleControlVtbl;
 
     wmp->ref = 1;
 
     init_player_ifaces(wmp);
 
+    ConnectionPointContainer_Init(wmp);
     hdc = GetDC(0);
     dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
     dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
diff --git a/dlls/wmp/tests/oleobj.c b/dlls/wmp/tests/oleobj.c
index 05861e1c10..46b0b72cd3 100644
--- a/dlls/wmp/tests/oleobj.c
+++ b/dlls/wmp/tests/oleobj.c
@@ -495,6 +495,43 @@ static const IDispatchVtbl DispatchVtbl = {
 
 static IDispatch Dispatch = { &DispatchVtbl };
 
+static HRESULT WINAPI WMPOCXEvents_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
+{
+    *ppv = NULL;
+
+    if(IsEqualGUID(&IID__WMPOCXEvents, riid) || IsEqualGUID(&IID_IDispatch, riid)) {
+        *ppv = iface;
+        return S_OK;
+    }
+
+    ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
+    return E_NOINTERFACE;
+}
+
+static HRESULT WINAPI WMPOCXEvents_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid,
+        LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
+        EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+    switch(dispIdMember) {
+    default:
+        ok(0, "unexpected call Invoke(%d)\n", dispIdMember);
+    }
+
+    return E_NOTIMPL;
+}
+
+static IDispatchVtbl WMPOcxEventsVtbl = {
+    WMPOCXEvents_QueryInterface,
+    Dispatch_AddRef,
+    Dispatch_Release,
+    Dispatch_GetTypeInfoCount,
+    Dispatch_GetTypeInfo,
+    Dispatch_GetIDsOfNames,
+    WMPOCXEvents_Invoke,
+};
+
+static IDispatch WMPOCXEvents = { &WMPOcxEventsVtbl };
+
 static HRESULT WINAPI InPlaceSiteWindowless_QueryInterface(IOleInPlaceSiteWindowless *iface, REFIID riid, void **ppv)
 {
     return cs_qi(riid, ppv);
@@ -788,6 +825,35 @@ static HRESULT cs_qi(REFIID riid, void **ppv)
     return S_OK;
 }
 
+static void test_ConnectionPoint(IOleObject *unk)
+{
+    IConnectionPointContainer *container;
+    IConnectionPoint *point;
+    HRESULT hres;
+
+    static DWORD dw = 100;
+
+    hres = IOleObject_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container);
+    ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres);
+    if(FAILED(hres))
+        return;
+
+    hres = IConnectionPointContainer_FindConnectionPoint(container, &IID__WMPOCXEvents, &point);
+    IConnectionPointContainer_Release(container);
+    ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
+    if(FAILED(hres))
+        return;
+
+    hres = IConnectionPoint_Advise(point, (IUnknown*)&WMPOCXEvents, &dw);
+    ok(hres == S_OK, "Advise failed: %08x\n", hres);
+    ok(dw == 1, "dw=%d, expected 1\n", dw);
+    hres = IConnectionPoint_Unadvise(point, dw);
+    ok(hres == S_OK, "Unadvise failed: %08x\n", hres);
+
+    IConnectionPoint_Release(point);
+}
+
+
 static void test_wmp_ifaces(IOleObject *oleobj)
 {
     IWMPSettings *settings, *settings_qi;
@@ -913,7 +979,7 @@ static void test_IConnectionPointContainer(IOleObject *oleobj)
 
     point = NULL;
     hres = IConnectionPointContainer_FindConnectionPoint(container, &IID__WMPOCXEvents, &point);
-    todo_wine ok(hres == S_OK, "got: %08x\n", hres);
+    ok(hres == S_OK, "got: %08x\n", hres);
     if(point)
         IConnectionPoint_Release(point);
 
@@ -1113,6 +1179,8 @@ static void test_wmp(void)
     ok(hres == E_FAIL || broken(hres == S_OK), "GetClientSite failed: %08x\n", hres);
     ok(!client_site, "client_site = %p\n", client_site);
 
+    test_ConnectionPoint(oleobj);
+
     IPersistStreamInit_Release(psi);
     IOleInPlaceObject_Release(ipobj);
 
diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h
index 1af0aef803..710793c513 100644
--- a/dlls/wmp/wmp_private.h
+++ b/dlls/wmp/wmp_private.h
@@ -19,9 +19,21 @@
 #define COBJMACROS
 
 #include "windows.h"
+#include "wine/heap.h"
 #include "ole2.h"
 #include "wmp.h"
 
+typedef struct {
+    IConnectionPoint IConnectionPoint_iface;
+
+    IConnectionPointContainer *container;
+
+    IDispatch **sinks;
+    DWORD sinks_size;
+
+    IID iid;
+} ConnectionPoint;
+
 struct WindowsMediaPlayer {
     IOleObject IOleObject_iface;
     IProvideClassInfo2 IProvideClassInfo2_iface;
@@ -38,9 +50,13 @@ struct WindowsMediaPlayer {
     IOleClientSite *client_site;
     HWND hwnd;
     SIZEL extent;
+
+    ConnectionPoint *wmpocx;
 };
 
 void init_player_ifaces(WindowsMediaPlayer*) DECLSPEC_HIDDEN;
+void ConnectionPointContainer_Init(WindowsMediaPlayer *wmp) DECLSPEC_HIDDEN;
+void ConnectionPointContainer_Destroy(WindowsMediaPlayer *wmp) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI WMPFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN;
 
-- 
2.16.1




More information about the wine-devel mailing list