[PATCH] wmp: Implement GetClassInfo().

Nikolay Sivov nsivov at codeweavers.com
Tue Aug 21 01:03:41 CDT 2018


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/wmp/oleobj.c       | 11 +++++--
 dlls/wmp/tests/oleobj.c | 12 ++++++++
 dlls/wmp/wmp_main.c     | 66 +++++++++++++++++++++++++++++++++++++++++
 dlls/wmp/wmp_private.h  | 15 ++++++++++
 4 files changed, 101 insertions(+), 3 deletions(-)

diff --git a/dlls/wmp/oleobj.c b/dlls/wmp/oleobj.c
index a90a0c2c6c..cbbd965c38 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 472b985244..2a69a102de 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,16 @@ 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, NULL);
+    ok(hres == E_POINTER, "Unexpected hr %#x.\n", hres);
+    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 273d193e58..2541fc54ff 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 9617be0c7f..ab9c6d098c 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;
 
-- 
2.18.0




More information about the wine-devel mailing list