Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 457 ++++++++++++++++++++++++++++++------- dlls/mfplat/mfplat.spec | 1 + dlls/mfplat/tests/mfplat.c | 17 +- include/mfapi.h | 2 + 4 files changed, 391 insertions(+), 86 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index ef0db5a276..45cddd42cc 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -85,7 +85,7 @@ 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 mft_registration { struct list entry; IClassFactory *factory; @@ -107,6 +107,7 @@ struct transform_activate { struct attributes attributes; IMFActivate IMFActivate_iface; + IClassFactory *factory; };
struct system_clock @@ -194,6 +195,8 @@ static ULONG WINAPI transform_activate_Release(IMFActivate *iface) if (!refcount) { clear_attributes_object(&activate->attributes); + if (activate->factory) + IClassFactory_Release(activate->factory); heap_free(activate); }
@@ -537,13 +540,11 @@ static const IMFActivateVtbl transform_activate_vtbl = transform_activate_DetachObject, };
-HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate) +static HRESULT create_transform_activate(IClassFactory *factory, IMFActivate **activate) { struct transform_activate *object; HRESULT hr;
- TRACE("%p.\n", activate); - object = heap_alloc_zero(sizeof(*object)); if (!object) return E_OUTOFMEMORY; @@ -555,12 +556,22 @@ HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate) }
object->IMFActivate_iface.lpVtbl = &transform_activate_vtbl; + object->factory = factory; + if (object->factory) + IClassFactory_AddRef(object->factory);
*activate = &object->IMFActivate_iface;
return S_OK; }
+HRESULT WINAPI MFCreateTransformActivate(IMFActivate **activate) +{ + TRACE("%p.\n", activate); + + return create_transform_activate(NULL, activate); +} + 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','\', @@ -648,7 +659,7 @@ static BOOL GUIDFromString(LPCWSTR s, GUID *id) id->Data4[(i-19)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]]; }
- if (!s[37]) return TRUE; + if (!s[36]) return TRUE; return FALSE; }
@@ -774,7 +785,7 @@ HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags return hr; }
-static void release_local_mft(struct local_mft *mft) +static void release_mft_registration(struct mft_registration *mft) { if (mft->factory) IClassFactory_Release(mft->factory); @@ -788,7 +799,7 @@ static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUI 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; + struct mft_registration *mft, *cur, *unreg_mft = NULL; HRESULT hr;
if (!factory && !clsid) @@ -807,7 +818,7 @@ static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUI if (clsid) mft->clsid = *clsid; mft->category = *category; - mft->flags = flags; + mft->flags = flags | MFT_ENUM_FLAG_LOCALMFT; if (FAILED(hr = heap_strdupW(name, &mft->name))) goto failed;
@@ -835,7 +846,7 @@ static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUI
EnterCriticalSection(&local_mfts_section);
- LIST_FOR_EACH_ENTRY(cur, &local_mfts, struct local_mft, entry) + LIST_FOR_EACH_ENTRY(cur, &local_mfts, struct mft_registration, entry) { if (cur->factory == factory) { @@ -849,11 +860,11 @@ static HRESULT mft_register_local(IClassFactory *factory, REFCLSID clsid, REFGUI LeaveCriticalSection(&local_mfts_section);
if (unreg_mft) - release_local_mft(unreg_mft); + release_mft_registration(unreg_mft);
failed: if (FAILED(hr)) - release_local_mft(mft); + release_mft_registration(mft);
return hr; } @@ -880,7 +891,7 @@ HRESULT WINAPI MFTRegisterLocalByCLSID(REFCLSID clsid, REFGUID category, LPCWSTR
static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid) { - struct local_mft *cur, *cur2; + struct mft_registration *cur, *cur2; BOOL unregister_all = !factory && !clsid; struct list unreg;
@@ -888,7 +899,7 @@ static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid)
EnterCriticalSection(&local_mfts_section);
- LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &local_mfts, struct local_mft, entry) + LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &local_mfts, struct mft_registration, entry) { if (!unregister_all) { @@ -911,10 +922,10 @@ static HRESULT mft_unregister_local(IClassFactory *factory, REFCLSID clsid) 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_FOR_EACH_ENTRY_SAFE(cur, cur2, &unreg, struct mft_registration, entry) { list_remove(&cur->entry); - release_local_mft(cur); + release_mft_registration(cur); }
return S_OK; @@ -945,135 +956,411 @@ MFTIME WINAPI MFGetSystemTime(void) return mf; }
-static BOOL match_type(const WCHAR *clsid_str, const WCHAR *type_str, MFT_REGISTER_TYPE_INFO *type) +static BOOL mft_is_type_info_match(struct mft_registration *mft, const GUID *category, UINT32 flags, + IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type, + const MFT_REGISTER_TYPE_INFO *output_type) +{ + BOOL matching = TRUE; + DWORD model; + int i; + + if (!IsEqualGUID(category, &mft->category)) + return FALSE; + + /* Default model is synchronous. */ + model = mft->flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE); + if (!model) + model = MFT_ENUM_FLAG_SYNCMFT; + if (!(model & flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE))) + return FALSE; + + /* These flags should be explicitly enabled. */ + if (mft->flags & ~flags & (MFT_ENUM_FLAG_FIELDOFUSE | MFT_ENUM_FLAG_TRANSCODE_ONLY)) + return FALSE; + + if (flags & MFT_ENUM_FLAG_SORTANDFILTER && !mft->factory && plugin_control + && IMFPluginControl_IsDisabled(plugin_control, MF_Plugin_Type_MFT, &mft->clsid) == S_OK) + { + return FALSE; + } + + if (input_type) + { + for (i = 0, matching = FALSE; input_type && i < mft->input_types_count; ++i) + { + if (!memcmp(&mft->input_types[i], input_type, sizeof(*input_type))) + { + matching = TRUE; + break; + } + } + } + + if (output_type && matching) + { + for (i = 0, matching = FALSE; i < mft->output_types_count; ++i) + { + if (!memcmp(&mft->output_types[i], output_type, sizeof(*output_type))) + { + matching = TRUE; + break; + } + } + } + + return matching; +} + +static void mft_get_reg_type_info(const WCHAR *clsidW, const WCHAR *typeW, MFT_REGISTER_TYPE_INFO **type, + UINT32 *count) { HKEY htransform, hfilter; DWORD reg_type, size; - LONG ret = FALSE; - MFT_REGISTER_TYPE_INFO *info = NULL; - int i; + + *type = NULL; + *count = 0;
if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform)) - return FALSE; + return;
- if (RegOpenKeyW(htransform, clsid_str, &hfilter)) + if (RegOpenKeyW(htransform, clsidW, &hfilter)) { RegCloseKey(htransform); - return FALSE; + return; }
- if (RegQueryValueExW(hfilter, type_str, NULL, ®_type, NULL, &size) != ERROR_SUCCESS) + if (RegQueryValueExW(hfilter, typeW, NULL, ®_type, NULL, &size)) goto out;
if (reg_type != REG_BINARY) goto out;
- if (!size || size % (sizeof(MFT_REGISTER_TYPE_INFO)) != 0) + if (!size || size % sizeof(**type)) goto out;
- info = HeapAlloc(GetProcessHeap(), 0, size); - if (!info) + if (!(*type = heap_alloc(size))) goto out;
- if (RegQueryValueExW(hfilter, type_str, NULL, ®_type, (LPBYTE)info, &size) != ERROR_SUCCESS) - goto out; + *count = size / sizeof(**type);
- for (i = 0; i < size / sizeof(MFT_REGISTER_TYPE_INFO); i++) + if (RegQueryValueExW(hfilter, typeW, NULL, ®_type, (BYTE *)*type, &size)) { - if (IsEqualGUID(&info[i].guidMajorType, &type->guidMajorType) && - IsEqualGUID(&info[i].guidSubtype, &type->guidSubtype)) - { - ret = TRUE; - break; - } + heap_free(*type); + *type = NULL; + *count = 0; }
out: - HeapFree(GetProcessHeap(), 0, info); RegCloseKey(hfilter); RegCloseKey(htransform); - return ret; }
-/*********************************************************************** - * MFTEnum (mfplat.@) - */ -HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type, - MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, - CLSID **pclsids, UINT32 *pcount) +static void mft_get_reg_flags(const WCHAR *clsidW, const WCHAR *nameW, DWORD *flags) { - WCHAR buffer[64], clsid_str[MAX_PATH] = {0}; - HKEY hcategory, hlist; - DWORD index = 0; - DWORD size = MAX_PATH; - CLSID *clsids = NULL; - UINT32 count = 0; - LONG ret; + DWORD ret, reg_type, size; + HKEY hroot, hmft;
- TRACE("(%s, %x, %p, %p, %p, %p, %p)\n", debugstr_guid(&category), flags, input_type, - output_type, attributes, pclsids, pcount); + *flags = 0;
- if (!pclsids || !pcount) - return E_INVALIDARG; + if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot)) + return; + + ret = RegOpenKeyW(hroot, clsidW, &hmft); + RegCloseKey(hroot); + if (ret) + return; + + reg_type = 0; + if (!RegQueryValueExW(hmft, nameW, NULL, ®_type, NULL, &size) && reg_type == REG_DWORD) + RegQueryValueExW(hmft, nameW, NULL, ®_type, (BYTE *)flags, &size); + + RegCloseKey(hmft); +} + +static HRESULT mft_collect_machine_reg(struct list *mfts, const GUID *category, UINT32 flags, + IMFPluginControl *plugin_control, const MFT_REGISTER_TYPE_INFO *input_type, + const MFT_REGISTER_TYPE_INFO *output_type) +{ + struct mft_registration mft, *cur; + HKEY hcategory, hlist; + WCHAR clsidW[64]; + DWORD ret, size; + int index = 0;
if (RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory)) return E_FAIL;
- GUIDToString(buffer, &category); - - ret = RegOpenKeyW(hcategory, buffer, &hlist); + GUIDToString(clsidW, category); + ret = RegOpenKeyW(hcategory, clsidW, &hlist); RegCloseKey(hcategory); - if (ret) return E_FAIL; + if (ret) + return E_FAIL;
- while (RegEnumKeyExW(hlist, index, clsid_str, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) + size = ARRAY_SIZE(clsidW); + while (!RegEnumKeyExW(hlist, index, clsidW, &size, NULL, NULL, NULL, NULL)) { - GUID clsid; - void *tmp; - - if (!GUIDFromString(clsid_str, &clsid)) + memset(&mft, 0, sizeof(mft)); + mft.category = *category; + if (!GUIDFromString(clsidW, &mft.clsid)) goto next;
- if (output_type && !match_type(clsid_str, outputtypesW, output_type)) - goto next; + mft_get_reg_flags(clsidW, mftflagsW, &mft.flags);
- if (input_type && !match_type(clsid_str, inputtypesW, input_type)) - goto next; + if (output_type) + mft_get_reg_type_info(clsidW, outputtypesW, &mft.output_types, &mft.output_types_count); + + if (input_type) + mft_get_reg_type_info(clsidW, inputtypesW, &mft.input_types, &mft.input_types_count);
- tmp = CoTaskMemRealloc(clsids, (count + 1) * sizeof(GUID)); - if (!tmp) + if (!mft_is_type_info_match(&mft, category, flags, plugin_control, input_type, output_type)) { - CoTaskMemFree(clsids); - RegCloseKey(hlist); - return E_OUTOFMEMORY; + heap_free(mft.input_types); + heap_free(mft.output_types); + goto next; }
- clsids = tmp; - clsids[count++] = clsid; + cur = heap_alloc(sizeof(*cur)); + /* Reuse allocated type arrays. */ + *cur = mft; + list_add_tail(mfts, &cur->entry);
next: - size = MAX_PATH; + size = ARRAY_SIZE(clsidW); index++; }
- *pclsids = clsids; - *pcount = count; - - RegCloseKey(hlist); return S_OK; }
+static BOOL mft_is_preferred(IMFPluginControl *plugin_control, const CLSID *clsid) +{ + CLSID preferred; + WCHAR *selector; + int index = 0; + + while (SUCCEEDED(IMFPluginControl_GetPreferredClsidByIndex(plugin_control, MF_Plugin_Type_MFT, index++, &selector, + &preferred))) + { + CoTaskMemFree(selector); + + if (IsEqualGUID(&preferred, clsid)) + return TRUE; + } + + return FALSE; +} + +static HRESULT mft_enum(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type, + const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count) +{ + IMFPluginControl *plugin_control = NULL; + struct list mfts, mfts_sorted, *result = &mfts; + struct mft_registration *mft, *mft2; + unsigned int obj_count; + HRESULT hr; + + *count = 0; + *activate = NULL; + + if (!flags) + flags = MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_LOCALMFT | MFT_ENUM_FLAG_SORTANDFILTER; + + /* Synchronous processing is default. */ + if (!(flags & (MFT_ENUM_FLAG_SYNCMFT | MFT_ENUM_FLAG_ASYNCMFT | MFT_ENUM_FLAG_HARDWARE))) + flags |= MFT_ENUM_FLAG_SYNCMFT; + + if (FAILED(hr = MFGetPluginControl(&plugin_control))) + { + WARN("Failed to get plugin control instance, hr %#x.\n", hr); + return hr; + } + + list_init(&mfts); + + /* Collect from registry */ + mft_collect_machine_reg(&mfts, &category, flags, plugin_control, input_type, output_type); + + /* Collect locally registered ones. */ + if (flags & MFT_ENUM_FLAG_LOCALMFT) + { + struct mft_registration *local; + + EnterCriticalSection(&local_mfts_section); + + LIST_FOR_EACH_ENTRY(local, &local_mfts, struct mft_registration, entry) + { + if (mft_is_type_info_match(local, &category, flags, plugin_control, input_type, output_type)) + { + mft = heap_alloc_zero(sizeof(*mft)); + + mft->clsid = local->clsid; + mft->factory = local->factory; + if (mft->factory) + IClassFactory_AddRef(mft->factory); + mft->flags = local->flags; + + list_add_tail(&mfts, &mft->entry); + } + } + + LeaveCriticalSection(&local_mfts_section); + } + + list_init(&mfts_sorted); + + if (flags & MFT_ENUM_FLAG_SORTANDFILTER) + { + /* Local registrations. */ + LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry) + { + if (mft->flags & MFT_ENUM_FLAG_LOCALMFT) + { + list_remove(&mft->entry); + list_add_tail(&mfts_sorted, &mft->entry); + } + } + + /* FIXME: Sort by merit value, for the ones that got it. Currently not handled. */ + + /* Preferred transforms. */ + LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry) + { + if (!mft->factory && mft_is_preferred(plugin_control, &mft->clsid)) + { + list_remove(&mft->entry); + list_add_tail(&mfts_sorted, &mft->entry); + } + } + + /* Append the rest. */ + LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry) + { + list_remove(&mft->entry); + list_add_tail(&mfts_sorted, &mft->entry); + } + + result = &mfts; + } + + IMFPluginControl_Release(plugin_control); + + /* Create activation objects from CLSID/IClassFactory. */ + + obj_count = list_count(result); + + if (obj_count) + { + if (!(*activate = CoTaskMemAlloc(obj_count * sizeof(**activate)))) + hr = E_OUTOFMEMORY; + + obj_count = 0; + + LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, result, struct mft_registration, entry) + { + IMFActivate *mft_activate; + + if (*activate) + { + if (SUCCEEDED(create_transform_activate(mft->factory, &mft_activate))) + { + (*activate)[obj_count] = mft_activate; + + /* FIXME: set some attributes */ + + obj_count++; + } + } + + list_remove(&mft->entry); + release_mft_registration(mft); + } + } + + if (!obj_count) + { + CoTaskMemFree(*activate); + *activate = NULL; + } + *count = obj_count; + + return hr; +} + +/*********************************************************************** + * MFTEnum (mfplat.@) + */ +HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type, + MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, CLSID **clsids, UINT32 *count) +{ + struct mft_registration *mft, *mft2; + unsigned int mft_count; + struct list mfts; + HRESULT hr; + + TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes, + clsids, count); + + if (!clsids || !count) + return E_INVALIDARG; + + *count = 0; + + list_init(&mfts); + + if (FAILED(hr = mft_collect_machine_reg(&mfts, &category, MFT_ENUM_FLAG_SYNCMFT, NULL, input_type, output_type))) + return hr; + + mft_count = list_count(&mfts); + + if (mft_count) + { + if (!(*clsids = CoTaskMemAlloc(mft_count * sizeof(**clsids)))) + hr = E_OUTOFMEMORY; + + mft_count = 0; + LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry) + { + if (*clsids) + (*clsids)[mft_count++] = mft->clsid; + list_remove(&mft->entry); + release_mft_registration(mft); + } + } + + if (!mft_count) + { + CoTaskMemFree(*clsids); + *clsids = NULL; + } + *count = mft_count; + + return hr; +} + /*********************************************************************** * MFTEnumEx (mfplat.@) */ HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type, - const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, - UINT32 *pcount) + const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count) { - FIXME("(%s, %x, %p, %p, %p, %p): stub\n", debugstr_guid(&category), flags, input_type, - output_type, activate, pcount); + TRACE("%s, %#x, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, activate, count);
- *pcount = 0; - return S_OK; + return mft_enum(category, flags, input_type, output_type, NULL, activate, count); +} + +/*********************************************************************** + * MFTEnum2 (mfplat.@) + */ +HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type, + const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count) +{ + TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes, + activate, count); + + if (attributes) + FIXME("Ignoring attributes.\n"); + + return mft_enum(category, flags, input_type, output_type, attributes, activate, count); }
/*********************************************************************** diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 85e28792c6..7e3bd4571c 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -144,6 +144,7 @@ @ stdcall MFStartup(long long) @ stub MFStreamDescriptorProtectMediaType @ stdcall MFTEnum(int128 long ptr ptr ptr ptr ptr) +@ stdcall MFTEnum2(int128 long ptr ptr ptr ptr ptr) @ stdcall MFTEnumEx(int128 long ptr ptr ptr ptr) @ stub MFTGetInfo @ stdcall MFTRegister(int128 int128 wstr long long ptr long ptr ptr) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 896cd93a46..a93bbfe7f1 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -89,6 +89,8 @@ static HRESULT (WINAPI *pMFTRegisterLocalByCLSID)(REFCLSID clsid, REFGUID catego static HRESULT (WINAPI *pMFTUnregisterLocal)(IClassFactory *factory); static HRESULT (WINAPI *pMFTUnregisterLocalByCLSID)(CLSID clsid); static HRESULT (WINAPI *pMFAllocateWorkQueueEx)(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue); +static HRESULT (WINAPI *pMFTEnumEx)(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type, + const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count);
static const WCHAR fileschemeW[] = L"file://";
@@ -659,13 +661,14 @@ static void init_functions(void) X(MFCreateDXGIDeviceManager); X(MFCreateSourceResolver); X(MFCreateMFByteStreamOnStream); + X(MFCreateTransformActivate); X(MFHeapAlloc); X(MFHeapFree); X(MFPutWaitingWorkItem); X(MFRegisterLocalByteStreamHandler); X(MFRegisterLocalSchemeHandler); X(MFRemovePeriodicCallback); - X(MFCreateTransformActivate); + X(MFTEnumEx); X(MFTRegisterLocal); X(MFTRegisterLocalByCLSID); X(MFTUnregisterLocal); @@ -4055,6 +4058,8 @@ static void test_MFTRegisterLocal(void) { IClassFactory test_factory = { &test_mft_factory_vtbl }; MFT_REGISTER_TYPE_INFO input_types[1]; + IMFActivate **activate; + UINT32 count, count2; HRESULT hr;
if (!pMFTRegisterLocal) @@ -4071,9 +4076,19 @@ static void test_MFTRegisterLocal(void) 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 = pMFTEnumEx(MFT_CATEGORY_OTHER, MFT_ENUM_FLAG_LOCALMFT, NULL, NULL, &activate, &count); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(count > 0, "Unexpected count %u.\n", count); + CoTaskMemFree(activate); + hr = pMFTUnregisterLocal(&test_factory); ok(hr == S_OK, "Failed to unregister MFT, hr %#x.\n", hr);
+ hr = pMFTEnumEx(MFT_CATEGORY_OTHER, MFT_ENUM_FLAG_LOCALMFT, NULL, NULL, &activate, &count2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(count2 < count, "Unexpected count %u.\n", count2); + CoTaskMemFree(activate); + hr = pMFTUnregisterLocal(&test_factory); ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Unexpected hr %#x.\n", hr);
diff --git a/include/mfapi.h b/include/mfapi.h index 910b45e68f..4d5ad5ad15 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -422,6 +422,8 @@ HRESULT WINAPI MFGetTimerPeriodicity(DWORD *periodicity); HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type, MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, CLSID **pclsids, UINT32 *pcount); +HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type, + const MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, IMFActivate ***activate, UINT32 *count); HRESULT WINAPI MFTEnumEx(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type, const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *pcount);