From: Paul Gofman pgofman@codeweavers.com
--- dlls/winhttp/request.c | 98 +++++++++++++++++++++------------- dlls/winhttp/winhttp_private.h | 1 + 2 files changed, 63 insertions(+), 36 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index f878fd18dc0..3f84443af0d 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -2178,6 +2178,7 @@ static DWORD send_request( struct request *request, const WCHAR *headers, DWORD request->read_reply_len = 0; free( request->redirect_location ); request->redirect_location = NULL; + request->recursive_request = FALSE;
if (request->flags & REQUEST_FLAG_WEBSOCKET_UPGRADE && request->websocket_set_send_buffer_size < MIN_WEBSOCKET_SEND_BUFFER_SIZE) @@ -2788,62 +2789,87 @@ static DWORD handle_passport_redirect( struct request *request ) return ERROR_SUCCESS; }
-static DWORD receive_response( struct request *request, BOOL async ) +static DWORD receive_server_response( struct request *request ) { DWORD ret, size, query, status;
- if (!request->netconn) return ERROR_WINHTTP_INCORRECT_HANDLE_STATE; + TRACE( "request %p.\n", request ); + + request->recursive_request = FALSE;
netconn_set_timeout( request->netconn, FALSE, request->receive_response_timeout ); - for (;;) + + if ((ret = read_reply( request ))) { - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 ); - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, - &request->read_reply_len, sizeof(request->read_reply_len) ); - if ((ret = read_reply( request ))) break; + TRACE( "read_reply ret %lu.\n", ret); + return ret; + }
- size = sizeof(DWORD); - query = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER; - if ((ret = query_headers( request, query, NULL, &status, &size, NULL ))) break; + size = sizeof(DWORD); + query = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER; + if ((ret = query_headers( request, query, NULL, &status, &size, NULL ))) + { + TRACE( "query_headers ret %lu.\n", ret); + return ret; + }
- set_content_length( request, status ); + set_content_length( request, status );
- if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request ); + if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request );
- if (status == HTTP_STATUS_REDIRECT && is_passport_request( request )) + if (status == HTTP_STATUS_REDIRECT && is_passport_request( request )) + { + ret = handle_passport_redirect( request ); + } + else if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status == HTTP_STATUS_REDIRECT_KEEP_VERB) + { + if (!(request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS || + request->hdr.redirect_policy == WINHTTP_OPTION_REDIRECT_POLICY_NEVER)) { - ret = handle_passport_redirect( request ); + if (++request->redirect_count > request->max_redirects) + { + TRACE("redirect_count %lu, max_redirects %lu.\n", request->redirect_count, request->max_redirects); + return ERROR_WINHTTP_REDIRECT_FAILED; + } + request->recursive_request = !(ret = handle_redirect( request, status )); } - else if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status == HTTP_STATUS_REDIRECT_KEEP_VERB) - { - if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS || - request->hdr.redirect_policy == WINHTTP_OPTION_REDIRECT_POLICY_NEVER) break; + } + else if (status == HTTP_STATUS_DENIED || status == HTTP_STATUS_PROXY_AUTH_REQ) + { + if (!(request->hdr.disable_flags & WINHTTP_DISABLE_AUTHENTICATION)) + request->recursive_request = !handle_authorization( request, status ); + }
- if (++request->redirect_count > request->max_redirects) return ERROR_WINHTTP_REDIRECT_FAILED; + if (request->netconn) netconn_set_timeout( request->netconn, FALSE, request->receive_timeout ); + if (request->content_length && !ret && !request->recursive_request) + { + ret = refill_buffer( request, FALSE ); + TRACE("refill_buffer ret %ld.\n", ret); + } + return ret; +} + +static DWORD receive_response( struct request *request, BOOL async ) +{ + DWORD ret;
- if ((ret = handle_redirect( request, status ))) break; + if (!request->netconn) return ERROR_WINHTTP_INCORRECT_HANDLE_STATE;
+ for (;;) + { + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 ); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, + &request->read_reply_len, sizeof(request->read_reply_len) ); + if ((ret = receive_server_response( request ))) break; + if (!request->recursive_request) break; + if (request->redirect_location) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REDIRECT, request->redirect_location, request->redirect_location_len + 1 ); - - /* recurse synchronously */ - if (!(ret = send_request( request, NULL, 0, request->optional, request->optional_len, 0, 0, FALSE ))) continue; - } - else if (status == HTTP_STATUS_DENIED || status == HTTP_STATUS_PROXY_AUTH_REQ) - { - if (request->hdr.disable_flags & WINHTTP_DISABLE_AUTHENTICATION) break; - - if (handle_authorization( request, status )) break; - - /* recurse synchronously */ - if (!(ret = send_request( request, NULL, 0, request->optional, request->optional_len, 0, 0, FALSE ))) continue; - } + /* recurse synchronously */ + if (!(ret = send_request( request, NULL, 0, request->optional, request->optional_len, 0, 0, FALSE ))) continue; break; }
- if (request->netconn) netconn_set_timeout( request->netconn, FALSE, request->receive_timeout ); - if (request->content_length) ret = refill_buffer( request, FALSE ); - if (async) { if (!ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NULL, 0 ); diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index ed0f6e590ab..cffad0e0c74 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -223,6 +223,7 @@ struct request int read_reply_len; WCHAR *redirect_location; DWORD redirect_location_len; + BOOL recursive_request; };
enum socket_state