Jacek Caban : urlmon: Fixed handling binding reading immediately from cache .

Alexandre Julliard julliard at winehq.org
Thu Mar 7 13:57:14 CST 2013


Module: wine
Branch: master
Commit: 7483f975de90cf13028c689460145d1a92f18ae5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7483f975de90cf13028c689460145d1a92f18ae5

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Mar  7 16:29:48 2013 +0100

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 b2c3d10..d5cef5c 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 890d013..5598780 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 ba23e74..faab45a 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;




More information about the wine-cvs mailing list