From: "Erich E. Hoover" <ehoover@mines.edu>
Subject: [PATCH 1/1] ws2_32: Revise AcceptEx behavior to send completions for canceled sockets (resend, deferred).
Message-Id: <CAEU2+vonayZERcCVgNeQKEx4PjoG7wGRu+ZXvmWP3Gns2PvaNA@mail.gmail.com>
Date: Wed, 7 Mar 2012 15:31:08 -0700

Real Name:
    Erich Hoover

Description:
    This patch changes how AcceptEx and the wine server use
completions so that canceled sockets still send completion
notifications.  The patch fixes a significant issue with the WoW
launcher and the Diablo 3 installer (fixes Bug #27657 and partially
fixes Bug #28898).

Changelog:
    ws2_32: Revise AcceptEx behavior to send completions for canceled sockets.

From 9914dc08caf0a31746be533a82de302f398948d2 Mon Sep 17 00:00:00 2001
From: Erich Hoover <ehoover@mines.edu>
Date: Wed, 7 Mar 2012 15:28:39 -0700
Subject: ws2_32: Revise AcceptEx behavior to send completions for canceled
 sockets.

---
 dlls/ws2_32/socket.c |    8 ++++----
 server/async.c       |    6 ++++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index d3a4590..dd818f2 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -1700,7 +1700,7 @@ static NTSTATUS WS2_async_accept( void *arg, IO_STATUS_BLOCK *iosb, NTSTATUS sta
     if (status != STATUS_PENDING)
         goto finish;
 
-    return STATUS_SUCCESS;
+    return STATUS_ALERTED;
 
 finish:
     iosb->u.Status = status;
@@ -1708,8 +1708,6 @@ finish:
 
     if (wsa->user_overlapped->hEvent)
         SetEvent(wsa->user_overlapped->hEvent);
-    if (wsa->cvalue)
-        WS_AddCompletion( HANDLE2SOCKET(wsa->listen_socket), wsa->cvalue, iosb->u.Status, iosb->Information );
 
     *apc = ws2_async_accept_apc;
     return status;
@@ -2040,7 +2038,9 @@ static BOOL WINAPI WS2_AcceptEx(SOCKET listener, SOCKET acceptor, PVOID dest, DW
         req->async.callback = wine_server_client_ptr( WS2_async_accept );
         req->async.iosb     = wine_server_client_ptr( overlapped );
         req->async.arg      = wine_server_client_ptr( wsa );
-        /* We don't set event or completion since we may also have to read */
+        req->async.cvalue   = cvalue;
+        /* We don't set event since we may also have to read, completion returns STATUS_ALERTED
+         * to indicate that no completion should be queued. */
         status = wine_server_call( req );
     }
     SERVER_END_REQ;
diff --git a/server/async.c b/server/async.c
index dd28dff..b8be5cd 100644
--- a/server/async.c
+++ b/server/async.c
@@ -256,10 +256,12 @@ void async_set_result( struct object *obj, unsigned int status, unsigned int tot
     else
     {
         if (async->timeout) remove_timeout_user( async->timeout );
+        if (async->completion && async->data.cvalue && status != STATUS_ALERTED)
+            add_completion( async->completion, async->comp_key, async->data.cvalue, status, total );
+        else if (async->completion && async->data.cvalue && status == STATUS_ALERTED)
+            status = STATUS_SUCCESS;
         async->timeout = NULL;
         async->status = status;
-        if (async->completion && async->data.cvalue)
-            add_completion( async->completion, async->comp_key, async->data.cvalue, status, total );
         if (apc)
         {
             apc_call_t data;
-- 
1.7.5.4