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