[PATCH 3/4] mfplat: Use file url scheme as a fallback.
Nikolay Sivov
nsivov at codeweavers.com
Thu May 2 09:09:09 CDT 2019
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfplat/main.c | 68 +++++++-----
dlls/mfplat/tests/mfplat.c | 211 +++++++++++++++++++++++++------------
2 files changed, 186 insertions(+), 93 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 83c8d34b92..803944d376 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -4956,12 +4956,46 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA
return hr;
}
-static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
+static HRESULT resolver_create_scheme_handler(const WCHAR *scheme, DWORD flags, IMFSchemeHandler **handler)
{
static const char schemehandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers";
static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
+ unsigned int i;
+ HRESULT hr;
+
+ TRACE("%s, %#x, %p.\n", debugstr_w(scheme), flags, handler);
+
+ /* FIXME: check local handlers first */
+
+ for (i = 0; i < ARRAY_SIZE(hkey_roots); ++i)
+ {
+ HKEY hkey, hkey_handler;
+
+ hr = MF_E_UNSUPPORTED_SCHEME;
+
+ if (RegOpenKeyA(hkey_roots[i], schemehandlerspath, &hkey))
+ continue;
+
+ if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
+ {
+ hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
+ RegCloseKey(hkey_handler);
+ }
+
+ RegCloseKey(hkey);
+
+ if (SUCCEEDED(hr))
+ break;
+ }
+
+ return hr;
+}
+
+static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler)
+{
+ static const WCHAR fileschemeW[] = {'f','i','l','e',':',0};
const WCHAR *ptr = url;
- unsigned int len, i;
+ unsigned int len;
WCHAR *scheme;
HRESULT hr;
@@ -4985,9 +5019,12 @@ static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSch
ptr++;
}
- /* Schemes must end with a ':' */
+ /* Schemes must end with a ':', if not found try "file:" */
if (ptr == url || *ptr != ':')
- return MF_E_UNSUPPORTED_SCHEME;
+ {
+ url = fileschemeW;
+ ptr = fileschemeW + ARRAY_SIZE(fileschemeW) - 1;
+ }
len = ptr - url;
scheme = heap_alloc((len + 1) * sizeof(WCHAR));
@@ -4997,26 +5034,9 @@ static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSch
memcpy(scheme, url, len * sizeof(WCHAR));
scheme[len] = 0;
- /* FIXME: check local handlers first */
-
- for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
- {
- HKEY hkey, hkey_handler;
-
- if (RegOpenKeyA(hkey_roots[i], schemehandlerspath, &hkey))
- continue;
-
- if (!RegOpenKeyW(hkey, scheme, &hkey_handler))
- {
- hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler);
- RegCloseKey(hkey_handler);
- }
-
- RegCloseKey(hkey);
-
- if (SUCCEEDED(hr))
- break;
- }
+ hr = resolver_create_scheme_handler(scheme, flags, handler);
+ if (FAILED(hr) && url != fileschemeW)
+ hr = resolver_create_scheme_handler(fileschemeW, flags, handler);
heap_free(scheme);
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index d2ae8f2a85..10c2fd1e21 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -63,6 +63,7 @@ static HRESULT (WINAPI *pMFAddPeriodicCallback)(MFPERIODICCALLBACK callback, IUn
static HRESULT (WINAPI *pMFRemovePeriodicCallback)(DWORD key);
static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0};
+static const WCHAR fileschemeW[] = {'f','i','l','e',':','/','/',0};
static WCHAR *load_resource(const WCHAR *name)
{
@@ -92,6 +93,48 @@ static WCHAR *load_resource(const WCHAR *name)
return pathW;
}
+struct test_callback
+{
+ IMFAsyncCallback IMFAsyncCallback_iface;
+ HANDLE event;
+};
+
+static struct test_callback *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
+{
+ return CONTAINING_RECORD(iface, struct test_callback, IMFAsyncCallback_iface);
+}
+
+static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
+{
+ if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
+ IsEqualIID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IMFAsyncCallback_AddRef(iface);
+ return S_OK;
+ }
+
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
+{
+ ok(flags != NULL && queue != NULL, "Unexpected arguments.\n");
+ return E_NOTIMPL;
+}
+
+
static BOOL check_clsid(CLSID *clsids, UINT32 count)
{
int i;
@@ -209,23 +252,61 @@ if(0)
ok(ret == S_OK || broken(ret == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)), "got %x\n", ret);
}
+static HRESULT WINAPI test_create_from_url_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
+{
+ struct test_callback *callback = impl_from_IMFAsyncCallback(iface);
+ IMFSourceResolver *resolver;
+ IUnknown *object, *object2;
+ MF_OBJECT_TYPE obj_type;
+ HRESULT hr;
+
+ ok(!!result, "Unexpected result object.\n");
+
+ resolver = (IMFSourceResolver *)IMFAsyncResult_GetStateNoAddRef(result);
+
+ hr = IMFSourceResolver_EndCreateObjectFromURL(resolver, result, &obj_type, &object);
+ ok(hr == S_OK, "Failed to create an object, hr %#x.\n", hr);
+
+ hr = IMFAsyncResult_GetObject(result, &object2);
+ ok(hr == S_OK, "Failed to get result object, hr %#x.\n", hr);
+ ok(object2 == object, "Unexpected object.\n");
+
+ IUnknown_Release(object);
+ IUnknown_Release(object2);
+
+ SetEvent(callback->event);
+
+ return S_OK;
+}
+
+static const IMFAsyncCallbackVtbl test_create_from_url_callback_vtbl =
+{
+ testcallback_QueryInterface,
+ testcallback_AddRef,
+ testcallback_Release,
+ testcallback_GetParameters,
+ test_create_from_url_callback_Invoke,
+};
+
static void test_source_resolver(void)
{
+ static const WCHAR file_type[] = {'v','i','d','e','o','/','m','p','4',0};
+ struct test_callback callback = { { &test_create_from_url_callback_vtbl } };
IMFSourceResolver *resolver, *resolver2;
- IMFByteStream *bytestream;
IMFAttributes *attributes;
IMFMediaSource *mediasource;
IMFPresentationDescriptor *descriptor;
IMFMediaTypeHandler *handler;
MF_OBJECT_TYPE obj_type;
IMFStreamDescriptor *sd;
+ IUnknown *cancel_cookie;
+ IMFByteStream *stream;
+ WCHAR pathW[MAX_PATH];
HRESULT hr;
WCHAR *filename;
BOOL selected;
GUID guid;
- static const WCHAR file_type[] = {'v','i','d','e','o','/','m','p','4',0};
-
if (!pMFCreateSourceResolver)
{
win_skip("MFCreateSourceResolver() not found\n");
@@ -249,8 +330,7 @@ static void test_source_resolver(void)
filename = load_resource(mp4file);
- hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST,
- MF_FILEFLAGS_NONE, filename, &bytestream);
+ hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, filename, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IMFSourceResolver_CreateObjectFromByteStream(
@@ -258,45 +338,38 @@ static void test_source_resolver(void)
&obj_type, (IUnknown **)&mediasource);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
- hr = IMFSourceResolver_CreateObjectFromByteStream(
- resolver, bytestream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
- NULL, (IUnknown **)&mediasource);
+ hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
+ NULL, (IUnknown **)&mediasource);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
- hr = IMFSourceResolver_CreateObjectFromByteStream(
- resolver, bytestream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
- &obj_type, NULL);
+ hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
+ &obj_type, NULL);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
- hr = IMFSourceResolver_CreateObjectFromByteStream(
- resolver, bytestream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
- &obj_type, (IUnknown **)&mediasource);
+ hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
+ &obj_type, (IUnknown **)&mediasource);
todo_wine ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got 0x%08x\n", hr);
if (hr == S_OK) IMFMediaSource_Release(mediasource);
- hr = IMFSourceResolver_CreateObjectFromByteStream(
- resolver, bytestream, NULL, MF_RESOLUTION_BYTESTREAM, NULL,
- &obj_type, (IUnknown **)&mediasource);
+ hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_BYTESTREAM, NULL,
+ &obj_type, (IUnknown **)&mediasource);
todo_wine ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got 0x%08x\n", hr);
- IMFByteStream_Release(bytestream);
+ IMFByteStream_Release(stream);
/* We have to create a new bytestream here, because all following
* calls to CreateObjectFromByteStream will fail. */
- hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST,
- MF_FILEFLAGS_NONE, filename, &bytestream);
+ hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, filename, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IUnknown_QueryInterface(bytestream, &IID_IMFAttributes,
- (void **)&attributes);
+ hr = IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IMFAttributes_SetString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, file_type);
ok(hr == S_OK, "Failed to set string value, hr %#x.\n", hr);
IMFAttributes_Release(attributes);
- hr = IMFSourceResolver_CreateObjectFromByteStream(
- resolver, bytestream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
- &obj_type, (IUnknown **)&mediasource);
+ hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL,
+ &obj_type, (IUnknown **)&mediasource);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(mediasource != NULL, "got %p\n", mediasource);
ok(obj_type == MF_OBJECT_MEDIASOURCE, "got %d\n", obj_type);
@@ -320,7 +393,42 @@ todo_wine
IMFPresentationDescriptor_Release(descriptor);
IMFMediaSource_Release(mediasource);
- IMFByteStream_Release(bytestream);
+ IMFByteStream_Release(stream);
+
+ /* Create from URL. */
+ callback.event = CreateEventA(NULL, FALSE, FALSE, NULL);
+
+ hr = IMFSourceResolver_CreateObjectFromURL(resolver, filename, MF_RESOLUTION_BYTESTREAM, NULL, &obj_type,
+ (IUnknown **)&stream);
+todo_wine
+ ok(hr == S_OK, "Failed to resolve url, hr %#x.\n", hr);
+ if (SUCCEEDED(hr))
+ IMFByteStream_Release(stream);
+
+ hr = IMFSourceResolver_BeginCreateObjectFromURL(resolver, filename, MF_RESOLUTION_BYTESTREAM, NULL,
+ &cancel_cookie, &callback.IMFAsyncCallback_iface, (IUnknown *)resolver);
+todo_wine {
+ ok(hr == S_OK, "Create request failed, hr %#x.\n", hr);
+ ok(cancel_cookie != NULL, "Unexpected cancel object.\n");
+}
+ if (cancel_cookie)
+ IUnknown_Release(cancel_cookie);
+
+ if (SUCCEEDED(hr))
+ WaitForSingleObject(callback.event, INFINITE);
+
+ CloseHandle(callback.event);
+
+ /* With explicit scheme. */
+ lstrcpyW(pathW, fileschemeW);
+ lstrcatW(pathW, filename);
+
+ hr = IMFSourceResolver_CreateObjectFromURL(resolver, pathW, MF_RESOLUTION_BYTESTREAM, NULL, &obj_type,
+ (IUnknown **)&stream);
+todo_wine
+ ok(hr == S_OK, "Failed to resolve url, hr %#x.\n", hr);
+ if (SUCCEEDED(hr))
+ IMFByteStream_Release(stream);
IMFSourceResolver_Release(resolver);
@@ -1131,10 +1239,10 @@ static void test_MFCreateMFByteStreamOnStream(void)
static void test_file_stream(void)
{
- IMFByteStream *bytestream;
- IMFByteStream *bytestream2;
+ IMFByteStream *bytestream, *bytestream2;
IMFAttributes *attributes = NULL;
MF_ATTRIBUTE_TYPE item_type;
+ WCHAR pathW[MAX_PATH];
DWORD caps, count;
WCHAR *filename;
IUnknown *unk;
@@ -1245,6 +1353,12 @@ static void test_file_stream(void)
IMFByteStream_Release(bytestream);
+ /* Explicit file: scheme */
+ lstrcpyW(pathW, fileschemeW);
+ lstrcatW(pathW, filename);
+ hr = MFCreateFile(MF_ACCESSMODE_READ, MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, pathW, &bytestream);
+ ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
+
hr = MFShutdown();
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
@@ -1524,47 +1638,6 @@ todo_wine
IMFSample_Release(sample);
}
-struct test_callback
-{
- IMFAsyncCallback IMFAsyncCallback_iface;
- HANDLE event;
-};
-
-static struct test_callback *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
-{
- return CONTAINING_RECORD(iface, struct test_callback, IMFAsyncCallback_iface);
-}
-
-static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
-{
- if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
- IsEqualIID(riid, &IID_IUnknown))
- {
- *obj = iface;
- IMFAsyncCallback_AddRef(iface);
- return S_OK;
- }
-
- *obj = NULL;
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface)
-{
- return 2;
-}
-
-static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
-{
- return 1;
-}
-
-static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
-{
- ok(flags != NULL && queue != NULL, "Unexpected arguments.\n");
- return E_NOTIMPL;
-}
-
static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
{
struct test_callback *callback = impl_from_IMFAsyncCallback(iface);
--
2.20.1
More information about the wine-devel
mailing list