mfplat: Implement CreateObjectFromURL().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6f81d51e38
commit
7a025d8318
|
@ -1908,6 +1908,7 @@ static const IMFMediaSourceVtbl mfsourcevtbl =
|
||||||
enum resolved_object_origin
|
enum resolved_object_origin
|
||||||
{
|
{
|
||||||
OBJECT_FROM_BYTESTREAM,
|
OBJECT_FROM_BYTESTREAM,
|
||||||
|
OBJECT_FROM_URL,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct resolver_queued_result
|
struct resolver_queued_result
|
||||||
|
@ -1937,6 +1938,7 @@ typedef struct source_resolver
|
||||||
IMFSourceResolver IMFSourceResolver_iface;
|
IMFSourceResolver IMFSourceResolver_iface;
|
||||||
LONG refcount;
|
LONG refcount;
|
||||||
IMFAsyncCallback stream_callback;
|
IMFAsyncCallback stream_callback;
|
||||||
|
IMFAsyncCallback url_callback;
|
||||||
CRITICAL_SECTION cs;
|
CRITICAL_SECTION cs;
|
||||||
struct list pending;
|
struct list pending;
|
||||||
} mfsourceresolver;
|
} mfsourceresolver;
|
||||||
|
@ -1951,6 +1953,11 @@ static struct source_resolver *impl_from_stream_IMFAsyncCallback(IMFAsyncCallbac
|
||||||
return CONTAINING_RECORD(iface, struct source_resolver, stream_callback);
|
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,
|
static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin,
|
||||||
IMFAsyncResult *result)
|
IMFAsyncResult *result)
|
||||||
{
|
{
|
||||||
|
@ -1960,6 +1967,7 @@ static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enu
|
||||||
{
|
{
|
||||||
IUnknown *handler;
|
IUnknown *handler;
|
||||||
IMFByteStreamHandler *stream_handler;
|
IMFByteStreamHandler *stream_handler;
|
||||||
|
IMFSchemeHandler *scheme_handler;
|
||||||
} handler;
|
} handler;
|
||||||
|
|
||||||
queued_result = heap_alloc(sizeof(*queued_result));
|
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->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, result, &queued_result->obj_type,
|
||||||
&queued_result->object);
|
&queued_result->object);
|
||||||
break;
|
break;
|
||||||
|
case OBJECT_FROM_URL:
|
||||||
|
queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, result, &queued_result->obj_type,
|
||||||
|
&queued_result->object);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
queued_result->hr = E_FAIL;
|
queued_result->hr = E_FAIL;
|
||||||
}
|
}
|
||||||
|
@ -2132,6 +2144,34 @@ static const IMFAsyncCallbackVtbl source_resolver_callback_stream_vtbl =
|
||||||
source_resolver_callback_stream_Invoke,
|
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)
|
static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler)
|
||||||
{
|
{
|
||||||
unsigned int j = 0, name_length, type;
|
unsigned int j = 0, name_length, type;
|
||||||
|
@ -2223,6 +2263,73 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA
|
||||||
return hr;
|
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,
|
static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin,
|
||||||
IMFAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
|
IMFAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out)
|
||||||
{
|
{
|
||||||
|
@ -2318,14 +2425,45 @@ static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface)
|
||||||
return refcount;
|
return refcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI mfsourceresolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
|
static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url,
|
||||||
DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object)
|
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,
|
static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream,
|
||||||
|
@ -2484,7 +2622,7 @@ static const IMFSourceResolverVtbl mfsourceresolvervtbl =
|
||||||
source_resolver_QueryInterface,
|
source_resolver_QueryInterface,
|
||||||
source_resolver_AddRef,
|
source_resolver_AddRef,
|
||||||
source_resolver_Release,
|
source_resolver_Release,
|
||||||
mfsourceresolver_CreateObjectFromURL,
|
source_resolver_CreateObjectFromURL,
|
||||||
source_resolver_CreateObjectFromByteStream,
|
source_resolver_CreateObjectFromByteStream,
|
||||||
mfsourceresolver_BeginCreateObjectFromURL,
|
mfsourceresolver_BeginCreateObjectFromURL,
|
||||||
mfsourceresolver_EndCreateObjectFromURL,
|
mfsourceresolver_EndCreateObjectFromURL,
|
||||||
|
@ -2511,6 +2649,7 @@ HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
|
||||||
|
|
||||||
object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
|
object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl;
|
||||||
object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
|
object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl;
|
||||||
|
object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl;
|
||||||
object->refcount = 1;
|
object->refcount = 1;
|
||||||
list_init(&object->pending);
|
list_init(&object->pending);
|
||||||
InitializeCriticalSection(&object->cs);
|
InitializeCriticalSection(&object->cs);
|
||||||
|
|
Loading…
Reference in New Issue