Signed-off-by: Hans Leidekker <hans(a)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 * );
};
--
2.20.1