From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/winhttp/handle.c | 7 ++++++- dlls/winhttp/net.c | 10 +++++++++- dlls/winhttp/request.c | 21 +++++++++++++++++++-- dlls/winhttp/session.c | 3 +++ dlls/winhttp/winhttp_private.h | 2 ++ 5 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/dlls/winhttp/handle.c b/dlls/winhttp/handle.c index 38959fd6456..33a4cd6bb71 100644 --- a/dlls/winhttp/handle.c +++ b/dlls/winhttp/handle.c @@ -142,7 +142,12 @@ BOOL free_handle( HINTERNET hinternet )
LeaveCriticalSection( &handle_cs );
- if (hdr) release_object( hdr ); + if (hdr) + { + if (hdr->vtbl->handle_closing) + hdr->vtbl->handle_closing( hdr ); + release_object( hdr ); + }
EnterCriticalSection( &handle_cs ); if (next_handle > handle && !handles[handle]) next_handle = handle; diff --git a/dlls/winhttp/net.c b/dlls/winhttp/net.c index 07a65c5465f..17520a54f63 100644 --- a/dlls/winhttp/net.c +++ b/dlls/winhttp/net.c @@ -269,7 +269,8 @@ void netconn_close( struct netconn *conn ) free(conn->extra_buf); DeleteSecurityContext(&conn->ssl_ctx); } - closesocket( conn->socket ); + if (conn->socket != -1) + closesocket( conn->socket ); release_host( conn->host ); free(conn); } @@ -629,6 +630,13 @@ DWORD netconn_recv( struct netconn *conn, void *buf, size_t len, int flags, int return ERROR_SUCCESS; }
+void netconn_cancel_io( struct netconn *conn ) +{ + SOCKET socket = InterlockedExchange( (LONG *)&conn->socket, -1 ); + + closesocket( socket ); +} + ULONG netconn_query_data_available( struct netconn *conn ) { return conn->secure ? conn->peek_len : 0; diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 4242551ee3b..269af0826c0 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -231,9 +231,10 @@ static BOOL task_needs_completion( struct task_header *task_hdr ) return !InterlockedExchange( &task_hdr->completion_sent, 1 ); }
-static void cancel_queue( struct queue *queue ) +static BOOL cancel_queue( struct queue *queue ) { struct task_header *task_hdr, *found; + BOOL cancelled = FALSE;
while (1) { @@ -250,9 +251,11 @@ static void cancel_queue( struct queue *queue ) } ReleaseSRWLockExclusive( &queue->lock ); if (!found) break; + cancelled = TRUE; found->callback( found, TRUE ); release_task( found ); } + return cancelled; }
static void free_header( struct header *header ) @@ -1885,7 +1888,8 @@ static void finished_reading( struct request *request )
if (!request->netconn) return;
- if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE; + if (request->netconn->socket == -1) close = TRUE; + else if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE; else if (!query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection, &size, NULL ) || !query_headers( request, WINHTTP_QUERY_PROXY_CONNECTION, NULL, connection, &size, NULL )) { @@ -3121,6 +3125,18 @@ BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, const void *buffer, DWORD to_w return !ret; }
+static void socket_handle_closing( struct object_header *hdr ) +{ + struct socket *socket = (struct socket *)hdr; + BOOL pending_tasks; + + pending_tasks = cancel_queue( &socket->send_q ); + pending_tasks = cancel_queue( &socket->recv_q ) || pending_tasks; + + if (pending_tasks) + netconn_cancel_io( socket->request->netconn ); +} + static BOOL socket_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen ) { FIXME( "unimplemented option %lu\n", option ); @@ -3151,6 +3167,7 @@ static BOOL socket_set_option( struct object_header *hdr, DWORD option, void *bu
static const struct object_vtbl socket_vtbl = { + socket_handle_closing, socket_destroy, socket_query_option, socket_set_option, diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 3b00d2448d1..01e95895eb3 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -242,6 +242,7 @@ static BOOL session_set_option( struct object_header *hdr, DWORD option, void *b
static const struct object_vtbl session_vtbl = { + NULL, session_destroy, session_query_option, session_set_option @@ -382,6 +383,7 @@ static BOOL connect_query_option( struct object_header *hdr, DWORD option, void
static const struct object_vtbl connect_vtbl = { + NULL, connect_destroy, connect_query_option, NULL @@ -1085,6 +1087,7 @@ static BOOL request_set_option( struct object_header *hdr, DWORD option, void *b
static const struct object_vtbl request_vtbl = { + NULL, request_destroy, request_query_option, request_set_option diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 17102107c77..98e05f068ba 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -30,6 +30,7 @@ struct object_header; struct object_vtbl { + void (*handle_closing) ( struct object_header * ); void (*destroy)( struct object_header * ); BOOL (*query_option)( struct object_header *, DWORD, void *, DWORD * ); BOOL (*set_option)( struct object_header *, DWORD, void *, DWORD ); @@ -370,6 +371,7 @@ DWORD netconn_recv( struct netconn *, void *, size_t, int, int * ) DECLSPEC_HIDD DWORD netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ) DECLSPEC_HIDDEN; DWORD netconn_secure_connect( struct netconn *, WCHAR *, DWORD, CredHandle *, BOOL ) DECLSPEC_HIDDEN; DWORD netconn_send( struct netconn *, const void *, size_t, int *, WSAOVERLAPPED * ) DECLSPEC_HIDDEN; +void netconn_cancel_io( struct netconn *conn ) DECLSPEC_HIDDEN; DWORD netconn_set_timeout( struct netconn *, BOOL, int ) DECLSPEC_HIDDEN; BOOL netconn_is_alive( struct netconn * ) DECLSPEC_HIDDEN; const void *netconn_get_certificate( struct netconn * ) DECLSPEC_HIDDEN;