[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