Signed-off-by: Hans Leidekker hans@codeweavers.com --- dlls/winhttp/request.c | 69 +++++++++++++++++++++++++++++++++- dlls/winhttp/winhttp_private.h | 8 ++++ 2 files changed, 75 insertions(+), 2 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 372e0e5e77..7f1c727cba 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -3469,10 +3469,75 @@ DWORD WINAPI WinHttpWebSocketReceive( HINTERNET hsocket, void *buf, DWORD len, D return ret; }
+static DWORD socket_shutdown( struct socket *socket, USHORT status, const void *reason, DWORD len, BOOL async ) +{ + DWORD ret; + + ret = send_frame( socket->request->netconn, WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE, status, reason, len, TRUE ); + if (async) + { + if (!ret) send_callback( &socket->hdr, WINHTTP_CALLBACK_STATUS_SHUTDOWN_COMPLETE, NULL, 0 ); + else + { + WINHTTP_WEB_SOCKET_ASYNC_RESULT result; + result.AsyncResult.dwResult = API_WRITE_DATA; + result.AsyncResult.dwError = ret; + result.Operation = WINHTTP_WEB_SOCKET_SHUTDOWN_OPERATION; + send_callback( &socket->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); + } + } + + if (!ret) socket->state = SOCKET_STATE_SHUTDOWN; + return ret; +} + +static void task_socket_shutdown( struct task_header *task ) +{ + struct socket *socket = (struct socket *)task->object; + struct socket_shutdown *s = (struct socket_shutdown *)task; + + socket_shutdown( socket, s->status, s->reason, s->len, TRUE ); +} + DWORD WINAPI WinHttpWebSocketShutdown( HINTERNET hsocket, USHORT status, void *reason, DWORD len ) { - FIXME("%p, %u, %p, %u\n", hsocket, status, reason, len); - return ERROR_INVALID_PARAMETER; + struct socket *socket; + DWORD ret; + + TRACE("%p, %u, %p, %u\n", hsocket, status, reason, len); + + if (len && !reason) return ERROR_INVALID_PARAMETER; + + if (!(socket = (struct socket *)grab_object( hsocket ))) return ERROR_INVALID_HANDLE; + if (socket->hdr.type != WINHTTP_HANDLE_TYPE_SOCKET) + { + release_object( &socket->hdr ); + return ERROR_WINHTTP_INCORRECT_HANDLE_TYPE; + } + if (socket->state >= SOCKET_STATE_SHUTDOWN) + { + release_object( &socket->hdr ); + return ERROR_WINHTTP_INCORRECT_HANDLE_STATE; + } + + if (socket->request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) + { + struct socket_shutdown *s; + + if (!(s = heap_alloc( sizeof(*s) ))) return FALSE; + s->hdr.object = &socket->hdr; + s->hdr.proc = task_socket_shutdown; + s->status = status; + s->reason = reason; + s->len = len; + + addref_object( &socket->hdr ); + ret = queue_task( &socket->hdr, &socket->send_q, (struct task_header *)s ); + } + else ret = socket_shutdown( socket, status, reason, len, FALSE ); + + release_object( &socket->hdr ); + return ret; }
DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reason, DWORD len ) diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 9cf9c396cb..7d81e35934 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -292,6 +292,14 @@ struct socket_receive DWORD len; };
+struct socket_shutdown +{ + struct task_header hdr; + USHORT status; + const void *reason; + DWORD len; +}; + struct object_header *addref_object( struct object_header * ) DECLSPEC_HIDDEN; struct object_header *grab_object( HINTERNET ) DECLSPEC_HIDDEN; void release_object( struct object_header * ) DECLSPEC_HIDDEN;