From: Reyka Matthies <openglfreak@googlemail.com> --- dlls/mf/main.c | 2 ++ dlls/mf/mf.idl | 6 ++++++ dlls/mf/mf.rgs | 16 ++++++++++++++-- dlls/mf/mf_private.h | 1 + dlls/mf/scheme_handler.c | 33 +++++++++++++++++++++++++++++++++ dlls/mf/tests/mf.c | 38 ++++---------------------------------- dlls/mfplat/mfplat.spec | 3 +++ dlls/mfplat/network.c | 5 +++++ 8 files changed, 68 insertions(+), 36 deletions(-) diff --git a/dlls/mf/main.c b/dlls/mf/main.c index 3aa81f4b454..4e1e1dd3468 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -732,6 +732,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 http_scheme_handler_factory = { { &class_factory_vtbl }, http_scheme_handler_construct }; static struct class_factory urlmon_scheme_handler_factory = { { &class_factory_vtbl }, urlmon_scheme_handler_construct }; static const struct class_object @@ -742,6 +743,7 @@ static const struct class_object class_objects[] = { { &CLSID_FileSchemePlugin, &file_scheme_handler_factory.IClassFactory_iface }, + { &CLSID_HttpSchemePlugin, &http_scheme_handler_factory.IClassFactory_iface }, { &CLSID_UrlmonSchemePlugin, &urlmon_scheme_handler_factory.IClassFactory_iface }, }; diff --git a/dlls/mf/mf.idl b/dlls/mf/mf.idl index 4f5ef36c965..ca05a991ca9 100644 --- a/dlls/mf/mf.idl +++ b/dlls/mf/mf.idl @@ -25,6 +25,12 @@ ] coclass FileSchemePlugin { } +[ + threading(both), + uuid(44cb442b-9da9-49df-b3fd-023777b16e50) +] +coclass HttpSchemePlugin {} + [ threading(both), uuid(9ec4b4f9-3029-45ad-947b-344de2a249e2) diff --git a/dlls/mf/mf.rgs b/dlls/mf/mf.rgs index f06576baccb..778b07e65ed 100644 --- a/dlls/mf/mf.rgs +++ b/dlls/mf/mf.rgs @@ -14,11 +14,23 @@ HKLM } 'http:' { - val '{9ec4b4f9-3029-45ad-947b-344de2a249e2}' = s 'Urlmon Scheme Handler' + val '{44cb442b-9da9-49df-b3fd-023777b16e50}' = s 'Http Scheme Handler' } 'https:' { - val '{9ec4b4f9-3029-45ad-947b-344de2a249e2}' = s 'Urlmon Scheme Handler' + val '{44cb442b-9da9-49df-b3fd-023777b16e50}' = s 'Http Scheme Handler' + } + 'httpd:' + { + val '{44cb442b-9da9-49df-b3fd-023777b16e50}' = s 'Http Scheme Handler' + } + 'httpsd:' + { + val '{44cb442b-9da9-49df-b3fd-023777b16e50}' = s 'Http Scheme Handler' + } + 'mms:' + { + val '{44cb442b-9da9-49df-b3fd-023777b16e50}' = s 'Http Scheme Handler' } } } diff --git a/dlls/mf/mf_private.h b/dlls/mf/mf_private.h index 0658db1de15..0d9c3c204ab 100644 --- a/dlls/mf/mf_private.h +++ b/dlls/mf/mf_private.h @@ -116,6 +116,7 @@ static inline const char *debugstr_propvar(const PROPVARIANT *v) extern const char *debugstr_media_type(IMFMediaType *media_type); extern HRESULT file_scheme_handler_construct(REFIID riid, void **obj); +extern HRESULT http_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); diff --git a/dlls/mf/scheme_handler.c b/dlls/mf/scheme_handler.c index 7e92748aeb9..3cd16319b2a 100644 --- a/dlls/mf/scheme_handler.c +++ b/dlls/mf/scheme_handler.c @@ -483,6 +483,39 @@ HRESULT file_scheme_handler_construct(REFIID riid, void **obj) return hr; } +WINAPI HRESULT __wine_create_http_bytestream(const WCHAR *url, void **out); + +static HRESULT http_stream_create(const WCHAR *url, DWORD flags, IMFByteStream **out) +{ + if (flags & MF_RESOLUTION_WRITE) + return E_INVALIDARG; + + return __wine_create_http_bytestream(url, (void **)out); +} + +HRESULT http_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 = http_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; diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 7e1fec84de9..4da4284e433 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -8401,7 +8401,6 @@ 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_if(i >= 2) ok(hr == S_OK, "got hr %#lx\n", hr); if (hr != S_OK) continue; @@ -8425,7 +8424,6 @@ static void test_scheme_resolvers(void) hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_CONTENT_TYPE, NULL); ok(hr == S_OK, "got hr %#lx\n", hr); hr = IMFAttributes_GetItem(attributes, &MF_BYTESTREAM_LAST_MODIFIED_TIME, NULL); - todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); IMFAttributes_Release(attributes); @@ -8433,8 +8431,7 @@ static void test_scheme_resolvers(void) ok(hr == S_OK, "got hr %#lx\n", hr); hr = IMFByteStream_GetCapabilities(byte_stream, &caps); ok(hr == S_OK, "got hr %#lx\n", hr); - todo_wine - ok(caps == (expect_caps | MFBYTESTREAM_IS_PARTIALLY_DOWNLOADED) + ok(caps == expect_caps || caps == (expect_caps | MFBYTESTREAM_IS_PARTIALLY_DOWNLOADED) || caps == (expect_caps | MFBYTESTREAM_DOES_NOT_USE_NETWORK), "got caps %#lx\n", caps); hr = IMFByteStream_GetLength(byte_stream, &length); @@ -8453,35 +8450,25 @@ static void test_scheme_resolvers(void) ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got hr %#lx\n", hr); hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"http://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); - todo_wine ok(hr == NS_E_SERVER_NOT_FOUND, "got hr %#lx\n", hr); hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"https://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); - todo_wine ok(hr == WININET_E_NAME_NOT_RESOLVED, "got hr %#lx\n", hr); hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"httpd://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); - todo_wine ok(hr == WININET_E_NAME_NOT_RESOLVED, "got hr %#lx\n", hr); hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"httpsd://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); - todo_wine ok(hr == WININET_E_NAME_NOT_RESOLVED, "got hr %#lx\n", hr); hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"mms://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); - todo_wine ok(hr == WININET_E_NAME_NOT_RESOLVED, "got hr %#lx\n", hr); hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"http://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); - todo_wine ok(hr == NS_E_FILE_NOT_FOUND, "got hr %#lx\n", hr); hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"https://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); - todo_wine ok(hr == NS_E_FILE_NOT_FOUND, "got hr %#lx\n", hr); hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"httpd://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); - todo_wine ok(hr == NS_E_FILE_NOT_FOUND, "got hr %#lx\n", hr); hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"httpsd://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); - todo_wine ok(hr == NS_E_FILE_NOT_FOUND, "got hr %#lx\n", hr); hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"mms://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &type, &object); - todo_wine ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE || hr == NS_E_FILE_NOT_FOUND, "got hr %#lx\n", hr); IMFSourceResolver_Release(resolver); @@ -11319,7 +11306,6 @@ static void test_network_bytestream(void) obj_type = (MF_OBJECT_TYPE)0xdeadbeef; object = NULL; hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"http://nonexistent.url/file.mp4", MF_RESOLUTION_BYTESTREAM, NULL, &obj_type, &object); - todo_wine ok(hr == NS_E_SERVER_NOT_FOUND, "Got hr %#lx.\n", hr); ok(obj_type == MF_OBJECT_INVALID, "Unexpected obj_type %#x.\n", obj_type); if (object) IUnknown_Release(object); @@ -11327,9 +11313,7 @@ static void test_network_bytestream(void) obj_type = (MF_OBJECT_TYPE)0xdeadbeef; object = NULL; hr = IMFSourceResolver_CreateObjectFromURL(resolver, L"http://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM, NULL, &obj_type, &object); - todo_wine ok(hr == NS_E_FILE_NOT_FOUND, "Got hr %#lx.\n", hr); - todo_wine ok(obj_type == MF_OBJECT_INVALID, "Unexpected obj_type %#x.\n", obj_type); if (object) IUnknown_Release(object); @@ -11352,7 +11336,6 @@ static void test_network_bytestream(void) hr = IMFAttributes_GetCount(attr, &count); ok(hr == S_OK, "Got hr %#lx\n", hr); - todo_wine ok(count == 3, "count = %u\n", count); PropVariantInit(&var); @@ -11361,7 +11344,6 @@ static void test_network_bytestream(void) ok(hr == S_OK, "Got hr %#lx\n", hr); ok(IsEqualGUID(&key, &MF_BYTESTREAM_EFFECTIVE_URL), "Got key %s\n", debugstr_guid(&key)); ok(var.vt == VT_LPWSTR, "Got type %d\n", var.vt); - todo_wine ok(!lstrcmpW(var.pwszVal, EFFECTIVE_URL), "Got value %s\n", var.pszVal); memset(&key, 0, sizeof(key)); PropVariantClear(&var); @@ -11370,21 +11352,15 @@ static void test_network_bytestream(void) ok(hr == S_OK, "Got hr %#lx\n", hr); ok(IsEqualGUID(&key, &MF_BYTESTREAM_CONTENT_TYPE), "Got key %s\n", debugstr_guid(&key)); ok(var.vt == VT_LPWSTR, "Got type %d\n", var.vt); - todo_wine ok(!lstrcmpW(var.pwszVal, CONTENT_TYPE), "Got value %s\n", var.pszVal); memset(&key, 0, sizeof(key)); PropVariantClear(&var); hr = IMFAttributes_GetItemByIndex(attr, 2, &key, &var); - todo_wine ok(hr == S_OK, "Got hr %#lx\n", hr); - todo_wine ok(IsEqualGUID(&key, &MF_BYTESTREAM_LAST_MODIFIED_TIME), "Got key %s\n", debugstr_guid(&key)); - todo_wine ok(var.vt == (VT_VECTOR | VT_I1 | VT_NULL), "Got type %d\n", var.vt); - todo_wine ok(var.blob.cbSize == sizeof(LAST_MODIFIED_TIME), "Got size %lu\n", var.blob.cbSize); - todo_wine ok(var.blob.pBlobData != NULL, "Got NULL value\n"); if (var.blob.cbSize == sizeof(LAST_MODIFIED_TIME) && var.blob.pBlobData) ok(!memcmp(var.blob.pBlobData, LAST_MODIFIED_TIME, sizeof(LAST_MODIFIED_TIME)), "Got wrong value\n"); @@ -11403,9 +11379,7 @@ static void test_network_bytestream(void) ptr = NULL; hr = IUnknown_QueryInterface(object, &IID_IMFByteStreamCacheControl, &ptr); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(ptr != NULL, "Got NULL ptr.\n"); if (SUCCEEDED(hr) && ptr) { @@ -11420,9 +11394,7 @@ static void test_network_bytestream(void) ptr = NULL; hr = IUnknown_QueryInterface(object, &IID_IMFByteStreamBuffering, &ptr); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(ptr != NULL, "Got NULL ptr.\n"); if (SUCCEEDED(hr) && ptr) { @@ -11489,9 +11461,7 @@ static void test_network_bytestream(void) ptr = NULL; hr = IUnknown_QueryInterface(object, &IID_IMFByteStreamTimeSeek, &ptr); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(ptr != NULL, "Got NULL ptr.\n"); if (SUCCEEDED(hr) && ptr) { @@ -11550,6 +11520,9 @@ static void test_network_bytestream(void) ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr); ok(written == 0, "written = %lu\n", written); + hr = IMFByteStream_BeginWrite((IMFByteStream*)object, tmp, 1000, (void *)(DWORD_PTR)0xdeadbeef, NULL); + ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr); + free(tmp); hr = IMFByteStream_GetLength((IMFByteStream*)object, &len); @@ -11557,7 +11530,6 @@ static void test_network_bytestream(void) ok(len != 0, "len = %I64u\n", len); hr = IMFByteStream_Flush((IMFByteStream*)object); - todo_wine ok(hr == S_OK, "Got hr %#lx\n", hr); } @@ -11585,9 +11557,7 @@ static void test_network_bytestream(void) ptr = NULL; hr = IUnknown_QueryInterface(object, &IID_IMFMediaEventGenerator, &ptr); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(ptr != NULL, "Got NULL ptr.\n"); if (SUCCEEDED(hr) && ptr) { diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 229230cd899..458a1d75a5b 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -181,3 +181,6 @@ @ stdcall -ret64 MFllMulDiv(int64 int64 int64 int64) @ stub PropVariantFromStream @ stub PropVariantToStream + +# Wine extension +@ stdcall __wine_create_http_bytestream(wstr ptr) diff --git a/dlls/mfplat/network.c b/dlls/mfplat/network.c index 8e2bb9468fa..da1d1213fc8 100644 --- a/dlls/mfplat/network.c +++ b/dlls/mfplat/network.c @@ -2052,3 +2052,8 @@ error: hr = MF_E_UNSUPPORTED_BYTESTREAM_TYPE; return hr; } + +WINAPI HRESULT __wine_create_http_bytestream(const WCHAR *url, void **out) +{ + return create_http_bytestream(url, out); +} -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10253