From: Torge Matthies tmatthies@codeweavers.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 e74a4ae8e4c..120343a1be2 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -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 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 @@ -559,6 +560,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 1f2ef17a8c9..adb35e14194 100644 --- a/dlls/mf/mf_private.h +++ b/dlls/mf/mf_private.h @@ -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 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 e8ae6701466..f0339d249fc 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -5380,7 +5380,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; @@ -5404,7 +5403,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);
@@ -5412,8 +5410,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); @@ -5432,35 +5429,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, "got hr %#lx\n", hr);
IMFSourceResolver_Release(resolver); @@ -6648,7 +6635,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); @@ -6656,9 +6642,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);
@@ -6681,7 +6665,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); @@ -6690,7 +6673,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); @@ -6699,21 +6681,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"); @@ -6732,9 +6708,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) { @@ -6749,9 +6723,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) { @@ -6818,9 +6790,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) { @@ -6879,6 +6849,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); @@ -6886,7 +6859,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); }
@@ -6914,9 +6886,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 7b356f9f457..f55f49b7e8c 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 d9a2981f5a7..2369dbf31fd 100644 --- a/dlls/mfplat/network.c +++ b/dlls/mfplat/network.c @@ -2012,3 +2012,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); +}