[PATCH] winhttp: Attempt to refill empty buffer before answering QueryDataAvailable

Andrew Eikum aeikum at codeweavers.com
Mon Oct 14 14:36:05 CDT 2013


---
 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 8c5a39a..930eb28 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 ab8b94c..e073e6a 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);
-- 
1.8.4




More information about the wine-patches mailing list