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 MODULE = mf.dll
IMPORTLIB = mf IMPORTLIB = mf
IMPORTS = advapi32 mfplat ole32 uuid mfuuid strmiids IMPORTS = advapi32 mfplat ole32 uuid mfuuid strmiids
DELAYIMPORTS = evr user32 DELAYIMPORTS = evr urlmon user32
EXTRADLLFLAGS = -Wb,--prefer-native EXTRADLLFLAGS = -Wb,--prefer-native
......
...@@ -549,6 +549,7 @@ static const IClassFactoryVtbl class_factory_vtbl = ...@@ -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 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 static const struct class_object
{ {
...@@ -558,6 +559,7 @@ static const struct class_object ...@@ -558,6 +559,7 @@ static const struct class_object
class_objects[] = class_objects[] =
{ {
{ &CLSID_FileSchemePlugin, &file_scheme_handler_factory.IClassFactory_iface }, { &CLSID_FileSchemePlugin, &file_scheme_handler_factory.IClassFactory_iface },
{ &CLSID_UrlmonSchemePlugin, &urlmon_scheme_handler_factory.IClassFactory_iface },
}; };
/******************************************************************************* /*******************************************************************************
......
...@@ -24,3 +24,9 @@ ...@@ -24,3 +24,9 @@
uuid(477ec299-1421-4bdd-971f-7ccb933f21ad) uuid(477ec299-1421-4bdd-971f-7ccb933f21ad)
] ]
coclass FileSchemePlugin { } coclass FileSchemePlugin { }
[
threading(both),
uuid(9ec4b4f9-3029-45ad-947b-344de2a249e2)
]
coclass UrlmonSchemePlugin {}
...@@ -12,6 +12,14 @@ HKLM ...@@ -12,6 +12,14 @@ HKLM
{ {
val '{477ec299-1421-4bdd-971f-7ccb933f21ad}' = s 'File Scheme Handler' 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) ...@@ -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 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_sample_copier_transform(IMFTransform *transform);
extern BOOL mf_is_sar_sink(IMFMediaSink *sink); extern BOOL mf_is_sar_sink(IMFMediaSink *sink);
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat); WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
typedef HRESULT (*create_stream_cb)(const WCHAR *url, DWORD flags, IMFByteStream **out);
struct scheme_handler_result struct scheme_handler_result
{ {
struct list entry; struct list entry;
...@@ -48,6 +50,7 @@ struct scheme_handler ...@@ -48,6 +50,7 @@ struct scheme_handler
IMFSourceResolver *resolver; IMFSourceResolver *resolver;
struct list results; struct list results;
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
create_stream_cb create_stream;
}; };
static struct scheme_handler *impl_from_IMFSchemeHandler(IMFSchemeHandler *iface) static struct scheme_handler *impl_from_IMFSchemeHandler(IMFSchemeHandler *iface)
...@@ -374,7 +377,6 @@ static HRESULT scheme_handler_get_resolver(struct scheme_handler *handler, IMFSo ...@@ -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 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 *handler = impl_from_IMFAsyncCallback(iface);
struct scheme_handler_result *handler_result; struct scheme_handler_result *handler_result;
MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID; MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID;
...@@ -383,7 +385,6 @@ static HRESULT WINAPI scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IM ...@@ -383,7 +385,6 @@ static HRESULT WINAPI scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IM
IMFSourceResolver *resolver; IMFSourceResolver *resolver;
IMFAsyncResult *caller; IMFAsyncResult *caller;
IMFByteStream *stream; IMFByteStream *stream;
const WCHAR *url;
HRESULT hr; HRESULT hr;
caller = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result); caller = (IMFAsyncResult *)IMFAsyncResult_GetStateNoAddRef(result);
...@@ -396,14 +397,7 @@ static HRESULT WINAPI scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IM ...@@ -396,14 +397,7 @@ static HRESULT WINAPI scheme_handler_callback_Invoke(IMFAsyncCallback *iface, IM
context = impl_from_IUnknown(context_object); context = impl_from_IUnknown(context_object);
/* Strip from scheme, MFCreateFile() won't be expecting it. */ if (SUCCEEDED(hr = handler->create_stream(context->url, context->flags, &stream)))
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 (context->flags & MF_RESOLUTION_MEDIASOURCE) if (context->flags & MF_RESOLUTION_MEDIASOURCE)
{ {
...@@ -458,6 +452,14 @@ static const IMFAsyncCallbackVtbl scheme_handler_callback_vtbl = ...@@ -458,6 +452,14 @@ static const IMFAsyncCallbackVtbl scheme_handler_callback_vtbl =
scheme_handler_callback_Invoke, 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) HRESULT file_scheme_handler_construct(REFIID riid, void **obj)
{ {
struct scheme_handler *handler; struct scheme_handler *handler;
...@@ -473,6 +475,58 @@ HRESULT file_scheme_handler_construct(REFIID riid, void **obj) ...@@ -473,6 +475,58 @@ HRESULT file_scheme_handler_construct(REFIID riid, void **obj)
handler->refcount = 1; handler->refcount = 1;
list_init(&handler->results); list_init(&handler->results);
InitializeCriticalSection(&handler->cs); 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); hr = IMFSchemeHandler_QueryInterface(&handler->IMFSchemeHandler_iface, riid, obj);
IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface); IMFSchemeHandler_Release(&handler->IMFSchemeHandler_iface);
......
...@@ -6472,7 +6472,7 @@ static void test_scheme_resolvers(void) ...@@ -6472,7 +6472,7 @@ static void test_scheme_resolvers(void)
for (i = 0; i < ARRAY_SIZE(urls); i++) for (i = 0; i < ARRAY_SIZE(urls); i++)
{ {
hr = IMFSourceResolver_CreateObjectFromURL(resolver, urls[i], MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); 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); ok(hr == S_OK, "got hr %#lx\n", hr);
if (hr != S_OK) if (hr != S_OK)
continue; continue;
...@@ -6485,7 +6485,6 @@ static void test_scheme_resolvers(void) ...@@ -6485,7 +6485,6 @@ static void test_scheme_resolvers(void)
PropVariantInit(&propvar); PropVariantInit(&propvar);
hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_EFFECTIVE_URL, &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); 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])) ok(!wcsncmp(expect_domain[i], propvar.pwszVal, wcslen(expect_domain[i]))
|| broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Win7 */, || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Win7 */,
"got url %s\n", debugstr_w(propvar.pwszVal)); "got url %s\n", debugstr_w(propvar.pwszVal));
...@@ -6493,7 +6492,6 @@ static void test_scheme_resolvers(void) ...@@ -6493,7 +6492,6 @@ static void test_scheme_resolvers(void)
ok(hr == S_OK, "got hr %#lx\n", hr); ok(hr == S_OK, "got hr %#lx\n", hr);
hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_CONTENT_TYPE, NULL); hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_CONTENT_TYPE, NULL);
todo_wine
ok(hr == S_OK, "got hr %#lx\n", hr); ok(hr == S_OK, "got hr %#lx\n", hr);
hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_LAST_MODIFIED_TIME, NULL); hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_LAST_MODIFIED_TIME, NULL);
todo_wine 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