[PATCH 2/2] mfplat: Add support for local MFT registration.

Nikolay Sivov nsivov at codeweavers.com
Wed Jan 29 06:36:21 CST 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mfplat/main.c         | 214 +++++++++++++++++++++++++++++++------
 dlls/mfplat/mfplat.spec    |   2 +-
 dlls/mfplat/tests/mfplat.c | 104 ++++++++++++++++++
 include/mfapi.h            |   1 +
 4 files changed, 288 insertions(+), 33 deletions(-)

diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index df11e189a2..c8beeda973 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -43,6 +43,27 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 
+static HRESULT heap_strdupW(const WCHAR *str, WCHAR **dest)
+{
+    HRESULT hr = S_OK;
+
+    if (str)
+    {
+        unsigned int size;
+
+        size = (lstrlenW(str) + 1) * sizeof(WCHAR);
+        *dest = heap_alloc(size);
+        if (*dest)
+            memcpy(*dest, str, size);
+        else
+            hr = E_OUTOFMEMORY;
+    }
+    else
+        *dest = NULL;
+
+    return hr;
+}
+
 static LONG platform_lock;
 
 struct local_handler
@@ -65,6 +86,24 @@ static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 };
 static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers);
 static struct list local_bytestream_handlers = LIST_INIT(local_bytestream_handlers);
 
+struct local_mft
+{
+    struct list entry;
+    IClassFactory *factory;
+    CLSID clsid;
+    GUID category;
+    WCHAR *name;
+    DWORD flags;
+    MFT_REGISTER_TYPE_INFO *input_types;
+    UINT32 input_types_count;
+    MFT_REGISTER_TYPE_INFO *output_types;
+    UINT32 output_types_count;
+};
+
+static CRITICAL_SECTION local_mfts_section = { NULL, -1, 0, 0, 0, 0 };
+
+static struct list local_mfts = LIST_INIT(local_mfts);
+
 struct transform_activate
 {
     struct attributes attributes;
@@ -736,34 +775,166 @@ HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags
     return hr;
 }
 
-HRESULT WINAPI MFTRegisterLocal(IClassFactory *factory, REFGUID category, LPCWSTR name,
-                           UINT32 flags, UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types,
-                           UINT32 coutput, const MFT_REGISTER_TYPE_INFO* output_types)
+static void release_local_mft(struct local_mft *mft)
 {
-    FIXME("(%p, %s, %s, %x, %u, %p, %u, %p)\n", factory, debugstr_guid(category), debugstr_w(name),
-                                                flags, cinput, input_types, coutput, output_types);
+    if (mft->factory)
+        IClassFactory_Release(mft->factory);
+    heap_free(mft->name);
+    heap_free(mft->input_types);
+    heap_free(mft->output_types);
+    heap_free(mft);
+}
 
-    return S_OK;
+static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
+        UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
+        const MFT_REGISTER_TYPE_INFO *output_types)
+{
+    struct local_mft *mft, *cur, *unreg_mft = NULL;
+    HRESULT hr;
+
+    if (!factory && !clsid)
+    {
+        WARN("Can't register without factory or CLSID.\n");
+        return E_FAIL;
+    }
+
+    mft = heap_alloc_zero(sizeof(*mft));
+    if (!mft)
+        return E_OUTOFMEMORY;
+
+    mft->factory = factory;
+    if (mft->factory)
+        IClassFactory_AddRef(mft->factory);
+    if (clsid)
+        mft->clsid = *clsid;
+    mft->category = *category;
+    mft->flags = flags;
+    if (FAILED(hr = heap_strdupW(name, &mft->name)))
+        goto failed;
+
+    if (input_count && input_types)
+    {
+        mft->input_types_count = input_count;
+        if (!(mft->input_types = heap_calloc(mft->input_types_count, sizeof(*input_types))))
+        {
+            hr = E_OUTOFMEMORY;
+            goto failed;
+        }
+        memcpy(mft->input_types, input_types, mft->input_types_count * sizeof(*input_types));
+    }
+
+    if (output_count && output_types)
+    {
+        mft->output_types_count = output_count;
+        if (!(mft->output_types = heap_calloc(mft->output_types_count, sizeof(*output_types))))
+        {
+            hr = E_OUTOFMEMORY;
+            goto failed;
+        }
+        memcpy(mft->output_types, output_types, mft->output_types_count * sizeof(*output_types));
+    }
+
+    EnterCriticalSection(&local_mfts_section);
+
+    LIST_FOR_EACH_ENTRY(cur, &local_mfts, struct local_mft, entry)
+    {
+        if (cur->factory == factory)
+        {
+            unreg_mft = cur;
+            list_remove(&cur->entry);
+            break;
+        }
+    }
+    list_add_tail(&local_mfts, &mft->entry);
+
+    LeaveCriticalSection(&local_mfts_section);
+
+    if (unreg_mft)
+        release_local_mft(unreg_mft);
+
+failed:
+    if (FAILED(hr))
+        release_local_mft(mft);
+
+    return hr;
 }
 
-HRESULT WINAPI MFTRegisterLocalByCLSID(REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
+HRESULT WINAPI MFTRegisterLocal(IClassFactory *factory, REFGUID category, LPCWSTR name, UINT32 flags,
         UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
         const MFT_REGISTER_TYPE_INFO *output_types)
 {
+    TRACE("%p, %s, %s, %#x, %u, %p, %u, %p.\n", factory, debugstr_guid(category), debugstr_w(name), flags, input_count,
+            input_types, output_count, output_types);
+
+    return mft_register_local(factory, NULL, category, name, flags, input_count, input_types, output_count, output_types);
+}
 
-    FIXME("%s, %s, %s, %#x, %u, %p, %u, %p.\n", debugstr_guid(clsid), debugstr_guid(category), debugstr_w(name), flags,
+HRESULT WINAPI MFTRegisterLocalByCLSID(REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
+        UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
+        const MFT_REGISTER_TYPE_INFO *output_types)
+{
+    TRACE("%s, %s, %s, %#x, %u, %p, %u, %p.\n", debugstr_guid(clsid), debugstr_guid(category), debugstr_w(name), flags,
             input_count, input_types, output_count, output_types);
 
-    return E_NOTIMPL;
+    return mft_register_local(NULL, clsid, category, name, flags, input_count, input_types, output_count, output_types);
 }
 
-HRESULT WINAPI MFTUnregisterLocal(IClassFactory *factory)
+static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid)
 {
-    FIXME("(%p)\n", factory);
+    struct local_mft *cur, *cur2;
+    BOOL unregister_all = !factory && !clsid;
+    struct list unreg;
+
+    list_init(&unreg);
+
+    EnterCriticalSection(&local_mfts_section);
+
+    LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &local_mfts, struct local_mft, entry)
+    {
+        if (!unregister_all)
+        {
+            if ((factory && cur->factory == factory) || IsEqualCLSID(&cur->clsid, clsid))
+            {
+                list_remove(&cur->entry);
+                list_add_tail(&unreg, &cur->entry);
+                break;
+            }
+        }
+        else
+        {
+            list_remove(&cur->entry);
+            list_add_tail(&unreg, &cur->entry);
+        }
+    }
+
+    LeaveCriticalSection(&local_mfts_section);
+
+    if (!unregister_all && list_empty(&unreg))
+        return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+
+    LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &unreg, struct local_mft, entry)
+    {
+        list_remove(&cur->entry);
+        release_local_mft(cur);
+    }
 
     return S_OK;
 }
 
+HRESULT WINAPI MFTUnregisterLocalByCLSID(CLSID clsid)
+{
+    TRACE("%s.\n", debugstr_guid(&clsid));
+
+    return mft_unregister_local(NULL, &clsid);
+}
+
+HRESULT WINAPI MFTUnregisterLocal(IClassFactory *factory)
+{
+    TRACE("%p.\n", factory);
+
+    return mft_unregister_local(factory, NULL);
+}
+
 MFTIME WINAPI MFGetSystemTime(void)
 {
     MFTIME mf;
@@ -7683,27 +7854,6 @@ static const IMFAsyncCallbackVtbl async_create_file_callback_vtbl =
     async_create_file_callback_Invoke,
 };
 
-static HRESULT heap_strdupW(const WCHAR *str, WCHAR **dest)
-{
-    HRESULT hr = S_OK;
-
-    if (str)
-    {
-        unsigned int size;
-
-        size = (lstrlenW(str) + 1) * sizeof(WCHAR);
-        *dest = heap_alloc(size);
-        if (*dest)
-            memcpy(*dest, str, size);
-        else
-            hr = E_OUTOFMEMORY;
-    }
-    else
-        *dest = NULL;
-
-    return hr;
-}
-
 /***********************************************************************
  *      MFBeginCreateFile (mfplat.@)
  */
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index e3ec8bcb8b..a13c192caf 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -150,7 +150,7 @@
 @ stdcall MFTRegisterLocalByCLSID(ptr ptr wstr long long ptr long ptr)
 @ stdcall MFTUnregister(int128)
 @ stdcall MFTUnregisterLocal(ptr)
-@ stub MFTUnregisterLocalByCLSID
+@ stdcall MFTUnregisterLocalByCLSID(int128)
 @ stub MFTraceError
 @ stub MFTraceFuncEnter
 @ stub MFUnblockThread
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index ba896f3711..d0e05650c2 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -78,6 +78,14 @@ static HRESULT (WINAPI *pMFRegisterLocalByteStreamHandler)(const WCHAR *extensio
         IMFActivate *activate);
 static HRESULT (WINAPI *pMFRegisterLocalSchemeHandler)(const WCHAR *scheme, IMFActivate *activate);
 static HRESULT (WINAPI *pMFCreateTransformActivate)(IMFActivate **activate);
+static HRESULT (WINAPI *pMFTRegisterLocal)(IClassFactory *factory, REFGUID category, LPCWSTR name,
+        UINT32 flags, UINT32 cinput, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 coutput,
+        const MFT_REGISTER_TYPE_INFO* output_types);
+static HRESULT (WINAPI *pMFTRegisterLocalByCLSID)(REFCLSID clsid, REFGUID category, LPCWSTR name, UINT32 flags,
+        UINT32 input_count, const MFT_REGISTER_TYPE_INFO *input_types, UINT32 output_count,
+        const MFT_REGISTER_TYPE_INFO *output_types);
+static HRESULT (WINAPI *pMFTUnregisterLocal)(IClassFactory *factory);
+static HRESULT (WINAPI *pMFTUnregisterLocalByCLSID)(CLSID clsid);
 
 static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0};
 static const WCHAR fileschemeW[] = {'f','i','l','e',':','/','/',0};
@@ -529,6 +537,10 @@ static void init_functions(void)
     X(MFRegisterLocalSchemeHandler);
     X(MFRemovePeriodicCallback);
     X(MFCreateTransformActivate);
+    X(MFTRegisterLocal);
+    X(MFTRegisterLocalByCLSID);
+    X(MFTUnregisterLocal);
+    X(MFTUnregisterLocalByCLSID);
 #undef X
 
     if ((mod = LoadLibraryA("d3d11.dll")))
@@ -3823,6 +3835,97 @@ static void test_MFCreateTransformActivate(void)
     IMFActivate_Release(activate);
 }
 
+static HRESULT WINAPI test_mft_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
+{
+    if (IsEqualIID(riid, &IID_IClassFactory) ||
+            IsEqualIID(riid, &IID_IUnknown))
+    {
+        *obj = iface;
+        IClassFactory_AddRef(iface);
+        return S_OK;
+    }
+
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI test_mft_factory_AddRef(IClassFactory *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI test_mft_factory_Release(IClassFactory *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI test_mft_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **obj)
+{
+    ok(0, "Unexpected call.\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI test_mft_factory_LockServer(IClassFactory *iface, BOOL fLock)
+{
+    return S_OK;
+}
+
+static const IClassFactoryVtbl test_mft_factory_vtbl =
+{
+    test_mft_factory_QueryInterface,
+    test_mft_factory_AddRef,
+    test_mft_factory_Release,
+    test_mft_factory_CreateInstance,
+    test_mft_factory_LockServer,
+};
+
+static void test_MFTRegisterLocal(void)
+{
+    IClassFactory test_factory = { &test_mft_factory_vtbl };
+    MFT_REGISTER_TYPE_INFO input_types[1];
+    HRESULT hr;
+
+    if (!pMFTRegisterLocal)
+    {
+        win_skip("MFTRegisterLocal() is not available.\n");
+        return;
+    }
+
+    input_types[0].guidMajorType = MFMediaType_Audio;
+    input_types[0].guidSubtype = MFAudioFormat_PCM;
+    hr = pMFTRegisterLocal(&test_factory, &MFT_CATEGORY_OTHER, L"Local MFT name", 0, 1, input_types, 0, NULL);
+    ok(hr == S_OK, "Failed to register MFT, hr %#x.\n", hr);
+
+    hr = pMFTRegisterLocal(&test_factory, &MFT_CATEGORY_OTHER, L"Local MFT name", 0, 1, input_types, 0, NULL);
+    ok(hr == S_OK, "Failed to register MFT, hr %#x.\n", hr);
+
+    hr = pMFTUnregisterLocal(&test_factory);
+    ok(hr == S_OK, "Failed to unregister MFT, hr %#x.\n", hr);
+
+    hr = pMFTUnregisterLocal(&test_factory);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Unexpected hr %#x.\n", hr);
+
+    hr = pMFTUnregisterLocal(NULL);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = pMFTRegisterLocalByCLSID(&MFT_CATEGORY_OTHER, &MFT_CATEGORY_OTHER, L"Local MFT name 2", 0, 1, input_types,
+            0, NULL);
+    ok(hr == S_OK, "Failed to register MFT, hr %#x.\n", hr);
+
+    hr = pMFTUnregisterLocal(NULL);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = pMFTUnregisterLocalByCLSID(MFT_CATEGORY_OTHER);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Unexpected hr %#x.\n", hr);
+
+    hr = pMFTRegisterLocalByCLSID(&MFT_CATEGORY_OTHER, &MFT_CATEGORY_OTHER, L"Local MFT name 2", 0, 1, input_types,
+            0, NULL);
+    ok(hr == S_OK, "Failed to register MFT, hr %#x.\n", hr);
+
+    hr = pMFTUnregisterLocalByCLSID(MFT_CATEGORY_OTHER);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+}
+
 START_TEST(mfplat)
 {
     CoInitialize(NULL);
@@ -3862,6 +3965,7 @@ START_TEST(mfplat)
     test_create_property_store();
     test_dxgi_device_manager();
     test_MFCreateTransformActivate();
+    test_MFTRegisterLocal();
 
     CoUninitialize();
 }
diff --git a/include/mfapi.h b/include/mfapi.h
index 182fb19dbf..7c9e713ac2 100644
--- a/include/mfapi.h
+++ b/include/mfapi.h
@@ -451,6 +451,7 @@ HRESULT WINAPI MFUnlockPlatform(void);
 HRESULT WINAPI MFUnlockWorkQueue(DWORD queue);
 HRESULT WINAPI MFTUnregister(CLSID clsid);
 HRESULT WINAPI MFTUnregisterLocal(IClassFactory *factory);
+HRESULT WINAPI MFTUnregisterLocalByCLSID(CLSID clsid);
 HRESULT WINAPI MFGetPluginControl(IMFPluginControl**);
 HRESULT WINAPI MFWrapMediaType(IMFMediaType *original, REFGUID major, REFGUID subtype, IMFMediaType **wrapped);
 HRESULT WINAPI MFUnwrapMediaType(IMFMediaType *wrapped, IMFMediaType **original);
-- 
2.24.1




More information about the wine-devel mailing list