diff --git a/dlls/urlmon/tests/protocol.c b/dlls/urlmon/tests/protocol.c index 725c3cc6d91..05f860242b5 100644 --- a/dlls/urlmon/tests/protocol.c +++ b/dlls/urlmon/tests/protocol.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007 Jacek Caban for CodeWeavers + * Copyright 2005-2009 Jacek Caban for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -77,11 +77,14 @@ DEFINE_EXPECT(ReportProgress_REDIRECTING); DEFINE_EXPECT(ReportProgress_ENCODING); DEFINE_EXPECT(ReportProgress_ACCEPTRANGES); DEFINE_EXPECT(ReportProgress_PROXYDETECTING); +DEFINE_EXPECT(ReportProgress_LOADINGMIMEHANDLER); +DEFINE_EXPECT(ReportProgress_DECODING); DEFINE_EXPECT(ReportData); DEFINE_EXPECT(ReportResult); DEFINE_EXPECT(GetBindString_ACCEPT_MIMES); DEFINE_EXPECT(GetBindString_USER_AGENT); DEFINE_EXPECT(GetBindString_POST_COOKIE); +DEFINE_EXPECT(GetBindString_URL); DEFINE_EXPECT(QueryService_HttpNegotiate); DEFINE_EXPECT(QueryService_InternetProtocol); DEFINE_EXPECT(QueryService_HttpSecurity); @@ -97,6 +100,17 @@ DEFINE_EXPECT(Read); DEFINE_EXPECT(SetPriority); DEFINE_EXPECT(LockRequest); DEFINE_EXPECT(UnlockRequest); +DEFINE_EXPECT(MimeFilter_CreateInstance); +DEFINE_EXPECT(MimeFilter_Start); +DEFINE_EXPECT(MimeFilter_ReportProgress); +DEFINE_EXPECT(MimeFilter_ReportData); +DEFINE_EXPECT(MimeFilter_ReportResult); +DEFINE_EXPECT(MimeFilter_Terminate); +DEFINE_EXPECT(MimeFilter_LockRequest); +DEFINE_EXPECT(MimeFilter_UnlockRequest); +DEFINE_EXPECT(MimeFilter_Read); +DEFINE_EXPECT(MimeFilter_Switch); +DEFINE_EXPECT(MimeFilter_Continue); static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0}; static const WCHAR index_url[] = @@ -108,6 +122,7 @@ static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0}; static const WCHAR hostW[] = {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0}; static const WCHAR winehq_ipW[] = {'2','0','9','.','4','6','.','2','5','.','1','3','4',0}; static const WCHAR emptyW[] = {0}; +static const WCHAR gzipW[] = {'g','z','i','p',0}; static HRESULT expect_hrResult; static LPCWSTR file_name, http_url, expect_wsz; @@ -116,16 +131,16 @@ static BOOL first_data_notif = FALSE, http_is_first = FALSE, http_post_test = FALSE; static int state = 0, prot_state; static DWORD bindf, ex_priority , pi; -static IInternetProtocol *binding_protocol; +static IInternetProtocol *binding_protocol, *filtered_protocol; static IInternetBindInfo *prot_bind_info; -static IInternetProtocolSink *binding_sink; +static IInternetProtocolSink *binding_sink, *filtered_sink; static void *expect_pv; static HANDLE event_complete, event_complete2; static BOOL binding_test; static PROTOCOLDATA protocoldata, *pdata; -static DWORD prot_read; +static DWORD prot_read, pi, filter_state; static BOOL security_problem = FALSE; -static BOOL async_read_pending; +static BOOL async_read_pending, mimefilter_test; static enum { FILE_TEST, @@ -416,9 +431,10 @@ static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOL HRESULT hres; if(tested_protocol == FTP_TEST) - CHECK_EXPECT2(Switch); + CHECK_EXPECT2(Switch); else - CHECK_EXPECT(Switch); + CHECK_EXPECT(Switch); + ok(pProtocolData != NULL, "pProtocolData == NULL\n"); pdata = pProtocolData; @@ -506,7 +522,7 @@ static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ok(lstrlenW(text_plain) <= lstrlenW(szStatusText) && !memcmp(szStatusText, text_plain, lstrlenW(text_plain)*sizeof(WCHAR)), "szStatusText != text/plain\n"); - else + else if(!mimefilter_test) ok(lstrlenW(text_htmlW) <= lstrlenW(szStatusText) && !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)), "szStatusText != text/html\n"); @@ -584,6 +600,14 @@ static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, SET_EXPECT(ReportProgress_CONNECTING); ok(!szStatusText, "szStatusText = %s\n", debugstr_w(szStatusText)); break; + case BINDSTATUS_LOADINGMIMEHANDLER: + CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER); + ok(!szStatusText, "szStatusText = %s\n", debugstr_w(szStatusText)); + break; + case BINDSTATUS_DECODING: + CHECK_EXPECT(ReportProgress_DECODING); + ok(!lstrcmpW(szStatusText, gzipW), "szStatusText = %s\n", debugstr_w(szStatusText)); + break; default: ok(0, "Unexpected status %d\n", ulStatusCode); }; @@ -594,7 +618,7 @@ static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax) { - if(tested_protocol == FILE_TEST) { + if(!mimefilter_test && tested_protocol == FILE_TEST) { CHECK_EXPECT2(ReportData); ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n", @@ -652,9 +676,15 @@ static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWOR return S_OK; do { - SET_EXPECT(Read); + if(mimefilter_test) + SET_EXPECT(MimeFilter_Read); + else + SET_EXPECT(Read); hres = IInternetProtocol_Read(binding_protocol, expect_pv=buf, sizeof(buf), &read); - CHECK_CALLED(Read); + if(mimefilter_test) + CHECK_CALLED(MimeFilter_Read); + else + CHECK_CALLED(Read); }while(hres == S_OK); } @@ -694,6 +724,116 @@ static IInternetProtocolSinkVtbl protocol_sink_vtbl = { static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl }; +static HRESULT WINAPI MimeProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static ULONG WINAPI MimeProtocolSink_AddRef(IInternetProtocolSink *iface) +{ + return 2; +} + +static ULONG WINAPI MimeProtocolSink_Release(IInternetProtocolSink *iface) +{ + return 1; +} + +static HRESULT WINAPI MimeProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData) +{ + HRESULT hres; + + CHECK_EXPECT(MimeFilter_Switch); + + SET_EXPECT(Switch); + hres = IInternetProtocolSink_Switch(filtered_sink, pProtocolData); + ok(hres == S_OK, "Switch failed: %08x\n", hres); + CHECK_CALLED(Switch); + + return S_OK; +} + +static HRESULT WINAPI MimeProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode, + LPCWSTR szStatusText) +{ + CHECK_EXPECT(MimeFilter_ReportProgress); + return S_OK; +} + +static HRESULT WINAPI MimeProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF, + ULONG ulProgress, ULONG ulProgressMax) +{ + DWORD read = 0; + BYTE buf[8192]; + HRESULT hres; + + CHECK_EXPECT(MimeFilter_ReportData); + + ok(ulProgress, "ulProgress == 0\n"); + + if(!filter_state) { + SET_EXPECT(Read); + hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read); + if(tested_protocol == HTTP_TEST) + ok(hres == S_OK || hres == E_PENDING || hres == S_FALSE, "Read failed: %08x\n", hres); + else + ok(hres == S_OK, "Read failed: %08x\n", hres); + CHECK_CALLED(Read); + + SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE); + hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, text_htmlW); + ok(hres == S_OK, "ReportProgress failed: %08x\n", hres); + CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); + + SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE); + hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW); + ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres); + CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE); + } + + SET_EXPECT(ReportData); + hres = IInternetProtocolSink_ReportData(filtered_sink, grfBSCF, ulProgress, ulProgressMax); + ok(hres == S_OK, "ReportData failed: %08x\n", hres); + CHECK_CALLED(ReportData); + + if(!filter_state) + filter_state = 1; + + return S_OK; +} + +static HRESULT WINAPI MimeProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult, + DWORD dwError, LPCWSTR szResult) +{ + HRESULT hres; + + CHECK_EXPECT(MimeFilter_ReportResult); + + ok(hrResult == S_OK, "hrResult = %08x\n", hrResult); + ok(dwError == ERROR_SUCCESS, "dwError = %u\n", dwError); + ok(!szResult, "szResult = %s\n", debugstr_w(szResult)); + + SET_EXPECT(ReportResult); + hres = IInternetProtocolSink_ReportResult(filtered_sink, hrResult, dwError, szResult); + ok(SUCCEEDED(hres), "ReportResult failed: %08x\n", hres); + CHECK_CALLED(ReportResult); + + return S_OK; +} + +static IInternetProtocolSinkVtbl mime_protocol_sink_vtbl = { + MimeProtocolSink_QueryInterface, + MimeProtocolSink_AddRef, + MimeProtocolSink_Release, + MimeProtocolSink_Switch, + MimeProtocolSink_ReportProgress, + MimeProtocolSink_ReportData, + MimeProtocolSink_ReportResult +}; + +static IInternetProtocolSink mime_protocol_sink = { &mime_protocol_sink_vtbl }; + static HRESULT QueryInterface(REFIID riid, void **ppv) { *ppv = NULL; @@ -706,6 +846,7 @@ static HRESULT QueryInterface(REFIID riid, void **ppv) if(*ppv) return S_OK; + ok(0, "unexpected call %s\n", debugstr_guid(riid)); return E_NOINTERFACE; } @@ -804,6 +945,19 @@ static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulS if(pcElFetched) ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched); return S_OK; + case BINDSTRING_URL: { + DWORD size; + + CHECK_EXPECT(GetBindString_URL); + ok(cEl == 1, "cEl=%d, expected 1\n", cEl); + ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched); + *pcElFetched = 1; + + size = (lstrlenW(binding_urls[tested_protocol])+1)*sizeof(WCHAR); + *ppwzStr = CoTaskMemAlloc(size); + memcpy(*ppwzStr, binding_urls[tested_protocol], size); + return S_OK; + } default: ok(0, "unexpected call\n"); } @@ -862,7 +1016,43 @@ static const IInternetPriorityVtbl InternetPriorityVtbl = { static IInternetPriority InternetPriority = { &InternetPriorityVtbl }; -static HRESULT WINAPI Protocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv) +static ULONG WINAPI Protocol_AddRef(IInternetProtocol *iface) +{ + return 2; +} + +static ULONG WINAPI Protocol_Release(IInternetProtocol *iface) +{ + return 1; +} + +static HRESULT WINAPI Protocol_Abort(IInternetProtocol *iface, HRESULT hrReason, + DWORD dwOptions) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Protocol_Suspend(IInternetProtocol *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Protocol_Resume(IInternetProtocol *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Protocol_Seek(IInternetProtocol *iface, + LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ProtocolEmul_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv) { if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) { *ppv = iface; @@ -885,16 +1075,6 @@ static HRESULT WINAPI Protocol_QueryInterface(IInternetProtocol *iface, REFIID r return E_NOINTERFACE; } -static ULONG WINAPI Protocol_AddRef(IInternetProtocol *iface) -{ - return 2; -} - -static ULONG WINAPI Protocol_Release(IInternetProtocol *iface) -{ - return 1; -} - static DWORD WINAPI thread_proc(PVOID arg) { HRESULT hres; @@ -928,29 +1108,47 @@ static DWORD WINAPI thread_proc(PVOID arg) ok(hres == S_OK, "Switch failed: %08x\n", hres); prot_state = 2; - SET_EXPECT(Switch); + if(mimefilter_test) + SET_EXPECT(MimeFilter_Switch); + else + SET_EXPECT(Switch); hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata); - CHECK_CALLED(Switch); ok(hres == S_OK, "Switch failed: %08x\n", hres); + if(mimefilter_test) + CHECK_CALLED(MimeFilter_Switch); + else + CHECK_CALLED(Switch); prot_state = 2; - SET_EXPECT(Switch); + if(mimefilter_test) + SET_EXPECT(MimeFilter_Switch); + else + SET_EXPECT(Switch); hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata); - CHECK_CALLED(Switch); ok(hres == S_OK, "Switch failed: %08x\n", hres); + if(mimefilter_test) + CHECK_CALLED(MimeFilter_Switch); + else + CHECK_CALLED(Switch); prot_state = 3; - SET_EXPECT(Switch); + if(mimefilter_test) + SET_EXPECT(MimeFilter_Switch); + else + SET_EXPECT(Switch); hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata); - CHECK_CALLED(Switch); ok(hres == S_OK, "Switch failed: %08x\n", hres); + if(mimefilter_test) + CHECK_CALLED(MimeFilter_Switch); + else + CHECK_CALLED(Switch); SetEvent(event_complete); return 0; } -static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, +static HRESULT WINAPI ProtocolEmul_Start(IInternetProtocol *iface, LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) { @@ -967,6 +1165,9 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, ok(!grfPI, "grfPI = %x\n", grfPI); ok(!dwReserved, "dwReserved = %lx\n", dwReserved); + if(binding_test) + ok(pOIProtSink == binding_sink, "pOIProtSink != binding_sink\n"); + memset(&bindinfo, 0, sizeof(bindinfo)); bindinfo.cbSize = sizeof(bindinfo); memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo)); @@ -1060,33 +1261,57 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres); CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE); + if(mimefilter_test) { + SET_EXPECT(MimeFilter_CreateInstance); + SET_EXPECT(MimeFilter_Start); + SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER); + } SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE); hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, - expect_wsz = text_htmlW); + mimefilter_test ? gzipW : (expect_wsz = text_htmlW)); ok(hres == S_OK, "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres); - CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); + if(mimefilter_test) { + CHECK_CALLED(MimeFilter_CreateInstance); + CHECK_CALLED(MimeFilter_Start); + CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER); + todo_wine CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); + }else { + CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); + } - SET_EXPECT(ReportData); + if(mimefilter_test) + SET_EXPECT(MimeFilter_ReportData); + else + SET_EXPECT(ReportData); hres = IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION, 13, 13); ok(hres == S_OK, "ReportData failed: %08x\n", hres); - CHECK_CALLED(ReportData); + if(mimefilter_test) + CHECK_CALLED(MimeFilter_ReportData); + else + CHECK_CALLED(ReportData); if(tested_protocol == BIND_TEST) { hres = IInternetProtocol_Terminate(binding_protocol, 0); ok(hres == E_FAIL, "Termiante failed: %08x\n", hres); } - SET_EXPECT(ReportResult); + if(mimefilter_test) + SET_EXPECT(MimeFilter_ReportResult); + else + SET_EXPECT(ReportResult); hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL); ok(hres == S_OK, "ReportResult failed: %08x\n", hres); - CHECK_CALLED(ReportResult); + if(mimefilter_test) + CHECK_CALLED(MimeFilter_ReportResult); + else + CHECK_CALLED(ReportResult); return S_OK; } -static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface, +static HRESULT WINAPI ProtocolEmul_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData) { DWORD bscf = 0, pr; @@ -1122,12 +1347,22 @@ static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface, IHttpNegotiate_Release(http_negotiate); ok(hres == S_OK, "OnResponse failed: %08x\n", hres); - if(!(pi & PI_MIMEVERIFICATION)) + if(mimefilter_test) { + SET_EXPECT(MimeFilter_CreateInstance); + SET_EXPECT(MimeFilter_Start); + SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER); + }else if(!(pi & PI_MIMEVERIFICATION)) { SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE); + } hres = IInternetProtocolSink_ReportProgress(binding_sink, - BINDSTATUS_MIMETYPEAVAILABLE, text_htmlW); - if(!(pi & PI_MIMEVERIFICATION)) + BINDSTATUS_MIMETYPEAVAILABLE, mimefilter_test ? gzipW : text_htmlW); + if(mimefilter_test) { + CHECK_CALLED(MimeFilter_CreateInstance); + CHECK_CALLED(MimeFilter_Start); + CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER); + }else if(!(pi & PI_MIMEVERIFICATION)) { CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); + } ok(hres == S_OK, "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres); @@ -1141,30 +1376,36 @@ static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface, } pr = prot_read; - if(pi & PI_MIMEVERIFICATION) { + if(mimefilter_test) { + SET_EXPECT(MimeFilter_ReportData); + }else if(pi & PI_MIMEVERIFICATION) { if(pr < 200) SET_EXPECT(Read); if(pr == 200) { SET_EXPECT(Read); SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE); } - } - if(!(pi & PI_MIMEVERIFICATION) || pr >= 200) + if(pr >= 200) + SET_EXPECT(ReportData); + }else { SET_EXPECT(ReportData); + } hres = IInternetProtocolSink_ReportData(binding_sink, bscf, 100, 400); ok(hres == S_OK, "ReportData failed: %08x\n", hres); - if(pi & PI_MIMEVERIFICATION) { + if(mimefilter_test) { + SET_EXPECT(MimeFilter_ReportData); + }else if(pi & PI_MIMEVERIFICATION) { if(pr < 200) CHECK_CALLED(Read); if(pr == 200) { CLEAR_CALLED(Read); CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); } - } - if(!(pi & PI_MIMEVERIFICATION) || pr >= 200) + }else { CHECK_CALLED(ReportData); + } if(prot_state == 3) prot_state = 4; @@ -1172,36 +1413,19 @@ static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface, return S_OK; } -static HRESULT WINAPI Protocol_Abort(IInternetProtocol *iface, HRESULT hrReason, - DWORD dwOptions) -{ - ok(0, "unexpected call\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI Protocol_Terminate(IInternetProtocol *iface, DWORD dwOptions) +static HRESULT WINAPI ProtocolEmul_Terminate(IInternetProtocol *iface, DWORD dwOptions) { CHECK_EXPECT(Terminate); ok(!dwOptions, "dwOptions=%d\n", dwOptions); return S_OK; } -static HRESULT WINAPI Protocol_Suspend(IInternetProtocol *iface) -{ - ok(0, "unexpected call\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI Protocol_Resume(IInternetProtocol *iface) -{ - ok(0, "unexpected call\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv, +static HRESULT WINAPI ProtocolEmul_Read(IInternetProtocol *iface, void *pv, ULONG cb, ULONG *pcbRead) { - if(pi & PI_MIMEVERIFICATION) { + if(mimefilter_test) { + CHECK_EXPECT2(Read); + }else if((pi & PI_MIMEVERIFICATION)) { CHECK_EXPECT2(Read); if(prot_read < 300) { @@ -1225,9 +1449,16 @@ static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv, if(prot_state == 3) { HRESULT hres; - SET_EXPECT(ReportResult); + if(mimefilter_test) + SET_EXPECT(MimeFilter_ReportResult); + else + SET_EXPECT(ReportResult); hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL); - CHECK_CALLED(ReportResult); + ok(hres == S_OK, "ReportResult failed: %08x\n", hres); + if(mimefilter_test) + CHECK_CALLED(MimeFilter_ReportResult); + else + CHECK_CALLED(ReportResult); return S_FALSE; } @@ -1242,44 +1473,232 @@ static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv, return S_OK; } -static HRESULT WINAPI Protocol_Seek(IInternetProtocol *iface, - LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) -{ - ok(0, "unexpected call\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI Protocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions) +static HRESULT WINAPI ProtocolEmul_LockRequest(IInternetProtocol *iface, DWORD dwOptions) { CHECK_EXPECT(LockRequest); ok(dwOptions == 0, "dwOptions=%x\n", dwOptions); return S_OK; } -static HRESULT WINAPI Protocol_UnlockRequest(IInternetProtocol *iface) +static HRESULT WINAPI ProtocolEmul_UnlockRequest(IInternetProtocol *iface) { CHECK_EXPECT(UnlockRequest); return S_OK; } static const IInternetProtocolVtbl ProtocolVtbl = { - Protocol_QueryInterface, + ProtocolEmul_QueryInterface, Protocol_AddRef, Protocol_Release, - Protocol_Start, - Protocol_Continue, + ProtocolEmul_Start, + ProtocolEmul_Continue, Protocol_Abort, - Protocol_Terminate, + ProtocolEmul_Terminate, Protocol_Suspend, Protocol_Resume, - Protocol_Read, + ProtocolEmul_Read, Protocol_Seek, - Protocol_LockRequest, - Protocol_UnlockRequest + ProtocolEmul_LockRequest, + ProtocolEmul_UnlockRequest }; static IInternetProtocol Protocol = { &ProtocolVtbl }; +static HRESULT WINAPI MimeProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv) +{ + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) { + *ppv = iface; + return S_OK; + } + + if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) { + *ppv = &mime_protocol_sink; + return S_OK; + } + + ok(0, "unexpected riid %s\n", debugstr_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; +} + +static HRESULT WINAPI MimeProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, + IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, + DWORD grfPI, HANDLE_PTR dwReserved) +{ + PROTOCOLFILTERDATA *data; + LPOLESTR url_str = NULL; + DWORD fetched = 0; + BINDINFO bindinfo; + DWORD cbindf = 0; + HRESULT hres; + + CHECK_EXPECT(MimeFilter_Start); + + ok(!lstrcmpW(szUrl, gzipW), "wrong url %s\n", debugstr_w(szUrl)); + ok(grfPI == (PI_FILTER_MODE|PI_FORCE_ASYNC), "grfPI=%x, expected PI_FILTER_MODE|PI_FORCE_ASYNC\n", grfPI); + ok(dwReserved, "dwReserved == 0\n"); + ok(pOIProtSink != NULL, "pOIProtSink == NULL\n"); + ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n"); + + if(binding_test) { + ok(pOIProtSink != binding_sink, "pOIProtSink == protocol_sink\n"); + ok(pOIBindInfo == prot_bind_info, "pOIBindInfo != bind_info\n"); + }else { + ok(pOIProtSink == &protocol_sink, "pOIProtSink != protocol_sink\n"); + ok(pOIBindInfo == &bind_info, "pOIBindInfo != bind_info\n"); + } + + data = (void*)dwReserved; + ok(data->cbSize == sizeof(*data), "data->cbSize = %d\n", data->cbSize); + ok(!data->pProtocolSink, "data->pProtocolSink != NULL\n"); + ok(data->pProtocol != NULL, "data->pProtocol == NULL\n"); + ok(!data->pUnk, "data->pUnk != NULL\n"); + ok(!data->dwFilterFlags, "data->dwProtocolFlags = %x\n", data->dwFilterFlags); + if(binding_test) { + IInternetProtocolSink *prot_sink; + + IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocolSink, (void**)&prot_sink); + ok(prot_sink == pOIProtSink, "QI(data->pProtocol, IID_IInternetProtocolSink) != pOIProtSink\n"); + IInternetProtocolSink_Release(prot_sink); + + ok(data->pProtocol != binding_protocol, "data->pProtocol == binding_protocol\n"); + + filtered_protocol = data->pProtocol; + IInternetProtocol_AddRef(filtered_protocol); + }else { + IInternetProtocol *prot; + + IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocol, (void**)&prot); + ok(prot == async_protocol, "QI(data->pProtocol, IID_IInternetProtocol) != async_protocol\n"); + IInternetProtocol_Release(prot); + + ok(data->pProtocol != async_protocol, "data->pProtocol == async_protocol\n"); + } + + filtered_sink = pOIProtSink; + + SET_EXPECT(ReportProgress_DECODING); + hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DECODING, gzipW); + ok(hres == S_OK, "ReportProgress(BINDSTATUS_DECODING) failed: %08x\n", hres); + CHECK_CALLED(ReportProgress_DECODING); + + SET_EXPECT(GetBindInfo); + memset(&bindinfo, 0, sizeof(bindinfo)); + bindinfo.cbSize = sizeof(bindinfo); + hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo); + ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres); + ok(cbindf == bindf, "cbindf = %x\n", cbindf); + CHECK_CALLED(GetBindInfo); + + SET_EXPECT(GetBindString_URL); + hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_URL, &url_str, 1, &fetched); + ok(hres == S_OK, "GetBindString(BINDSTRING_URL) failed: %08x\n", hres); + ok(fetched == 1, "fetched = %d\n", fetched); + ok(!lstrcmpW(url_str, binding_urls[tested_protocol]), "wrong url_str %s\n", debugstr_w(url_str)); + CoTaskMemFree(url_str); + CHECK_CALLED(GetBindString_URL); + + return S_OK; +} + +static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface, + PROTOCOLDATA *pProtocolData) +{ + CHECK_EXPECT(MimeFilter_Continue); + return E_NOTIMPL; +} + +static HRESULT WINAPI MimeProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions) +{ + HRESULT hres; + + CHECK_EXPECT(MimeFilter_Terminate); + + ok(!dwOptions, "dwOptions = %x\n", dwOptions); + + SET_EXPECT(Terminate); + hres = IInternetProtocol_Terminate(filtered_protocol, dwOptions); + ok(hres == S_OK, "Terminate failed: %08x\n", hres); + CHECK_CALLED(Terminate); + + return S_OK; +} + +static HRESULT WINAPI MimeProtocol_Read(IInternetProtocol *iface, void *pv, + ULONG cb, ULONG *pcbRead) +{ + BYTE buf[2096]; + DWORD read = 0; + HRESULT hres; + + CHECK_EXPECT(MimeFilter_Read); + + ok(pv != NULL, "pv == NULL\n"); + ok(cb != 0, "cb == 0\n"); + ok(pcbRead != NULL, "pcbRead == NULL\n"); + + SET_EXPECT(Read); + hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read); + ok(hres == S_OK || hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres); + CHECK_CALLED(Read); + + if(pcbRead) { + ok(*pcbRead == 0, "*pcbRead=%d, expected 0\n", *pcbRead); + *pcbRead = read; + } + + memset(pv, 'x', read); + return hres; +} + +static HRESULT WINAPI MimeProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions) +{ + HRESULT hres; + + CHECK_EXPECT(MimeFilter_LockRequest); + + ok(!dwOptions, "dwOptions = %x\n", dwOptions); + + SET_EXPECT(LockRequest); + hres = IInternetProtocol_LockRequest(filtered_protocol, dwOptions); + ok(hres == S_OK, "LockRequest failed: %08x\n", hres); + CHECK_CALLED(LockRequest); + + return S_OK; +} + +static HRESULT WINAPI MimeProtocol_UnlockRequest(IInternetProtocol *iface) +{ + HRESULT hres; + + CHECK_EXPECT(MimeFilter_UnlockRequest); + + SET_EXPECT(UnlockRequest); + hres = IInternetProtocol_UnlockRequest(filtered_protocol); + ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres); + CHECK_CALLED(UnlockRequest); + + return S_OK; +} + +static const IInternetProtocolVtbl MimeProtocolVtbl = { + MimeProtocol_QueryInterface, + Protocol_AddRef, + Protocol_Release, + MimeProtocol_Start, + Protocol_Continue, + Protocol_Abort, + MimeProtocol_Terminate, + Protocol_Suspend, + Protocol_Resume, + MimeProtocol_Read, + Protocol_Seek, + MimeProtocol_LockRequest, + MimeProtocol_UnlockRequest +}; + +static IInternetProtocol MimeProtocol = { &MimeProtocolVtbl }; + static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) { ok(0, "unexpected call\n"); @@ -1325,14 +1744,44 @@ static const IClassFactoryVtbl ClassFactoryVtbl = { static IClassFactory ClassFactory = { &ClassFactoryVtbl }; -static void init_test(int prot, BOOL is_binding) +static HRESULT WINAPI MimeFilter_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv) +{ + CHECK_EXPECT(MimeFilter_CreateInstance); + + ok(!outer, "outer = %p\n", outer); + ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid %s\n", debugstr_guid(riid)); + + *ppv = &MimeProtocol; + return S_OK; +} + +static const IClassFactoryVtbl MimeFilterCFVtbl = { + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + MimeFilter_CreateInstance, + ClassFactory_LockServer +}; + +static IClassFactory mimefilter_cf = { &MimeFilterCFVtbl }; + +#define TEST_BINDING 1 +#define TEST_FILTER 2 + +static void init_test(int prot, DWORD flags) { tested_protocol = prot; - binding_test = is_binding; + binding_test = (flags & TEST_BINDING) != 0; first_data_notif = TRUE; prot_read = 0; prot_state = 0; async_read_pending = TRUE; + mimefilter_test = (flags & TEST_FILTER) != 0; + filter_state = 0; + ResetEvent(event_complete); + ResetEvent(event_complete2); + async_protocol = binding_protocol = filtered_protocol = NULL; + filtered_sink = NULL; } static void test_priority(IInternetProtocol *protocol) @@ -1588,7 +2037,7 @@ static void test_file_protocol(void) { static const char html_doc[] = ""; trace("Testing file protocol...\n"); - init_test(FILE_TEST, FALSE); + init_test(FILE_TEST, 0); SetLastError(0xdeadbeef); file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, @@ -1897,7 +2346,7 @@ static void test_https_protocol(void) '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0}; trace("Testing https protocol (from urlmon)...\n"); - init_test(HTTPS_TEST, FALSE); + init_test(HTTPS_TEST, 0); bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE; test_http_protocol_url(codeweavers_url, TRUE, TRUE); } @@ -2034,7 +2483,7 @@ static void test_mk_protocol(void) static const WCHAR wrong_url2[] = {'m','k',':','/','t','e','s','t','.','h','t','m','l',0}; trace("Testing mk protocol...\n"); - init_test(MK_TEST, FALSE); + init_test(MK_TEST, 0); hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk); @@ -2093,7 +2542,6 @@ static void test_mk_protocol(void) static void test_CreateBinding(void) { - IInternetProtocolSink *sink; IInternetProtocol *protocol; IInternetPriority *priority; IInternetSession *session; @@ -2107,7 +2555,7 @@ static void test_CreateBinding(void) static const WCHAR wsz_test[] = {'t','e','s','t',0}; trace("Testing CreateBinding...\n"); - init_test(BIND_TEST, TRUE); + init_test(BIND_TEST, TEST_BINDING); hres = CoInternetGetSession(0, &session, 0); ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres); @@ -2123,7 +2571,7 @@ static void test_CreateBinding(void) hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info); ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres); - hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&sink); + hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink); ok(hres == S_OK, "Could not get IInternetProtocolSink: %08x\n", hres); hres = IInternetProtocol_Start(protocol, test_url, NULL, &bind_info, 0, 0); @@ -2194,36 +2642,37 @@ static void test_CreateBinding(void) CHECK_CALLED(Terminate); SET_EXPECT(Continue); - hres = IInternetProtocolSink_Switch(sink, &protocoldata); + hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata); ok(hres == S_OK, "Switch failed: %08x\n", hres); CHECK_CALLED(Continue); - hres = IInternetProtocolSink_ReportProgress(sink, + hres = IInternetProtocolSink_ReportProgress(binding_sink, BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW); ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres); - hres = IInternetProtocolSink_ReportResult(sink, S_OK, ERROR_SUCCESS, NULL); + hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL); ok(hres == E_FAIL, "ReportResult failed: %08x, expected E_FAIL\n", hres); - hres = IInternetProtocolSink_ReportData(sink, 0, 0, 0); + hres = IInternetProtocolSink_ReportData(binding_sink, 0, 0, 0); ok(hres == S_OK, "ReportData failed: %08x\n", hres); - IInternetProtocolSink_Release(sink); + IInternetProtocolSink_Release(binding_sink); IInternetPriority_Release(priority); IInternetBindInfo_Release(prot_bind_info); IInternetProtocol_Release(protocol); IInternetSession_Release(session); } -static void test_binding(int prot, DWORD grf_pi) +static void test_binding(int prot, DWORD grf_pi, BOOL test_filter) { IInternetProtocol *protocol; IInternetSession *session; ULONG ref; HRESULT hres; - trace("Testing %s binding (grfPI %x)...\n", debugstr_w(protocol_names[prot]), grf_pi); - init_test(prot, TRUE); + trace("Testing %s binding (grfPI %x%s)...\n", debugstr_w(protocol_names[prot]), grf_pi, + test_filter ? " testing MIME filter" : ""); + init_test(prot, TEST_BINDING | (test_filter ? TEST_FILTER : 0)); pi = grf_pi; hres = CoInternetGetSession(0, &session, 0); @@ -2264,36 +2713,76 @@ static void test_binding(int prot, DWORD grf_pi) if(prot == HTTP_TEST || prot == HTTPS_TEST) { while(prot_state < 4) { WaitForSingleObject(event_complete, INFINITE); - SET_EXPECT(Continue); - IInternetProtocol_Continue(protocol, pdata); - CHECK_CALLED(Continue); + if(mimefilter_test && filtered_protocol) { + SET_EXPECT(Continue); + IInternetProtocol_Continue(filtered_protocol, pdata); + CHECK_CALLED(Continue); + }else { + SET_EXPECT(Continue); + IInternetProtocol_Continue(protocol, pdata); + CHECK_CALLED(Continue); + } SetEvent(event_complete2); } - WaitForSingleObject(event_complete, INFINITE); }else { - SET_EXPECT(LockRequest); + if(mimefilter_test) + SET_EXPECT(MimeFilter_LockRequest); + else + SET_EXPECT(LockRequest); hres = IInternetProtocol_LockRequest(protocol, 0); ok(hres == S_OK, "LockRequest failed: %08x\n", hres); - CHECK_CALLED(LockRequest); + if(mimefilter_test) + CHECK_CALLED(MimeFilter_LockRequest); + else + CHECK_CALLED(LockRequest); - SET_EXPECT(UnlockRequest); + if(mimefilter_test) + SET_EXPECT(MimeFilter_UnlockRequest); + else + SET_EXPECT(UnlockRequest); hres = IInternetProtocol_UnlockRequest(protocol); ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres); - CHECK_CALLED(UnlockRequest); + if(mimefilter_test) + CHECK_CALLED(MimeFilter_UnlockRequest); + else + CHECK_CALLED(UnlockRequest); } - SET_EXPECT(Terminate); + if(mimefilter_test) + SET_EXPECT(MimeFilter_Terminate); + else + SET_EXPECT(Terminate); hres = IInternetProtocol_Terminate(protocol, 0); ok(hres == S_OK, "Terminate failed: %08x\n", hres); - CHECK_CALLED(Terminate); + if(mimefilter_test) + CHECK_CALLED(MimeFilter_Terminate); + else + CHECK_CALLED(Terminate); + if(filtered_protocol) + IInternetProtocol_Release(filtered_protocol); IInternetBindInfo_Release(prot_bind_info); IInternetProtocolSink_Release(binding_sink); ref = IInternetProtocol_Release(protocol); ok(!ref, "ref=%u, expected 0\n", ref); } +static void register_filter(void) +{ + IInternetSession *session; + HRESULT hres; + + static const WCHAR gzipW[] = {'g','z','i','p',0}; + + CoInternetGetSession(0, &session, 0); + + hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, gzipW); + ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres); + + IInternetSession_Release(session); +} + START_TEST(protocol) { OleInitialize(NULL); @@ -2301,6 +2790,8 @@ START_TEST(protocol) event_complete = CreateEvent(NULL, FALSE, FALSE, NULL); event_complete2 = CreateEvent(NULL, FALSE, FALSE, NULL); + register_filter(); + test_file_protocol(); test_http_protocol(); test_https_protocol(); @@ -2308,10 +2799,12 @@ START_TEST(protocol) test_gopher_protocol(); test_mk_protocol(); test_CreateBinding(); - test_binding(FILE_TEST, 0); - test_binding(HTTP_TEST, 0); - test_binding(FILE_TEST, PI_MIMEVERIFICATION); - test_binding(HTTP_TEST, PI_MIMEVERIFICATION); + test_binding(FILE_TEST, 0, FALSE); + test_binding(HTTP_TEST, 0, FALSE); + test_binding(FILE_TEST, PI_MIMEVERIFICATION, FALSE); + test_binding(HTTP_TEST, PI_MIMEVERIFICATION, FALSE); + test_binding(FILE_TEST, PI_MIMEVERIFICATION, TRUE); + test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TRUE); CloseHandle(event_complete); CloseHandle(event_complete2);