winhttp: Only read server reply in send_request() if the whole request is sent.

Fixes a regression introduced by
aa8f97e829.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54184
This commit is contained in:
Paul Gofman 2022-12-19 17:06:13 -06:00 committed by Alexandre Julliard
parent 2677546e0a
commit 3f51fcf8ac
3 changed files with 66 additions and 17 deletions

View file

@ -2216,9 +2216,9 @@ static DWORD send_request( struct request *request, const WCHAR *headers, DWORD
{
struct connect *connect = request->connect;
struct session *session = connect->session;
DWORD ret, len, buflen, content_length;
char *wire_req;
int bytes_sent;
DWORD ret, len;
TRACE( "request state %d.\n", request->state );
@ -2305,14 +2305,29 @@ static DWORD send_request( struct request *request, const WCHAR *headers, DWORD
request->optional_len = optional_len;
len += optional_len;
}
netconn_set_timeout( request->netconn, FALSE, request->receive_response_timeout );
request->read_reply_status = read_reply( request );
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_SENT, &len, sizeof(len) );
if (request->state == REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED)
request->state = REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REQUEST_SENT;
buflen = sizeof(content_length);
if (query_headers( request, WINHTTP_QUERY_FLAG_REQUEST_HEADERS | WINHTTP_QUERY_CONTENT_LENGTH
| WINHTTP_QUERY_FLAG_NUMBER, NULL, &content_length, &buflen, NULL ))
content_length = total_len;
if (content_length <= optional_len)
{
netconn_set_timeout( request->netconn, FALSE, request->receive_response_timeout );
request->read_reply_status = read_reply( request );
if (request->state == REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED)
request->state = REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REPLY_RECEIVED;
else
request->state = REQUEST_RESPONSE_STATE_REPLY_RECEIVED;
}
else
request->state = REQUEST_RESPONSE_STATE_REQUEST_SENT;
{
if (request->state == REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED)
request->state = REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REQUEST_SENT;
else
request->state = REQUEST_RESPONSE_STATE_REQUEST_SENT;
}
end:
if (async)
@ -2895,10 +2910,24 @@ static DWORD receive_response( struct request *request )
case REQUEST_RESPONSE_STATE_REQUEST_SENT:
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 );
if (async_mode)
{
request->state = REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REQUEST_SENT;
return queue_receive_response( request );
}
/* fallthrough */
case REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REQUEST_SENT:
netconn_set_timeout( request->netconn, FALSE, request->receive_response_timeout );
request->read_reply_status = read_reply( request );
request->state = REQUEST_RESPONSE_STATE_REPLY_RECEIVED;
break;
case REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REQUEST_SENT:
request->state = REQUEST_RESPONSE_STATE_REQUEST_SENT;
case REQUEST_RESPONSE_STATE_REPLY_RECEIVED:
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 );
break;
case REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REPLY_RECEIVED:
request->state = REQUEST_RESPONSE_STATE_REPLY_RECEIVED;
break;
default:

View file

@ -1852,6 +1852,8 @@ struct test_recursion_context
DWORD main_thread_id;
DWORD receive_response_thread_id;
BOOL headers_available;
DWORD total_len;
BYTE *send_buffer;
};
/* The limit is 128 before Win7 and 3 on newer Windows. */
@ -1872,17 +1874,29 @@ static void CALLBACK test_recursion_callback( HINTERNET handle, DWORD_PTR contex
case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
if (status == context->call_receive_response_status)
{
context->receive_response_thread_id = GetCurrentThreadId();
ret = WinHttpReceiveResponse( context->request, NULL );
ok( ret, "failed to receive response, GetLastError() %lu\n", GetLastError() );
if (context->total_len)
{
ret = WinHttpWriteData( context->request, context->send_buffer, context->total_len, NULL );
ok(ret, "failed.\n");
}
else
{
context->receive_response_thread_id = GetCurrentThreadId();
ret = WinHttpReceiveResponse( context->request, NULL );
ok( ret, "failed to receive response, GetLastError() %lu\n", GetLastError() );
}
}
break;
case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
trace("WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE thread %04lx.\n", GetCurrentThreadId());
context->receive_response_thread_id = GetCurrentThreadId();
ret = WinHttpReceiveResponse( context->request, NULL );
ok( ret, "failed to receive response, GetLastError() %lu\n", GetLastError() );
break;
case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
if (context->call_receive_response_status == WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE)
ok( GetCurrentThreadId() == context->receive_response_thread_id,
"expected callback to be called from the same thread, got %lx.\n", GetCurrentThreadId() );
else
if (context->call_receive_response_status != WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE)
ok( GetCurrentThreadId() != context->main_thread_id,
"expected callback to be called from the other thread, got main.\n" );
context->headers_available = TRUE;
@ -1933,7 +1947,6 @@ static void CALLBACK test_recursion_callback( HINTERNET handle, DWORD_PTR contex
InterlockedDecrement( &context->recursion_count );
break;
case WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE:
case WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED:
if (!context->headers_available
&& context->call_receive_response_status == WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE)
ok( GetCurrentThreadId() == context->receive_response_thread_id,
@ -1979,7 +1992,10 @@ static void test_recursion(void)
ok( ret, "failed to receive response, GetLastError() %lu\n", GetLastError() );
context.call_receive_response_status = WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE;
ret = WinHttpSendRequest( request, NULL, 0, NULL, 0, 0, (DWORD_PTR)&context );
context.total_len = 1;
context.send_buffer = &b;
b = 0;
ret = WinHttpSendRequest( request, NULL, 0, NULL, 0, context.total_len, (DWORD_PTR)&context );
err = GetLastError();
if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
{
@ -1994,6 +2010,8 @@ static void test_recursion(void)
ok( ret, "failed to send request, GetLastError() %lu\n", GetLastError() );
WaitForSingleObject( context.wait, INFINITE );
context.total_len = 0;
context.send_buffer = NULL;
size = sizeof(status);
ret = WinHttpQueryHeaders( request, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,

View file

@ -181,6 +181,8 @@ enum request_response_state
REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED,
REQUEST_RESPONSE_STATE_REQUEST_SENT,
REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REQUEST_SENT,
REQUEST_RESPONSE_STATE_REPLY_RECEIVED,
REQUEST_RESPONSE_STATE_READ_RESPONSE_QUEUED_REPLY_RECEIVED,
REQUEST_RESPONSE_RECURSIVE_REQUEST,
REQUEST_RESPONSE_STATE_RESPONSE_RECEIVED,
};