Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 416 +++++++++++++++++++++++++++++++++++++ dlls/mfplat/mfplat.spec | 2 +- dlls/mfplat/tests/mfplat.c | 25 +++ include/mftransform.idl | 2 + 4 files changed, 444 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 910b923542..df11e189a2 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -65,6 +65,12 @@ 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 transform_activate +{ + struct attributes attributes; + IMFActivate IMFActivate_iface; +}; + struct system_clock { IMFClock IMFClock_iface; @@ -107,6 +113,416 @@ static struct system_clock *impl_from_IMFClock(IMFClock *iface) return CONTAINING_RECORD(iface, struct system_clock, IMFClock_iface); }
+static struct transform_activate *impl_from_IMFActivate(IMFActivate *iface) +{ + return CONTAINING_RECORD(iface, struct transform_activate, IMFActivate_iface); +} + +static HRESULT WINAPI transform_activate_QueryInterface(IMFActivate *iface, REFIID riid, void **out) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualIID(riid, &IID_IMFActivate) || + IsEqualIID(riid, &IID_IMFAttributes) || + IsEqualIID(riid, &IID_IUnknown)) + { + *out = iface; + IMFActivate_AddRef(iface); + return S_OK; + } + + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI transform_activate_AddRef(IMFActivate *iface) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + ULONG refcount = InterlockedIncrement(&activate->attributes.ref); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI transform_activate_Release(IMFActivate *iface) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + ULONG refcount = InterlockedDecrement(&activate->attributes.ref); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + clear_attributes_object(&activate->attributes); + heap_free(activate); + } + + return refcount; +} + +static HRESULT WINAPI transform_activate_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value); + + return attributes_GetItem(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type); + + return attributes_GetItemType(&activate->attributes, key, type); +} + +static HRESULT WINAPI transform_activate_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value, + BOOL *result) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result); + + return attributes_CompareItem(&activate->attributes, key, value, result); +} + +static HRESULT WINAPI transform_activate_Compare(IMFActivate *iface, IMFAttributes *theirs, + MF_ATTRIBUTES_MATCH_TYPE match_type, BOOL *ret) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %p, %d, %p.\n", iface, theirs, match_type, ret); + + return attributes_Compare(&activate->attributes, theirs, match_type, ret); +} + +static HRESULT WINAPI transform_activate_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value); + + return attributes_GetUINT32(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value); + + return attributes_GetUINT64(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_GetDouble(IMFActivate *iface, REFGUID key, double *value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value); + + return attributes_GetDouble(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_GetGUID(IMFActivate *iface, REFGUID key, GUID *value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value); + + return attributes_GetGUID(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length); + + return attributes_GetStringLength(&activate->attributes, key, length); +} + +static HRESULT WINAPI transform_activate_GetString(IMFActivate *iface, REFGUID key, WCHAR *value, + UINT32 size, UINT32 *length) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), value, size, length); + + return attributes_GetString(&activate->attributes, key, value, size, length); +} + +static HRESULT WINAPI transform_activate_GetAllocatedString(IMFActivate *iface, REFGUID key, WCHAR **value, + UINT32 *length) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length); + + return attributes_GetAllocatedString(&activate->attributes, key, value, length); +} + +static HRESULT WINAPI transform_activate_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size); + + return attributes_GetBlobSize(&activate->attributes, key, size); +} + +static HRESULT WINAPI transform_activate_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf, UINT32 bufsize, + UINT32 *blobsize) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p, %d, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize); + + return attributes_GetBlob(&activate->attributes, key, buf, bufsize, blobsize); +} + +static HRESULT WINAPI transform_activate_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size); + + return attributes_GetAllocatedBlob(&activate->attributes, key, buf, size); +} + +static HRESULT WINAPI transform_activate_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **out) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out); + + return attributes_GetUnknown(&activate->attributes, key, riid, out); +} + +static HRESULT WINAPI transform_activate_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value)); + + return attributes_SetItem(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_DeleteItem(IMFActivate *iface, REFGUID key) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s.\n", iface, debugstr_attr(key)); + + return attributes_DeleteItem(&activate->attributes, key); +} + +static HRESULT WINAPI transform_activate_DeleteAllItems(IMFActivate *iface) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p.\n", iface); + + return attributes_DeleteAllItems(&activate->attributes); +} + +static HRESULT WINAPI transform_activate_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value); + + return attributes_SetUINT32(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value)); + + return attributes_SetUINT64(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_SetDouble(IMFActivate *iface, REFGUID key, double value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value); + + return attributes_SetDouble(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value)); + + return attributes_SetGUID(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value)); + + return attributes_SetString(&activate->attributes, key, value); +} + +static HRESULT WINAPI transform_activate_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size); + + return attributes_SetBlob(&activate->attributes, key, buf, size); +} + +static HRESULT WINAPI transform_activate_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown); + + return attributes_SetUnknown(&activate->attributes, key, unknown); +} + +static HRESULT WINAPI transform_activate_LockStore(IMFActivate *iface) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p.\n", iface); + + return attributes_LockStore(&activate->attributes); +} + +static HRESULT WINAPI transform_activate_UnlockStore(IMFActivate *iface) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p.\n", iface); + + return attributes_UnlockStore(&activate->attributes); +} + +static HRESULT WINAPI transform_activate_GetCount(IMFActivate *iface, UINT32 *count) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %p.\n", iface, count); + + return attributes_GetCount(&activate->attributes, count); +} + +static HRESULT WINAPI transform_activate_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key, + PROPVARIANT *value) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %u, %p, %p.\n", iface, index, key, value); + + return attributes_GetItemByIndex(&activate->attributes, index, key, value); +} + +static HRESULT WINAPI transform_activate_CopyAllItems(IMFActivate *iface, IMFAttributes *dest) +{ + struct transform_activate *activate = impl_from_IMFActivate(iface); + + TRACE("%p, %p.\n", iface, dest); + + return attributes_CopyAllItems(&activate->attributes, dest); +} + +static HRESULT WINAPI transform_activate_ActivateObject(IMFActivate *iface, REFIID riid, void **obj) +{ + FIXME("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_activate_ShutdownObject(IMFActivate *iface) +{ + FIXME("%p.\n", iface); + + return E_NOTIMPL; +} + +static HRESULT WINAPI transform_activate_DetachObject(IMFActivate *iface) +{ + FIXME("%p.\n", iface); + + return E_NOTIMPL; +} + +static const IMFActivateVtbl transform_activate_vtbl = +{ + transform_activate_QueryInterface, + transform_activate_AddRef, + transform_activate_Release, + transform_activate_GetItem, + transform_activate_GetItemType, + transform_activate_CompareItem, + transform_activate_Compare, + transform_activate_GetUINT32, + transform_activate_GetUINT64, + transform_activate_GetDouble, + transform_activate_GetGUID, + transform_activate_GetStringLength, + transform_activate_GetString, + transform_activate_GetAllocatedString, + transform_activate_GetBlobSize, + transform_activate_GetBlob, + transform_activate_GetAllocatedBlob, + transform_activate_GetUnknown, + transform_activate_SetItem, + transform_activate_DeleteItem, + transform_activate_DeleteAllItems, + transform_activate_SetUINT32, + transform_activate_SetUINT64, + transform_activate_SetDouble, + transform_activate_SetGUID, + transform_activate_SetString, + transform_activate_SetBlob, + transform_activate_SetUnknown, + transform_activate_LockStore, + transform_activate_UnlockStore, + transform_activate_GetCount, + transform_activate_GetItemByIndex, + transform_activate_CopyAllItems, + transform_activate_ActivateObject, + transform_activate_ShutdownObject, + transform_activate_DetachObject, +}; + +HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate) +{ + struct transform_activate *object; + HRESULT hr; + + TRACE("%p.\n", activate); + + object = heap_alloc_zero(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + if (FAILED(hr = init_attributes_object(&object->attributes, 0))) + { + heap_free(object); + return hr; + } + + object->IMFActivate_iface.lpVtbl = &transform_activate_vtbl; + + *activate = &object->IMFActivate_iface; + + return S_OK; +} + static const WCHAR transform_keyW[] = {'M','e','d','i','a','F','o','u','n','d','a','t','i','o','n','\', 'T','r','a','n','s','f','o','r','m','s',0}; static const WCHAR categories_keyW[] = {'M','e','d','i','a','F','o','u','n','d','a','t','i','o','n','\', diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index e48242fa15..e3ec8bcb8b 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -66,7 +66,7 @@ @ stdcall MFCreateSystemTimeSource(ptr) @ stub MFCreateSystemUnderlyingClock @ stub MFCreateTempFile -@ stub MFCreateTransformActivate +@ stdcall MFCreateTransformActivate(ptr) @ stub MFCreateURLFromPath @ stub MFCreateUdpSockets @ stub MFCreateVideoMediaType diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index b61d91d14e..ba896f3711 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -77,6 +77,7 @@ static HRESULT (WINAPI *pMFRemovePeriodicCallback)(DWORD key); static HRESULT (WINAPI *pMFRegisterLocalByteStreamHandler)(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate); static HRESULT (WINAPI *pMFRegisterLocalSchemeHandler)(const WCHAR *scheme, IMFActivate *activate); +static HRESULT (WINAPI *pMFCreateTransformActivate)(IMFActivate **activate);
static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0}; static const WCHAR fileschemeW[] = {'f','i','l','e',':','/','/',0}; @@ -527,6 +528,7 @@ static void init_functions(void) X(MFRegisterLocalByteStreamHandler); X(MFRegisterLocalSchemeHandler); X(MFRemovePeriodicCallback); + X(MFCreateTransformActivate); #undef X
if ((mod = LoadLibraryA("d3d11.dll"))) @@ -3799,6 +3801,28 @@ static void test_dxgi_device_manager(void) IMFDXGIDeviceManager_Release(manager2); }
+static void test_MFCreateTransformActivate(void) +{ + IMFActivate *activate; + UINT32 count; + HRESULT hr; + + if (!pMFCreateTransformActivate) + { + win_skip("MFCreateTransformActivate() is not available.\n"); + return; + } + + hr = pMFCreateTransformActivate(&activate); + ok(hr == S_OK, "Failed to create activator, hr %#x.\n", hr); + + hr = IMFActivate_GetCount(activate, &count); + ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr); + ok(!count, "Unexpected attribute count %u.\n", count); + + IMFActivate_Release(activate); +} + START_TEST(mfplat) { CoInitialize(NULL); @@ -3837,6 +3861,7 @@ START_TEST(mfplat) test_local_handlers(); test_create_property_store(); test_dxgi_device_manager(); + test_MFCreateTransformActivate();
CoUninitialize(); } diff --git a/include/mftransform.idl b/include/mftransform.idl index ca2f781a6b..5c4860c367 100644 --- a/include/mftransform.idl +++ b/include/mftransform.idl @@ -121,3 +121,5 @@ interface IMFTransform : IUnknown [local] HRESULT ProcessOutput([in] DWORD flags, [in] DWORD count, [in,out,size_is(count)] MFT_OUTPUT_DATA_BUFFER *samples, [out] DWORD *status); } + +cpp_quote("HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate);")
Signed-off-by: Nikolay Sivov nsivov@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);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=64054
Your paranoid android.
=== debian10 (32 bit report) ===
mfplat: mfplat.c:2891: Test failed: Unexpected refcount 1Unhandled exception: page fault on read access to 0x00000009 in 32-bit code (0x71421f13).
Report errors: mfplat:mfplat crashed (c0000005)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=64053
Your paranoid android.
=== w1064v1809_ar (32 bit report) ===
mfplat: mfplat.c:2397: Test failed: Unexpected return value 0x102. mfplat.c:1748: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:1751: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:1754: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. mfplat.c:1757: Test failed: Unexpected result, hr 0xc00d3e85. 18a8:mfplat: unhandled exception c0000005 at 00404E2B