mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-30 04:48:36 +00:00
mf/scheme_handler: Implement http(s):// scheme handler using urlmon.
This commit is contained in:
parent
70970429a0
commit
8143a57500
|
@ -1,7 +1,7 @@
|
|||
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
|
||||
|
|
Loading…
Reference in a new issue