Signed-off-by: Paul Gofman pgofman@codeweavers.com --- v2: - no changes.
dlls/winhttp/request.c | 74 +++++++++++++++++++--------------- dlls/winhttp/winhttp_private.h | 15 +++++++ 2 files changed, 56 insertions(+), 33 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index b409c4cdced..36a3bb909b9 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -146,15 +146,23 @@ void stop_queue( struct queue *queue ) TRACE("stopped %p\n", queue); }
-static DWORD queue_task( struct queue *queue, PTP_WORK_CALLBACK task, void *ctx ) +static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +{ + struct task_header *task_hdr = ctx; + + task_hdr->callback( task_hdr ); +} + +static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_header *task_hdr ) { TP_WORK *work; DWORD ret;
if ((ret = start_queue( queue ))) return ret;
- if (!(work = CreateThreadpoolWork( task, ctx, &queue->env ))) return GetLastError(); - TRACE("queueing %p in %p\n", work, queue); + if (!(work = CreateThreadpoolWork( task_callback, task_hdr, &queue->env ))) return GetLastError(); + TRACE("queueing %p in %p\n", task_hdr, queue); + task_hdr->callback = task; SubmitThreadpoolWork( work ); CloseThreadpoolWork( work );
@@ -2167,11 +2175,11 @@ end: return ret; }
-static void CALLBACK task_send_request( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static void task_send_request( void *ctx ) { struct send_request *s = ctx;
- TRACE("running %p\n", work); + TRACE( "running %p\n", ctx ); send_request( s->request, s->headers, s->headers_len, s->optional, s->optional_len, s->total_len, s->context, TRUE );
release_object( &s->request->hdr ); @@ -2219,7 +2227,7 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, const WCHAR *headers, DWORD s->context = context;
addref_object( &request->hdr ); - if ((ret = queue_task( &request->queue, task_send_request, s ))) + if ((ret = queue_task( &request->queue, task_send_request, &s->task_hdr ))) { release_object( &request->hdr ); free( s->headers ); @@ -2753,11 +2761,11 @@ static DWORD receive_response( struct request *request, BOOL async ) return ret; }
-static void CALLBACK task_receive_response( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static void task_receive_response( void *ctx ) { struct receive_response *r = ctx;
- TRACE("running %p\n", work); + TRACE("running %p\n", ctx); receive_response( r->request, TRUE );
release_object( &r->request->hdr ); @@ -2794,7 +2802,7 @@ BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved ) r->request = request;
addref_object( &request->hdr ); - if ((ret = queue_task( &request->queue, task_receive_response, r ))) + if ((ret = queue_task( &request->queue, task_receive_response, &r->task_hdr ))) { release_object( &request->hdr ); free( r ); @@ -2852,11 +2860,11 @@ done: return ret; }
-static void CALLBACK task_query_data_available( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static void task_query_data_available( void *ctx ) { struct query_data *q = ctx;
- TRACE("running %p\n", work); + TRACE("running %p\n", ctx); query_data_available( q->request, q->available, TRUE );
release_object( &q->request->hdr ); @@ -2895,7 +2903,7 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available ) q->available = available;
addref_object( &request->hdr ); - if ((ret = queue_task( &request->queue, task_query_data_available, q ))) + if ((ret = queue_task( &request->queue, task_query_data_available, &q->task_hdr ))) { release_object( &request->hdr ); free( q ); @@ -2909,11 +2917,11 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available ) return !ret || ret == ERROR_IO_PENDING; }
-static void CALLBACK task_read_data( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static void task_read_data( void *ctx ) { struct read_data *r = ctx;
- TRACE("running %p\n", work); + TRACE("running %p\n", ctx); read_data( r->request, r->buffer, r->to_read, r->read, TRUE );
release_object( &r->request->hdr ); @@ -2954,7 +2962,7 @@ BOOL WINAPI WinHttpReadData( HINTERNET hrequest, void *buffer, DWORD to_read, DW r->read = read;
addref_object( &request->hdr ); - if ((ret = queue_task( &request->queue, task_read_data, r ))) + if ((ret = queue_task( &request->queue, task_read_data, &r->task_hdr ))) { release_object( &request->hdr ); free( r ); @@ -2990,11 +2998,11 @@ static DWORD write_data( struct request *request, const void *buffer, DWORD to_w return ret; }
-static void CALLBACK task_write_data( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static void task_write_data( void *ctx ) { struct write_data *w = ctx;
- TRACE("running %p\n", work); + TRACE("running %p\n", ctx); write_data( w->request, w->buffer, w->to_write, w->written, TRUE );
release_object( &w->request->hdr ); @@ -3034,7 +3042,7 @@ BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, const void *buffer, DWORD to_w w->written = written;
addref_object( &request->hdr ); - if ((ret = queue_task( &request->queue, task_write_data, w ))) + if ((ret = queue_task( &request->queue, task_write_data, &w->task_hdr ))) { release_object( &request->hdr ); free( w ); @@ -3392,12 +3400,12 @@ static DWORD socket_send( struct socket *socket, WINHTTP_WEB_SOCKET_BUFFER_TYPE return send_frame( socket, opcode, 0, buf, len, final, ovr ); }
-static void CALLBACK task_socket_send( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static void task_socket_send( void *ctx ) { struct socket_send *s = ctx; DWORD ret;
- TRACE("running %p\n", work); + TRACE("running %p\n", ctx);
if (s->complete_async) ret = complete_send_frame( s->socket, &s->ovr, s->buf ); else ret = socket_send( s->socket, s->type, s->buf, s->len, NULL ); @@ -3479,7 +3487,7 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_ s->len = len;
addref_object( &socket->hdr ); - if ((ret = queue_task( &socket->send_q, task_socket_send, s ))) + if ((ret = queue_task( &socket->send_q, task_socket_send, &s->task_hdr ))) { InterlockedDecrement( &socket->hdr.pending_sends ); InterlockedExchange( &socket->pending_noncontrol_send, 0 ); @@ -3596,11 +3604,11 @@ static DWORD receive_frame( struct socket *socket, DWORD *ret_len, enum socket_o return ERROR_SUCCESS; }
-static void CALLBACK task_socket_send_pong( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static void task_socket_send_pong( void *ctx ) { struct socket_send *s = ctx;
- TRACE("running %p\n", work); + TRACE("running %p\n", ctx);
if (s->complete_async) complete_send_frame( s->socket, &s->ovr, NULL ); else send_frame( s->socket, SOCKET_OPCODE_PONG, 0, NULL, 0, TRUE, NULL ); @@ -3638,7 +3646,7 @@ static DWORD socket_send_pong( struct socket *socket ) s->complete_async = complete_async; s->socket = socket; addref_object( &socket->hdr ); - if ((ret = queue_task( &socket->send_q, task_socket_send_pong, s ))) + if ((ret = queue_task( &socket->send_q, task_socket_send_pong, &s->task_hdr ))) { InterlockedDecrement( &socket->hdr.pending_sends ); release_object( &socket->hdr ); @@ -3817,13 +3825,13 @@ static DWORD socket_receive( struct socket *socket, void *buf, DWORD len, DWORD return ret; }
-static void CALLBACK task_socket_receive( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static void task_socket_receive( void *ctx ) { struct socket_receive *r = ctx; DWORD ret, count; WINHTTP_WEB_SOCKET_BUFFER_TYPE type;
- TRACE("running %p\n", work); + TRACE("running %p\n", ctx); ret = socket_receive( r->socket, r->buf, r->len, &count, &type );
if (receive_io_complete( r->socket )) @@ -3893,7 +3901,7 @@ DWORD WINAPI WinHttpWebSocketReceive( HINTERNET hsocket, void *buf, DWORD len, D r->len = len;
addref_object( &socket->hdr ); - if ((ret = queue_task( &socket->recv_q, task_socket_receive, r ))) + if ((ret = queue_task( &socket->recv_q, task_socket_receive, &r->task_hdr ))) { InterlockedDecrement( &socket->hdr.pending_receives ); release_object( &socket->hdr ); @@ -3919,12 +3927,12 @@ static void socket_shutdown_complete( struct socket *socket, DWORD ret ) } }
-static void CALLBACK task_socket_shutdown( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static void task_socket_shutdown( void *ctx ) { struct socket_shutdown *s = ctx; DWORD ret;
- TRACE("running %p\n", work); + TRACE("running %p\n", ctx);
if (s->complete_async) ret = complete_send_frame( s->socket, &s->ovr, s->reason ); else ret = send_frame( s->socket, SOCKET_OPCODE_CLOSE, s->status, s->reason, s->len, TRUE, NULL ); @@ -3971,7 +3979,7 @@ static DWORD send_socket_shutdown( struct socket *socket, USHORT status, const v s->send_callback = send_callback;
addref_object( &socket->hdr ); - if ((ret = queue_task( &socket->send_q, task_socket_shutdown, s ))) + if ((ret = queue_task( &socket->send_q, task_socket_shutdown, &s->task_hdr ))) { InterlockedDecrement( &socket->hdr.pending_sends ); release_object( &socket->hdr ); @@ -4057,12 +4065,12 @@ static void socket_close_complete( struct socket *socket, DWORD ret ) } }
-static void CALLBACK task_socket_close( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static void task_socket_close( void *ctx ) { struct socket_shutdown *s = ctx; DWORD ret;
- TRACE("running %p\n", work); + TRACE("running %p\n", ctx);
ret = socket_close( s->socket ); socket_close_complete( s->socket, ret ); @@ -4132,7 +4140,7 @@ DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reas s->socket = socket;
addref_object( &socket->hdr ); - if ((ret = queue_task( &socket->recv_q, task_socket_close, s ))) + if ((ret = queue_task( &socket->recv_q, task_socket_close, &s->task_hdr ))) { release_object( &socket->hdr ); free( s ); diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 19ef9a35e2d..96bd7b53747 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -273,8 +273,16 @@ struct socket BOOL last_receive_final; };
+typedef void (*TASK_CALLBACK)( void *ctx ); + +struct task_header +{ + TASK_CALLBACK callback; +}; + struct send_request { + struct task_header task_hdr; struct request *request; WCHAR *headers; DWORD headers_len; @@ -286,17 +294,20 @@ struct send_request
struct receive_response { + struct task_header task_hdr; struct request *request; };
struct query_data { + struct task_header task_hdr; struct request *request; DWORD *available; };
struct read_data { + struct task_header task_hdr; struct request *request; void *buffer; DWORD to_read; @@ -305,6 +316,7 @@ struct read_data
struct write_data { + struct task_header task_hdr; struct request *request; const void *buffer; DWORD to_write; @@ -313,6 +325,7 @@ struct write_data
struct socket_send { + struct task_header task_hdr; struct socket *socket; WINHTTP_WEB_SOCKET_BUFFER_TYPE type; const void *buf; @@ -323,6 +336,7 @@ struct socket_send
struct socket_receive { + struct task_header task_hdr; struct socket *socket; void *buf; DWORD len; @@ -330,6 +344,7 @@ struct socket_receive
struct socket_shutdown { + struct task_header task_hdr; struct socket *socket; USHORT status; char reason[123];
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- v2: - don't release object in WinHttpWriteData on queue_task() error; - free task structure in caller on queue_task() error.
dlls/winhttp/request.c | 164 +++++++++++---------------------- dlls/winhttp/winhttp_private.h | 9 +- 2 files changed, 55 insertions(+), 118 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 36a3bb909b9..a825ac71d33 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -151,9 +151,12 @@ static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx, T struct task_header *task_hdr = ctx;
task_hdr->callback( task_hdr ); + release_object( task_hdr->obj ); + free( task_hdr ); }
-static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_header *task_hdr ) +static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_header *task_hdr, + struct object_header *obj ) { TP_WORK *work; DWORD ret; @@ -163,6 +166,8 @@ static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_he if (!(work = CreateThreadpoolWork( task_callback, task_hdr, &queue->env ))) return GetLastError(); TRACE("queueing %p in %p\n", task_hdr, queue); task_hdr->callback = task; + task_hdr->obj = obj; + addref_object( obj ); SubmitThreadpoolWork( work ); CloseThreadpoolWork( work );
@@ -2178,13 +2183,12 @@ end: static void task_send_request( void *ctx ) { struct send_request *s = ctx; + struct request *request = (struct request *)s->task_hdr.obj;
TRACE( "running %p\n", ctx ); - send_request( s->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 );
- release_object( &s->request->hdr ); free( s->headers ); - free( s ); }
/*********************************************************************** @@ -2218,7 +2222,6 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, const WCHAR *headers, DWORD struct send_request *s;
if (!(s = malloc( sizeof(*s) ))) return FALSE; - s->request = request; s->headers = strdupW( headers ); s->headers_len = headers_len; s->optional = optional; @@ -2226,10 +2229,8 @@ BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, const WCHAR *headers, DWORD s->total_len = total_len; s->context = context;
- addref_object( &request->hdr ); - if ((ret = queue_task( &request->queue, task_send_request, &s->task_hdr ))) + if ((ret = queue_task( &request->queue, task_send_request, &s->task_hdr, &request->hdr ))) { - release_object( &request->hdr ); free( s->headers ); free( s ); } @@ -2764,12 +2765,10 @@ static DWORD receive_response( struct request *request, BOOL async ) static void task_receive_response( void *ctx ) { struct receive_response *r = ctx; + struct request *request = (struct request *)r->task_hdr.obj;
TRACE("running %p\n", ctx); - receive_response( r->request, TRUE ); - - release_object( &r->request->hdr ); - free( r ); + receive_response( request, TRUE ); }
/*********************************************************************** @@ -2799,14 +2798,9 @@ BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved ) struct receive_response *r;
if (!(r = malloc( sizeof(*r) ))) return FALSE; - r->request = request;
- addref_object( &request->hdr ); - if ((ret = queue_task( &request->queue, task_receive_response, &r->task_hdr ))) - { - release_object( &request->hdr ); + if ((ret = queue_task( &request->queue, task_receive_response, &r->task_hdr, &request->hdr ))) free( r ); - } } else ret = receive_response( request, FALSE );
@@ -2863,12 +2857,10 @@ done: static void task_query_data_available( void *ctx ) { struct query_data *q = ctx; + struct request *request = (struct request *)q->task_hdr.obj;
TRACE("running %p\n", ctx); - query_data_available( q->request, q->available, TRUE ); - - release_object( &q->request->hdr ); - free( q ); + query_data_available( request, q->available, TRUE ); }
/*********************************************************************** @@ -2899,16 +2891,12 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available ) struct query_data *q;
if (!(q = malloc( sizeof(*q) ))) return FALSE; - q->request = request; q->available = available;
- addref_object( &request->hdr ); - if ((ret = queue_task( &request->queue, task_query_data_available, &q->task_hdr ))) - { - release_object( &request->hdr ); + if ((ret = queue_task( &request->queue, task_query_data_available, &q->task_hdr, &request->hdr ))) free( q ); - } - else ret = ERROR_IO_PENDING; + else + ret = ERROR_IO_PENDING; } else ret = query_data_available( request, available, async );
@@ -2920,12 +2908,10 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available ) static void task_read_data( void *ctx ) { struct read_data *r = ctx; + struct request *request = (struct request *)r->task_hdr.obj;
TRACE("running %p\n", ctx); - read_data( r->request, r->buffer, r->to_read, r->read, TRUE ); - - release_object( &r->request->hdr ); - free( r ); + read_data( request, r->buffer, r->to_read, r->read, TRUE ); }
/*********************************************************************** @@ -2956,18 +2942,14 @@ BOOL WINAPI WinHttpReadData( HINTERNET hrequest, void *buffer, DWORD to_read, DW struct read_data *r;
if (!(r = malloc( sizeof(*r) ))) return FALSE; - r->request = request; r->buffer = buffer; r->to_read = to_read; r->read = read;
- addref_object( &request->hdr ); - if ((ret = queue_task( &request->queue, task_read_data, &r->task_hdr ))) - { - release_object( &request->hdr ); + if ((ret = queue_task( &request->queue, task_read_data, &r->task_hdr, &request->hdr ))) free( r ); - } - else ret = ERROR_IO_PENDING; + else + ret = ERROR_IO_PENDING; } else ret = read_data( request, buffer, to_read, read, async );
@@ -3001,12 +2983,10 @@ static DWORD write_data( struct request *request, const void *buffer, DWORD to_w static void task_write_data( void *ctx ) { struct write_data *w = ctx; + struct request *request = (struct request *)w->task_hdr.obj;
TRACE("running %p\n", ctx); - write_data( w->request, w->buffer, w->to_write, w->written, TRUE ); - - release_object( &w->request->hdr ); - free( w ); + write_data( request, w->buffer, w->to_write, w->written, TRUE ); }
/*********************************************************************** @@ -3036,17 +3016,12 @@ BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, const void *buffer, DWORD to_w struct write_data *w;
if (!(w = malloc( sizeof(*w) ))) return FALSE; - w->request = request; w->buffer = buffer; w->to_write = to_write; w->written = written;
- addref_object( &request->hdr ); - if ((ret = queue_task( &request->queue, task_write_data, &w->task_hdr ))) - { - release_object( &request->hdr ); + if ((ret = queue_task( &request->queue, task_write_data, &w->task_hdr, &request->hdr ))) free( w ); - } } else ret = write_data( request, buffer, to_write, written, FALSE );
@@ -3403,19 +3378,17 @@ static DWORD socket_send( struct socket *socket, WINHTTP_WEB_SOCKET_BUFFER_TYPE static void task_socket_send( void *ctx ) { struct socket_send *s = ctx; + struct socket *socket = (struct socket *)s->task_hdr.obj; DWORD ret;
TRACE("running %p\n", ctx);
- if (s->complete_async) ret = complete_send_frame( s->socket, &s->ovr, s->buf ); - else ret = socket_send( s->socket, s->type, s->buf, s->len, NULL ); + if (s->complete_async) ret = complete_send_frame( socket, &s->ovr, s->buf ); + else ret = socket_send( socket, s->type, s->buf, s->len, NULL );
- send_io_complete( &s->socket->hdr ); - InterlockedExchange( &s->socket->pending_noncontrol_send, 0 ); - socket_send_complete( s->socket, ret, s->type, s->len ); - - release_object( &s->socket->hdr ); - free( s ); + send_io_complete( &socket->hdr ); + InterlockedExchange( &socket->pending_noncontrol_send, 0 ); + socket_send_complete( socket, ret, s->type, s->len ); }
DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_TYPE type, void *buf, DWORD len ) @@ -3481,21 +3454,14 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_ { s->complete_async = complete_async; TRACE("queueing, complete_async %#x.\n", complete_async); - s->socket = socket; s->type = type; s->buf = buf; s->len = len;
- addref_object( &socket->hdr ); - if ((ret = queue_task( &socket->send_q, task_socket_send, &s->task_hdr ))) - { - InterlockedDecrement( &socket->hdr.pending_sends ); - InterlockedExchange( &socket->pending_noncontrol_send, 0 ); - release_object( &socket->hdr ); + if ((ret = queue_task( &socket->send_q, task_socket_send, &s->task_hdr, &socket->hdr ))) free( s ); - } } - else + if (!async_send || ret) { InterlockedDecrement( &socket->hdr.pending_sends ); InterlockedExchange( &socket->pending_noncontrol_send, 0 ); @@ -3607,16 +3573,14 @@ static DWORD receive_frame( struct socket *socket, DWORD *ret_len, enum socket_o static void task_socket_send_pong( void *ctx ) { struct socket_send *s = ctx; + struct socket *socket = (struct socket *)s->task_hdr.obj;
TRACE("running %p\n", ctx);
- if (s->complete_async) complete_send_frame( s->socket, &s->ovr, NULL ); - else send_frame( s->socket, SOCKET_OPCODE_PONG, 0, NULL, 0, TRUE, NULL ); - - send_io_complete( &s->socket->hdr ); + if (s->complete_async) complete_send_frame( socket, &s->ovr, NULL ); + else send_frame( socket, SOCKET_OPCODE_PONG, 0, NULL, 0, TRUE, NULL );
- release_object( &s->socket->hdr ); - free( s ); + send_io_complete( &socket->hdr ); }
static DWORD socket_send_pong( struct socket *socket ) @@ -3644,12 +3608,9 @@ static DWORD socket_send_pong( struct socket *socket ) if (async_send) { s->complete_async = complete_async; - s->socket = socket; - addref_object( &socket->hdr ); - if ((ret = queue_task( &socket->send_q, task_socket_send_pong, &s->task_hdr ))) + if ((ret = queue_task( &socket->send_q, task_socket_send_pong, &s->task_hdr, &socket->hdr ))) { InterlockedDecrement( &socket->hdr.pending_sends ); - release_object( &socket->hdr ); free( s ); } } @@ -3828,20 +3789,21 @@ static DWORD socket_receive( struct socket *socket, void *buf, DWORD len, DWORD static void task_socket_receive( void *ctx ) { struct socket_receive *r = ctx; + struct socket *socket = (struct socket *)r->task_hdr.obj; DWORD ret, count; WINHTTP_WEB_SOCKET_BUFFER_TYPE type;
TRACE("running %p\n", ctx); - ret = socket_receive( r->socket, r->buf, r->len, &count, &type ); + ret = socket_receive( socket, r->buf, r->len, &count, &type );
- if (receive_io_complete( r->socket )) + if (receive_io_complete( socket )) { if (!ret) { WINHTTP_WEB_SOCKET_STATUS status; status.dwBytesTransferred = count; status.eBufferType = type; - send_callback( &r->socket->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, &status, sizeof(status) ); + send_callback( &socket->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, &status, sizeof(status) ); } else { @@ -3849,12 +3811,9 @@ static void task_socket_receive( void *ctx ) result.AsyncResult.dwResult = API_READ_DATA; result.AsyncResult.dwError = ret; result.Operation = WINHTTP_WEB_SOCKET_RECEIVE_OPERATION; - send_callback( &r->socket->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); + send_callback( &socket->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); } } - - release_object( &r->socket->hdr ); - free( r ); }
DWORD WINAPI WinHttpWebSocketReceive( HINTERNET hsocket, void *buf, DWORD len, DWORD *ret_len, @@ -3896,15 +3855,12 @@ DWORD WINAPI WinHttpWebSocketReceive( HINTERNET hsocket, void *buf, DWORD len, D InterlockedDecrement( &socket->hdr.pending_receives ); return ERROR_OUTOFMEMORY; } - r->socket = socket; r->buf = buf; r->len = len;
- addref_object( &socket->hdr ); - if ((ret = queue_task( &socket->recv_q, task_socket_receive, &r->task_hdr ))) + if ((ret = queue_task( &socket->recv_q, task_socket_receive, &r->task_hdr, &socket->hdr ))) { InterlockedDecrement( &socket->hdr.pending_receives ); - release_object( &socket->hdr ); free( r ); } } @@ -3930,17 +3886,16 @@ static void socket_shutdown_complete( struct socket *socket, DWORD ret ) static void task_socket_shutdown( void *ctx ) { struct socket_shutdown *s = ctx; + struct socket *socket = (struct socket *)s->task_hdr.obj; DWORD ret;
TRACE("running %p\n", ctx);
- if (s->complete_async) ret = complete_send_frame( s->socket, &s->ovr, s->reason ); - else ret = send_frame( s->socket, SOCKET_OPCODE_CLOSE, s->status, s->reason, s->len, TRUE, NULL ); + if (s->complete_async) ret = complete_send_frame( socket, &s->ovr, s->reason ); + else ret = send_frame( socket, SOCKET_OPCODE_CLOSE, s->status, s->reason, s->len, TRUE, NULL );
- send_io_complete( &s->socket->hdr ); - if (s->send_callback) socket_shutdown_complete( s->socket, ret ); - release_object( &s->socket->hdr ); - free( s ); + send_io_complete( &socket->hdr ); + if (s->send_callback) socket_shutdown_complete( socket, ret ); }
static DWORD send_socket_shutdown( struct socket *socket, USHORT status, const void *reason, DWORD len, @@ -3972,17 +3927,14 @@ static DWORD send_socket_shutdown( struct socket *socket, USHORT status, const v if (async_send) { s->complete_async = complete_async; - s->socket = socket; s->status = status; memcpy( s->reason, reason, len ); s->len = len; s->send_callback = send_callback;
- addref_object( &socket->hdr ); - if ((ret = queue_task( &socket->send_q, task_socket_shutdown, &s->task_hdr ))) + if ((ret = queue_task( &socket->send_q, task_socket_shutdown, &s->task_hdr, &socket->hdr ))) { InterlockedDecrement( &socket->hdr.pending_sends ); - release_object( &socket->hdr ); free( s ); } } @@ -4068,15 +4020,13 @@ static void socket_close_complete( struct socket *socket, DWORD ret ) static void task_socket_close( void *ctx ) { struct socket_shutdown *s = ctx; + struct socket *socket = (struct socket *)s->task_hdr.obj; DWORD ret;
TRACE("running %p\n", ctx);
- ret = socket_close( s->socket ); - socket_close_complete( s->socket, ret ); - - release_object( &s->socket->hdr ); - free( s ); + ret = socket_close( socket ); + socket_close_complete( socket, ret ); }
DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reason, DWORD len ) @@ -4137,14 +4087,8 @@ DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reas struct socket_shutdown *s;
if (!(s = calloc( 1, sizeof(*s) ))) return FALSE; - s->socket = socket; - - addref_object( &socket->hdr ); - if ((ret = queue_task( &socket->recv_q, task_socket_close, &s->task_hdr ))) - { - release_object( &socket->hdr ); + if ((ret = queue_task( &socket->recv_q, task_socket_close, &s->task_hdr, &socket->hdr ))) free( s ); - } } else ret = socket_close( socket );
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 96bd7b53747..35f3e64b5a3 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -278,12 +278,12 @@ typedef void (*TASK_CALLBACK)( void *ctx ); struct task_header { TASK_CALLBACK callback; + struct object_header *obj; };
struct send_request { struct task_header task_hdr; - struct request *request; WCHAR *headers; DWORD headers_len; void *optional; @@ -295,20 +295,17 @@ struct send_request struct receive_response { struct task_header task_hdr; - struct request *request; };
struct query_data { struct task_header task_hdr; - struct request *request; DWORD *available; };
struct read_data { struct task_header task_hdr; - struct request *request; void *buffer; DWORD to_read; DWORD *read; @@ -317,7 +314,6 @@ struct read_data struct write_data { struct task_header task_hdr; - struct request *request; const void *buffer; DWORD to_write; DWORD *written; @@ -326,7 +322,6 @@ struct write_data struct socket_send { struct task_header task_hdr; - struct socket *socket; WINHTTP_WEB_SOCKET_BUFFER_TYPE type; const void *buf; DWORD len; @@ -337,7 +332,6 @@ struct socket_send struct socket_receive { struct task_header task_hdr; - struct socket *socket; void *buf; DWORD len; }; @@ -345,7 +339,6 @@ struct socket_receive struct socket_shutdown { struct task_header task_hdr; - struct socket *socket; USHORT status; char reason[123]; DWORD len;
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- v2: - no changes.
dlls/winhttp/request.c | 86 +++++++++++++++++++++++----------- dlls/winhttp/session.c | 1 + dlls/winhttp/winhttp_private.h | 7 ++- 3 files changed, 64 insertions(+), 30 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index a825ac71d33..fe703c19109 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -122,54 +122,82 @@ static const WCHAR *attribute_table[] = NULL /* WINHTTP_QUERY_PASSPORT_CONFIG = 78 */ };
-static DWORD start_queue( struct queue *queue ) +void init_queue( struct queue *queue ) { - if (queue->pool) return ERROR_SUCCESS; - - if (!(queue->pool = CreateThreadpool( NULL ))) return GetLastError(); - SetThreadpoolThreadMinimum( queue->pool, 1 ); - SetThreadpoolThreadMaximum( queue->pool, 1 ); - - memset( &queue->env, 0, sizeof(queue->env) ); - queue->env.Version = 1; - queue->env.Pool = queue->pool; - - TRACE("started %p\n", queue); - return ERROR_SUCCESS; + InitializeSRWLock( &queue->lock ); + list_init( &queue->queued_tasks ); + queue->callback_running = FALSE; }
void stop_queue( struct queue *queue ) { - if (!queue->pool) return; - CloseThreadpool( queue->pool ); - queue->pool = NULL; + assert( list_empty( &queue->queued_tasks )); TRACE("stopped %p\n", queue); }
-static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work ) +static struct task_header *get_next_task( struct queue *queue ) { - struct task_header *task_hdr = ctx; + struct list *entry;
- task_hdr->callback( task_hdr ); - release_object( task_hdr->obj ); - free( task_hdr ); + AcquireSRWLockExclusive( &queue->lock ); + assert( queue->callback_running ); + if ((entry = list_head( &queue->queued_tasks ))) + list_remove( entry ); + else + queue->callback_running = FALSE; + ReleaseSRWLockExclusive( &queue->lock ); + if (!entry) return NULL; + return LIST_ENTRY( entry, struct task_header, entry ); +} + +static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx ) +{ + struct task_header *task, *next_task; + struct queue *queue = ctx; + + TRACE( "instance %p.\n", instance ); + + task = get_next_task( queue ); + while (task) + { + task->callback( task ); + /* Queue object may be freed by release_object() unless there is another task referencing it. */ + next_task = get_next_task( queue ); + release_object( task->obj ); + free( task ); + task = next_task; + } + TRACE( "instance %p exiting.\n", instance ); }
static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_header *task_hdr, struct object_header *obj ) { - TP_WORK *work; - DWORD ret; - - if ((ret = start_queue( queue ))) return ret; + BOOL callback_running;
- if (!(work = CreateThreadpoolWork( task_callback, task_hdr, &queue->env ))) return GetLastError(); TRACE("queueing %p in %p\n", task_hdr, queue); task_hdr->callback = task; task_hdr->obj = obj; addref_object( obj ); - SubmitThreadpoolWork( work ); - CloseThreadpoolWork( work ); + + AcquireSRWLockExclusive( &queue->lock ); + list_add_tail( &queue->queued_tasks, &task_hdr->entry ); + if (!(callback_running = queue->callback_running)) + { + if ((queue->callback_running = TrySubmitThreadpoolCallback( task_callback, queue, NULL ))) + callback_running = TRUE; + else + list_remove( &task_hdr->entry ); + } + ReleaseSRWLockExclusive( &queue->lock ); + + if (!callback_running) + { + release_object( obj ); + free( task_hdr ); + ERR( "Submiting threadpool callback failed, err %lu.\n", GetLastError() ); + return ERROR_OUTOFMEMORY; + }
return ERROR_SUCCESS; } @@ -3096,6 +3124,8 @@ HINTERNET WINAPI WinHttpWebSocketCompleteUpgrade( HINTERNET hrequest, DWORD_PTR socket->hdr.notify_mask = request->hdr.notify_mask; socket->hdr.context = context; InitializeSRWLock( &socket->send_lock ); + init_queue( &socket->send_q ); + init_queue( &socket->recv_q );
addref_object( &request->hdr ); socket->request = request; diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 7c55adb8475..3b00d2448d1 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -1160,6 +1160,7 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, const WCHAR *verb, cons request->hdr.notify_mask = connect->hdr.notify_mask; request->hdr.context = connect->hdr.context; request->hdr.redirect_policy = connect->hdr.redirect_policy; + init_queue( &request->queue );
addref_object( &connect->hdr ); request->connect = connect; diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 35f3e64b5a3..4754d9258d1 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -159,8 +159,9 @@ struct authinfo
struct queue { - TP_POOL *pool; - TP_CALLBACK_ENVIRON env; + SRWLOCK lock; + struct list queued_tasks; + BOOL callback_running; };
enum request_flags @@ -277,6 +278,7 @@ typedef void (*TASK_CALLBACK)( void *ctx );
struct task_header { + struct list entry; TASK_CALLBACK callback; struct object_header *obj; }; @@ -355,6 +357,7 @@ BOOL free_handle( HINTERNET ) DECLSPEC_HIDDEN;
void send_callback( struct object_header *, DWORD, LPVOID, DWORD ) DECLSPEC_HIDDEN; void close_connection( struct request * ) DECLSPEC_HIDDEN; +void init_queue( struct queue *queue ) DECLSPEC_HIDDEN; void stop_queue( struct queue * ) DECLSPEC_HIDDEN;
void netconn_close( struct netconn * ) DECLSPEC_HIDDEN;
Signed-off-by: Hans Leidekker hans@codeweavers.com