From 5fac827fd7b177a23639e986efae0e96f44aa2b7 Mon Sep 17 00:00:00 2001 From: Thomas Mullaly Date: Sun, 1 May 2011 00:30:17 -0400 Subject: [PATCH] urlmon: Honor E_ABORT for URLDownloadToFile status callbacks. --- dlls/urlmon/download.c | 28 ++++++++- dlls/urlmon/tests/url.c | 128 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 147 insertions(+), 9 deletions(-) diff --git a/dlls/urlmon/download.c b/dlls/urlmon/download.c index 9759e71d18e..c20c87c5a1a 100644 --- a/dlls/urlmon/download.c +++ b/dlls/urlmon/download.c @@ -28,6 +28,7 @@ typedef struct { LONG ref; IBindStatusCallback *callback; + IBinding *binding; LPWSTR file_name; LPWSTR cache_file; } DownloadBSC; @@ -89,6 +90,8 @@ static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface) if(!ref) { if(This->callback) IBindStatusCallback_Release(This->callback); + if(This->binding) + IBinding_Release(This->binding); heap_free(This->file_name); heap_free(This->cache_file); heap_free(This); @@ -101,13 +104,19 @@ static HRESULT WINAPI DownloadBSC_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved, IBinding *pbind) { DownloadBSC *This = impl_from_IBindStatusCallback(iface); + HRESULT hres = S_OK; TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind); - if(This->callback) - IBindStatusCallback_OnStartBinding(This->callback, dwReserved, pbind); + if(This->callback) { + hres = IBindStatusCallback_OnStartBinding(This->callback, dwReserved, pbind); - return S_OK; + IBinding_AddRef(pbind); + This->binding = pbind; + } + + /* Windows seems to ignore E_NOTIMPL if it's returned from the client. */ + return hres == E_NOTIMPL ? S_OK : hres; } static HRESULT WINAPI DownloadBSC_GetPriority(IBindStatusCallback *iface, LONG *pnPriority) @@ -132,6 +141,13 @@ static HRESULT on_progress(DownloadBSC *This, ULONG progress, ULONG progress_max return S_OK; hres = IBindStatusCallback_OnProgress(This->callback, progress, progress_max, status_code, status_text); + if(hres == E_ABORT) { + if(This->binding) + IBinding_Abort(This->binding); + else + FIXME("No binding, not sure what to do!\n"); + } + return hres; } @@ -191,6 +207,11 @@ static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface, if(This->callback) IBindStatusCallback_OnStopBinding(This->callback, hresult, szError); + if(This->binding) { + IBinding_Release(This->binding); + This->binding = NULL; + } + return S_OK; } @@ -311,6 +332,7 @@ static HRESULT DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR file_na ret->ref = 1; ret->file_name = heap_strdupW(file_name); ret->cache_file = NULL; + ret->binding = NULL; if(callback) IBindStatusCallback_AddRef(callback); diff --git a/dlls/urlmon/tests/url.c b/dlls/urlmon/tests/url.c index 0b573126440..eb4d31625a5 100644 --- a/dlls/urlmon/tests/url.c +++ b/dlls/urlmon/tests/url.c @@ -1631,8 +1631,11 @@ static HRESULT WINAPI statusclb_OnProgress(IBindStatusCallbackEx *iface, ULONG u if(emulate_protocol && (test_protocol == HTTP_TEST || test_protocol == HTTPS_TEST || test_protocol == WINETEST_TEST)) SetEvent(complete_event); - if(abort_progress) + if(abort_progress) { + if(filedwl_api) + binding_hres = E_ABORT; return E_ABORT; + } break; case BINDSTATUS_MIMETYPEAVAILABLE: @@ -1789,11 +1792,14 @@ static HRESULT WINAPI statusclb_OnStopBinding(IBindStatusCallbackEx *iface, HRES if (hresult == HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED)) return S_OK; - if(filedwl_api) - ok(SUCCEEDED(hresult), "binding failed: %08x\n", hresult); - else if(invalid_cn_accepted) - ok(hresult == binding_hres, "binding failed: %08x, expected %08x\n", hresult, binding_hres); - else + if(filedwl_api) { + if(!abort_progress && !abort_start) + ok(SUCCEEDED(hresult), "binding failed: %08x\n", hresult); + else if(abort_start && abort_hres == E_NOTIMPL) + todo_wine ok(hresult == S_FALSE, "binding failed: %08x, expected S_FALSE\n", hresult); + else + ok(hresult == E_ABORT, "binding failed: %08x, expected E_ABORT\n", hresult); + } else ok(hresult == binding_hres, "binding failed: %08x, expected %08x\n", hresult, binding_hres); ok(szError == NULL, "szError should be NULL\n"); @@ -3328,6 +3334,113 @@ static void test_URLDownloadToFile(DWORD prot, BOOL emul) ok(res, "DeleteFile failed: %u\n", GetLastError()); } +static void test_URLDownloadToFile_abort(void) +{ + HRESULT hres; + + init_bind_test(HTTP_TEST, BINDTEST_FILEDWLAPI|BINDTEST_ABORT_PROGRESS, TYMED_FILE); + + SET_EXPECT(GetBindInfo); + SET_EXPECT(QueryInterface_IInternetProtocol); + SET_EXPECT(QueryInterface_IServiceProvider); + SET_EXPECT(QueryService_IInternetProtocol); + SET_EXPECT(OnStartBinding); + SET_EXPECT(QueryInterface_IHttpNegotiate); + SET_EXPECT(QueryInterface_IHttpNegotiate2); + SET_EXPECT(BeginningTransaction); + SET_EXPECT(GetRootSecurityId); + SET_EXPECT(QueryInterface_IWindowForBindingUI); + SET_EXPECT(OnProgress_CONNECTING); + SET_EXPECT(OnProgress_SENDINGREQUEST); + SET_EXPECT(OnStopBinding); + + hres = URLDownloadToFileW(NULL, urls[HTTP_TEST], dwl_htmlW, 0, (IBindStatusCallback*)&bsc); + ok(hres == E_ABORT, "URLDownloadToFile failed: %08x, expected E_ABORT\n", hres); + + CHECK_CALLED(GetBindInfo); + CHECK_CALLED(QueryInterface_IInternetProtocol); + CHECK_CALLED(QueryInterface_IServiceProvider); + CHECK_CALLED(QueryService_IInternetProtocol); + CHECK_CALLED(OnStartBinding); + CHECK_CALLED(QueryInterface_IHttpNegotiate); + CHECK_CALLED(QueryInterface_IHttpNegotiate2); + CHECK_CALLED(BeginningTransaction); + CHECK_CALLED(GetRootSecurityId); + CLEAR_CALLED(QueryInterface_IWindowForBindingUI); + CHECK_CALLED(OnProgress_SENDINGREQUEST); + CLEAR_CALLED(OnProgress_CONNECTING); + CHECK_CALLED(OnStopBinding); + + init_bind_test(HTTP_TEST, BINDTEST_FILEDWLAPI|BINDTEST_ABORT_START, TYMED_FILE); + + SET_EXPECT(GetBindInfo); + SET_EXPECT(QueryInterface_IInternetProtocol); + SET_EXPECT(QueryInterface_IServiceProvider); + SET_EXPECT(QueryService_IInternetProtocol); + SET_EXPECT(OnStartBinding); + SET_EXPECT(OnStopBinding); + + abort_hres = E_ABORT; + hres = URLDownloadToFileW(NULL, urls[HTTP_TEST], dwl_htmlW, 0, (IBindStatusCallback*)&bsc); + ok(hres == E_ABORT, "URLDownloadToFile failed: %08x, expected E_ABORT\n", hres); + + CHECK_CALLED(GetBindInfo); + todo_wine CHECK_CALLED(QueryInterface_IInternetProtocol); + todo_wine CHECK_CALLED(QueryInterface_IServiceProvider); + todo_wine CHECK_CALLED(QueryService_IInternetProtocol); + CHECK_CALLED(OnStartBinding); + CHECK_CALLED(OnStopBinding); + + init_bind_test(HTTP_TEST, BINDTEST_FILEDWLAPI|BINDTEST_ABORT_START, TYMED_FILE); + + SET_EXPECT(GetBindInfo); + SET_EXPECT(QueryInterface_IInternetProtocol); + SET_EXPECT(QueryInterface_IServiceProvider); + SET_EXPECT(QueryService_IInternetProtocol); + SET_EXPECT(OnStartBinding); + SET_EXPECT(QueryInterface_IHttpNegotiate); + SET_EXPECT(QueryInterface_IHttpNegotiate2); + SET_EXPECT(BeginningTransaction); + SET_EXPECT(GetRootSecurityId); + SET_EXPECT(QueryInterface_IWindowForBindingUI); + SET_EXPECT(OnResponse); + SET_EXPECT(OnProgress_CONNECTING); + SET_EXPECT(OnProgress_SENDINGREQUEST); + SET_EXPECT(OnProgress_MIMETYPEAVAILABLE); + SET_EXPECT(OnProgress_BEGINDOWNLOADDATA); + SET_EXPECT(OnProgress_DOWNLOADINGDATA); + SET_EXPECT(OnProgress_ENDDOWNLOADDATA); + SET_EXPECT(OnStopBinding); + + /* URLDownloadToFile doesn't abort if E_NOTIMPL is returned from the + * IBindStatusCallback's OnStartBinding function. + */ + abort_hres = E_NOTIMPL; + hres = URLDownloadToFileW(NULL, urls[HTTP_TEST], dwl_htmlW, 0, (IBindStatusCallback*)&bsc); + ok(hres == S_OK, "URLDownloadToFile failed: %08x\n", hres); + + CHECK_CALLED(GetBindInfo); + CHECK_CALLED(QueryInterface_IInternetProtocol); + CHECK_CALLED(QueryInterface_IServiceProvider); + CHECK_CALLED(QueryService_IInternetProtocol); + CHECK_CALLED(OnStartBinding); + CHECK_CALLED(QueryInterface_IHttpNegotiate); + CHECK_CALLED(QueryInterface_IHttpNegotiate2); + CHECK_CALLED(BeginningTransaction); + CHECK_CALLED(GetRootSecurityId); + CLEAR_CALLED(QueryInterface_IWindowForBindingUI); + CHECK_CALLED(OnResponse); + CLEAR_CALLED(OnProgress_CONNECTING); + CHECK_CALLED(OnProgress_SENDINGREQUEST); + CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE); + CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA); + CHECK_CALLED(OnProgress_DOWNLOADINGDATA); + CHECK_CALLED(OnProgress_ENDDOWNLOADDATA); + CHECK_CALLED(OnStopBinding); + + DeleteFileA(dwl_htmlA); +} + static void set_file_url(char *path) { CHAR file_urlA[INTERNET_MAX_URL_LENGTH]; @@ -3728,6 +3841,9 @@ START_TEST(url) trace("test URLDownloadToFile for http protocol...\n"); test_URLDownloadToFile(HTTP_TEST, FALSE); + trace("test URLDownloadToFile abort...\n"); + test_URLDownloadToFile_abort(); + trace("test emulated http abort...\n"); test_BindToStorage(HTTP_TEST, BINDTEST_EMULATE|BINDTEST_ABORT, TYMED_ISTREAM);