From 04f0426fe6b0e4e8a3cb7da30ec317d5a1ecf65d Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Mon, 14 Oct 2013 14:36:05 -0500 Subject: [PATCH] winhttp: Attempt to refill empty buffer before answering QueryDataAvailable. --- dlls/winhttp/request.c | 6 ++++ dlls/winhttp/tests/winhttp.c | 59 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 8c5a39af5d6..930eb281d40 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -2391,6 +2391,12 @@ static BOOL query_data_available( request_t *request, DWORD *available, BOOL asy { DWORD count = get_available_data( request ); + if (!count) + { + refill_buffer( request, async ); + count = get_available_data( request ); + } + if (async) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &count, sizeof(count) ); TRACE("%u bytes available\n", count); if (available) *available = count; diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index ab8b94c7415..e073e6a7ec3 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -1800,6 +1800,8 @@ struct server_info int port; }; +#define BIG_BUFFER_LEN 0x2250 + static DWORD CALLBACK server_thread(LPVOID param) { struct server_info *si = param; @@ -1857,6 +1859,13 @@ static DWORD CALLBACK server_thread(LPVOID param) else send(c, noauthmsg, sizeof noauthmsg - 1, 0); } + if (strstr(buffer, "/big")) + { + char msg[BIG_BUFFER_LEN]; + memset(msg, 'm', sizeof(msg)); + send(c, okmsg, sizeof(okmsg) - 1, 0); + send(c, msg, sizeof(msg), 0); + } if (strstr(buffer, "/no_headers")) { send(c, page1, sizeof page1 - 1, 0); @@ -2129,6 +2138,55 @@ static void test_bad_header( int port ) WinHttpCloseHandle( ses ); } +static void test_multiple_reads(int port) +{ + static const WCHAR bigW[] = {'b','i','g',0}; + HINTERNET ses, con, req; + DWORD total_len = 0; + BOOL ret; + + ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0); + ok(ses != NULL, "failed to open session %u\n", GetLastError()); + + con = WinHttpConnect(ses, localhostW, port, 0); + ok(con != NULL, "failed to open a connection %u\n", GetLastError()); + + req = WinHttpOpenRequest(con, NULL, bigW, NULL, NULL, NULL, 0); + ok(req != NULL, "failed to open a request %u\n", GetLastError()); + + ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0); + ok(ret, "failed to send request %u\n", GetLastError()); + + ret = WinHttpReceiveResponse(req, NULL); + ok(ret == TRUE, "expected success\n"); + + for (;;) + { + DWORD len = 0xdeadbeef; + ret = WinHttpQueryDataAvailable( req, &len ); + ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() ); + if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" ); + if (len) + { + DWORD bytes_read; + char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 ); + + ret = WinHttpReadData( req, buf, len, &bytes_read ); + ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len ); + + HeapFree( GetProcessHeap(), 0, buf ); + if (!bytes_read) break; + total_len += bytes_read; + } + if (!len) break; + } + ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len); + + WinHttpCloseHandle(req); + WinHttpCloseHandle(con); + WinHttpCloseHandle(ses); +} + static void test_connection_info( int port ) { static const WCHAR basicW[] = {'/','b','a','s','i','c',0}; @@ -3038,6 +3096,7 @@ START_TEST (winhttp) test_no_headers(si.port); test_basic_authentication(si.port); test_bad_header(si.port); + test_multiple_reads(si.port); /* send the basic request again to shutdown the server thread */ test_basic_request(si.port, NULL, quitW);