[PATCH] mfplat: Implement MFTGetInfo().

Nikolay Sivov nsivov at codeweavers.com
Wed Jan 19 09:10:20 CST 2022


Signed-off-by: Nikolay Sivov <nsivov at 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);
-- 
2.34.1




More information about the wine-devel mailing list