[PATCH] winhttp: Implement WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT.

Hans Leidekker hans at codeweavers.com
Mon Sep 10 06:24:34 CDT 2018


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/winhttp/request.c         |   6 +-
 dlls/winhttp/session.c         | 138 ++++++++++++++++++++++++++++-------------
 dlls/winhttp/tests/winhttp.c   |  68 +++++++++++++++++++-
 dlls/winhttp/winhttp_private.h |   6 +-
 4 files changed, 169 insertions(+), 49 deletions(-)

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 3e6d2af396..80694da02e 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -1741,7 +1741,7 @@ static BOOL open_connection( request_t *request )
             return FALSE;
         }
         netconn_set_timeout( netconn, TRUE, request->send_timeout );
-        netconn_set_timeout( netconn, FALSE, request->recv_timeout );
+        netconn_set_timeout( netconn, FALSE, request->receive_response_timeout );
         if (is_secure)
         {
             if (connect->session->proxy_server &&
@@ -1776,7 +1776,7 @@ static BOOL open_connection( request_t *request )
         TRACE("using connection %p\n", netconn);
 
         netconn_set_timeout( netconn, TRUE, request->send_timeout );
-        netconn_set_timeout( netconn, FALSE, request->recv_timeout );
+        netconn_set_timeout( netconn, FALSE, request->receive_response_timeout );
         request->netconn = netconn;
     }
 
@@ -2628,6 +2628,7 @@ static BOOL receive_response( request_t *request, BOOL async )
     BOOL ret;
     DWORD size, query, status;
 
+    netconn_set_timeout( request->netconn, FALSE, request->receive_response_timeout );
     for (;;)
     {
         if (!(ret = read_reply( request )))
@@ -2665,6 +2666,7 @@ static BOOL receive_response( request_t *request, BOOL async )
         break;
     }
 
+    netconn_set_timeout( request->netconn, FALSE, request->receive_timeout );
     if (request->content_length) refill_buffer( request, FALSE );
 
     if (async)
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c
index b697d4febf..959cafa209 100644
--- a/dlls/winhttp/session.c
+++ b/dlls/winhttp/session.c
@@ -46,10 +46,11 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
 
-#define DEFAULT_RESOLVE_TIMEOUT     0
-#define DEFAULT_CONNECT_TIMEOUT     20000
-#define DEFAULT_SEND_TIMEOUT        30000
-#define DEFAULT_RECEIVE_TIMEOUT     30000
+#define DEFAULT_RESOLVE_TIMEOUT             0
+#define DEFAULT_CONNECT_TIMEOUT             20000
+#define DEFAULT_SEND_TIMEOUT                30000
+#define DEFAULT_RECEIVE_TIMEOUT             30000
+#define DEFAULT_RECEIVE_RESPONSE_TIMEOUT    ~0u
 
 void set_last_error( DWORD error )
 {
@@ -132,18 +133,27 @@ static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         *(DWORD *)buffer = session->resolve_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_CONNECT_TIMEOUT:
         *(DWORD *)buffer = session->connect_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_SEND_TIMEOUT:
         *(DWORD *)buffer = session->send_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_RECEIVE_TIMEOUT:
-        *(DWORD *)buffer = session->recv_timeout;
+        *(DWORD *)buffer = session->receive_timeout;
+        *buflen = sizeof(DWORD);
+        return TRUE;
+
+    case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+        *(DWORD *)buffer = session->receive_response_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     default:
         FIXME("unimplemented option %u\n", option);
         set_last_error( ERROR_INVALID_PARAMETER );
@@ -193,31 +203,44 @@ static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
     case WINHTTP_OPTION_DISABLE_FEATURE:
         set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
         return FALSE;
+
     case WINHTTP_OPTION_RESOLVE_TIMEOUT:
         session->resolve_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_CONNECT_TIMEOUT:
         session->connect_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_SEND_TIMEOUT:
         session->send_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_RECEIVE_TIMEOUT:
-        session->recv_timeout = *(DWORD *)buffer;
+        session->receive_timeout = *(DWORD *)buffer;
         return TRUE;
+
+    case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+        session->receive_response_timeout = *(DWORD *)buffer;
+        return TRUE;
+
     case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH:
         FIXME("WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: 0x%x\n", *(DWORD *)buffer);
         return TRUE;
+
     case WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT:
         TRACE("WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: %p\n", *(HANDLE *)buffer);
         session->unload_event = *(HANDLE *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_MAX_CONNS_PER_SERVER:
         FIXME("WINHTTP_OPTION_MAX_CONNS_PER_SERVER: %d\n", *(DWORD *)buffer);
         return TRUE;
+
     case WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER:
         FIXME("WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER: %d\n", *(DWORD *)buffer);
         return TRUE;
+
     default:
         FIXME("unimplemented option %u\n", option);
         set_last_error( ERROR_WINHTTP_INVALID_OPTION );
@@ -253,7 +276,8 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWST
     session->resolve_timeout = DEFAULT_RESOLVE_TIMEOUT;
     session->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
     session->send_timeout = DEFAULT_SEND_TIMEOUT;
-    session->recv_timeout = DEFAULT_RECEIVE_TIMEOUT;
+    session->receive_timeout = DEFAULT_RECEIVE_TIMEOUT;
+    session->receive_response_timeout = DEFAULT_RECEIVE_RESPONSE_TIMEOUT;
     list_init( &session->cookie_cache );
 
     if (agent && !(session->agent = strdupW( agent ))) goto end;
@@ -334,18 +358,27 @@ static BOOL connect_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         *(DWORD *)buffer = connect->session->resolve_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_CONNECT_TIMEOUT:
         *(DWORD *)buffer = connect->session->connect_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_SEND_TIMEOUT:
         *(DWORD *)buffer = connect->session->send_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_RECEIVE_TIMEOUT:
-        *(DWORD *)buffer = connect->session->recv_timeout;
+        *(DWORD *)buffer = connect->session->receive_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
+    case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+        *(DWORD *)buffer = connect->session->receive_response_timeout;
+        *buflen = sizeof(DWORD);
+        return TRUE;
+
     default:
         FIXME("unimplemented option %u\n", option);
         set_last_error( ERROR_INVALID_PARAMETER );
@@ -795,16 +828,24 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
         *(DWORD *)buffer = request->resolve_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_CONNECT_TIMEOUT:
         *(DWORD *)buffer = request->connect_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_SEND_TIMEOUT:
         *(DWORD *)buffer = request->send_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
+
     case WINHTTP_OPTION_RECEIVE_TIMEOUT:
-        *(DWORD *)buffer = request->recv_timeout;
+        *(DWORD *)buffer = request->receive_timeout;
+        *buflen = sizeof(DWORD);
+        return TRUE;
+
+    case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+        *(DWORD *)buffer = request->receive_response_timeout;
         *buflen = sizeof(DWORD);
         return TRUE;
 
@@ -927,14 +968,21 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
     case WINHTTP_OPTION_RESOLVE_TIMEOUT:
         request->resolve_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_CONNECT_TIMEOUT:
         request->connect_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_SEND_TIMEOUT:
         request->send_timeout = *(DWORD *)buffer;
         return TRUE;
+
     case WINHTTP_OPTION_RECEIVE_TIMEOUT:
-        request->recv_timeout = *(DWORD *)buffer;
+        request->receive_timeout = *(DWORD *)buffer;
+        return TRUE;
+
+    case WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT:
+        request->receive_response_timeout = *(DWORD *)buffer;
         return TRUE;
 
     case WINHTTP_OPTION_USERNAME:
@@ -977,6 +1025,7 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
         }
         FIXME("WINHTTP_OPTION_CLIENT_CERT_CONTEXT\n");
         return TRUE;
+
     case WINHTTP_OPTION_ENABLE_FEATURE:
         if(buflen == sizeof( DWORD ) && *(DWORD *)buffer == WINHTTP_ENABLE_SSL_REVOCATION)
         {
@@ -989,9 +1038,11 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
             SetLastError( ERROR_INVALID_PARAMETER );
             return FALSE;
         }
+
     case WINHTTP_OPTION_CONNECT_RETRIES:
         FIXME("WINHTTP_OPTION_CONNECT_RETRIES\n");
         return TRUE;
+
     default:
         FIXME("unimplemented option %u\n", option);
         set_last_error( ERROR_WINHTTP_INVALID_OPTION );
@@ -1094,7 +1145,8 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR o
     request->resolve_timeout = connect->session->resolve_timeout;
     request->connect_timeout = connect->session->connect_timeout;
     request->send_timeout = connect->session->send_timeout;
-    request->recv_timeout = connect->session->recv_timeout;
+    request->receive_timeout = connect->session->receive_timeout;
+    request->receive_response_timeout = connect->session->receive_response_timeout;
 
     if (!verb || !verb[0]) verb = getW;
     if (!(request->verb = strdupW( verb ))) goto end;
@@ -2024,8 +2076,6 @@ BOOL WINAPI WinHttpSetTimeouts( HINTERNET handle, int resolve, int connect, int
 {
     BOOL ret = TRUE;
     object_header_t *hdr;
-    request_t *request;
-    session_t *session;
 
     TRACE("%p, %d, %d, %d, %d\n", handle, resolve, connect, send, receive);
 
@@ -2043,43 +2093,45 @@ BOOL WINAPI WinHttpSetTimeouts( HINTERNET handle, int resolve, int connect, int
 
     switch(hdr->type)
     {
-        case WINHTTP_HANDLE_TYPE_REQUEST:
-            request = (request_t *)hdr;
-            request->connect_timeout = connect;
-
-            if (resolve < 0) resolve = 0;
-            request->resolve_timeout = resolve;
-
-            if (send < 0) send = 0;
-            request->send_timeout = send;
+    case WINHTTP_HANDLE_TYPE_REQUEST:
+    {
+        request_t *request = (request_t *)hdr;
+        request->connect_timeout = connect;
 
-            if (receive < 0) receive = 0;
-            request->recv_timeout = receive;
+        if (resolve < 0) resolve = 0;
+        request->resolve_timeout = resolve;
 
-            if (request->netconn)
-            {
-                if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE;
-                if (netconn_set_timeout( request->netconn, FALSE, receive )) ret = FALSE;
-            }
-            break;
+        if (send < 0) send = 0;
+        request->send_timeout = send;
 
-        case WINHTTP_HANDLE_TYPE_SESSION:
-            session = (session_t *)hdr;
-            session->connect_timeout = connect;
+        if (receive < 0) receive = 0;
+        request->receive_timeout = receive;
 
-            if (resolve < 0) resolve = 0;
-            session->resolve_timeout = resolve;
+        if (request->netconn)
+        {
+            if (netconn_set_timeout( request->netconn, TRUE, send )) ret = FALSE;
+            if (netconn_set_timeout( request->netconn, FALSE, receive )) ret = FALSE;
+        }
+        break;
+    }
+    case WINHTTP_HANDLE_TYPE_SESSION:
+    {
+        session_t *session = (session_t *)hdr;
+        session->connect_timeout = connect;
 
-            if (send < 0) send = 0;
-            session->send_timeout = send;
+        if (resolve < 0) resolve = 0;
+        session->resolve_timeout = resolve;
 
-            if (receive < 0) receive = 0;
-            session->recv_timeout = receive;
-            break;
+        if (send < 0) send = 0;
+        session->send_timeout = send;
 
-        default:
-            set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
-            ret = FALSE;
+        if (receive < 0) receive = 0;
+        session->receive_timeout = receive;
+        break;
+    }
+    default:
+        set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
+        ret = FALSE;
     }
     release_object( hdr );
     if (ret) set_last_error( ERROR_SUCCESS );
diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c
index a3c8507fea..1c72c07574 100644
--- a/dlls/winhttp/tests/winhttp.c
+++ b/dlls/winhttp/tests/winhttp.c
@@ -1383,7 +1383,7 @@ static void test_set_default_proxy_config(void)
     set_default_proxy_reg_value( saved_proxy_settings, len, type );
 }
 
-static void test_Timeouts (void)
+static void test_timeouts(void)
 {
     BOOL ret;
     DWORD value, size;
@@ -1972,6 +1972,70 @@ static void test_Timeouts (void)
     ok(ret, "%u\n", GetLastError());
     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
 
+    /* response timeout */
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    ok(value == ~0u, "got %u\n", value);
+
+    SetLastError(0xdeadbeef);
+    value = 30000;
+    ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
+    ok(ret, "%u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    todo_wine ok(value == 0xbeefdead, "got %u\n", value);
+
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    ok(value == ~0u, "got %u\n", value);
+
+    SetLastError(0xdeadbeef);
+    value = 30000;
+    ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
+    ok(!ret, "expected failure\n");
+    ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    ok(value == ~0u, "got %u\n", value);
+
+    SetLastError(0xdeadbeef);
+    value = 48878;
+    ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
+    ok(ret, "%u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    todo_wine ok(value == 48879, "got %u\n", value);
+
+    SetLastError(0xdeadbeef);
+    value = 48880;
+    ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, sizeof(value));
+    ok(ret, "%u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    value = 0xdeadbeef;
+    size  = sizeof(value);
+    ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT, &value, &size);
+    ok(ret, "%u\n", GetLastError());
+    ok(value == 48880, "got %u\n", value);
+
     WinHttpCloseHandle(req);
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
@@ -4563,7 +4627,7 @@ START_TEST (winhttp)
     test_QueryOption();
     test_set_default_proxy_config();
     test_empty_headers_param();
-    test_Timeouts();
+    test_timeouts();
     test_resolve_timeout();
     test_credentials();
     test_IWinHttpRequest_Invoke();
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index 838561fe66..6b4e3b0405 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -98,7 +98,8 @@ typedef struct
     int resolve_timeout;
     int connect_timeout;
     int send_timeout;
-    int recv_timeout;
+    int receive_timeout;
+    int receive_response_timeout;
     LPWSTR proxy_server;
     LPWSTR proxy_bypass;
     LPWSTR proxy_username;
@@ -198,7 +199,8 @@ typedef struct
     int resolve_timeout;
     int connect_timeout;
     int send_timeout;
-    int recv_timeout;
+    int receive_timeout;
+    int receive_response_timeout;
     LPWSTR status_text;
     DWORD content_length; /* total number of bytes to be read */
     DWORD content_read;   /* bytes read so far */
-- 
2.11.0




More information about the wine-devel mailing list