Signed-off-by: Anton Romanov theli.ua@gmail.com --- dlls/wmp/oleobj.c | 3 + dlls/wmp/player.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++- dlls/wmp/tests/oleobj.c | 20 +++++ dlls/wmp/wmp_private.h | 1 + 4 files changed, 235 insertions(+), 2 deletions(-)
diff --git a/dlls/wmp/oleobj.c b/dlls/wmp/oleobj.c index 1baf45a439..b3d65840fc 100644 --- a/dlls/wmp/oleobj.c +++ b/dlls/wmp/oleobj.c @@ -270,6 +270,9 @@ static HRESULT WINAPI OleObject_QueryInterface(IOleObject *iface, REFIID riid, v }else if(IsEqualGUID(riid, &IID_IWMPSettings)) { TRACE("(%p)->(IID_IWMPSettings %p)\n", This, ppv); *ppv = &This->IWMPSettings_iface; + }else if(IsEqualGUID(riid, &IID_IWMPControls)) { + TRACE("(%p)->(IID_IWMPControls %p)\n", This, ppv); + *ppv = &This->IWMPControls_iface; }else if(IsEqualGUID(riid, &IID_IOleControl)) { TRACE("(%p)->(IID_IOleControl %p)\n", This, ppv); *ppv = &This->IOleControl_iface; diff --git a/dlls/wmp/player.c b/dlls/wmp/player.c index accf5401ed..64ddfca704 100644 --- a/dlls/wmp/player.c +++ b/dlls/wmp/player.c @@ -32,6 +32,11 @@ static inline WindowsMediaPlayer *impl_from_IWMPPlayer(IWMPPlayer *iface) return CONTAINING_RECORD(iface, WindowsMediaPlayer, IWMPPlayer_iface); }
+static inline WindowsMediaPlayer *impl_from_IWMPControls(IWMPControls *iface) +{ + return CONTAINING_RECORD(iface, WindowsMediaPlayer, IWMPControls_iface); +} + static HRESULT WINAPI WMPPlayer4_QueryInterface(IWMPPlayer4 *iface, REFIID riid, void **ppv) { WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface); @@ -121,8 +126,12 @@ static HRESULT WINAPI WMPPlayer4_get_playState(IWMPPlayer4 *iface, WMPPlayState static HRESULT WINAPI WMPPlayer4_get_controls(IWMPPlayer4 *iface, IWMPControls **ppControl) { WindowsMediaPlayer *This = impl_from_IWMPPlayer4(iface); - FIXME("(%p)->(%p)\n", This, ppControl); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, ppControl); + + IWMPControls_AddRef(&This->IWMPControls_iface); + *ppControl = &This->IWMPControls_iface; + return S_OK; }
static HRESULT WINAPI WMPPlayer4_get_settings(IWMPPlayer4 *iface, IWMPSettings **ppSettings) @@ -931,9 +940,209 @@ static const IWMPSettingsVtbl WMPSettingsVtbl = { WMPSettings_put_enableErrorDialogs };
+HRESULT WINAPI WMPControls_fastForward(IWMPControls *iface) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_fastReverse(IWMPControls *iface) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_get_currentItem(IWMPControls *iface, IWMPMedia **ppIWMPMedia) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%p)\n", This, ppIWMPMedia); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_get_currentMarker(IWMPControls *iface, LONG *plMarker) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%p)\n", This, plMarker); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_get_currentPosition(IWMPControls *iface, DOUBLE *pdCurrentPosition) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%p)\n", This, pdCurrentPosition); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_get_currentPositionString(IWMPControls *iface, BSTR *pbstrCurrentPosition) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%p)\n", This, pbstrCurrentPosition); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPControls_get_isAvailable(IWMPControls *iface, BSTR bstrItem, VARIANT_BOOL *pIsAvailable) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(bstrItem)); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_next(IWMPControls *iface) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_pause(IWMPControls *iface) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_play(IWMPControls *iface) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_playItem(IWMPControls *iface, IWMPMedia *pIWMPMedia) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%p)\n", This, pIWMPMedia); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_previous(IWMPControls *iface) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_put_currentItem(IWMPControls *iface, IWMPMedia *pIWMPMedia) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%p)\n", This, pIWMPMedia); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_put_currentMarker(IWMPControls *iface, LONG lMarker) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%d)\n", This, lMarker); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_put_currentPosition(IWMPControls *iface, DOUBLE dCurrentPosition) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%f)\n", This, dCurrentPosition); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_stop(IWMPControls *iface) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)\n", This); + return E_NOTIMPL; +} + +HRESULT WINAPI WMPControls_QueryInterface(IWMPControls *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(riid, &IID_IDispatch)) { + *ppv = iface; + }else if(IsEqualGUID(riid, &IID_IWMPControls)) { + *ppv = iface; + }else { + WARN("Unsupported interface (%s)\n", wine_dbgstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI WMPControls_AddRef(IWMPControls *iface) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + return IOleObject_AddRef(&This->IOleObject_iface); +} + +static ULONG WINAPI WMPControls_Release(IWMPControls *iface) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + return IOleObject_Release(&This->IOleObject_iface); +} + +static HRESULT WINAPI WMPControls_GetTypeInfoCount(IWMPControls *iface, UINT *pctinfo) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%p)\n", This, pctinfo); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPControls_GetTypeInfo(IWMPControls *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%u %d %p)\n", This, iTInfo, lcid, ppTInfo); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPControls_GetIDsOfNames(IWMPControls *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%s %p %u %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); + return E_NOTIMPL; +} + +static HRESULT WINAPI WMPControls_Invoke(IWMPControls *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + WindowsMediaPlayer *This = impl_from_IWMPControls(iface); + FIXME("(%p)->(%d %s %d %x %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, + wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + return E_NOTIMPL; +} + +static const IWMPControlsVtbl WMPControlsVtbl = { + WMPControls_QueryInterface, + WMPControls_AddRef, + WMPControls_Release, + WMPControls_GetTypeInfoCount, + WMPControls_GetTypeInfo, + WMPControls_GetIDsOfNames, + WMPControls_Invoke, + WMPControls_get_isAvailable, + WMPControls_play, + WMPControls_stop, + WMPControls_pause, + WMPControls_fastForward, + WMPControls_fastReverse, + WMPControls_get_currentPosition, + WMPControls_put_currentPosition, + WMPControls_get_currentPositionString, + WMPControls_next, + WMPControls_previous, + WMPControls_get_currentItem, + WMPControls_put_currentItem, + WMPControls_get_currentMarker, + WMPControls_put_currentMarker, + WMPControls_playItem, +}; + void init_player_ifaces(WindowsMediaPlayer *wmp) { wmp->IWMPPlayer4_iface.lpVtbl = &WMPPlayer4Vtbl; wmp->IWMPPlayer_iface.lpVtbl = &WMPPlayerVtbl; wmp->IWMPSettings_iface.lpVtbl = &WMPSettingsVtbl; + wmp->IWMPControls_iface.lpVtbl = &WMPControlsVtbl; } diff --git a/dlls/wmp/tests/oleobj.c b/dlls/wmp/tests/oleobj.c index 46b0b72cd3..67950e0118 100644 --- a/dlls/wmp/tests/oleobj.c +++ b/dlls/wmp/tests/oleobj.c @@ -859,11 +859,31 @@ static void test_wmp_ifaces(IOleObject *oleobj) IWMPSettings *settings, *settings_qi; IWMPPlayer4 *player4; IWMPPlayer *player; + IWMPControls *controls; HRESULT hres;
hres = IOleObject_QueryInterface(oleobj, &IID_IWMPPlayer4, (void**)&player4); ok(hres == S_OK, "Could not get IWMPPlayer4 iface: %08x\n", hres);
+ controls = NULL; + hres = IWMPPlayer4_get_controls(player4, &controls); + ok(hres == S_OK, "get_controls failed: %08x\n", hres); + ok(controls != NULL, "controls = NULL\n"); + + player = NULL; + hres = IWMPControls_QueryInterface(controls, &IID_IWMPPlayer, (void**)&player); + ok(hres != S_OK, "Getting IWMPPlayer from IWMPControls SUCCEEDED\n"); + ok(player == NULL, "player != NULL\n"); + + IWMPControls_Release(controls); + + controls = NULL; + hres = IWMPPlayer4_QueryInterface(player4, &IID_IWMPControls, (void**)&controls); + ok(hres == S_OK, "Getting IWMPControls from IWMPPlayer failed: %08x\n", hres); + ok(controls != NULL, "controls = NULL\n"); + + IWMPControls_Release(controls); + settings = NULL; hres = IWMPPlayer4_get_settings(player4, &settings); ok(hres == S_OK, "get_settings failed: %08x\n", hres); diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h index 710793c513..65de6bbd09 100644 --- a/dlls/wmp/wmp_private.h +++ b/dlls/wmp/wmp_private.h @@ -44,6 +44,7 @@ struct WindowsMediaPlayer { IWMPPlayer4 IWMPPlayer4_iface; IWMPPlayer IWMPPlayer_iface; IWMPSettings IWMPSettings_iface; + IWMPControls IWMPControls_iface;
LONG ref;
Hi Anton,
On 02/12/2018 10:36 PM, Anton Romanov wrote:
+HRESULT WINAPI WMPControls_QueryInterface(IWMPControls *iface, REFIID riid, void **ppv) +{
- if(IsEqualGUID(riid, &IID_IDispatch)) {
*ppv = iface;
- }else if(IsEqualGUID(riid, &IID_IWMPControls)) {
*ppv = iface;
- }else {
WARN("Unsupported interface (%s)\n", wine_dbgstr_guid(riid));
*ppv = NULL;
return E_NOINTERFACE;
- }
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
+}
This breaks COM rules: if iface1->QI(IID_iface2) returns iface2, then iface2->QI(IID_iface1) should work as well. I tried your tests and it seems that MS violates this rule as well, but in a different way than you do. What's even more important, interface returned by QI is not the same as returned by get_controls(). get_controls() should return a different object. I guess that your application needs get_controls() working, not QI(IID_IWMPControls)? I'd suggest to implement IWMPControls in a separated object (I guess that's what you really want to fix) and ignore the fact that it's also returned by QI() to avoid messing with broken behaviour.
Also, please use consistent implementation order: IUnknown functions first followed by other parent's interfaces (like IDispatch), followed by actual interface implementation.
Thanks, Jacek