From 7483f975de90cf13028c689460145d1a92f18ae5 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 7 Mar 2013 16:29:48 +0100 Subject: [PATCH] urlmon: Fixed handling binding reading immediately from cache. --- dlls/urlmon/http.c | 15 ++++++-- dlls/urlmon/protocol.c | 81 ++++++++++++++++++++++++++------------- dlls/urlmon/urlmon_main.h | 2 + 3 files changed, 67 insertions(+), 31 deletions(-) diff --git a/dlls/urlmon/http.c b/dlls/urlmon/http.c index b2c3d10fff5..d5cef5c4500 100644 --- a/dlls/urlmon/http.c +++ b/dlls/urlmon/http.c @@ -445,11 +445,18 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques do { error = send_http_request(This); - if(error == ERROR_IO_PENDING || error == ERROR_SUCCESS) + switch(error) { + case ERROR_IO_PENDING: return S_OK; - - hres = handle_http_error(This, error); - + case ERROR_SUCCESS: + /* + * If sending response ended synchronously, it means that we have the whole data + * available locally (most likely in cache). + */ + return protocol_syncbinding(&This->base); + default: + hres = handle_http_error(This, error); + } } while(hres == RPC_E_RETRY); WARN("HttpSendRequest failed: %d\n", error); diff --git a/dlls/urlmon/protocol.c b/dlls/urlmon/protocol.c index 890d013312b..559878064bf 100644 --- a/dlls/urlmon/protocol.c +++ b/dlls/urlmon/protocol.c @@ -70,6 +70,55 @@ static void all_data_read(Protocol *protocol) report_result(protocol, S_OK); } +static HRESULT start_downloading(Protocol *protocol) +{ + HRESULT hres; + + hres = protocol->vtbl->start_downloading(protocol); + if(FAILED(hres)) { + protocol_close_connection(protocol); + report_result(protocol, hres); + return S_OK; + } + + if(protocol->bindf & BINDF_NEEDFILE) { + WCHAR cache_file[MAX_PATH]; + DWORD buflen = sizeof(cache_file); + + if(InternetQueryOptionW(protocol->request, INTERNET_OPTION_DATAFILE_NAME, cache_file, &buflen)) { + report_progress(protocol, BINDSTATUS_CACHEFILENAMEAVAILABLE, cache_file); + }else { + FIXME("Could not get cache file\n"); + } + } + + protocol->flags |= FLAG_FIRST_CONTINUE_COMPLETE; + return S_OK; +} + +HRESULT protocol_syncbinding(Protocol *protocol) +{ + BOOL res; + HRESULT hres; + + protocol->flags |= FLAG_SYNC_READ; + + hres = start_downloading(protocol); + if(FAILED(hres)) + return hres; + + res = InternetQueryDataAvailable(protocol->request, &protocol->query_available, 0, 0); + if(res) + protocol->available_bytes = protocol->query_available; + else + WARN("InternetQueryDataAvailable failed: %u\n", GetLastError()); + + protocol->flags |= FLAG_FIRST_DATA_REPORTED|FLAG_LAST_DATA_REPORTED; + IInternetProtocolSink_ReportData(protocol->protocol_sink, BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE, + protocol->available_bytes, protocol->content_length); + return S_OK; +} + static void request_complete(Protocol *protocol, INTERNET_ASYNC_RESULT *ar) { PROTOCOLDATA data; @@ -298,12 +347,7 @@ HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data) BOOL is_start; HRESULT hres; - if (!data) { - WARN("Expected pProtocolData to be non-NULL\n"); - return S_OK; - } - - is_start = data->pData == UlongToPtr(BINDSTATUS_DOWNLOADINGDATA); + is_start = !data || data->pData == UlongToPtr(BINDSTATUS_DOWNLOADINGDATA); if(!protocol->request) { WARN("Expected request to be non-NULL\n"); @@ -325,29 +369,12 @@ HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data) return write_post_stream(protocol); if(is_start) { - hres = protocol->vtbl->start_downloading(protocol); - if(FAILED(hres)) { - protocol_close_connection(protocol); - report_result(protocol, hres); + hres = start_downloading(protocol); + if(FAILED(hres)) return S_OK; - } - - if(protocol->bindf & BINDF_NEEDFILE) { - WCHAR cache_file[MAX_PATH]; - DWORD buflen = sizeof(cache_file); - - if(InternetQueryOptionW(protocol->request, INTERNET_OPTION_DATAFILE_NAME, - cache_file, &buflen)) { - report_progress(protocol, BINDSTATUS_CACHEFILENAMEAVAILABLE, cache_file); - }else { - FIXME("Could not get cache file\n"); - } - } - - protocol->flags |= FLAG_FIRST_CONTINUE_COMPLETE; } - if(data->pData >= UlongToPtr(BINDSTATUS_DOWNLOADINGDATA)) { + if(!data || data->pData >= UlongToPtr(BINDSTATUS_DOWNLOADINGDATA)) { if(!protocol->available_bytes) { if(protocol->query_available) { protocol->available_bytes = protocol->query_available; @@ -400,7 +427,7 @@ HRESULT protocol_read(Protocol *protocol, void *buf, ULONG size, ULONG *read_ret return S_FALSE; } - if(!(protocol->flags & FLAG_REQUEST_COMPLETE) || !protocol->available_bytes) { + if(!(protocol->flags & FLAG_SYNC_READ) && (!(protocol->flags & FLAG_REQUEST_COMPLETE) || !protocol->available_bytes)) { *read_ret = 0; return E_PENDING; } diff --git a/dlls/urlmon/urlmon_main.h b/dlls/urlmon/urlmon_main.h index ba23e74a8fe..faab45a7acf 100644 --- a/dlls/urlmon/urlmon_main.h +++ b/dlls/urlmon/urlmon_main.h @@ -149,6 +149,7 @@ struct ProtocolVtbl { #define FLAG_LAST_DATA_REPORTED 0x0010 #define FLAG_RESULT_REPORTED 0x0020 #define FLAG_ERROR 0x0040 +#define FLAG_SYNC_READ 0x0080 HRESULT protocol_start(Protocol*,IInternetProtocol*,IUri*,IInternetProtocolSink*,IInternetBindInfo*) DECLSPEC_HIDDEN; HRESULT protocol_continue(Protocol*,PROTOCOLDATA*) DECLSPEC_HIDDEN; @@ -156,6 +157,7 @@ HRESULT protocol_read(Protocol*,void*,ULONG,ULONG*) DECLSPEC_HIDDEN; HRESULT protocol_lock_request(Protocol*) DECLSPEC_HIDDEN; HRESULT protocol_unlock_request(Protocol*) DECLSPEC_HIDDEN; HRESULT protocol_abort(Protocol*,HRESULT) DECLSPEC_HIDDEN; +HRESULT protocol_syncbinding(Protocol*) DECLSPEC_HIDDEN; void protocol_close_connection(Protocol*) DECLSPEC_HIDDEN; void find_domain_name(const WCHAR*,DWORD,INT*) DECLSPEC_HIDDEN;