From f193c265547a3fb629ea4bff62844b4af2f71c54 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 3 Aug 2005 10:56:26 +0000 Subject: [PATCH] Added about protocol implementation. --- dlls/mshtml/protocol.c | 91 ++++++++++++++++++++++++++++++++---- dlls/mshtml/tests/protocol.c | 79 +++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 10 deletions(-) diff --git a/dlls/mshtml/protocol.c b/dlls/mshtml/protocol.c index 3434f9262f1..914a980d361 100644 --- a/dlls/mshtml/protocol.c +++ b/dlls/mshtml/protocol.c @@ -138,7 +138,12 @@ static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock) typedef struct { const IInternetProtocolVtbl *lpInternetProtocolVtbl; + LONG ref; + + BYTE *data; + ULONG data_len; + ULONG cur; } AboutProtocol; static HRESULT WINAPI AboutProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv) @@ -184,6 +189,7 @@ static ULONG WINAPI AboutProtocol_Release(IInternetProtocol *iface) TRACE("(%p) ref=%lx\n", iface, ref); if(!ref) { + HeapFree(GetProcessHeap(), 0, This->data); HeapFree(GetProcessHeap(), 0, This); UNLOCK_MODULE(); } @@ -196,9 +202,53 @@ static HRESULT WINAPI AboutProtocol_Start(IInternetProtocol *iface, LPCWSTR szUr DWORD grfPI, DWORD dwReserved) { AboutProtocol *This = (AboutProtocol*)iface; - FIXME("(%p)->(%s %p %p %08lx %ld)\n", This, debugstr_w(szUrl), pOIProtSink, + BINDINFO bindinfo; + DWORD grfBINDF = 0; + LPCWSTR text = NULL; + + static const WCHAR html_begin[] = {0xfeff,'<','H','T','M','L','>',0}; + static const WCHAR html_end[] = {'<','/','H','T','M','L','>',0}; + static const WCHAR wszBlank[] = {'b','l','a','n','k',0}; + static const WCHAR wszAbout[] = {'a','b','o','u','t',':'}; + + /* NOTE: + * the about protocol seems not to work as I would expect. It creates html document + * for a given url, eg. about:some_text -> some_text except for the case when + * some_text = "blank", when document is blank (). The same happens + * when the url does not have "about:" in the beginning. + */ + + TRACE("(%p)->(%s %p %p %08lx %ld)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); - return E_NOTIMPL; + + memset(&bindinfo, 0, sizeof(bindinfo)); + bindinfo.cbSize = sizeof(BINDINFO); + IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo); + + if(strlenW(szUrl)>=sizeof(wszAbout)/sizeof(WCHAR) && !memcmp(wszAbout, szUrl, sizeof(wszAbout))) { + text = szUrl + sizeof(wszAbout)/sizeof(WCHAR); + if(!strcmpW(wszBlank, text)) + text = NULL; + } + + This->data_len = sizeof(html_begin)+sizeof(html_end)-sizeof(WCHAR) + + (text ? strlenW(text)*sizeof(WCHAR) : 0); + This->data = HeapAlloc(GetProcessHeap(), 0, This->data_len); + + memcpy(This->data, html_begin, sizeof(html_begin)); + if(text) + strcatW((LPWSTR)This->data, text); + strcatW((LPWSTR)This->data, html_end); + + This->cur = 0; + + IInternetProtocolSink_ReportData(pOIProtSink, + BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE, + This->data_len, This->data_len); + + IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL); + + return S_OK; } static HRESULT WINAPI AboutProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData) @@ -219,8 +269,8 @@ static HRESULT WINAPI AboutProtocol_Abort(IInternetProtocol *iface, HRESULT hrRe static HRESULT WINAPI AboutProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions) { AboutProtocol *This = (AboutProtocol*)iface; - FIXME("(%p)->(%08lx)\n", This, dwOptions); - return E_NOTIMPL; + TRACE("(%p)->(%08lx)\n", This, dwOptions); + return S_OK; } static HRESULT WINAPI AboutProtocol_Suspend(IInternetProtocol *iface) @@ -240,8 +290,21 @@ static HRESULT WINAPI AboutProtocol_Resume(IInternetProtocol *iface) static HRESULT WINAPI AboutProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead) { AboutProtocol *This = (AboutProtocol*)iface; - FIXME("(%p)->(%lu %p)\n", This, cb, pcbRead); - return E_NOTIMPL; + + TRACE("(%p)->(%p %lu %p)\n", This, pv, cb, pcbRead); + + if(!This->data) + return E_FAIL; + + *pcbRead = (cb > This->data_len-This->cur ? This->data_len-This->cur : cb); + + if(!*pcbRead) + return S_FALSE; + + memcpy(pv, This->data, *pcbRead); + This->cur += *pcbRead; + + return S_OK; } static HRESULT WINAPI AboutProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove, @@ -255,15 +318,19 @@ static HRESULT WINAPI AboutProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER static HRESULT WINAPI AboutProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions) { AboutProtocol *This = (AboutProtocol*)iface; - FIXME("(%p)->(%ld)\n", This, dwOptions); - return E_NOTIMPL; + + TRACE("(%p)->(%ld)\n", This, dwOptions); + + return S_OK; } static HRESULT WINAPI AboutProtocol_UnlockRequest(IInternetProtocol *iface) { AboutProtocol *This = (AboutProtocol*)iface; - FIXME("(%p)\n", This); - return E_NOTIMPL; + + TRACE("(%p)\n", This); + + return S_OK; } static const IInternetProtocolVtbl AboutProtocolVtbl = { @@ -294,6 +361,10 @@ static HRESULT WINAPI AboutProtocolFactory_CreateInstance(IClassFactory *iface, ret->lpInternetProtocolVtbl = &AboutProtocolVtbl; ret->ref = 0; + ret->data = NULL; + ret->data_len = 0; + ret->cur = 0; + hres = IUnknown_QueryInterface((IUnknown*)ret, riid, ppv); if(SUCCEEDED(hres)) diff --git a/dlls/mshtml/tests/protocol.c b/dlls/mshtml/tests/protocol.c index fdd71934887..5e7c1cb28d2 100644 --- a/dlls/mshtml/tests/protocol.c +++ b/dlls/mshtml/tests/protocol.c @@ -29,6 +29,7 @@ #include "initguid.h" DEFINE_GUID(CLSID_ResProtocol, 0x3050F3BC, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B); +DEFINE_GUID(CLSID_AboutProtocol, 0x3050F406, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B); static BOOL expect_GetBindInfo = FALSE, called_GetBindInfo = FALSE; static BOOL expect_ReportProgress = FALSE, called_ReportProgress = FALSE; @@ -312,6 +313,83 @@ static void test_res_protocol(void) protocol_start(protocol, blank_url); hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb); ok(hres == S_OK, "Read failed: %08lx\n", hres); + hres = IInternetProtocol_Terminate(protocol, 0); + ok(hres == S_OK, "Terminate failed: %08lx\n", hres); + + IInternetProtocol_Release(protocol); + } + + IClassFactory_Release(factory); + } + + IUnknown_Release(unk); +} + +static void test_about_protocol(void) +{ + IInternetProtocolInfo *protocol_info; + IUnknown *unk; + IClassFactory *factory; + HRESULT hres; + + static const WCHAR blank_url[] = {'a','b','o','u','t',':','b','l','a','n','k',0}; + static const WCHAR test_url[] = {'a','b','o','u','t',':','t','e','s','t',0}; + static const WCHAR res_url[] = {'r','e','s',':','b','l','a','n','k',0}; + static const WCHAR blank_html[] = {0xfeff,'<','H','T','M','L','>','<','/','H','T','M','L','>',0}; + static const WCHAR test_html[] = + {0xfeff,'<','H','T','M','L','>','t','e','s','t','<','/','H','T','M','L','>',0}; + + hres = CoGetClassObject(&CLSID_AboutProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk); + ok(hres == S_OK, "CoGetClassObject failed: %08lx\n", hres); + if(!SUCCEEDED(hres)) + return; + + hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info); + ok(hres == S_OK, "Could not get IInternetProtocolInfo interface: %08lx\n", hres); + if(SUCCEEDED(hres)) { + /* TODO: test IInternetProtocol interface */ + IInternetProtocol_Release(protocol_info); + } + + hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory); + ok(hres == S_OK, "Could not get IClassFactory interface\n"); + if(SUCCEEDED(hres)) { + IInternetProtocol *protocol; + BYTE buf[512]; + ULONG cb; + hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol); + ok(hres == S_OK, "Could not get IInternetProtocol: %08lx\n", hres); + + if(SUCCEEDED(hres)) { + protocol_start(protocol, blank_url); + hres = IInternetProtocol_LockRequest(protocol, 0); + ok(hres == S_OK, "LockRequest failed: %08lx\n", hres); + hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb); + ok(hres == S_OK, "Read failed: %08lx\n", hres); + ok(cb == sizeof(blank_html), "cb=%ld, expected %d\n", cb, sizeof(blank_html)); + ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n"); + hres = IInternetProtocol_UnlockRequest(protocol); + ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres); + + protocol_start(protocol, test_url); + hres = IInternetProtocol_LockRequest(protocol, 0); + ok(hres == S_OK, "LockRequest failed: %08lx\n", hres); + hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb); + ok(hres == S_OK, "Read failed: %08lx\n", hres); + ok(cb == sizeof(test_html), "cb=%ld, expected %d\n", cb, sizeof(test_html)); + ok(!memcmp(buf, test_html, cb), "Readed wrong data\n"); + hres = IInternetProtocol_UnlockRequest(protocol); + ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres); + + protocol_start(protocol, res_url); + hres = IInternetProtocol_LockRequest(protocol, 0); + ok(hres == S_OK, "LockRequest failed: %08lx\n", hres); + hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb); + ok(hres == S_OK, "Read failed: %08lx\n", hres); + ok(cb == sizeof(blank_html), "cb=%ld, expected %d\n", cb, sizeof(blank_html)); + ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n"); + hres = IInternetProtocol_UnlockRequest(protocol); + ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres); IInternetProtocol_Release(protocol); } @@ -327,6 +405,7 @@ START_TEST(protocol) OleInitialize(NULL); test_res_protocol(); + test_about_protocol(); OleUninitialize(); }