Signed-off-by: Anton Romanov theli.ua@gmail.com --- dlls/wmp/Makefile.in | 3 +- dlls/wmp/events.c | 388 ++++++++++++++++++++++++++++++++++++++++++++++++ dlls/wmp/oleobj.c | 78 +++------- dlls/wmp/player.c | 9 +- dlls/wmp/tests/oleobj.c | 2 +- dlls/wmp/wmp_main.c | 2 + dlls/wmp/wmp_private.h | 36 +++-- 7 files changed, 438 insertions(+), 80 deletions(-) create mode 100644 dlls/wmp/events.c
diff --git a/dlls/wmp/Makefile.in b/dlls/wmp/Makefile.in index 71ca0e5c7a..14d0a5694f 100644 --- a/dlls/wmp/Makefile.in +++ b/dlls/wmp/Makefile.in @@ -1,9 +1,10 @@ MODULE = wmp.dll -IMPORTS = user32 gdi32 oleaut32 +IMPORTS = uuid 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..204b2f6527 --- /dev/null +++ b/dlls/wmp/events.c @@ -0,0 +1,388 @@ +#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++; + } + + 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 call_sink(ConnectionPoint *This, DISPID dispid, DISPPARAMS *dispparams) +{ + DWORD i; + + for(i=0; i<This->sinks_size; i++) { + if(This->sinks[i]) + IDispatch_Invoke(This->sinks[i], dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, + DISPATCH_METHOD, dispparams, NULL, NULL, NULL); + } +} + +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 ea989f00e3..8ac978218e 100644 --- a/dlls/wmp/oleobj.c +++ b/dlls/wmp/oleobj.c @@ -18,11 +18,11 @@
#include "wmp_private.h" #include "olectl.h" - #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(wmp);
+ static HWND get_container_hwnd(WindowsMediaPlayer *This) { IOleWindow *ole_window; @@ -306,6 +306,8 @@ static ULONG WINAPI OleObject_Release(IOleObject *iface)
if(!ref) { release_client_site(This); + ConnectionPointContainer_Destroy(This); + destroy_player(This); heap_free(This); }
@@ -874,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) { @@ -941,22 +894,25 @@ 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); - - hdc = GetDC(0); - dpi_x = GetDeviceCaps(hdc, LOGPIXELSX); - dpi_y = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(0, hdc); + hres = init_player(wmp); + if (hres == S_OK) { + ConnectionPointContainer_Init(wmp); + hdc = GetDC(0); + dpi_x = GetDeviceCaps(hdc, LOGPIXELSX); + dpi_y = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(0, hdc);
- wmp->extent.cx = MulDiv(192, 2540, dpi_x); - wmp->extent.cy = MulDiv(192, 2540, dpi_y); + wmp->extent.cx = MulDiv(192, 2540, dpi_x); + wmp->extent.cy = MulDiv(192, 2540, dpi_y);
- hres = IOleObject_QueryInterface(&wmp->IOleObject_iface, riid, ppv); - IOleObject_Release(&wmp->IOleObject_iface); + hres = IOleObject_QueryInterface(&wmp->IOleObject_iface, riid, ppv); + IOleObject_Release(&wmp->IOleObject_iface); + } + if(hres != S_OK) + destroy_player(wmp); return hres; } diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index 4c11c88d74..c410d6ef8f 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -22,6 +22,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(wmp);
+static void update_state(WindowsMediaPlayer *wmp, int state); + static inline WindowsMediaPlayer *impl_from_IWMPPlayer4(IWMPPlayer4 *iface) { return CONTAINING_RECORD(iface, WindowsMediaPlayer, IWMPPlayer4_iface); @@ -661,8 +663,13 @@ static const IWMPSettingsVtbl WMPSettingsVtbl = { WMPSettings_put_enableErrorDialogs };
-void init_player_ifaces(WindowsMediaPlayer *wmp) +void destroy_player(WindowsMediaPlayer* wmp) { + heap_free(wmp); +} + +HRESULT init_player(WindowsMediaPlayer *wmp) { wmp->IWMPPlayer4_iface.lpVtbl = &WMPPlayer4Vtbl; wmp->IWMPSettings_iface.lpVtbl = &WMPSettingsVtbl; + return S_OK; } diff --git a/dlls/wmp/tests/oleobj.c b/dlls/wmp/tests/oleobj.c index 2b646d7b1d..08c000590a 100644 --- a/dlls/wmp/tests/oleobj.c +++ b/dlls/wmp/tests/oleobj.c @@ -896,7 +896,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);
diff --git a/dlls/wmp/wmp_main.c b/dlls/wmp/wmp_main.c index 29b096f7fd..b97ad2879d 100644 --- a/dlls/wmp/wmp_main.c +++ b/dlls/wmp/wmp_main.c @@ -26,6 +26,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(wmp);
HINSTANCE wmp_instance;
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); + static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) { *ppv = NULL; diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h index 7b7f51cd63..d599c5bc6b 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; @@ -37,27 +49,19 @@ struct WindowsMediaPlayer { IOleClientSite *client_site; HWND hwnd; SIZEL extent; + + ConnectionPoint *wmpocx; };
-void init_player_ifaces(WindowsMediaPlayer*) DECLSPEC_HIDDEN; +HRESULT init_player(WindowsMediaPlayer*) DECLSPEC_HIDDEN; +void destroy_player(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;
+void call_sink(ConnectionPoint *This, DISPID dispid, DISPPARAMS *dispparams); + void unregister_wmp_class(void) DECLSPEC_HIDDEN;
extern HINSTANCE wmp_instance DECLSPEC_HIDDEN; - -static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t len) -{ - return HeapAlloc(GetProcessHeap(), 0, len); -} - -static inline void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(size_t len) -{ - return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); -} - -static inline BOOL heap_free(void *mem) -{ - return HeapFree(GetProcessHeap(), 0, mem); -}