mfplat: Implement MFTEnumEx().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
be08f2c203
commit
c0b1d7b593
|
@ -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)
|
||||
{
|
||||
HKEY htransform, hfilter;
|
||||
DWORD reg_type, size;
|
||||
LONG ret = FALSE;
|
||||
MFT_REGISTER_TYPE_INFO *info = NULL;
|
||||
BOOL matching = TRUE;
|
||||
DWORD model;
|
||||
int i;
|
||||
|
||||
if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
|
||||
if (!IsEqualGUID(category, &mft->category))
|
||||
return FALSE;
|
||||
|
||||
if (RegOpenKeyW(htransform, clsid_str, &hfilter))
|
||||
/* 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)
|
||||
{
|
||||
RegCloseKey(htransform);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (RegQueryValueExW(hfilter, type_str, NULL, ®_type, NULL, &size) != ERROR_SUCCESS)
|
||||
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;
|
||||
|
||||
*type = NULL;
|
||||
*count = 0;
|
||||
|
||||
if (RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform))
|
||||
return;
|
||||
|
||||
if (RegOpenKeyW(htransform, clsidW, &hfilter))
|
||||
{
|
||||
RegCloseKey(htransform);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void mft_get_reg_flags(const WCHAR *clsidW, const WCHAR *nameW, DWORD *flags)
|
||||
{
|
||||
DWORD ret, reg_type, size;
|
||||
HKEY hroot, hmft;
|
||||
|
||||
*flags = 0;
|
||||
|
||||
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(clsidW, category);
|
||||
ret = RegOpenKeyW(hcategory, clsidW, &hlist);
|
||||
RegCloseKey(hcategory);
|
||||
if (ret)
|
||||
return E_FAIL;
|
||||
|
||||
size = ARRAY_SIZE(clsidW);
|
||||
while (!RegEnumKeyExW(hlist, index, clsidW, &size, NULL, NULL, NULL, NULL))
|
||||
{
|
||||
memset(&mft, 0, sizeof(mft));
|
||||
mft.category = *category;
|
||||
if (!GUIDFromString(clsidW, &mft.clsid))
|
||||
goto next;
|
||||
|
||||
mft_get_reg_flags(clsidW, mftflagsW, &mft.flags);
|
||||
|
||||
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);
|
||||
|
||||
if (!mft_is_type_info_match(&mft, category, flags, plugin_control, input_type, output_type))
|
||||
{
|
||||
heap_free(mft.input_types);
|
||||
heap_free(mft.output_types);
|
||||
goto next;
|
||||
}
|
||||
|
||||
cur = heap_alloc(sizeof(*cur));
|
||||
/* Reuse allocated type arrays. */
|
||||
*cur = mft;
|
||||
list_add_tail(mfts, &cur->entry);
|
||||
|
||||
next:
|
||||
size = ARRAY_SIZE(clsidW);
|
||||
index++;
|
||||
}
|
||||
|
||||
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 **pclsids, UINT32 *pcount)
|
||||
MFT_REGISTER_TYPE_INFO *output_type, IMFAttributes *attributes, CLSID **clsids, UINT32 *count)
|
||||
{
|
||||
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;
|
||||
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, pclsids, pcount);
|
||||
TRACE("%s, %#x, %p, %p, %p, %p, %p.\n", debugstr_guid(&category), flags, input_type, output_type, attributes,
|
||||
clsids, count);
|
||||
|
||||
if (!pclsids || !pcount)
|
||||
if (!clsids || !count)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory))
|
||||
return E_FAIL;
|
||||
*count = 0;
|
||||
|
||||
GUIDToString(buffer, &category);
|
||||
list_init(&mfts);
|
||||
|
||||
ret = RegOpenKeyW(hcategory, buffer, &hlist);
|
||||
RegCloseKey(hcategory);
|
||||
if (ret) return E_FAIL;
|
||||
if (FAILED(hr = mft_collect_machine_reg(&mfts, &category, MFT_ENUM_FLAG_SYNCMFT, NULL, input_type, output_type)))
|
||||
return hr;
|
||||
|
||||
while (RegEnumKeyExW(hlist, index, clsid_str, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
|
||||
mft_count = list_count(&mfts);
|
||||
|
||||
if (mft_count)
|
||||
{
|
||||
GUID clsid;
|
||||
void *tmp;
|
||||
if (!(*clsids = CoTaskMemAlloc(mft_count * sizeof(**clsids))))
|
||||
hr = E_OUTOFMEMORY;
|
||||
|
||||
if (!GUIDFromString(clsid_str, &clsid))
|
||||
goto next;
|
||||
|
||||
if (output_type && !match_type(clsid_str, outputtypesW, output_type))
|
||||
goto next;
|
||||
|
||||
if (input_type && !match_type(clsid_str, inputtypesW, input_type))
|
||||
goto next;
|
||||
|
||||
tmp = CoTaskMemRealloc(clsids, (count + 1) * sizeof(GUID));
|
||||
if (!tmp)
|
||||
mft_count = 0;
|
||||
LIST_FOR_EACH_ENTRY_SAFE(mft, mft2, &mfts, struct mft_registration, entry)
|
||||
{
|
||||
CoTaskMemFree(clsids);
|
||||
RegCloseKey(hlist);
|
||||
return E_OUTOFMEMORY;
|
||||
if (*clsids)
|
||||
(*clsids)[mft_count++] = mft->clsid;
|
||||
list_remove(&mft->entry);
|
||||
release_mft_registration(mft);
|
||||
}
|
||||
|
||||
clsids = tmp;
|
||||
clsids[count++] = clsid;
|
||||
|
||||
next:
|
||||
size = MAX_PATH;
|
||||
index++;
|
||||
}
|
||||
|
||||
*pclsids = clsids;
|
||||
*pcount = count;
|
||||
if (!mft_count)
|
||||
{
|
||||
CoTaskMemFree(*clsids);
|
||||
*clsids = NULL;
|
||||
}
|
||||
*count = mft_count;
|
||||
|
||||
RegCloseKey(hlist);
|
||||
return S_OK;
|
||||
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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue