From 470ea0d51bee73ca5012eb9ffe70f3f92add7506 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 21 Aug 2018 10:19:39 +0300 Subject: [PATCH] wmp: Implement GetClassInfo(). Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/wmp/oleobj.c | 11 +++++-- dlls/wmp/tests/oleobj.c | 10 +++++++ dlls/wmp/wmp_main.c | 66 +++++++++++++++++++++++++++++++++++++++++ dlls/wmp/wmp_private.h | 15 ++++++++++ 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/dlls/wmp/oleobj.c b/dlls/wmp/oleobj.c index a90a0c2c6c3..cbbd965c38b 100644 --- a/dlls/wmp/oleobj.c +++ b/dlls/wmp/oleobj.c @@ -760,11 +760,16 @@ static ULONG WINAPI ProvideClassInfo2_Release(IProvideClassInfo2 *iface) return IOleObject_Release(&This->IOleObject_iface); } -static HRESULT WINAPI ProvideClassInfo2_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ppTI) +static HRESULT WINAPI ProvideClassInfo2_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ti) { WindowsMediaPlayer *This = impl_from_IProvideClassInfo2(iface); - FIXME("(%p)->(%p)\n", This, ppTI); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, ti); + + if (!ti) + return E_POINTER; + + return get_typeinfo(WindowsMediaPlayer_tid, ti); } static HRESULT WINAPI ProvideClassInfo2_GetGUID(IProvideClassInfo2 *iface, DWORD dwGuidKind, GUID *pGUID) diff --git a/dlls/wmp/tests/oleobj.c b/dlls/wmp/tests/oleobj.c index 472b9852447..2250b75aa9b 100644 --- a/dlls/wmp/tests/oleobj.c +++ b/dlls/wmp/tests/oleobj.c @@ -1199,6 +1199,8 @@ static void test_wmp(void) IOleObject *oleobj; IWMPCore *wmpcore; DWORD misc_status; + TYPEATTR *attr; + ITypeInfo *ti; RECT pos = {0,0,100,100}; HWND hwnd; GUID guid; @@ -1232,6 +1234,14 @@ static void test_wmp(void) ok(hres == S_OK, "GetGUID failed: %08x\n", hres); ok(IsEqualGUID(&guid, &IID__WMPOCXEvents), "guid = %s\n", wine_dbgstr_guid(&guid)); + hres = IProvideClassInfo2_GetClassInfo(class_info, &ti); + ok(hres == S_OK, "Failed to get class info, hr %#x.\n", hres); + hres = ITypeInfo_GetTypeAttr(ti, &attr); + ok(hres == S_OK, "Failed to get type attributes, hr %#x.\n", hres); + ok(IsEqualGUID(&CLSID_WindowsMediaPlayer, &attr->guid), "Unexpected typeinfo guid %s\n", wine_dbgstr_guid(&attr->guid)); + ITypeInfo_ReleaseTypeAttr(ti, attr); + ITypeInfo_Release(ti); + IProvideClassInfo2_Release(class_info); test_QI((IUnknown*)oleobj); diff --git a/dlls/wmp/wmp_main.c b/dlls/wmp/wmp_main.c index 273d193e589..2541fc54ffb 100644 --- a/dlls/wmp/wmp_main.c +++ b/dlls/wmp/wmp_main.c @@ -27,6 +27,71 @@ WINE_DEFAULT_DEBUG_CHANNEL(wmp); HINSTANCE wmp_instance; DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); +static REFIID tid_ids[] = { +#define XIID(iface) &IID_ ## iface, +#define CTID(name) &CLSID_ ## name, +TID_LIST +#undef XIID +#undef CTID +}; + +static ITypeLib *typelib; +static ITypeInfo *typeinfos[LAST_tid]; + +static HRESULT load_typelib(void) +{ + ITypeLib *tl; + HRESULT hr; + + hr = LoadRegTypeLib(&LIBID_WMPLib, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl); + if (FAILED(hr)) { + ERR("LoadRegTypeLib failed: %08x\n", hr); + return hr; + } + + if (InterlockedCompareExchangePointer((void **)&typelib, tl, NULL)) + ITypeLib_Release(tl); + return hr; +} + +HRESULT get_typeinfo(typeinfo_id tid, ITypeInfo **typeinfo) +{ + HRESULT hr; + + if (!typelib) + hr = load_typelib(); + if (!typelib) + return hr; + + if (!typeinfos[tid]) { + ITypeInfo *ti; + + hr = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti); + if (FAILED(hr)) { + ERR("GetTypeInfoOfGuid (%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hr); + return hr; + } + + if (InterlockedCompareExchangePointer((void **)(typeinfos + tid), ti, NULL)) + ITypeInfo_Release(ti); + } + + *typeinfo = typeinfos[tid]; + ITypeInfo_AddRef(*typeinfo); + return S_OK; +} + +static void release_typelib(void) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(typeinfos); i++) + if (typeinfos[i]) + ITypeInfo_Release(typeinfos[i]); + + ITypeLib_Release(typelib); +} + static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) { *ppv = NULL; @@ -93,6 +158,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) case DLL_PROCESS_DETACH: unregister_wmp_class(); unregister_player_msg_class(); + release_typelib(); break; } diff --git a/dlls/wmp/wmp_private.h b/dlls/wmp/wmp_private.h index 9617be0c7f1..ab9c6d098c4 100644 --- a/dlls/wmp/wmp_private.h +++ b/dlls/wmp/wmp_private.h @@ -25,6 +25,21 @@ #include "dshow.h" #include "wmp.h" +#define TID_LIST \ + XIID(NULL) \ + CTID(WindowsMediaPlayer) + +typedef enum { +#define XIID(iface) iface ## _tid, +#define CTID(name) name ## _tid, +TID_LIST +#undef XIID +#undef CTID + LAST_tid +} typeinfo_id; + +HRESULT get_typeinfo(typeinfo_id tid, ITypeInfo **typeinfo) DECLSPEC_HIDDEN; + typedef struct { IConnectionPoint IConnectionPoint_iface;