winhttp: Always return result at once if available in WinHttpQueryDataAvailable().
This commit is contained in:
parent
5529b00a44
commit
fd2534422b
3 changed files with 77 additions and 6 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue