Nikolay Sivov : mfplat: Implement CreateObjectFromURL().

Alexandre Julliard julliard at winehq.org
Tue Mar 12 16:56:15 CDT 2019


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Mar 12 09:07:42 2019 +0300

mfplat: Implement CreateObjectFromURL().

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

---

 dlls/mfplat/main.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 145 insertions(+), 6 deletions(-)

diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 06be27d..c57dd10 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -1908,6 +1908,7 @@ static const IMFMediaSourceVtbl mfsourcevtbl =
 enum resolved_object_origin
 {
     OBJECT_FROM_BYTESTREAM,
+    OBJECT_FROM_URL,
 };
 
 struct resolver_queued_result
@@ -1937,6 +1938,7 @@ typedef struct source_resolver
     IMFSourceResolver IMFSourceResolver_iface;
     LONG refcount;
     IMFAsyncCallback stream_callback;
+    IMFAsyncCallback url_callback;
     CRITICAL_SECTION cs;
     struct list pending;
 } mfsourceresolver;
@@ -1951,6 +1953,11 @@ static struct source_resolver *impl_from_stream_IMFAsyncCallback(IMFAsyncCallbac
     return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
 }
 
+static struct source_resolver *impl_from_url_IMFAsyncCallback(IMFAsyncCallback *iface)
+{
+    return CONTAINING_RECORD(iface, struct source_resolver, url_callback);
+}
+
 static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
         IMFAsyncResult *result)
 {
@@ -1960,6 +1967,7 @@ static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enu
     {
         IUnknown *handler;
         IMFByteStreamHandler *stream_handler;
+        IMFSchemeHandler *scheme_handler;
     } handler;
 
     queued_result = heap_alloc(sizeof(*queued_result));
@@ -1972,6 +1980,10 @@ static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enu
             queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, result, &queued_result->obj_type,
                     &queued_result->object);
             break;
+        case OBJECT_FROM_URL:
+            queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, result, &queued_result->obj_type,
+                    &queued_result->object);
+            break;
         default:
             queued_result->hr = E_FAIL;
     }
@@ -2132,6 +2144,34 @@ static const IMFAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
     source_resolver_callback_stream_Invoke,
 };
 
+static ULONG WINAPI source_resolver_callback_url_AddRef(IMFAsyncCallback *iface)
+{
+    struct source_resolver *resolver = impl_from_url_IMFAsyncCallback(iface);
+    return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface);
+}
+
+static ULONG WINAPI source_resolver_callback_url_Release(IMFAsyncCallback *iface)
+{
+    struct source_resolver *resolver = impl_from_url_IMFAsyncCallback(iface);
+    return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface);
+}
+
+static HRESULT WINAPI source_resolver_callback_url_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
+{
+    struct source_resolver *resolver = impl_from_url_IMFAsyncCallback(iface);
+
+    return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result);
+}
+
+static const IMFAsyncCallbackVtbl source_resolver_callback_url_vtbl =
+{
+    source_resolver_callback_QueryInterface,
+    source_resolver_callback_url_AddRef,
+    source_resolver_callback_url_Release,
+    source_resolver_callback_GetParameters,
+    source_resolver_callback_url_Invoke,
+};
+
 static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
 {
     unsigned int j = 0, name_length, type;
@@ -2223,6 +2263,73 @@ 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 const char schemehandlerspath[] = "Software\\Microsoft\\Windows Media Foundation\\SchemeHandlers";
+    static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
+    const WCHAR *ptr = url;
+    unsigned int len, i;
+    WCHAR *scheme;
+    HRESULT hr;
+
+    /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
+    while (*ptr)
+    {
+        WCHAR ch = tolowerW(*ptr);
+
+        if (*ptr == '*' && ptr == url)
+        {
+             ptr++;
+             break;
+        }
+        else if (!(*ptr >= '0' && *ptr <= '9') &&
+                !(ch >= 'a' && ch <= 'z') &&
+                *ptr != '+' && *ptr != '-' && *ptr != '.')
+        {
+            break;
+        }
+
+        ptr++;
+    }
+
+    /* Schemes must end with a ':' */
+    if (ptr == url || *ptr != ':')
+        return MF_E_UNSUPPORTED_SCHEME;
+
+    len = ptr - url;
+    scheme = heap_alloc((len + 1) * sizeof(WCHAR));
+    if (!scheme)
+        return E_OUTOFMEMORY;
+
+    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;
+    }
+
+    heap_free(scheme);
+
+    return hr;
+}
+
 static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
         IMFAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
 {
@@ -2318,14 +2425,45 @@ static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
     return refcount;
 }
 
-static HRESULT WINAPI mfsourceresolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
-    DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
+static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
+        DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
 {
-    mfsourceresolver *This = impl_from_IMFSourceResolver(iface);
+    struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
+    IMFSchemeHandler *handler;
+    IMFAsyncResult *result;
+    MFASYNCRESULT *data;
+    HRESULT hr;
 
-    FIXME("(%p)->(%s, %#x, %p, %p, %p): stub\n", This, debugstr_w(url), flags, props, obj_type, object);
+    TRACE("%p, %s, %#x, %p, %p, %p\n", iface, debugstr_w(url), flags, props, obj_type, object);
 
-    return E_NOTIMPL;
+    if (!url || !obj_type || !object)
+        return E_POINTER;
+
+    if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler)))
+        return hr;
+
+    hr = MFCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result);
+    IMFSchemeHandler_Release(handler);
+    if (FAILED(hr))
+        return hr;
+
+    data = (MFASYNCRESULT *)result;
+    data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+
+    hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, &resolver->stream_callback,
+            (IUnknown *)result);
+    if (FAILED(hr))
+    {
+        IMFAsyncResult_Release(result);
+        return hr;
+    }
+
+    WaitForSingleObject(data->hEvent, INFINITE);
+
+    hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object);
+    IMFAsyncResult_Release(result);
+
+    return hr;
 }
 
 static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
@@ -2484,7 +2622,7 @@ static const IMFSourceResolverVtbl mfsourceresolvervtbl =
     source_resolver_QueryInterface,
     source_resolver_AddRef,
     source_resolver_Release,
-    mfsourceresolver_CreateObjectFromURL,
+    source_resolver_CreateObjectFromURL,
     source_resolver_CreateObjectFromByteStream,
     mfsourceresolver_BeginCreateObjectFromURL,
     mfsourceresolver_EndCreateObjectFromURL,
@@ -2511,6 +2649,7 @@ HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
 
     object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
     object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
+    object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
     object->refcount = 1;
     list_init(&object->pending);
     InitializeCriticalSection(&object->cs);




More information about the wine-cvs mailing list