Module: wine Branch: master Commit: b6a7cc91123f1c78e02472e8839c4727d27b67bd URL: http://source.winehq.org/git/wine.git/?a=commit;h=b6a7cc91123f1c78e02472e883...
Author: Jacek Caban jacek@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;