Nikolay Sivov : mf: Implement MFGetSupportedMimeTypes()/MFGetSupportedSchemes().

Alexandre Julliard julliard at winehq.org
Wed Mar 4 16:50:07 CST 2020


Module: wine
Branch: master
Commit: 18cf1debeb32190cad0ddaa18ac92262db3130ba
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=18cf1debeb32190cad0ddaa18ac92262db3130ba

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Mar  4 11:06:06 2020 +0300

mf: Implement MFGetSupportedMimeTypes()/MFGetSupportedSchemes().

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mf/Makefile.in |   2 +-
 dlls/mf/main.c      | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 dlls/mf/mf.spec     |   2 +-
 dlls/mf/tests/mf.c  |  34 +++++++++++++++
 include/mfidl.idl   |   1 +
 5 files changed, 153 insertions(+), 5 deletions(-)

diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in
index d23349c9cf..fe156e43ab 100644
--- a/dlls/mf/Makefile.in
+++ b/dlls/mf/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = mf.dll
 IMPORTLIB = mf
-IMPORTS   = mfplat ole32 uuid mfuuid
+IMPORTS   = advapi32 mfplat ole32 uuid mfuuid
 
 EXTRADLLFLAGS = -mno-cygwin
 
diff --git a/dlls/mf/main.c b/dlls/mf/main.c
index 5d645db200..1700b179e5 100644
--- a/dlls/mf/main.c
+++ b/dlls/mf/main.c
@@ -1081,14 +1081,127 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
     return TRUE;
 }
 
+static HRESULT prop_string_vector_append(PROPVARIANT *vector, unsigned int *count, BOOL unique, const WCHAR *str)
+{
+    WCHAR *ptrW;
+    int len, i;
+
+    if (unique)
+    {
+        for (i = 0; i < vector->calpwstr.cElems; ++i)
+        {
+            if (!lstrcmpW(vector->calpwstr.pElems[i], str))
+                return S_OK;
+        }
+    }
+
+    if (!vector->calpwstr.cElems || *count > vector->calpwstr.cElems - 1)
+    {
+        unsigned int new_count;
+        WCHAR **ptr;
+
+        new_count = *count ? *count * 2 : 10;
+        ptr = CoTaskMemRealloc(vector->calpwstr.pElems, new_count * sizeof(*vector->calpwstr.pElems));
+        if (!ptr)
+            return E_OUTOFMEMORY;
+        vector->calpwstr.pElems = ptr;
+        *count = new_count;
+    }
+
+    len = lstrlenW(str);
+    if (!(vector->calpwstr.pElems[vector->calpwstr.cElems] = ptrW = CoTaskMemAlloc((len + 1) * sizeof(WCHAR))))
+        return E_OUTOFMEMORY;
+
+    lstrcpyW(ptrW, str);
+    vector->calpwstr.cElems++;
+
+    return S_OK;
+}
+
+static int __cdecl qsort_string_compare(const void *a, const void *b)
+{
+    return lstrcmpW(a, b);
+}
+
+static HRESULT mf_get_handler_strings(const WCHAR *path, WCHAR filter, unsigned int maxlen, PROPVARIANT *dst)
+{
+    static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
+    HRESULT hr = S_OK;
+    int i, index;
+    WCHAR *buffW;
+
+    buffW = heap_calloc(maxlen, sizeof(*buffW));
+    if (!buffW)
+        return E_OUTOFMEMORY;
+
+    memset(dst, 0, sizeof(*dst));
+    dst->vt = VT_VECTOR | VT_LPWSTR;
+
+    for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
+    {
+        unsigned int count;
+        DWORD size;
+        HKEY hkey;
+
+        if (RegOpenKeyW(hkey_roots[i], path, &hkey))
+            continue;
+
+        index = 0;
+        size = maxlen;
+        count = dst->calpwstr.cElems;
+        while (!RegEnumKeyExW(hkey, index++, buffW, &size, NULL, NULL, NULL, NULL))
+        {
+            if (filter && !wcschr(buffW, filter))
+                continue;
+            if (FAILED(hr = prop_string_vector_append(dst, &count, i > 0, buffW)))
+                break;
+            size = maxlen;
+        }
+
+        /* Sort last pass results. */
+        qsort(&dst->calpwstr.pElems[count], dst->calpwstr.cElems - count, sizeof(*dst->calpwstr.pElems),
+                qsort_string_compare);
+
+        RegCloseKey(hkey);
+    }
+
+    if (FAILED(hr))
+        PropVariantClear(dst);
+
+    heap_free(buffW);
+
+    return hr;
+}
+
 /***********************************************************************
  *      MFGetSupportedMimeTypes (mf.@)
  */
-HRESULT WINAPI MFGetSupportedMimeTypes(PROPVARIANT *array)
+HRESULT WINAPI MFGetSupportedMimeTypes(PROPVARIANT *dst)
 {
-    FIXME("(%p) stub\n", array);
+    unsigned int maxlen;
 
-    return E_NOTIMPL;
+    TRACE("%p.\n", dst);
+
+    if (!dst)
+        return E_POINTER;
+
+    /* According to RFC4288 it's 127/127 characters. */
+    maxlen = 127 /* type */ + 1 /* / */ + 127 /* subtype */ + 1;
+    return mf_get_handler_strings(L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers", '/',
+            maxlen,  dst);
+}
+
+/***********************************************************************
+ *      MFGetSupportedSchemes (mf.@)
+ */
+HRESULT WINAPI MFGetSupportedSchemes(PROPVARIANT *dst)
+{
+    TRACE("%p.\n", dst);
+
+    if (!dst)
+        return E_POINTER;
+
+    return mf_get_handler_strings(L"Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers", 0, 64, dst);
 }
 
 /***********************************************************************
diff --git a/dlls/mf/mf.spec b/dlls/mf/mf.spec
index e396d01519..29676005ad 100644
--- a/dlls/mf/mf.spec
+++ b/dlls/mf/mf.spec
@@ -74,7 +74,7 @@
 @ stub MFGetMultipleServiceProviders
 @ stdcall MFGetService(ptr ptr ptr ptr)
 @ stdcall MFGetSupportedMimeTypes(ptr)
-@ stub MFGetSupportedSchemes
+@ stdcall MFGetSupportedSchemes(ptr)
 @ stub MFGetTopoNodeCurrentType
 @ stub MFReadSequencerSegmentOffset
 @ stub MFRequireProtectedEnvironment
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 5a690880d1..aa72e71292 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -2719,6 +2719,38 @@ static void test_MFCreateSimpleTypeHandler(void)
     IMFMediaTypeHandler_Release(handler);
 }
 
+static void test_MFGetSupportedMimeTypes(void)
+{
+    PROPVARIANT value;
+    HRESULT hr;
+
+    hr = MFGetSupportedMimeTypes(NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+
+    value.vt = VT_EMPTY;
+    hr = MFGetSupportedMimeTypes(&value);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
+
+    PropVariantClear(&value);
+}
+
+static void test_MFGetSupportedSchemes(void)
+{
+    PROPVARIANT value;
+    HRESULT hr;
+
+    hr = MFGetSupportedSchemes(NULL);
+    ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+
+    value.vt = VT_EMPTY;
+    hr = MFGetSupportedSchemes(&value);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
+
+    PropVariantClear(&value);
+}
+
 START_TEST(mf)
 {
     test_topology();
@@ -2734,4 +2766,6 @@ START_TEST(mf)
     test_sar();
     test_evr();
     test_MFCreateSimpleTypeHandler();
+    test_MFGetSupportedMimeTypes();
+    test_MFGetSupportedSchemes();
 }
diff --git a/include/mfidl.idl b/include/mfidl.idl
index fa3a2d132a..e27294d488 100644
--- a/include/mfidl.idl
+++ b/include/mfidl.idl
@@ -595,6 +595,7 @@ cpp_quote("HRESULT WINAPI MFCreateTopoLoader(IMFTopoLoader **loader);")
 cpp_quote("HRESULT WINAPI MFCreateVideoRendererActivate(HWND hwnd, IMFActivate **activate);")
 cpp_quote("HRESULT WINAPI MFEnumDeviceSources(IMFAttributes *attributes, IMFActivate ***sources, UINT32 *count);")
 cpp_quote("HRESULT WINAPI MFGetSupportedMimeTypes(PROPVARIANT *array);")
+cpp_quote("HRESULT WINAPI MFGetSupportedSchemes(PROPVARIANT *array);")
 cpp_quote("HRESULT WINAPI MFGetService(IUnknown *object, REFGUID service, REFIID iid, void **obj);")
 cpp_quote("MFTIME  WINAPI MFGetSystemTime(void);")
 cpp_quote("HRESULT WINAPI MFShutdownObject(IUnknown *object);")




More information about the wine-cvs mailing list