Jacek Caban : urlmon: Use separated variable for InternetQueryDataAvailable to avoid races.

Alexandre Julliard julliard at winehq.org
Fri Feb 22 14:14:00 CST 2013


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Feb 22 14:13:19 2013 +0100

urlmon: Use separated variable for InternetQueryDataAvailable to avoid races.

---

 dlls/urlmon/protocol.c    |   55 ++++++++++++++++++++++++++------------------
 dlls/urlmon/urlmon_main.h |    1 +
 2 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/dlls/urlmon/protocol.c b/dlls/urlmon/protocol.c
index c7c61da..890d013 100644
--- a/dlls/urlmon/protocol.c
+++ b/dlls/urlmon/protocol.c
@@ -349,30 +349,35 @@ HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data)
 
     if(data->pData >= UlongToPtr(BINDSTATUS_DOWNLOADINGDATA)) {
         if(!protocol->available_bytes) {
-            BOOL res;
-
-            /* InternetQueryDataAvailable may immediately fork and perform its asynchronous
-             * read, so clear the flag _before_ calling so it does not incorrectly get cleared
-             * after the status callback is called */
-            protocol->flags &= ~FLAG_REQUEST_COMPLETE;
-            res = InternetQueryDataAvailable(protocol->request, &protocol->available_bytes, 0, 0);
-            if(res) {
-                TRACE("available %u bytes\n", protocol->available_bytes);
-                if(!protocol->available_bytes) {
-                    if(is_start) {
-                        TRACE("empty file\n");
-                        all_data_read(protocol);
-                    }else {
-                        WARN("unexpected end of file?\n");
-                        report_result(protocol, INET_E_DOWNLOAD_FAILURE);
+            if(protocol->query_available) {
+                protocol->available_bytes = protocol->query_available;
+            }else {
+                BOOL res;
+
+                /* InternetQueryDataAvailable may immediately fork and perform its asynchronous
+                 * read, so clear the flag _before_ calling so it does not incorrectly get cleared
+                 * after the status callback is called */
+                protocol->flags &= ~FLAG_REQUEST_COMPLETE;
+                res = InternetQueryDataAvailable(protocol->request, &protocol->query_available, 0, 0);
+                if(res) {
+                    TRACE("available %u bytes\n", protocol->query_available);
+                    if(!protocol->query_available) {
+                        if(is_start) {
+                            TRACE("empty file\n");
+                            all_data_read(protocol);
+                        }else {
+                            WARN("unexpected end of file?\n");
+                            report_result(protocol, INET_E_DOWNLOAD_FAILURE);
+                        }
+                        return S_OK;
                     }
+                    protocol->available_bytes = protocol->query_available;
+                }else if(GetLastError() != ERROR_IO_PENDING) {
+                    protocol->flags |= FLAG_REQUEST_COMPLETE;
+                    WARN("InternetQueryDataAvailable failed: %d\n", GetLastError());
+                    report_result(protocol, INET_E_DATA_NOT_AVAILABLE);
                     return S_OK;
                 }
-            }else if(GetLastError() != ERROR_IO_PENDING) {
-                protocol->flags |= FLAG_REQUEST_COMPLETE;
-                WARN("InternetQueryDataAvailable failed: %d\n", GetLastError());
-                report_result(protocol, INET_E_DATA_NOT_AVAILABLE);
-                return S_OK;
             }
 
             protocol->flags |= FLAG_REQUEST_COMPLETE;
@@ -421,12 +426,14 @@ HRESULT protocol_read(Protocol *protocol, void *buf, ULONG size, ULONG *read_ret
         protocol->current_position += len;
         protocol->available_bytes -= len;
 
+        TRACE("current_position %d, available_bytes %d\n", protocol->current_position, protocol->available_bytes);
+
         if(!protocol->available_bytes) {
             /* InternetQueryDataAvailable may immediately fork and perform its asynchronous
              * read, so clear the flag _before_ calling so it does not incorrectly get cleared
              * after the status callback is called */
             protocol->flags &= ~FLAG_REQUEST_COMPLETE;
-            res = InternetQueryDataAvailable(protocol->request, &protocol->available_bytes, 0, 0);
+            res = InternetQueryDataAvailable(protocol->request, &protocol->query_available, 0, 0);
             if(!res) {
                 if (GetLastError() == ERROR_IO_PENDING) {
                     hres = E_PENDING;
@@ -438,10 +445,12 @@ HRESULT protocol_read(Protocol *protocol, void *buf, ULONG size, ULONG *read_ret
                 break;
             }
 
-            if(!protocol->available_bytes) {
+            if(!protocol->query_available) {
                 all_data_read(protocol);
                 break;
             }
+
+            protocol->available_bytes = protocol->query_available;
         }
     }
 
diff --git a/dlls/urlmon/urlmon_main.h b/dlls/urlmon/urlmon_main.h
index 01de984..ba23e74 100644
--- a/dlls/urlmon/urlmon_main.h
+++ b/dlls/urlmon/urlmon_main.h
@@ -104,6 +104,7 @@ typedef struct {
     ULONG current_position;
     ULONG content_length;
     ULONG available_bytes;
+    ULONG query_available;
 
     IStream *post_stream;
 




More information about the wine-cvs mailing list