Commit 8143a575 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

mf/scheme_handler: Implement http(s):// scheme handler using urlmon.

parent 70970429
MODULE = mf.dll
IMPORTLIB = mf
IMPORTS = advapi32 mfplat ole32 uuid mfuuid strmiids
DELAYIMPORTS = evr user32
DELAYIMPORTS = evr urlmon user32
EXTRADLLFLAGS = -Wb,--prefer-native
......
......@@ -549,6 +549,7 @@ static const IClassFactoryVtbl class_factory_vtbl =
};
static struct class_factory file_scheme_handler_factory = { { &class_factory_vtbl }, file_scheme_handler_construct };
static struct class_factory urlmon_scheme_handler_factory = { { &class_factory_vtbl }, urlmon_scheme_handler_construct };
static const struct class_object
{
......@@ -558,6 +559,7 @@ static const struct class_object
class_objects[] =
{
{ &CLSID_FileSchemePlugin, &file_scheme_handler_factory.IClassFactory_iface },
{ &CLSID_UrlmonSchemePlugin, &urlmon_scheme_handler_factory.IClassFactory_iface },
};
/*******************************************************************************
......
......@@ -24,3 +24,9 @@
uuid(477ec299-1421-4bdd-971f-7ccb933f21ad)
]
coclass FileSchemePlugin { }
[
threading(both),
uuid(9ec4b4f9-3029-45ad-947b-344de2a249e2)
]
coclass UrlmonSchemePlugin {}
......@@ -12,6 +12,14 @@ HKLM
{
val '{477ec299-1421-4bdd-971f-7ccb933f21ad}' = s 'File Scheme Handler'
}
'http:'
{
val '{9ec4b4f9-3029-45ad-947b-344de2a249e2}' = s 'Urlmon Scheme Handler'
}
'https:'
{
val '{9ec4b4f9-3029-45ad-947b-344de2a249e2}' = s 'Urlmon Scheme Handler'
}
}
}
}
......
......@@ -114,6 +114,7 @@ static inline const char *debugstr_propvar(const PROPVARIANT *v)
}
extern HRESULT file_scheme_handler_construct(REFIID riid, void **obj);
extern HRESULT urlmon_scheme_handler_construct(REFIID riid, void **obj);
extern BOOL mf_is_sample_copier_transform(IMFTransform *transform);
extern BOOL mf_is_sar_sink(IMFMediaSink *sink);
......
......@@ -32,6 +32,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
typedef HRESULT (*create_stream_cb)(const WCHAR *url, DWORD flags, IMFByteStream **out);
struct scheme_handler_result
{
struct list entry;
......@@ -48,6 +50,7 @@ struct scheme_handler
IMFSourceResolver *resolver;
struct list results;
CRITICAL_SECTION cs;
create_stream_cb create_stream;
};
static struct scheme_handler *impl_from_IMFSchemeHandler(IMFSchemeHandler *iface)
......@@ -374,7 +377,6 @@ static HRESULT scheme_handler_get_resolver(struct scheme_handler *handler, IMFSo
static HRESULT WINAPI scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
{
static const WCHAR schemeW[] = {'f','i','l','e',':','/','/'};
struct scheme_handler *handler = impl_from_IMFAsyncCallback(iface);
struct scheme_handler_result *handler_result;
MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID;
......@@ -383,7 +385,6 @@ static HRESULT WINAPI scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IM
IMFSourceResolver *resolver;
IMFAsyncResult *caller;
IMFByteStream *stream;
const WCHAR *url;
HRESULT hr;
caller = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result);
......@@ -396,14 +397,7 @@ static HRESULT WINAPI scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IM
context = impl_from_IUnknown(context_object);
/* Strip from scheme, MFCreateFile() won't be expecting it. */
url = context->url;
if (!wcsnicmp(context->url, schemeW, ARRAY_SIZE(schemeW)))
url += ARRAY_SIZE(schemeW);
hr = MFCreateFile(context->flags & MF_RESOLUTION_WRITE ? MF_ACCESSMODE_READWRITE : MF_ACCESSMODE_READ,
MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, url, &stream);
if (SUCCEEDED(hr))
if (SUCCEEDED(hr = handler->create_stream(context->url, context->flags, &stream)))
{
if (context->flags & MF_RESOLUTION_MEDIASOURCE)
{
......@@ -458,6 +452,14 @@ static const IMFAsyncCallbackVtbl scheme_handler_callback_vtbl =
scheme_handler_callback_Invoke,
};
static HRESULT file_stream_create(const WCHAR *url, DWORD flags, IMFByteStream **out)
{
if (!wcsnicmp(url, L"file://", 7))
url += 7;
return MFCreateFile(flags & MF_RESOLUTION_WRITE ? MF_ACCESSMODE_READWRITE : MF_ACCESSMODE_READ,
MF_OPENMODE_FAIL_IF_NOT_EXIST, MF_FILEFLAGS_NONE, url, out);
}
HRESULT file_scheme_handler_construct(REFIID riid, void **obj)
{
struct scheme_handler *handler;
......@@ -473,6 +475,58 @@ HRESULT file_scheme_handler_construct(REFIID riid, void **obj)
handler->refcount = 1;
list_init(&handler->results);
InitializeCriticalSection(&handler->cs);
handler->create_stream = file_stream_create;
hr = IMFSchemeHandler_QueryInterface(&handler->IMFSchemeHandler_iface, riid, obj);
IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
return hr;
}
static HRESULT urlmon_stream_create(const WCHAR *url, DWORD flags, IMFByteStream **out)
{
IMFAttributes *attributes;
IStream *stream;
HRESULT hr;
if (flags & MF_RESOLUTION_WRITE)
return E_INVALIDARG;
if (FAILED(hr = URLOpenBlockingStreamW(NULL, url, &stream, 0, NULL)))
{
WARN("Failed to open url %s, hr %#lx\n", debugstr_w(url), hr);
return hr;
}
hr = MFCreateMFByteStreamOnStream(stream, out);
IStream_Release(stream);
if (FAILED(hr))
return hr;
IMFByteStream_QueryInterface(*out, &IID_IMFAttributes, (void **)&attributes);
IMFAttributes_DeleteItem(attributes, &MF_BYTESTREAM_ORIGIN_NAME);
IMFAttributes_SetString(attributes, &MF_BYTESTREAM_EFFECTIVE_URL, url);
IMFAttributes_SetString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, L"application/octet-stream");
IMFAttributes_Release(attributes);
return hr;
}
HRESULT urlmon_scheme_handler_construct(REFIID riid, void **obj)
{
struct scheme_handler *handler;
HRESULT hr;
TRACE("%s, %p.\n", debugstr_guid(riid), obj);
if (!(handler = calloc(1, sizeof(*handler))))
return E_OUTOFMEMORY;
handler->IMFSchemeHandler_iface.lpVtbl = &scheme_handler_vtbl;
handler->IMFAsyncCallback_iface.lpVtbl = &scheme_handler_callback_vtbl;
handler->refcount = 1;
list_init(&handler->results);
InitializeCriticalSection(&handler->cs);
handler->create_stream = urlmon_stream_create;
hr = IMFSchemeHandler_QueryInterface(&handler->IMFSchemeHandler_iface, riid, obj);
IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
......
......@@ -6472,7 +6472,7 @@ static void test_scheme_resolvers(void)
for (i = 0; i < ARRAY_SIZE(urls); i++)
{
hr = IMFSourceResolver_CreateObjectFromURL(resolver, urls[i], MF_RESOLUTION_BYTESTREAM, NULL, &type, &object);
todo_wine
todo_wine_if(i >= 2)
ok(hr == S_OK, "got hr %#lx\n", hr);
if (hr != S_OK)
continue;
......@@ -6485,7 +6485,6 @@ static void test_scheme_resolvers(void)
PropVariantInit(&propvar);
hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_EFFECTIVE_URL, &propvar);
ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Win7 */, "got hr %#lx\n", hr);
todo_wine
ok(!wcsncmp(expect_domain[i], propvar.pwszVal, wcslen(expect_domain[i]))
|| broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Win7 */,
"got url %s\n", debugstr_w(propvar.pwszVal));
......@@ -6493,7 +6492,6 @@ static void test_scheme_resolvers(void)
ok(hr == S_OK, "got hr %#lx\n", hr);
hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_CONTENT_TYPE, NULL);
todo_wine
ok(hr == S_OK, "got hr %#lx\n", hr);
hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_LAST_MODIFIED_TIME, NULL);
todo_wine
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment