diff --git a/dlls/inetcomm/Makefile.in b/dlls/inetcomm/Makefile.in index 596eabbf223..690e302b6e8 100644 --- a/dlls/inetcomm/Makefile.in +++ b/dlls/inetcomm/Makefile.in @@ -1,6 +1,6 @@ MODULE = inetcomm.dll IMPORTLIB = inetcomm -IMPORTS = uuid propsys oleaut32 ole32 ws2_32 user32 advapi32 +IMPORTS = uuid urlmon propsys oleaut32 ole32 ws2_32 user32 advapi32 C_SRCS = \ imaptransport.c \ diff --git a/dlls/inetcomm/mimeole.c b/dlls/inetcomm/mimeole.c index de37f090c07..c55be72faa5 100644 --- a/dlls/inetcomm/mimeole.c +++ b/dlls/inetcomm/mimeole.c @@ -35,6 +35,7 @@ #include "wine/list.h" #include "wine/debug.h" +#include "wine/unicode.h" #include "inetcomm_private.h" @@ -3562,10 +3563,70 @@ HRESULT WINAPI MimeGetAddressFormatW(REFIID riid, void *object, DWORD addr_type, return E_NOTIMPL; } +static HRESULT WINAPI mime_obj_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + FIXME("(%s %p)\n", debugstr_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI mime_obj_AddRef(IUnknown *iface) +{ + TRACE("\n"); + return 2; +} + +static ULONG WINAPI mime_obj_Release(IUnknown *iface) +{ + TRACE("\n"); + return 1; +} + +static const IUnknownVtbl mime_obj_vtbl = { + mime_obj_QueryInterface, + mime_obj_AddRef, + mime_obj_Release +}; + +static IUnknown mime_obj = { &mime_obj_vtbl }; + HRESULT WINAPI MimeOleObjectFromMoniker(BINDF bindf, IMoniker *moniker, IBindCtx *binding, REFIID riid, void **out, IMoniker **moniker_new) { - FIXME("(0x%08x, %p, %p, %s, %p, %p) stub\n", bindf, moniker, binding, debugstr_guid(riid), out, moniker_new); + WCHAR *display_name, *mhtml_url; + size_t len; + HRESULT hres; - return E_NOTIMPL; + static const WCHAR mhtml_prefixW[] = {'m','h','t','m','l',':'}; + + WARN("(0x%08x, %p, %p, %s, %p, %p) semi-stub\n", bindf, moniker, binding, debugstr_guid(riid), out, moniker_new); + + if(!IsEqualGUID(&IID_IUnknown, riid)) { + FIXME("Unsupported riid %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; + } + + hres = IMoniker_GetDisplayName(moniker, NULL, NULL, &display_name); + if(FAILED(hres)) + return hres; + + TRACE("display name %s\n", debugstr_w(display_name)); + + len = strlenW(display_name); + mhtml_url = heap_alloc((len+1)*sizeof(WCHAR) + sizeof(mhtml_prefixW)); + if(!mhtml_url) + return E_OUTOFMEMORY; + + memcpy(mhtml_url, mhtml_prefixW, sizeof(mhtml_prefixW)); + strcpyW(mhtml_url + sizeof(mhtml_prefixW)/sizeof(WCHAR), display_name); + HeapFree(GetProcessHeap(), 0, display_name); + + hres = CreateURLMoniker(NULL, mhtml_url, moniker_new); + heap_free(mhtml_url); + if(FAILED(hres)) + return hres; + + /* FIXME: We most likely should start binding here and return something more meaningful as mime object. */ + *out = &mime_obj; + return S_OK; } diff --git a/dlls/inetcomm/tests/Makefile.in b/dlls/inetcomm/tests/Makefile.in index 4bd83cb1160..5a5b16d538d 100644 --- a/dlls/inetcomm/tests/Makefile.in +++ b/dlls/inetcomm/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = inetcomm.dll -IMPORTS = inetcomm oleaut32 ole32 +IMPORTS = inetcomm urlmon oleaut32 ole32 C_SRCS = \ mimeintl.c \ diff --git a/dlls/inetcomm/tests/mimeole.c b/dlls/inetcomm/tests/mimeole.c index 15b267f30fe..fe19893c808 100644 --- a/dlls/inetcomm/tests/mimeole.c +++ b/dlls/inetcomm/tests/mimeole.c @@ -106,6 +106,27 @@ static const char mhtml_page1[] = "\r\n\t\t\t\tVGVzdA==\r\n\r\n" "------=_NextPart_000_00--"; +static WCHAR *a2w(const char *str) +{ + WCHAR *ret; + int len; + + if(!str) + return NULL; + + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + return ret; +} + +static int strcmp_wa(const WCHAR *strw, const char *stra) +{ + WCHAR buf[512]; + MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR)); + return lstrcmpW(strw, buf); +} + static void test_CreateVirtualStream(void) { HRESULT hr; @@ -1207,6 +1228,53 @@ static void test_mhtml_protocol(void) test_mhtml_protocol_info(); } +static void test_MimeOleObjectFromMoniker(void) +{ + IMoniker *mon, *new_mon; + WCHAR *mhtml_url, *url; + IBindCtx *bind_ctx; + IUnknown *unk; + unsigned i; + HRESULT hres; + + static const struct { + const char *url; + const char *mhtml_url; + } tests[] = { + {"file:///x:\\dir\\file.mht", "mhtml:file://x:\\dir\\file.mht"}, + {"file:///x:/dir/file.mht", "mhtml:file://x:\\dir\\file.mht"}, + {"http://www.winehq.org/index.html?query#hash", "mhtml:http://www.winehq.org/index.html?query#hash"}, + {"../test.mht", "mhtml:../test.mht"} + }; + + for(i = 0; i < sizeof(tests)/sizeof(*tests); i++) { + url = a2w(tests[i].url); + hres = CreateURLMoniker(NULL, url, &mon); + ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres); + HeapFree(GetProcessHeap(), 0, url); + + hres = CreateBindCtx(0, &bind_ctx); + ok(hres == S_OK, "CreateBindCtx failed: %08x\n", hres); + + hres = MimeOleObjectFromMoniker(0, mon, bind_ctx, &IID_IUnknown, (void**)&unk, &new_mon); + ok(hres == S_OK || broken(!i && hres == INET_E_RESOURCE_NOT_FOUND), "MimeOleObjectFromMoniker failed: %08x\n", hres); + IBindCtx_Release(bind_ctx); + if(hres == INET_E_RESOURCE_NOT_FOUND) { /* winxp */ + win_skip("Broken MHTML behaviour found. Skipping some tests.\n"); + return; + } + + hres = IMoniker_GetDisplayName(new_mon, NULL, NULL, &mhtml_url); + ok(hres == S_OK, "GetDisplayName failed: %08x\n", hres); + ok(!strcmp_wa(mhtml_url, tests[i].mhtml_url), "[%d] unexpected mhtml URL: %s\n", i, wine_dbgstr_w(mhtml_url)); + CoTaskMemFree(mhtml_url); + + IUnknown_Release(unk); + IMoniker_Release(new_mon); + IMoniker_Release(mon); + } +} + START_TEST(mimeole) { OleInitialize(NULL); @@ -1223,6 +1291,7 @@ START_TEST(mimeole) test_BodyDeleteProp(); test_MimeOleGetPropertySchema(); test_mhtml_message(); + test_MimeOleObjectFromMoniker(); test_mhtml_protocol(); OleUninitialize(); }