From 5082ebfd440fb3d496dc2fcbdd0367c903165820 Mon Sep 17 00:00:00 2001
From: Dongwan Kim <dongwan_kim@tmax.co.kr>
Date: Wed, 28 Apr 2021 18:10:11 +0900
Subject: [PATCH] ws2_32/sock: WSARecv/WSASend checks async pendings of the
 socket.

---
 dlls/ws2_32/socket.c           | 30 ++++++++++++++++++++++++++++--
 include/wine/server_protocol.h | 14 ++++++++++++++
 server/request.h               |  2 ++
 server/sock.c                  | 25 +++++++++++++++++++++++++
 4 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 29464fb94c9..3616476f194 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -2360,6 +2360,24 @@ static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserv
     release_async_io( &wsa->io );
 }
 
+
+static int WS_QueryAsyncWaiting( SOCKET sock, int type  )
+{
+    int result=0;
+
+    SERVER_START_REQ( query_async_waiting )
+    {
+        req->handle  = wine_server_obj_handle( SOCKET2HANDLE(sock) );
+        req->type   = type;
+        wine_server_call(req);
+	result =  reply->state;
+    }
+    SERVER_END_REQ;
+    if( result )  errno = EAGAIN;
+    return result;
+
+}
+
 /***********************************************************************
  *              WS2_recv                (INTERNAL)
  *
@@ -5492,7 +5510,12 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
     }
 
     flags = convert_flags(dwFlags);
-    n = WS2_send( fd, wsa, flags );
+    if(WS_QueryAsyncWaiting(s , ASYNC_TYPE_WRITE))
+	n = -1;
+    else
+        n = WS2_send( fd, wsa, flags );
+
+
     if (n == -1 && errno != EAGAIN)
     {
         err = wsaErrno();
@@ -7918,7 +7941,10 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
     flags = convert_flags(wsa->flags);
     for (;;)
     {
-        n = WS2_recv( fd, wsa, flags );
+	if( WS_QueryAsyncWaiting(s , ASYNC_TYPE_READ) )
+	    n = -1;
+	else
+            n = WS2_recv( fd, wsa, flags );
         if (n == -1)
         {
             /* Unix-like systems return EINVAL when attempting to read OOB data from
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 563799b6bdc..e19391b1e0b 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -2877,7 +2877,18 @@ struct register_async_reply
 #define ASYNC_TYPE_WRITE 0x02
 #define ASYNC_TYPE_WAIT  0x03
 
+struct query_async_waiting_request
+{
+    struct request_header __header;
+    obj_handle_t  handle;
+    int type;
 
+};
+struct query_async_waiting_reply
+{
+    struct reply_header __header;
+    int state;
+};
 
 struct cancel_async_request
 {
@@ -5649,6 +5660,7 @@ enum request
     REQ_terminate_job,
     REQ_suspend_process,
     REQ_resume_process,
+    REQ_query_async_waiting,
     REQ_NB_REQUESTS
 };
 
@@ -5929,6 +5941,7 @@ union generic_request
     struct terminate_job_request terminate_job_request;
     struct suspend_process_request suspend_process_request;
     struct resume_process_request resume_process_request;
+    struct query_async_waiting_request query_async_waiting_request;
 };
 union generic_reply
 {
@@ -6207,6 +6220,7 @@ union generic_reply
     struct terminate_job_reply terminate_job_reply;
     struct suspend_process_reply suspend_process_reply;
     struct resume_process_reply resume_process_reply;
+    struct query_async_waiting_reply query_async_waiting_reply;
 };
 
 /* ### protocol_version begin ### */
diff --git a/server/request.h b/server/request.h
index 0512d536ad5..9eca6fb9590 100644
--- a/server/request.h
+++ b/server/request.h
@@ -392,6 +392,7 @@ DECL_HANDLER(get_job_info);
 DECL_HANDLER(terminate_job);
 DECL_HANDLER(suspend_process);
 DECL_HANDLER(resume_process);
+DECL_HANDLER(query_async_waiting);
 
 #ifdef WANT_REQUEST_HANDLERS
 
@@ -671,6 +672,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_terminate_job,
     (req_handler)req_suspend_process,
     (req_handler)req_resume_process,
+    (req_handler)req_query_async_waiting,
 };
 
 C_ASSERT( sizeof(abstime_t) == 8 );
diff --git a/server/sock.c b/server/sock.c
index 39f02036da8..b638a71ba79 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -1767,6 +1767,31 @@ struct object *create_socket_device( struct object *root, const struct unicode_s
     return create_named_object( root, &socket_device_ops, name, attr, sd );
 }
 
+DECL_HANDLER( query_async_waiting )
+{
+    struct sock *sock;
+    struct async *async;
+    reply->state = 0;
+
+    if (!(sock = (struct sock *)get_handle_obj( current->process, req->handle,
+                                                FILE_READ_ATTRIBUTES, &sock_ops))) return;
+    if (get_unix_fd( sock->fd ) == -1) return;
+
+    if (is_fd_overlapped( sock->fd ))
+    {
+	if(req->type == ASYNC_TYPE_READ  &&  ( async = find_pending_async(&sock->read_q) )) {
+	    reply->state = 1;
+	    release_object(async);
+	}
+	if(req->type == ASYNC_TYPE_WRITE && ( async = find_pending_async(&sock->write_q )) )
+	{
+	    reply->state = 1;
+	    release_object(async);
+	}
+    }
+    release_object( &sock->obj );
+
+}
 /* set socket event parameters */
 DECL_HANDLER(set_socket_event)
 {
-- 
2.30.2

