From: Paul Gofman pgofman@codeweavers.com
--- dlls/winhttp/request.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 4a64095797a..9fe8e1c4782 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -3062,9 +3062,11 @@ static DWORD query_data_ready( struct request *request ) return count; }
-static BOOL skip_async_queue( struct request *request, BOOL *wont_block ) +static BOOL skip_async_queue( struct request *request, BOOL *wont_block, DWORD to_read ) { - *wont_block = end_of_read_data( request ) || query_data_ready( request ); + if (!request->read_chunked) + to_read = min( to_read, request->content_length - request->content_read ); + *wont_block = end_of_read_data( request ) || query_data_ready( request ) >= to_read; return request->hdr.recursion_count < 3 && *wont_block; }
@@ -3133,7 +3135,7 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available ) return FALSE; }
- if (!(async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) || skip_async_queue( request, &wont_block )) + if (!(async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) || skip_async_queue( request, &wont_block, 1 )) { ret = query_data_available( request, available, async ); } @@ -3229,7 +3231,7 @@ BOOL WINAPI WinHttpReadData( HINTERNET hrequest, void *buffer, DWORD to_read, DW return FALSE; }
- if (!(async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) || skip_async_queue( request, &wont_block )) + if (!(async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) || skip_async_queue( request, &wont_block, to_read )) { ret = read_data( request, buffer, to_read, read, async ); }
WinHttpReadData() doesn't short read available data, it reads until the full requested size is read or end of data is reached. So currently it may block without queuing async read.
As a side effect, this is supposed to fix one crash scenario in Halo Infinite. When WinHttpReadData fails (due to network timeout) the game crashes in its code after closing request handle in error callback and going back through callback call stack. And doesn't crash if the failing WinHttpReadData was queued async and broke the recursion. With this patch failing case should never happen as WinHttpReadData should be executed synchronously only when it doesn't perform any network read and failure to read may happen only when the read is queued asynchronously and broke the recursion.
This merge request was approved by Hans Leidekker.