mfplat: Add support for local MFT registration.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
be45be2de7
commit
97f646edab
|
@ -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,32 +775,164 @@ 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 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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
FIXME("%s, %s, %s, %#x, %u, %p, %u, %p.\n", debugstr_guid(clsid), debugstr_guid(category), debugstr_w(name), flags,
|
||||
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);
|
||||
}
|
||||
|
||||
static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid)
|
||||
{
|
||||
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)
|
||||
{
|
||||
FIXME("(%p)\n", factory);
|
||||
TRACE("%p.\n", factory);
|
||||
|
||||
return S_OK;
|
||||
return mft_unregister_local(factory, NULL);
|
||||
}
|
||||
|
||||
MFTIME WINAPI MFGetSystemTime(void)
|
||||
|
@ -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.@)
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue