Commit fd253442 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

winhttp: Always return result at once if available in WinHttpQueryDataAvailable().

parent 5529b00a
......@@ -257,6 +257,16 @@ static BOOL cancel_queue( struct queue *queue )
return cancelled;
}
static void task_send_callback( void *ctx, BOOL abort )
{
struct send_callback *s = ctx;
if (abort) return;
TRACE( "running %p\n", ctx );
send_callback( s->task_hdr.obj, s->status, s->info, s->buflen );
}
static void free_header( struct header *header )
{
free( header->field );
......@@ -3052,9 +3062,10 @@ static DWORD query_data_ready( struct request *request )
return count;
}
static BOOL skip_async_queue( struct request *request )
static BOOL skip_async_queue( struct request *request, BOOL *wont_block )
{
return request->hdr.recursion_count < 3 && (end_of_read_data( request ) || query_data_ready( request ));
*wont_block = end_of_read_data( request ) || query_data_ready( request );
return request->hdr.recursion_count < 3 && *wont_block;
}
static DWORD query_data_available( struct request *request, DWORD *available, BOOL async )
......@@ -3106,6 +3117,7 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
DWORD ret;
struct request *request;
BOOL async;
BOOL wont_block = FALSE;
TRACE("%p, %p\n", hrequest, available);
......@@ -3121,7 +3133,44 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
return FALSE;
}
if ((async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) && !skip_async_queue( request ))
if (!(async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) || skip_async_queue( request, &wont_block ))
{
ret = query_data_available( request, available, async );
}
else if (wont_block)
{
/* Data available but recursion limit reached, only queue callback. */
struct send_callback *s;
if (!(s = malloc( sizeof(*s) )))
{
release_object( &request->hdr );
SetLastError( ERROR_OUTOFMEMORY );
return FALSE;
}
if (!(ret = query_data_available( request, &s->count, FALSE )))
{
if (available) *available = s->count;
s->status = WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE;
s->info = &s->count;
s->buflen = sizeof(s->count);
}
else
{
s->result.dwResult = API_QUERY_DATA_AVAILABLE;
s->result.dwError = ret;
s->status = WINHTTP_CALLBACK_STATUS_REQUEST_ERROR;
s->info = &s->result;
s->buflen = sizeof(s->result);
}
if ((ret = queue_task( &request->queue, task_send_callback, &s->task_hdr, &request->hdr )))
free( s );
else
ret = ERROR_IO_PENDING;
}
else
{
struct query_data *q;
......@@ -3139,7 +3188,6 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
else
ret = ERROR_IO_PENDING;
}
else ret = query_data_available( request, available, async );
release_object( &request->hdr );
SetLastError( ret );
......@@ -3165,6 +3213,7 @@ BOOL WINAPI WinHttpReadData( HINTERNET hrequest, void *buffer, DWORD to_read, DW
DWORD ret;
struct request *request;
BOOL async;
BOOL wont_block;
TRACE( "%p, %p, %lu, %p\n", hrequest, buffer, to_read, read );
......@@ -3180,7 +3229,7 @@ BOOL WINAPI WinHttpReadData( HINTERNET hrequest, void *buffer, DWORD to_read, DW
return FALSE;
}
if ((async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) && !skip_async_queue( request ))
if ((async = request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) && !skip_async_queue( request, &wont_block ))
{
struct read_data *r;
......
......@@ -1929,6 +1929,9 @@ static void CALLBACK test_recursion_callback( HINTERNET handle, DWORD_PTR contex
break;
case WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
{
static DWORD len;
if (!buflen)
{
SetEvent( context->wait );
......@@ -1939,13 +1942,19 @@ static void CALLBACK test_recursion_callback( HINTERNET handle, DWORD_PTR contex
context->max_recursion_read = max( context->max_recursion_read, context->recursion_count );
context->read_from_callback = TRUE;
InterlockedIncrement( &context->recursion_count );
ret = WinHttpQueryDataAvailable( context->request, NULL );
len = 0xdeadbeef;
/* Use static variable len here so write to it doesn't destroy the stack on old Windows which
* doesn't set the value at once. */
ret = WinHttpQueryDataAvailable( context->request, &len );
err = GetLastError();
ok( ret, "failed to query data available, GetLastError() %lu\n", err );
ok( err == ERROR_SUCCESS || err == ERROR_IO_PENDING, "got %lu\n", err );
ok( len != 0xdeadbeef || broken( len == 0xdeadbeef ) /* Win7 */, "got %lu.\n", len );
if (err == ERROR_SUCCESS) context->have_sync_callback = TRUE;
InterlockedDecrement( &context->recursion_count );
break;
}
case WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE:
if (!context->headers_available
&& context->call_receive_response_status == WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE)
......
......@@ -312,6 +312,19 @@ struct task_header
volatile LONG completion_sent;
};
struct send_callback
{
struct task_header task_hdr;
DWORD status;
void *info;
DWORD buflen;
union
{
WINHTTP_ASYNC_RESULT result;
DWORD count;
};
};
struct send_request
{
struct task_header task_hdr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment