Signed-off-by: Hans Leidekker hans@codeweavers.com --- dlls/winhttp/request.c | 174 +++++++++++++++++---------------- dlls/winhttp/session.c | 12 ++- dlls/winhttp/winhttp_private.h | 18 ++-- 3 files changed, 109 insertions(+), 95 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 1324005f1d..9b72253a26 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -121,27 +121,25 @@ static const WCHAR *attribute_table[] = NULL /* WINHTTP_QUERY_PASSPORT_CONFIG = 78 */ };
-static struct task_header *dequeue_task( struct request *request ) +static struct task_header *dequeue_task( struct queue *queue ) { struct task_header *task;
- EnterCriticalSection( &request->task_cs ); - TRACE("%u tasks queued\n", list_count( &request->task_queue )); - task = LIST_ENTRY( list_head( &request->task_queue ), struct task_header, entry ); + EnterCriticalSection( &queue->cs ); + TRACE("%u tasks queued in %p\n", list_count(&queue->tasks), queue); + task = LIST_ENTRY( list_head( &queue->tasks ), struct task_header, entry ); if (task) list_remove( &task->entry ); - LeaveCriticalSection( &request->task_cs ); + LeaveCriticalSection( &queue->cs );
TRACE("returning task %p\n", task); return task; }
-static void CALLBACK task_proc( TP_CALLBACK_INSTANCE *instance, void *ctx ) +static void CALLBACK run_queue( TP_CALLBACK_INSTANCE *instance, void *ctx ) { - struct request *request = ctx; - HANDLE handles[2]; + struct queue *queue = ctx; + HANDLE handles[] = { queue->wait, queue->cancel };
- handles[0] = request->task_wait; - handles[1] = request->task_cancel; for (;;) { DWORD err = WaitForMultipleObjects( 2, handles, FALSE, INFINITE ); @@ -150,21 +148,19 @@ static void CALLBACK task_proc( TP_CALLBACK_INSTANCE *instance, void *ctx ) case WAIT_OBJECT_0: { struct task_header *task; - while ((task = dequeue_task( request ))) + while ((task = dequeue_task( queue ))) { task->proc( task ); - release_object( &task->request->hdr ); + release_object( task->object ); heap_free( task ); } break; } case WAIT_OBJECT_0 + 1: TRACE("exiting\n"); - CloseHandle( request->task_cancel ); - CloseHandle( request->task_wait ); - request->task_cs.DebugInfo->Spare[0] = 0; - DeleteCriticalSection( &request->task_cs ); - request->hdr.vtbl->destroy( &request->hdr ); + CloseHandle( queue->wait ); + CloseHandle( queue->cancel ); + queue->object->vtbl->destroy( queue->object ); return;
default: @@ -174,38 +170,43 @@ static void CALLBACK task_proc( TP_CALLBACK_INSTANCE *instance, void *ctx ) } }
-static DWORD queue_task( struct task_header *task ) +static DWORD start_queue( struct object_header *object, struct queue *queue ) { - struct request *request = task->request; + DWORD ret = ERROR_OUTOFMEMORY;
- if (!request->task_wait) + if (queue->wait) return ERROR_SUCCESS; + + queue->object = object; + list_init( &queue->tasks ); + if (!(queue->wait = CreateEventW( NULL, FALSE, FALSE, NULL ))) goto error; + if (!(queue->cancel = CreateEventW( NULL, FALSE, FALSE, NULL ))) goto error; + if (!TrySubmitThreadpoolCallback( run_queue, queue, NULL )) ret = GetLastError(); + else { - if (!(request->task_wait = CreateEventW( NULL, FALSE, FALSE, NULL ))) return ERROR_OUTOFMEMORY; - if (!(request->task_cancel = CreateEventW( NULL, FALSE, FALSE, NULL ))) - { - CloseHandle( request->task_wait ); - request->task_wait = NULL; - return ERROR_OUTOFMEMORY; - } - if (!TrySubmitThreadpoolCallback( task_proc, request, NULL )) - { - CloseHandle( request->task_wait ); - request->task_wait = NULL; - CloseHandle( request->task_cancel ); - request->task_cancel = NULL; - return GetLastError(); - } - request->task_proc_running = TRUE; - InitializeCriticalSection( &request->task_cs ); - request->task_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": request.task_cs"); + queue->proc_running = TRUE; + TRACE("started %p\n", queue); + return ERROR_SUCCESS; }
- EnterCriticalSection( &request->task_cs ); - TRACE("queueing task %p\n", task ); - list_add_tail( &request->task_queue, &task->entry ); - LeaveCriticalSection( &request->task_cs ); +error: + CloseHandle( queue->wait ); + queue->wait = NULL; + CloseHandle( queue->cancel ); + queue->cancel = NULL; + return ret; +} + +static DWORD queue_task( struct object_header *object, struct queue *queue, struct task_header *task ) +{ + DWORD ret; + if ((ret = start_queue( object, queue ))) return ret; + + EnterCriticalSection( &queue->cs ); + TRACE("queueing task %p in %p\n", task, queue); + list_add_tail( &queue->tasks, &task->entry ); + LeaveCriticalSection( &queue->cs );
- SetEvent( request->task_wait ); + SetEvent( queue->wait ); return ERROR_SUCCESS; }
@@ -2215,8 +2216,10 @@ end:
static void task_send_request( struct task_header *task ) { + struct request *request = (struct request *)task->object; struct send_request *s = (struct send_request *)task; - send_request( s->hdr.request, s->headers, s->headers_len, s->optional, s->optional_len, s->total_len, s->context, TRUE ); + + send_request( request, s->headers, s->headers_len, s->optional, s->optional_len, s->total_len, s->context, TRUE ); heap_free( s->headers ); }
@@ -2250,8 +2253,8 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD heade { struct send_request *s;
- if (!(s = heap_alloc( sizeof(struct send_request) ))) return FALSE; - s->hdr.request = request; + if (!(s = heap_alloc( sizeof(*s) ))) return FALSE; + s->hdr.object = &request->hdr; s->hdr.proc = task_send_request; s->headers = strdupW( headers ); s->headers_len = headers_len; @@ -2261,10 +2264,9 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD heade s->context = context;
addref_object( &request->hdr ); - ret = queue_task( (struct task_header *)s ); + ret = queue_task( &request->hdr, &request->queue, (struct task_header *)s ); } - else - ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context, FALSE ); + else ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context, FALSE );
release_object( &request->hdr ); SetLastError( ret ); @@ -2795,8 +2797,8 @@ static DWORD receive_response( struct request *request, BOOL async )
static void task_receive_response( struct task_header *task ) { - struct receive_response *r = (struct receive_response *)task; - receive_response( r->hdr.request, TRUE ); + struct request *request = (struct request *)task->object; + receive_response( request, TRUE ); }
/*********************************************************************** @@ -2825,15 +2827,14 @@ BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved ) { struct receive_response *r;
- if (!(r = heap_alloc( sizeof(struct receive_response) ))) return FALSE; - r->hdr.request = request; - r->hdr.proc = task_receive_response; + if (!(r = heap_alloc( sizeof(*r) ))) return FALSE; + r->hdr.object = &request->hdr; + r->hdr.proc = task_receive_response;
addref_object( &request->hdr ); - ret = queue_task( (struct task_header *)r ); + ret = queue_task( &request->hdr, &request->queue, (struct task_header *)r ); } - else - ret = receive_response( request, FALSE ); + else ret = receive_response( request, FALSE );
release_object( &request->hdr ); SetLastError( ret ); @@ -2875,8 +2876,10 @@ done:
static void task_query_data_available( struct task_header *task ) { + struct request *request = (struct request *)task->object; struct query_data *q = (struct query_data *)task; - query_data_available( q->hdr.request, q->available, TRUE ); + + query_data_available( request, q->available, TRUE ); }
/*********************************************************************** @@ -2905,16 +2908,15 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available ) { struct query_data *q;
- if (!(q = heap_alloc( sizeof(struct query_data) ))) return FALSE; - q->hdr.request = request; - q->hdr.proc = task_query_data_available; - q->available = available; + if (!(q = heap_alloc( sizeof(*q) ))) return FALSE; + q->hdr.object = &request->hdr; + q->hdr.proc = task_query_data_available; + q->available = available;
addref_object( &request->hdr ); - ret = queue_task( (struct task_header *)q ); + ret = queue_task( &request->hdr, &request->queue, (struct task_header *)q ); } - else - ret = query_data_available( request, available, FALSE ); + else ret = query_data_available( request, available, FALSE );
release_object( &request->hdr ); SetLastError( ret ); @@ -2923,8 +2925,10 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
static void task_read_data( struct task_header *task ) { + struct request *request = (struct request *)task->object; struct read_data *r = (struct read_data *)task; - read_data( r->hdr.request, r->buffer, r->to_read, r->read, TRUE ); + + read_data( request, r->buffer, r->to_read, r->read, TRUE ); }
/*********************************************************************** @@ -2953,18 +2957,17 @@ BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer, DWORD to_read, L { struct read_data *r;
- if (!(r = heap_alloc( sizeof(struct read_data) ))) return FALSE; - r->hdr.request = request; - r->hdr.proc = task_read_data; - r->buffer = buffer; - r->to_read = to_read; - r->read = read; + if (!(r = heap_alloc( sizeof(*r) ))) return FALSE; + r->hdr.object = &request->hdr; + r->hdr.proc = task_read_data; + r->buffer = buffer; + r->to_read = to_read; + r->read = read;
addref_object( &request->hdr ); - ret = queue_task( (struct task_header *)r ); + ret = queue_task( &request->hdr, &request->queue, (struct task_header *)r ); } - else - ret = read_data( request, buffer, to_read, read, FALSE ); + else ret = read_data( request, buffer, to_read, read, FALSE );
release_object( &request->hdr ); SetLastError( ret ); @@ -2995,8 +2998,10 @@ static DWORD write_data( struct request *request, const void *buffer, DWORD to_w
static void task_write_data( struct task_header *task ) { + struct request *request = (struct request *)task->object; struct write_data *w = (struct write_data *)task; - write_data( w->hdr.request, w->buffer, w->to_write, w->written, TRUE ); + + write_data( request, w->buffer, w->to_write, w->written, TRUE ); }
/*********************************************************************** @@ -3025,18 +3030,17 @@ BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, LPCVOID buffer, DWORD to_write { struct write_data *w;
- if (!(w = heap_alloc( sizeof(struct write_data) ))) return FALSE; - w->hdr.request = request; - w->hdr.proc = task_write_data; - w->buffer = buffer; - w->to_write = to_write; - w->written = written; + if (!(w = heap_alloc( sizeof(*w) ))) return FALSE; + w->hdr.object = &request->hdr; + w->hdr.proc = task_write_data; + w->buffer = buffer; + w->to_write = to_write; + w->written = written;
addref_object( &request->hdr ); - ret = queue_task( (struct task_header *)w ); + ret = queue_task( &request->hdr, &request->queue, (struct task_header *)w ); } - else - ret = write_data( request, buffer, to_write, written, FALSE ); + else ret = write_data( request, buffer, to_write, written, FALSE );
release_object( &request->hdr ); SetLastError( ret ); diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index a5ec8b22f3..186b70e4a2 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -578,11 +578,11 @@ static void request_destroy( struct object_header *hdr )
TRACE("%p\n", request);
- if (request->task_proc_running) + if (request->queue.proc_running) { /* Signal to the task proc to quit. It will call this again when it does. */ - request->task_proc_running = FALSE; - SetEvent( request->task_cancel ); + request->queue.proc_running = FALSE; + SetEvent( request->queue.cancel ); return; } release_object( &request->connect->hdr ); @@ -613,6 +613,9 @@ static void request_destroy( struct object_header *hdr ) heap_free( request->creds[i][j].password ); } } + + request->queue.cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &request->queue.cs ); heap_free( request ); }
@@ -1117,7 +1120,8 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR o request->hdr.notify_mask = connect->hdr.notify_mask; request->hdr.context = connect->hdr.context; request->hdr.redirect_policy = connect->hdr.redirect_policy; - list_init( &request->task_queue ); + InitializeCriticalSection( &request->queue.cs ); + request->queue.cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": request.queue.cs");
addref_object( &connect->hdr ); request->connect = connect; diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 9b07b64b09..207696e674 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -155,6 +155,16 @@ struct authinfo BOOL finished; /* finished authenticating */ };
+struct queue +{ + struct object_header *object; + CRITICAL_SECTION cs; + BOOL proc_running; + HANDLE wait; + HANDLE cancel; + struct list tasks; +}; + enum request_flags { REQUEST_FLAG_WEBSOCKET_UPGRADE = 0x01, @@ -196,11 +206,7 @@ struct request DWORD num_headers; struct authinfo *authinfo; struct authinfo *proxy_authinfo; - HANDLE task_wait; - HANDLE task_cancel; - BOOL task_proc_running; - struct list task_queue; - CRITICAL_SECTION task_cs; + struct queue queue; struct { WCHAR *username; @@ -217,7 +223,7 @@ struct socket struct task_header { struct list entry; - struct request *request; + struct object_header *object; void (*proc)( struct task_header * ); };