Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 153 ++++++++++++++++++++++++++++++++++--- dlls/mfplat/mfplat.spec | 2 +- dlls/mfplat/tests/mfplat.c | 61 +++++++++++++-- include/mfapi.h | 2 + 4 files changed, 203 insertions(+), 15 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index f36c960f852..e2f892ed91d 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -631,7 +631,7 @@ static const BYTE guid_conv_table[256] = 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */ };
-static WCHAR* GUIDToString(WCHAR *str, REFGUID guid) +static WCHAR* guid_to_string(WCHAR *str, REFGUID guid) { swprintf(str, 39, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], @@ -706,7 +706,7 @@ static HRESULT register_transform(const CLSID *clsid, const WCHAR *name, UINT32 WCHAR str[250]; UINT8 *blob;
- GUIDToString(buffer, clsid); + guid_to_string(buffer, clsid); swprintf(str, ARRAY_SIZE(str), L"%s\%s", transform_keyW, buffer);
if ((ret = RegCreateKeyW(HKEY_CLASSES_ROOT, str, &hclsid))) @@ -767,8 +767,8 @@ static HRESULT register_category(CLSID *clsid, GUID *category) WCHAR guid1[64], guid2[64]; WCHAR str[350];
- GUIDToString(guid1, category); - GUIDToString(guid2, clsid); + guid_to_string(guid1, category); + guid_to_string(guid2, clsid);
swprintf(str, ARRAY_SIZE(str), L"%s\%s\%s", categories_keyW, guid1, guid2);
@@ -1030,7 +1030,7 @@ static BOOL mft_is_type_info_match(struct mft_registration *mft, const GUID *cat return matching; }
-static void mft_get_reg_type_info(const WCHAR *clsidW, const WCHAR *typeW, MFT_REGISTER_TYPE_INFO **type, +static void mft_get_reg_type_info_internal(const WCHAR *clsidW, const WCHAR *typeW, MFT_REGISTER_TYPE_INFO **type, UINT32 *count) { HKEY htransform, hfilter; @@ -1109,7 +1109,7 @@ static HRESULT mft_collect_machine_reg(struct list *mfts, const GUID *category, if (RegOpenKeyW(HKEY_CLASSES_ROOT, categories_keyW, &hcategory)) return E_FAIL;
- GUIDToString(clsidW, category); + guid_to_string(clsidW, category); ret = RegOpenKeyW(hcategory, clsidW, &hlist); RegCloseKey(hcategory); if (ret) @@ -1126,10 +1126,10 @@ static HRESULT mft_collect_machine_reg(struct list *mfts, const GUID *category, mft_get_reg_flags(clsidW, L"MFTFlags", &mft.flags);
if (output_type) - mft_get_reg_type_info(clsidW, L"OutputTypes", &mft.output_types, &mft.output_types_count); + mft_get_reg_type_info_internal(clsidW, L"OutputTypes", &mft.output_types, &mft.output_types_count);
if (input_type) - mft_get_reg_type_info(clsidW, L"InputTypes", &mft.input_types, &mft.input_types_count); + mft_get_reg_type_info_internal(clsidW, L"InputTypes", &mft.input_types, &mft.input_types_count);
if (!mft_is_type_info_match(&mft, category, flags, plugin_control, input_type, output_type)) { @@ -1416,7 +1416,7 @@ HRESULT WINAPI MFTUnregister(CLSID clsid)
TRACE("(%s)\n", debugstr_guid(&clsid));
- GUIDToString(buffer, &clsid); + guid_to_string(buffer, &clsid);
if (!RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &htransform)) { @@ -1442,6 +1442,141 @@ HRESULT WINAPI MFTUnregister(CLSID clsid) return S_OK; }
+static HRESULT mft_get_name(HKEY hkey, WCHAR **name) +{ + DWORD size; + + if (!name) + return S_OK; + + *name = NULL; + + if (!RegQueryValueExW(hkey, NULL, NULL, NULL, NULL, &size)) + { + if (!(*name = CoTaskMemAlloc(size))) + return E_OUTOFMEMORY; + + RegQueryValueExW(hkey, NULL, NULL, NULL, (BYTE *)*name, &size); + } + + return S_OK; +} + +static HRESULT mft_get_reg_type_info(const WCHAR *clsid, const WCHAR *key, MFT_REGISTER_TYPE_INFO **ret_types, + UINT32 *ret_count) +{ + MFT_REGISTER_TYPE_INFO *types = NULL; + UINT32 count = 0; + + if (!ret_types) + return S_OK; + + mft_get_reg_type_info_internal(clsid, key, &types, &count); + if (count) + { + if (!(*ret_types = CoTaskMemAlloc(count * sizeof(**ret_types)))) + { + free(types); + return E_OUTOFMEMORY; + } + + memcpy(*ret_types, types, count * sizeof(**ret_types)); + *ret_count = count; + } + + free(types); + + return S_OK; +} + +static HRESULT mft_get_attributes(HKEY hkey, IMFAttributes **ret) +{ + IMFAttributes *attributes; + UINT8 *blob; + DWORD size; + HRESULT hr; + + if (!ret) + return S_OK; + + if (FAILED(hr = MFCreateAttributes(&attributes, 0))) + return hr; + + if (!RegQueryValueExW(hkey, L"Attributes", NULL, NULL, NULL, &size) && size) + { + if (!(blob = malloc(size))) + { + IMFAttributes_Release(attributes); + return E_OUTOFMEMORY; + } + + if (!RegQueryValueExW(hkey, L"Attributes", NULL, NULL, blob, &size)) + { + if (FAILED(hr = MFInitAttributesFromBlob(attributes, blob, size))) + WARN("Failed to initialize attributes, hr %#x.\n", hr); + } + + free(blob); + } + + if (SUCCEEDED(hr)) + { + *ret = attributes; + IMFAttributes_AddRef(*ret); + } + + IMFAttributes_Release(attributes); + + return hr; +} + +/*********************************************************************** + * MFTGetInfo (mfplat.@) + */ +HRESULT WINAPI MFTGetInfo(CLSID clsid, WCHAR **name, MFT_REGISTER_TYPE_INFO **input_types, + UINT32 *input_types_count, MFT_REGISTER_TYPE_INFO **output_types, UINT32 *output_types_count, + IMFAttributes **attributes) +{ + HRESULT hr = S_OK; + WCHAR clsidW[64]; + HKEY hroot, hmft; + DWORD ret; + + TRACE("%s, %p, %p, %p, %p, %p, %p.\n", debugstr_guid(&clsid), name, input_types, + input_types_count, output_types, output_types_count, attributes); + + guid_to_string(clsidW, &clsid); + + if ((ret = RegOpenKeyW(HKEY_CLASSES_ROOT, transform_keyW, &hroot))) + return HRESULT_FROM_WIN32(ret); + + ret = RegOpenKeyW(hroot, clsidW, &hmft); + RegCloseKey(hroot); + if (ret) + return HRESULT_FROM_WIN32(ret); + + if (input_types_count) + *input_types_count = 0; + + if (output_types_count) + *output_types_count = 0; + + hr = mft_get_name(hmft, name); + + if (SUCCEEDED(hr)) + hr = mft_get_reg_type_info(clsidW, L"InputTypes", input_types, input_types_count); + + if (SUCCEEDED(hr)) + hr = mft_get_reg_type_info(clsidW, L"OutputTypes", output_types, output_types_count); + + if (SUCCEEDED(hr)) + hr = mft_get_attributes(hmft, attributes); + + RegCloseKey(hmft); + + return hr; +} + /*********************************************************************** * MFStartup (mfplat.@) */ diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 6cc3fb07105..44d98a957e2 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -160,7 +160,7 @@ @ 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 MFTGetInfo(int128 ptr ptr ptr ptr ptr ptr) @ stdcall MFTRegister(int128 int128 wstr long long ptr long ptr ptr) @ stdcall MFTRegisterLocal(ptr ptr wstr long long ptr long ptr) @ stdcall MFTRegisterLocalByCLSID(ptr ptr wstr long long ptr long ptr) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 21eab6d1172..207bd61b8dc 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -396,6 +396,7 @@ static BOOL check_clsid(CLSID *clsids, UINT32 count)
static void test_register(void) { + MFT_REGISTER_TYPE_INFO *in_types, *out_types; WCHAR name[] = L"Wine test"; MFT_REGISTER_TYPE_INFO input[] = { @@ -405,17 +406,19 @@ static void test_register(void) { { DUMMY_CLSID, DUMMY_GUID2 } }; + UINT32 count, in_count, out_count; + IMFAttributes *attributes; + WCHAR *mft_name; CLSID *clsids; - UINT32 count; - HRESULT ret; + HRESULT hr, ret;
ret = MFTRegister(DUMMY_CLSID, MFT_CATEGORY_OTHER, name, 0, 1, input, 1, output, NULL); if (ret == E_ACCESSDENIED) { - win_skip("Not enough permissions to register a filter\n"); + win_skip("Not enough permissions to register a transform.\n"); return; } - ok(ret == S_OK, "Failed to register dummy filter: %x\n", ret); + ok(ret == S_OK, "Failed to register dummy transform, hr %#x.\n", ret);
if(0) { @@ -445,6 +448,49 @@ if(0) ret = MFTEnum(MFT_CATEGORY_OTHER, 0, NULL, NULL, NULL, &clsids, NULL); ok(ret == E_POINTER, "Failed to enumerate filters: %x\n", ret); } + hr = MFTGetInfo(DUMMY_CLSID, &mft_name, NULL, NULL, NULL, NULL, NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!lstrcmpW(mft_name, L"Wine test"), "Unexpected name %s.\n", wine_dbgstr_w(mft_name)); + CoTaskMemFree(mft_name); + + hr = MFTGetInfo(DUMMY_CLSID, NULL, NULL, NULL, NULL, NULL, NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + in_count = out_count = 1; + hr = MFTGetInfo(DUMMY_CLSID, NULL, NULL, &in_count, NULL, &out_count, NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!in_count, "Unexpected count %u.\n", in_count); + ok(!out_count, "Unexpected count %u.\n", out_count); + + hr = MFTGetInfo(DUMMY_CLSID, NULL, NULL, NULL, NULL, NULL, &attributes); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!attributes, "Unexpected attributes.\n"); + IMFAttributes_Release(attributes); + + hr = MFTGetInfo(DUMMY_CLSID, &mft_name, &in_types, &in_count, &out_types, &out_count, &attributes); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!lstrcmpW(mft_name, L"Wine test"), "Unexpected name %s.\n", wine_dbgstr_w(mft_name)); + ok(!!in_types, "Unexpected pointer.\n"); + ok(!!out_types, "Unexpected pointer.\n"); + ok(in_count == 1, "Unexpected count %u.\n", in_count); + ok(out_count == 1, "Unexpected count %u.\n", out_count); + ok(IsEqualGUID(&in_types->guidMajorType, &DUMMY_CLSID), "Unexpected type guid %s.\n", + wine_dbgstr_guid(&in_types->guidMajorType)); + ok(IsEqualGUID(&in_types->guidSubtype, &DUMMY_GUID1), "Unexpected type guid %s.\n", + wine_dbgstr_guid(&in_types->guidSubtype)); + ok(IsEqualGUID(&out_types->guidMajorType, &DUMMY_CLSID), "Unexpected type guid %s.\n", + wine_dbgstr_guid(&out_types->guidMajorType)); + ok(IsEqualGUID(&out_types->guidSubtype, &DUMMY_GUID2), "Unexpected type guid %s.\n", + wine_dbgstr_guid(&out_types->guidSubtype)); + ok(!!attributes, "Unexpected attributes.\n"); + count = 1; + hr = IMFAttributes_GetCount(attributes, &count); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!count, "Unexpected count %u.\n", count); + CoTaskMemFree(mft_name); + CoTaskMemFree(in_types); + CoTaskMemFree(out_types); + IMFAttributes_Release(attributes);
count = 0; clsids = NULL; @@ -5213,9 +5259,11 @@ static const IClassFactoryVtbl test_mft_factory_vtbl = static void test_MFTRegisterLocal(void) { IClassFactory test_factory = { &test_mft_factory_vtbl }; - MFT_REGISTER_TYPE_INFO input_types[1]; + MFT_REGISTER_TYPE_INFO input_types[1], *in_types, *out_types; + IMFAttributes *attributes; IMFActivate **activate; UINT32 count, count2; + WCHAR *name; HRESULT hr;
if (!pMFTRegisterLocal) @@ -5255,6 +5303,9 @@ static void test_MFTRegisterLocal(void) 0, NULL); ok(hr == S_OK, "Failed to register MFT, hr %#x.\n", hr);
+ hr = MFTGetInfo(MFT_CATEGORY_OTHER, &name, &in_types, &count, &out_types, &count2, &attributes); + ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Unexpected hr %#x.\n", hr); + hr = pMFTUnregisterLocal(NULL); ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
diff --git a/include/mfapi.h b/include/mfapi.h index bcb5d26121e..5b60833f529 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -558,6 +558,8 @@ HRESULT WINAPI MFTEnum2(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INF 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); +HRESULT WINAPI MFTGetInfo(CLSID clsid, WCHAR **name, MFT_REGISTER_TYPE_INFO **input_types, UINT32 *input_types_count, + MFT_REGISTER_TYPE_INFO **output_types, UINT32 *output_types_count, IMFAttributes **attributes); BOOL WINAPI MFIsFormatYUV(DWORD format); HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *attributes, const UINT8 *buffer, UINT size); HRESULT WINAPI MFInitMediaTypeFromWaveFormatEx(IMFMediaType *mediatype, const WAVEFORMATEX *format, UINT32 size);