diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c
index 2e6f8f7d4aa119ae45367eb70acc368ac7f75bb3..9c5dd6d2fe0585c527cfc0004524cbc7ad613365 100644
--- a/dlls/kernel/comm.c
+++ b/dlls/kernel/comm.c
@@ -93,8 +93,8 @@
 #include "winerror.h"
 
 #include "wine/server.h"
-#include "async.h"
 #include "wine/unicode.h"
+#include "thread.h"
 
 #include "wine/debug.h"
 
@@ -125,32 +125,15 @@ static inline void release_comm_fd( HANDLE handle, int fd )
  * Asynchronous I/O for asynchronous wait requests                     *
  */
 
-static DWORD commio_get_async_count (const async_private *ovp);
-static void commio_async_cleanup  (async_private *ovp);
-
-static async_ops commio_async_ops =
-{
-    commio_get_async_count,        /* get_count */
-    NULL,                          /* call_completion */
-    commio_async_cleanup           /* cleanup */
-};
-
 typedef struct async_commio
 {
-    struct async_private             async;
-    char                             *buffer;
+    HANDLE              handle;
+    PIO_APC_ROUTINE     apc_internal;
+    int                 type;
+    char*               buffer;
+    int                 fd;
 } async_commio;
 
-static DWORD commio_get_async_count (const struct async_private *ovp)
-{
-    return 0;
-}
-
-static void commio_async_cleanup  (async_private *ovp)
-{
-    HeapFree(GetProcessHeap(), 0, ovp );
-}
-
 /***********************************************************************/
 
 #if !defined(TIOCINQ) && defined(FIONREAD)
@@ -1928,17 +1911,27 @@ BOOL WINAPI GetCommModemStatus(
  *  This function is called while the client is waiting on the
  *  server, so we can't make any server calls here.
  */
-static void COMM_WaitCommEventService(async_private *ovp)
+static void WINAPI COMM_WaitCommEventService(void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
 {
     async_commio *commio = (async_commio*) ovp;
-    IO_STATUS_BLOCK* iosb = commio->async.iosb;
 
-    TRACE("iosb %p\n",iosb);
+    TRACE("iosb %p\n", iosb);
 
-    /* FIXME: detect other events */
-    *commio->buffer = EV_RXCHAR;
-
-    iosb->u.Status = STATUS_SUCCESS;
+    switch (status)
+    {
+    case STATUS_ALERTED: /* got some new stuff */
+        /* FIXME: detect other events */
+        *commio->buffer = EV_RXCHAR;
+        iosb->u.Status = STATUS_SUCCESS;
+        break;
+    default:
+        iosb->u.Status = status;
+        break;
+    }
+    wine_server_release_fd( commio->handle, commio->fd );
+    if ( ((LPOVERLAPPED)iosb)->hEvent != INVALID_HANDLE_VALUE )
+        NtSetEvent( ((LPOVERLAPPED)iosb)->hEvent, NULL );
+    HeapFree(GetProcessHeap(), 0, commio );
 }
 
 
@@ -1952,44 +1945,52 @@ static BOOL COMM_WaitCommEvent(
     LPDWORD lpdwEvents,        /* [out] event(s) that were detected */
     LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
 {
-    int fd;
-    async_commio *ovp;
+    int                 fd;
+    async_commio*       commio;
+    NTSTATUS            status;
 
-    if(!lpOverlapped)
+    if (!lpOverlapped)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
-    if(NtResetEvent(lpOverlapped->hEvent,NULL))
+    if (NtResetEvent(lpOverlapped->hEvent,NULL))
         return FALSE;
 
     fd = get_comm_fd( hFile, GENERIC_WRITE );
-    if(fd<0)
-	return FALSE;
+    if (fd < 0) return FALSE;
 
-    ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
-    if(!ovp)
+    commio = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
+    if (!commio)
     {
         release_comm_fd( hFile, fd );
         return FALSE;
     }
 
-    ovp->async.ops = &commio_async_ops;
-    ovp->async.handle = hFile;
-    ovp->async.fd = fd;  /* FIXME */
-    ovp->async.type = ASYNC_TYPE_WAIT;
-    ovp->async.func = COMM_WaitCommEventService;
-    ovp->async.event = lpOverlapped->hEvent;
-    ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
-    ovp->buffer = (char *)lpdwEvents;
+    commio->handle = hFile;
+    commio->type = ASYNC_TYPE_WAIT;
+    commio->apc_internal = COMM_WaitCommEventService;
+    commio->buffer = (char *)lpdwEvents;
+    commio->fd = fd;  /* FIXME */
 
     lpOverlapped->InternalHigh = 0;
     lpOverlapped->Offset = 0;
     lpOverlapped->OffsetHigh = 0;
 
-    if ( !register_new_async (&ovp->async) )
-        SetLastError( ERROR_IO_PENDING );
+    SERVER_START_REQ( register_async )
+    {
+        req->handle = hFile;
+        req->io_apc = COMM_WaitCommEventService;
+        req->io_user = commio;
+        req->io_sb = (IO_STATUS_BLOCK*)lpOverlapped;
+        req->count = 0;
+        status = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+
+    if ( status ) SetLastError( RtlNtStatusToDosError(status) );
+    else NtCurrentTeb()->num_async_io++;
 
     return FALSE;
 }
diff --git a/dlls/kernel/file.c b/dlls/kernel/file.c
index e63bb8e48c65b316823431422259b065752df5a3..b1817ac8cf30914327729d0097ecf241a4e436e5 100644
--- a/dlls/kernel/file.c
+++ b/dlls/kernel/file.c
@@ -43,7 +43,8 @@
 #include "excpt.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
-#include "async.h"
+#include "thread.h"
+#include "wine/server.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(file);
 
@@ -512,7 +513,7 @@ BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped,
         else
         {
             /* busy loop */
-            while ( (volatile DWORD)lpOverlapped->Internal == STATUS_PENDING )
+            while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
                 Sleep( 10 );
         }
     }
@@ -532,7 +533,7 @@ BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped,
     }
     if ( r == WAIT_FAILED )
     {
-        ERR("wait operation failed\n");
+        WARN("wait operation failed\n");
         return FALSE;
     }
     if (lpTransferred) *lpTransferred = lpOverlapped->InternalHigh;
@@ -556,17 +557,14 @@ BOOL WINAPI GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped,
  */
 BOOL WINAPI CancelIo(HANDLE handle)
 {
-    async_private *ovp,*t;
+    IO_STATUS_BLOCK    io_status;
 
-    TRACE("handle = %p\n",handle);
-
-    for (ovp = NtCurrentTeb()->pending_list; ovp; ovp = t)
+    NtCancelIoFile(handle, &io_status);
+    if (io_status.u.Status)
     {
-        t = ovp->next;
-        if ( ovp->handle == handle )
-             cancel_async ( ovp );
+        SetLastError( RtlNtStatusToDosError( io_status.u.Status ) );
+        return FALSE;
     }
-    SleepEx(1,TRUE);
     return TRUE;
 }
 
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index bfd72541e2ec1b7ebc9e3c9e28d47d876e40f820..6bf457ae9a1d9e2e21b28f53865d2d201898d315 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -62,7 +62,6 @@
 #include "wine/unicode.h"
 #include "wine/debug.h"
 #include "wine/server.h"
-#include "async.h"
 #include "ntdll_misc.h"
 
 #include "winternl.h"
@@ -222,59 +221,66 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB
 /***********************************************************************
  *                  Asynchronous file I/O                              *
  */
-static DWORD fileio_get_async_count(const async_private *ovp);
-static void CALLBACK fileio_call_completion_func(ULONG_PTR data);
-static void fileio_async_cleanup(async_private *ovp);
-
-static async_ops fileio_async_ops =
-{
-    fileio_get_async_count,        /* get_count */
-    fileio_call_completion_func,   /* call_completion */
-    fileio_async_cleanup           /* cleanup */
-};
-
-static async_ops fileio_nocomp_async_ops =
-{
-    fileio_get_async_count,        /* get_count */
-    NULL,                          /* call_completion */
-    fileio_async_cleanup           /* cleanup */
-};
+static void WINAPI FILE_AsyncReadService(void*, PIO_STATUS_BLOCK, ULONG);
+static void WINAPI FILE_AsyncWriteService(void*, PIO_STATUS_BLOCK, ULONG);
 
 typedef struct async_fileio
 {
-    struct async_private             async;
-    PIO_APC_ROUTINE                  apc;
-    void*                            apc_user;
-    char                             *buffer;
-    unsigned int                     count;
-    off_t                            offset;
-    int                              queue_apc_on_error;
-    BOOL                             avail_mode;
+    HANDLE              handle;
+    PIO_APC_ROUTINE     apc;
+    void*               apc_user;
+    char*               buffer;
+    unsigned int        count;
+    off_t               offset;
+    int                 queue_apc_on_error;
+    BOOL                avail_mode;
+    int                 fd;
+    HANDLE              event;
 } async_fileio;
 
-static DWORD fileio_get_async_count(const struct async_private *ovp)
+static void fileio_terminate(async_fileio *fileio, IO_STATUS_BLOCK* iosb)
 {
-    const async_fileio *fileio = (const async_fileio*) ovp;
+    TRACE("data: %p\n", fileio);
 
-    if (fileio->count < fileio->async.iosb->Information)
-    	return 0;
-    return fileio->count - fileio->async.iosb->Information;
-}
+    wine_server_release_fd( fileio->handle, fileio->fd );
+    if ( fileio->event != INVALID_HANDLE_VALUE )
+        NtSetEvent( fileio->event, NULL );
 
-static void CALLBACK fileio_call_completion_func(ULONG_PTR data)
-{
-    async_fileio *ovp = (async_fileio*) data;
-    TRACE("data: %p\n", ovp);
+    if (fileio->apc && 
+        (iosb->u.Status == STATUS_SUCCESS || fileio->queue_apc_on_error))
+        fileio->apc( fileio->apc_user, iosb, iosb->Information );
 
-    if ((ovp->async.iosb->u.Status == STATUS_SUCCESS) || ovp->queue_apc_on_error)
-        ovp->apc( ovp->apc_user, ovp->async.iosb, ovp->async.iosb->Information );
-
-    fileio_async_cleanup( &ovp->async );
+    RtlFreeHeap( GetProcessHeap(), 0, fileio );
 }
 
-static void fileio_async_cleanup( struct async_private *ovp )
+
+static ULONG fileio_queue_async(async_fileio* fileio, IO_STATUS_BLOCK* iosb, 
+                                BOOL do_read)
 {
-    RtlFreeHeap( GetProcessHeap(), 0, ovp );
+    PIO_APC_ROUTINE     apc = do_read ? FILE_AsyncReadService : FILE_AsyncWriteService;
+    NTSTATUS            status;
+
+    SERVER_START_REQ( register_async )
+    {
+        req->handle = fileio->handle;
+        req->io_apc = apc;
+        req->io_sb = iosb;
+        req->io_user = fileio;
+        req->type = do_read ? ASYNC_TYPE_READ : ASYNC_TYPE_WRITE;
+        req->count = (fileio->count < iosb->Information) ? 
+            0 : fileio->count - iosb->Information;
+        status = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+
+    if ( status ) iosb->u.Status = status;
+    if ( iosb->u.Status != STATUS_PENDING )
+    {
+        (apc)( fileio, iosb, iosb->u.Status );
+        return iosb->u.Status;
+    }
+    NtCurrentTeb()->num_async_io++;
+    return STATUS_SUCCESS;
 }
 
 /***********************************************************************
@@ -326,55 +332,75 @@ NTSTATUS FILE_GetNtStatus(void)
  *  This function is called while the client is waiting on the
  *  server, so we can't make any server calls here.
  */
-static void FILE_AsyncReadService(async_private *ovp)
+static void WINAPI FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, ULONG status)
 {
-    async_fileio *fileio = (async_fileio*) ovp;
-    IO_STATUS_BLOCK*  io_status = fileio->async.iosb;
+    async_fileio *fileio = (async_fileio*)user;
     int result;
-    int already = io_status->Information;
+    int already = iosb->Information;
 
-    TRACE("%p %p\n", io_status, fileio->buffer );
+    TRACE("%p %p %lu\n", iosb, fileio->buffer, status);
 
-    /* check to see if the data is ready (non-blocking) */
-
-    if ( fileio->avail_mode )
-        result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
-    else
+    switch (status)
     {
-        result = pread(ovp->fd, &fileio->buffer[already], fileio->count - already,
-                       fileio->offset + already);
-        if ((result < 0) && (errno == ESPIPE))
-            result = read(ovp->fd, &fileio->buffer[already], fileio->count - already);
-    }
+    case STATUS_ALERTED: /* got some new data */
+        if (iosb->u.Status != STATUS_PENDING) FIXME("unexpected status %08lx\n", iosb->u.Status);
+        /* check to see if the data is ready (non-blocking) */
+        if ( fileio->avail_mode )
+            result = read(fileio->fd, &fileio->buffer[already], 
+                          fileio->count - already);
+        else
+        {
+            result = pread(fileio->fd, &fileio->buffer[already],
+                           fileio->count - already,
+                           fileio->offset + already);
+            if ((result < 0) && (errno == ESPIPE))
+                result = read(fileio->fd, &fileio->buffer[already], 
+                              fileio->count - already);
+        }
 
-    if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
-    {
-        TRACE("Deferred read %d\n",errno);
-        io_status->u.Status = STATUS_PENDING;
-        return;
-    }
+        if (result < 0)
+        {
+            if (errno == EAGAIN || errno == EINTR)
+            {
+                TRACE("Deferred read %d\n", errno);
+                iosb->u.Status = STATUS_PENDING;
+            }
+            else /* check to see if the transfer is complete */
+                iosb->u.Status = FILE_GetNtStatus();
+        }
+        else if (result == 0)
+        {
+            iosb->u.Status = iosb->Information ? STATUS_SUCCESS : STATUS_END_OF_FILE;
+        }
+        else
+        {
+            iosb->Information += result;
+            if (iosb->Information >= fileio->count || fileio->avail_mode)
+                iosb->u.Status = STATUS_SUCCESS;
+            else
+            {
+                /* if we only have to read the available data, and none is available,
+                 * simply cancel the request. If data was available, it has been read
+                 * while in by previous call (NtDelayExecution)
+                 */
+                iosb->u.Status = (fileio->avail_mode) ? STATUS_SUCCESS : STATUS_PENDING;
+            }
 
-    /* check to see if the transfer is complete */
-    if (result < 0)
-    {
-        io_status->u.Status = FILE_GetNtStatus();
-        return;
-    }
-    else if (result == 0)
-    {
-        io_status->u.Status = io_status->Information ? STATUS_SUCCESS : STATUS_END_OF_FILE;
-        return;
+            TRACE("read %d more bytes %ld/%d so far (%s)\n",
+                  result, iosb->Information, fileio->count, 
+                  (iosb->u.Status == STATUS_SUCCESS) ? "success" : "pending");
+        }
+        /* queue another async operation ? */
+        if (iosb->u.Status == STATUS_PENDING)
+            fileio_queue_async(fileio, iosb, TRUE);
+        else
+            fileio_terminate(fileio, iosb);
+        break;
+    default:
+        iosb->u.Status = status;
+        fileio_terminate(fileio, iosb);
+        break;
     }
-
-    TRACE("status before: %s\n", (io_status->u.Status == STATUS_SUCCESS) ? "success" : "pending");
-    io_status->Information += result;
-    if (io_status->Information >= fileio->count || fileio->avail_mode )
-        io_status->u.Status = STATUS_SUCCESS;
-    else
-        io_status->u.Status = STATUS_PENDING;
-
-    TRACE("read %d more bytes %ld/%d so far (%s)\n",
-          result, io_status->Information, fileio->count, (io_status->u.Status == STATUS_SUCCESS) ? "success" : "pending");
 }
 
 
@@ -439,44 +465,41 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
 
     if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
     {
-        async_fileio*   ovp;
+        async_fileio*   fileio;
         NTSTATUS ret;
 
-        if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
+        if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
         {
             wine_server_release_fd( hFile, unix_handle );
             if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
             return STATUS_NO_MEMORY;
         }
-        ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
-        ovp->async.handle = hFile;
-        ovp->async.fd = unix_handle;  /* FIXME */
-        ovp->async.type = ASYNC_TYPE_READ;
-        ovp->async.func = FILE_AsyncReadService;
-        ovp->async.event = hEvent;
-        ovp->async.iosb = io_status;
-        ovp->count = length;
+        fileio->handle = hFile;
+        fileio->count = length;
         if ( offset == NULL ) 
-            ovp->offset = 0;
+            fileio->offset = 0;
         else
         {
-            ovp->offset = offset->QuadPart;
-            if (offset->u.HighPart && ovp->offset == offset->u.LowPart)
+            fileio->offset = offset->QuadPart;
+            if (offset->u.HighPart && fileio->offset == offset->u.LowPart)
                 FIXME("High part of offset is lost\n");
         } 
-        ovp->apc = apc;
-        ovp->apc_user = apc_user;
-        ovp->buffer = buffer;
-        ovp->queue_apc_on_error = 0;
-        ovp->avail_mode = (flags & FD_FLAG_AVAILABLE);
+        fileio->apc = apc;
+        fileio->apc_user = apc_user;
+        fileio->buffer = buffer;
+        fileio->queue_apc_on_error = 0;
+        fileio->avail_mode = (flags & FD_FLAG_AVAILABLE);
+        fileio->fd = unix_handle;  /* FIXME */
+        fileio->event = hEvent;
         NtResetEvent(hEvent, NULL);
 
-        ret = register_new_async(&ovp->async);
+        io_status->u.Status = STATUS_PENDING;
+        ret = fileio_queue_async(fileio, io_status, TRUE);
         if (ret != STATUS_SUCCESS)
         {
             wine_server_release_fd( hFile, unix_handle );
             if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
-            RtlFreeHeap(GetProcessHeap(), 0, ovp);
+            RtlFreeHeap(GetProcessHeap(), 0, fileio);
             return ret;
         }
         if (flags & FD_FLAG_TIMEOUT)
@@ -484,7 +507,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
             ret = NtWaitForSingleObject(hEvent, TRUE, NULL);
             NtClose(hEvent);
             if (ret != STATUS_USER_APC)
-                ovp->queue_apc_on_error = 1;
+                fileio->queue_apc_on_error = 1;
         }
         else
         {
@@ -499,16 +522,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
              * returning errors because apc's are run only during alertable
              * waits */
             if (ret != STATUS_USER_APC)
-                ovp->queue_apc_on_error = 1;
-            /* if we only have to read the available data, and none is available,
-             * simply cancel the request. If data was available, it has been read
-             * while in by previous call (NtDelayExecution)
-             */
-            if ((flags & FD_FLAG_AVAILABLE) && io_status->u.Status == STATUS_PENDING)
-            {
-                io_status->u.Status = STATUS_SUCCESS;
-                register_old_async(&ovp->async);
-            }
+                fileio->queue_apc_on_error = 1;
         }
         TRACE("= 0x%08lx\n", io_status->u.Status);
         return io_status->u.Status;
@@ -550,43 +564,50 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
  *  This function is called while the client is waiting on the
  *  server, so we can't make any server calls here.
  */
-static void FILE_AsyncWriteService(struct async_private *ovp)
+static void WINAPI FILE_AsyncWriteService(void *ovp, IO_STATUS_BLOCK *iosb, ULONG status)
 {
     async_fileio *fileio = (async_fileio *) ovp;
-    PIO_STATUS_BLOCK io_status = fileio->async.iosb;
     int result;
-    int already = io_status->Information;
-
-    TRACE("(%p %p)\n",io_status,fileio->buffer);
-
-    /* write some data (non-blocking) */
+    int already = iosb->Information;
 
-    if ( fileio->avail_mode )
-        result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
-    else
-    {
-        result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
-                        fileio->offset + already);
-        if ((result < 0) && (errno == ESPIPE))
-            result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
-    }
+    TRACE("(%p %p %lu)\n",iosb, fileio->buffer, status);
 
-    if ((result < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+    switch (status)
     {
-        io_status->u.Status = STATUS_PENDING;
-        return;
-    }
+    case STATUS_ALERTED:
+        /* write some data (non-blocking) */
+        if ( fileio->avail_mode )
+            result = write(fileio->fd, &fileio->buffer[already], 
+                           fileio->count - already);
+        else
+        {
+            result = pwrite(fileio->fd, &fileio->buffer[already], 
+                            fileio->count - already, fileio->offset + already);
+            if ((result < 0) && (errno == ESPIPE))
+                result = write(fileio->fd, &fileio->buffer[already], 
+                               fileio->count - already);
+        }
 
-    /* check to see if the transfer is complete */
-    if (result < 0)
-    {
-        io_status->u.Status = FILE_GetNtStatus();
-        return;
+        if (result < 0)
+        {
+            if (errno == EAGAIN || errno == EINTR) iosb->u.Status = STATUS_PENDING;
+            else iosb->u.Status = FILE_GetNtStatus();
+        }
+        else
+        {
+            iosb->Information += result;
+            iosb->u.Status = (iosb->Information < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
+            TRACE("wrote %d more bytes %ld/%d so far\n", 
+                  result, iosb->Information, fileio->count);
+        }
+        if (iosb->u.Status == STATUS_PENDING)
+            fileio_queue_async(fileio, iosb, FALSE);
+        break;
+    default:
+        iosb->u.Status = status;
+        fileio_terminate(fileio, iosb);
+        break;
     }
-
-    io_status->Information += result;
-    io_status->u.Status = (io_status->Information < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
-    TRACE("wrote %d more bytes %ld/%d so far\n",result,io_status->Information,fileio->count);
 }
 
 /******************************************************************************
@@ -651,46 +672,52 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
 
     if (flags & (FD_FLAG_OVERLAPPED|FD_FLAG_TIMEOUT))
     {
-        async_fileio*   ovp;
+        async_fileio*   fileio;
         NTSTATUS ret;
 
-        if (!(ovp = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
+        if (!(fileio = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(async_fileio))))
         {
             wine_server_release_fd( hFile, unix_handle );
+            if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
             return STATUS_NO_MEMORY;
         }
-        ovp->async.ops = (apc ? &fileio_async_ops : &fileio_nocomp_async_ops );
-        ovp->async.handle = hFile;
-        ovp->async.fd = unix_handle;  /* FIXME */
-        ovp->async.type = ASYNC_TYPE_WRITE;
-        ovp->async.func = FILE_AsyncWriteService;
-        ovp->async.event = hEvent;
-        ovp->async.iosb = io_status;
-        ovp->count = length;
-        if (offset) {
-            ovp->offset = offset->QuadPart;
-            if (offset->u.HighPart && ovp->offset == offset->u.LowPart)
+        fileio->handle = hFile;
+        fileio->count = length;
+        if (offset)
+        {
+            fileio->offset = offset->QuadPart;
+            if (offset->u.HighPart && fileio->offset == offset->u.LowPart)
                 FIXME("High part of offset is lost\n");
-        } else {
-            ovp->offset = 0;
         }
-        ovp->apc = apc;
-        ovp->apc_user = apc_user;
-        ovp->buffer = (void*)buffer;
-        ovp->queue_apc_on_error = 0;
-        ovp->avail_mode = (flags & FD_FLAG_AVAILABLE);
+        else  
+        {
+            fileio->offset = 0;
+        }
+        fileio->apc = apc;
+        fileio->apc_user = apc_user;
+        fileio->buffer = (void*)buffer;
+        fileio->queue_apc_on_error = 0;
+        fileio->avail_mode = (flags & FD_FLAG_AVAILABLE);
+        fileio->fd = unix_handle;  /* FIXME */
+        fileio->event = hEvent;
         NtResetEvent(hEvent, NULL);
 
         io_status->Information = 0;
-        ret = register_new_async(&ovp->async);
+        io_status->u.Status = STATUS_PENDING;
+        ret = fileio_queue_async(fileio, io_status, FALSE);
         if (ret != STATUS_SUCCESS)
+        {
+            wine_server_release_fd( hFile, unix_handle );
+            if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent);
+            RtlFreeHeap(GetProcessHeap(), 0, fileio);
             return ret;
+        }
         if (flags & FD_FLAG_TIMEOUT)
         {
             ret = NtWaitForSingleObject(hEvent, TRUE, NULL);
             NtClose(hEvent);
             if (ret != STATUS_USER_APC)
-                ovp->queue_apc_on_error = 1;
+                fileio->queue_apc_on_error = 1;
         }
         else
         {
@@ -705,7 +732,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
              * returning errors because apc's are run only during alertable
              * waits */
             if (ret != STATUS_USER_APC)
-                ovp->queue_apc_on_error = 1;
+                fileio->queue_apc_on_error = 1;
         }
         return io_status->u.Status;
     }
@@ -1688,9 +1715,23 @@ NTSTATUS WINAPI NtDeleteFile( POBJECT_ATTRIBUTES ObjectAttributes )
  *
  *
  */
-NTSTATUS WINAPI NtCancelIoFile( HANDLE FileHandle,
-    PIO_STATUS_BLOCK IoStatusBlock)
+NTSTATUS WINAPI NtCancelIoFile( HANDLE hFile, PIO_STATUS_BLOCK io_status )
 {
-    FIXME("%p %p\n", FileHandle, IoStatusBlock );
-    return STATUS_NOT_IMPLEMENTED;
+    LARGE_INTEGER timeout;
+
+    TRACE("%p %p\n", hFile, io_status );
+
+    SERVER_START_REQ( cancel_async )
+    {
+        req->handle = hFile;
+        wine_server_call( req );
+    }
+    SERVER_END_REQ;
+    /* Let some APC be run, so that we can run the remaining APCs on hFile
+     * either the cancelation of the pending one, but also the execution
+     * of the queued APC, but not yet run. This is needed to ensure proper
+     * clean-up of allocated data.
+     */
+    timeout.u.LowPart = timeout.u.HighPart = 0;
+    return io_status->u.Status = NtDelayExecution( TRUE, &timeout );
 }
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 19733fbb80813c42d4ef204b08511f48dedc51d1..adec16a6113c753d53878726ad13fac60e0e5c4c 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -51,7 +51,6 @@
 #include "winbase.h"
 #include "winreg.h"
 #include "winternl.h"
-#include "async.h"
 #include "thread.h"
 #include "wine/server.h"
 #include "wine/debug.h"
@@ -604,35 +603,6 @@ NTSTATUS WINAPI NtSetTimerResolution(IN ULONG resolution,
 }
 
 
-/***********************************************************************
- *           check_async_list
- *
- * Process a status event from the server.
- */
-static void WINAPI check_async_list(async_private *asp, DWORD status)
-{
-    async_private *ovp;
-    DWORD ovp_status;
-
-    for( ovp = NtCurrentTeb()->pending_list; ovp && ovp != asp; ovp = ovp->next );
-
-    if(!ovp)
-            return;
-
-    if( status != STATUS_ALERTED )
-    {
-        ovp_status = status;
-        ovp->iosb->u.Status = status;
-    }
-    else ovp_status = ovp->iosb->u.Status;
-
-    if( ovp_status == STATUS_PENDING ) ovp->func( ovp );
-
-    /* This will destroy all but PENDING requests */
-    register_old_async( ovp );
-}
-
-
 /***********************************************************************
  *              wait_reply
  *
@@ -697,7 +667,7 @@ static void call_apcs( BOOL alertable )
         }
         SERVER_END_REQ;
 
-        switch(type)
+        switch (type)
         {
         case APC_NONE:
             return;  /* no more APCs */
@@ -714,7 +684,8 @@ static void call_apcs( BOOL alertable )
             proc( arg3, time.u.LowPart, time.u.HighPart );
             break;
         case APC_ASYNC_IO:
-            check_async_list( arg1, (DWORD) arg2 );
+            NtCurrentTeb()->num_async_io--;
+            proc( arg1, (IO_STATUS_BLOCK*)arg2, (ULONG)arg3 );
             break;
         default:
             server_protocol_error( "get_apc_request: bad type %d\n", type );
@@ -810,7 +781,7 @@ NTSTATUS WINAPI NtYieldExecution(void)
 NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeout )
 {
     /* if alertable or async I/O in progress, we need to query the server */
-    if (alertable || NtCurrentTeb()->pending_list)
+    if (alertable || NtCurrentTeb()->num_async_io)
     {
         UINT flags = SELECT_INTERRUPTIBLE;
         if (alertable) flags |= SELECT_ALERTABLE;
diff --git a/dlls/winsock/socket.c b/dlls/winsock/socket.c
index 0199e824ce1087d0d0030beef72b698a2851a3de..41dda63676ccbce76ae20fc4cc7bd2bddbd51020 100644
--- a/dlls/winsock/socket.c
+++ b/dlls/winsock/socket.c
@@ -128,6 +128,7 @@
 #include "thread.h"
 #include "wine/server.h"
 #include "wine/debug.h"
+#include "ntstatus.h"
 #include "wine/unicode.h"
 
 #ifdef HAVE_IPX
@@ -161,39 +162,24 @@ inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
 /****************************************************************
  * Async IO declarations
  ****************************************************************/
-#include "async.h"
-
-static DWORD ws2_async_get_count  (const struct async_private *ovp);
-static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
-static void ws2_async_cleanup ( struct async_private *ovp );
-
-static struct async_ops ws2_async_ops =
-{
-    ws2_async_get_count,
-    ws2_async_call_completion,
-    ws2_async_cleanup
-};
-
-static struct async_ops ws2_nocomp_async_ops =
-{
-    ws2_async_get_count,
-    NULL,                     /* call_completion */
-    ws2_async_cleanup
-};
 
 typedef struct ws2_async
 {
-    async_private                       async;
+    HANDLE                              hSocket;
+    enum ws2_mode {ws2m_read, ws2m_write, ws2m_sd_read, ws2m_sd_write} mode;
     LPWSAOVERLAPPED                     user_overlapped;
     LPWSAOVERLAPPED_COMPLETION_ROUTINE  completion_func;
     struct iovec                        *iovec;
     int                                 n_iovecs;
     struct WS_sockaddr                  *addr;
-    union {
+    union
+    {
         int val;     /* for send operations */
         int *ptr;    /* for recv operations */
     }                                   addrlen;
     DWORD                               flags;
+    int                                 fd;
+    HANDLE                              event;
 } ws2_async;
 
 /****************************************************************/
@@ -290,7 +276,7 @@ static const int ws_ip_map[][2] =
     { 0, 0 }
 };
 
-inline static DWORD NtStatusToWSAError ( const DWORD status )
+inline static DWORD NtStatusToWSAError( const DWORD status )
 {
     /* We only need to cover the status codes set by server async request handling */
     DWORD wserr;
@@ -311,7 +297,7 @@ inline static DWORD NtStatusToWSAError ( const DWORD status )
         else
         {
             wserr = RtlNtStatusToDosError( status );
-            FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
+            FIXME( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
         }
     }
     return wserr;
@@ -322,7 +308,7 @@ inline static unsigned int set_error( unsigned int err )
 {
     if (err)
     {
-        err = NtStatusToWSAError ( err );
+        err = NtStatusToWSAError( err );
         SetLastError( err );
     }
     return err;
@@ -611,7 +597,7 @@ static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
     {
 	unsigned int i;
 
-	for( i = 0; i < wsfds->fd_count; i++ )
+	for ( i = 0; i < wsfds->fd_count; i++ )
 	    if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
         wsfds->fd_count = 0;
     }
@@ -818,7 +804,6 @@ static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr,
         *uaddrlen=wsaddrlen;
         return (const struct sockaddr*)wsaddr;
     }
-    return NULL;
 }
 
 /* Allocates a Unix sockaddr structure to receive the data */
@@ -916,138 +901,164 @@ inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_socka
  * Functions for handling overlapped I/O
  **************************************************************************/
 
-static DWORD ws2_async_get_count (const struct async_private *ovp)
+static void CALLBACK ws2_async_terminate(ws2_async* as, IO_STATUS_BLOCK* iosb)
 {
-    return ovp->iosb->Information;
-}
+    TRACE( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, iosb );
 
-static void ws2_async_cleanup ( struct async_private *ap )
-{
-    struct ws2_async *as = (struct ws2_async*) ap;
+    wine_server_release_fd( as->hSocket, as->fd );
+    if ( as->event != INVALID_HANDLE_VALUE )
+        NtSetEvent( as->event, NULL );
 
-    TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->async.iosb );
+    if (as->completion_func)
+        as->completion_func( NtStatusToWSAError (iosb->u.Status),
+                             iosb->Information, as->user_overlapped, as->flags );
     if ( !as->user_overlapped )
     {
 #if 0
         /* FIXME: I don't think this is really used */
         if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
-            WSACloseEvent ( as->overlapped->hEvent  );
+            WSACloseEvent( as->overlapped->hEvent  );
 #endif
-        HeapFree ( GetProcessHeap(), 0, as->async.iosb );
+        HeapFree( GetProcessHeap(), 0, iosb );
     }
 
-    HeapFree ( GetProcessHeap(), 0, as->iovec );
-    HeapFree ( GetProcessHeap(), 0, as );
-}
-
-static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
-{
-    ws2_async* as = (ws2_async*) data;
-
-    TRACE ("data: %p\n", as);
-
-    as->completion_func ( NtStatusToWSAError (as->async.iosb->u.Status),
-                          as->async.iosb->Information,
-                          as->user_overlapped,
-                          as->flags );
-    ws2_async_cleanup ( &as->async );
+    HeapFree( GetProcessHeap(), 0, as->iovec );
+    HeapFree( GetProcessHeap(), 0, as );
 }
 
 /***********************************************************************
  *              WS2_make_async          (INTERNAL)
  */
 
-static void WS2_async_recv (async_private *as);
-static void WS2_async_send (async_private *as);
+static void WINAPI WS2_async_recv(void*, IO_STATUS_BLOCK*, ULONG);
+static void WINAPI WS2_async_send(void*, IO_STATUS_BLOCK*, ULONG);
+static void WINAPI WS2_async_shutdown( void*, IO_STATUS_BLOCK*, ULONG);
 
 inline static struct ws2_async*
-WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
-                LPDWORD lpFlags, struct WS_sockaddr *addr,
-                LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
-                LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+WS2_make_async(SOCKET s, int fd, enum ws2_mode mode, struct iovec *iovec, DWORD dwBufferCount,
+               LPDWORD lpFlags, struct WS_sockaddr *addr,
+               LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
+               LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
+               IO_STATUS_BLOCK **piosb)
 {
-    struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
+    struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof( ws2_async ) );
 
-    TRACE ( "wsa %p\n", wsa );
+    TRACE( "wsa %p\n", wsa );
 
     if (!wsa)
         return NULL;
 
-    wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
-    wsa->async.handle = (HANDLE) s;
-    wsa->async.fd = fd;
-    wsa->async.type = type;
-    switch (type)
+    wsa->hSocket = (HANDLE) s;
+    wsa->mode = mode;
+    switch (mode)
     {
-    case ASYNC_TYPE_READ:
+    case ws2m_read:
+    case ws2m_sd_read:
         wsa->flags = *lpFlags;
-        wsa->async.func = WS2_async_recv;
         wsa->addrlen.ptr = addrlen;
         break;
-    case ASYNC_TYPE_WRITE:
+    case ws2m_write:
+    case ws2m_sd_write:
         wsa->flags = 0;
-        wsa->async.func = WS2_async_send;
         wsa->addrlen.val = *addrlen;
         break;
     default:
-        ERR ("Invalid async type: %d\n", type);
+        ERR("Invalid async mode: %d\n", mode);
     }
     wsa->user_overlapped = lpOverlapped;
     wsa->completion_func = lpCompletionRoutine;
     wsa->iovec = iovec;
     wsa->n_iovecs = dwBufferCount;
     wsa->addr = addr;
+    wsa->fd = fd;
+    wsa->event = INVALID_HANDLE_VALUE;
 
     if ( lpOverlapped )
     {
-        wsa->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
-        wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
-    }
-    else
-    {
-        wsa->async.iosb = HeapAlloc ( GetProcessHeap(), 0,
-                                      sizeof (IO_STATUS_BLOCK) );
-        if ( !wsa->async.iosb )
-            goto error;
-        wsa->async.event = INVALID_HANDLE_VALUE;
+        *piosb = (IO_STATUS_BLOCK*)lpOverlapped;
+        if (!lpCompletionRoutine)
+        {
+            wsa->event = lpOverlapped->hEvent;
+            NtResetEvent(wsa->event, NULL);
+        }
     }
+    else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
+        goto error;
 
-    wsa->async.iosb->Information = 0;
-    TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, iosb %p, uov %p, cfunc %p\n",
-            wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
-            wsa->async.iosb, wsa->user_overlapped, wsa->completion_func );
+    (*piosb)->Information = 0;
+    (*piosb)->u.Status = STATUS_PENDING;
+    TRACE( "wsa %p, h %p, ev %p, fd %d, iosb %p, uov %p, cfunc %p\n",
+           wsa, wsa->hSocket, wsa->event, wsa->fd,
+           *piosb, wsa->user_overlapped, wsa->completion_func );
 
     return wsa;
 
 error:
-    TRACE ("Error\n");
-    HeapFree ( GetProcessHeap(), 0, wsa );
+    TRACE("Error\n");
+    HeapFree( GetProcessHeap(), 0, wsa );
     return NULL;
 }
 
+static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
+{
+    PIO_APC_ROUTINE     apc;
+    int                 type;
+    NTSTATUS            status;
+
+    switch (wsa->mode)
+    {
+    case ws2m_read:     apc = WS2_async_recv;     type = ASYNC_TYPE_READ;  break;
+    case ws2m_write:    apc = WS2_async_send;     type = ASYNC_TYPE_WRITE; break;
+    case ws2m_sd_read:  apc = WS2_async_shutdown; type = ASYNC_TYPE_READ;  break;
+    case ws2m_sd_write: apc = WS2_async_shutdown; type = ASYNC_TYPE_WRITE; break;
+    default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER;
+    }
+
+    SERVER_START_REQ( register_async )
+    {
+        req->handle = wsa->hSocket;
+        req->io_apc = apc;
+        req->io_sb = iosb;
+        req->io_user = wsa;
+        req->type = type;
+        req->count = iosb->Information;
+        status = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+
+    if ( status ) iosb->u.Status = status;
+    if ( iosb->u.Status != STATUS_PENDING )
+    {
+        (apc)( wsa, iosb, iosb->u.Status );
+        return iosb->u.Status;
+    }
+    NtCurrentTeb()->num_async_io++;
+    return STATUS_SUCCESS;
+}
+
 /***********************************************************************
  *              WS2_recv                (INTERNAL)
  *
  * Workhorse for both synchronous and asynchronous recv() operations.
  */
-static int WS2_recv ( int fd, struct iovec* iov, int count,
-                      struct WS_sockaddr *lpFrom, LPINT lpFromlen,
+static int WS2_recv( int fd, struct iovec* iov, int count,
+                     struct WS_sockaddr *lpFrom, LPINT lpFromlen,
                       LPDWORD lpFlags )
 {
     struct msghdr hdr;
     int n;
-    TRACE ( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
-            fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
+    TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
+           fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
 
     hdr.msg_name = NULL;
 
     if ( lpFrom )
     {
         hdr.msg_namelen = *lpFromlen;
-        hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
+        hdr.msg_name = ws_sockaddr_alloc( lpFrom, lpFromlen, &hdr.msg_namelen );
         if ( !hdr.msg_name )
         {
-            WSASetLastError ( WSAEFAULT );
+            WSASetLastError( WSAEFAULT );
             n = -1;
             goto out;
         }
@@ -1066,27 +1077,27 @@ static int WS2_recv ( int fd, struct iovec* iov, int count,
     hdr.msg_flags = 0;
 #endif
 
-    if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
+    if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
     {
-        TRACE ( "recvmsg error %d\n", errno);
+        TRACE( "recvmsg error %d\n", errno);
         goto out;
     }
 
     if ( lpFrom &&
-         ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
-                            lpFrom, lpFromlen ) != 0 )
+         ws_sockaddr_u2ws( hdr.msg_name, hdr.msg_namelen,
+                           lpFrom, lpFromlen ) != 0 )
     {
         /* The from buffer was too small, but we read the data
          * anyway. Is that really bad?
          */
-        WSASetLastError ( WSAEFAULT );
-        WARN ( "Address buffer too small\n" );
+        WSASetLastError( WSAEFAULT );
+        WARN( "Address buffer too small\n" );
     }
 
 out:
 
-    ws_sockaddr_free ( hdr.msg_name, lpFrom );
-    TRACE ("-> %d\n", n);
+    ws_sockaddr_free( hdr.msg_name, lpFrom );
+    TRACE("-> %d\n", n);
     return n;
 }
 
@@ -1095,43 +1106,51 @@ out:
  *
  * Handler for overlapped recv() operations.
  */
-static void WS2_async_recv ( async_private *as )
+static void WINAPI WS2_async_recv( void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
 {
-    ws2_async* wsa = (ws2_async*) as;
+    ws2_async* wsa = (ws2_async*) ovp;
     int result, err;
 
-    TRACE ( "async %p\n", wsa );
+    TRACE( "(%p %p %lx)\n", wsa, iosb, status );
 
-    if ( wsa->async.iosb->u.Status != STATUS_PENDING )
+    switch (status)
     {
-        TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
-        return;
-    }
-
-    result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
-                        wsa->addr, wsa->addrlen.ptr, &wsa->flags );
-
-    if (result >= 0)
-    {
-        wsa->async.iosb->u.Status = STATUS_SUCCESS;
-        wsa->async.iosb->Information = result;
-        TRACE ( "received %d bytes\n", result );
-        _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
+    case STATUS_ALERTED:
+        result = WS2_recv( wsa->fd, wsa->iovec, wsa->n_iovecs,
+                           wsa->addr, wsa->addrlen.ptr, &wsa->flags );
+        if (result >= 0)
+        {
+            iosb->u.Status = STATUS_SUCCESS;
+            iosb->Information = result;
+            TRACE( "received %d bytes\n", result );
+            _enable_event( wsa->hSocket, FD_READ, 0, 0 );
+        }
+        else
+        {
+            err = wsaErrno();
+            if ( err == WSAEINTR || err == WSAEWOULDBLOCK )  /* errno: EINTR / EAGAIN */
+            {
+                iosb->u.Status = STATUS_PENDING;
+                _enable_event( wsa->hSocket, FD_READ, 0, 0 );
+                TRACE( "still pending\n" );
+            }
+            else
+            {
+                iosb->u.Status = err; /* FIXME: is this correct ???? */
+                TRACE( "Error: %x\n", err );
+            }
+        }
+        if (iosb->u.Status == STATUS_PENDING)
+            ws2_queue_async(wsa, iosb);
+        else
+            ws2_async_terminate(wsa, iosb);
+        break;
+    default:
+        FIXME( "status: %ld\n", status );
+        iosb->u.Status = status;
+        ws2_async_terminate(wsa, iosb);
         return;
     }
-
-    err = wsaErrno ();
-    if ( err == WSAEINTR || err == WSAEWOULDBLOCK )  /* errno: EINTR / EAGAIN */
-    {
-        wsa->async.iosb->u.Status = STATUS_PENDING;
-        _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
-        TRACE ( "still pending\n" );
-    }
-    else
-    {
-        wsa->async.iosb->u.Status = err;
-        TRACE ( "Error: %x\n", err );
-    }
 }
 
 /***********************************************************************
@@ -1139,22 +1158,22 @@ static void WS2_async_recv ( async_private *as )
  *
  * Workhorse for both synchronous and asynchronous send() operations.
  */
-static int WS2_send ( int fd, struct iovec* iov, int count,
-                      const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
+static int WS2_send( int fd, struct iovec* iov, int count,
+                     const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
 {
     struct msghdr hdr;
     int n = -1;
-    TRACE ( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
-            fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
+    TRACE( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
+           fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
 
     hdr.msg_name = NULL;
 
     if ( to )
     {
-        hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
+        hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u( to, tolen, &hdr.msg_namelen );
         if ( !hdr.msg_name )
         {
-            WSASetLastError ( WSAEFAULT );
+            WSASetLastError( WSAEFAULT );
             goto out;
         }
 
@@ -1195,10 +1214,10 @@ static int WS2_send ( int fd, struct iovec* iov, int count,
     hdr.msg_flags = 0;
 #endif
 
-    n = sendmsg (fd, &hdr, dwFlags);
+    n = sendmsg(fd, &hdr, dwFlags);
 
 out:
-    ws_sockaddr_free ( hdr.msg_name, to );
+    ws_sockaddr_free( hdr.msg_name, to );
     return n;
 }
 
@@ -1207,45 +1226,57 @@ out:
  *
  * Handler for overlapped send() operations.
  */
-static void WS2_async_send ( async_private *as )
+static void WINAPI WS2_async_send(void* as, IO_STATUS_BLOCK* iosb, ULONG status)
 {
     ws2_async* wsa = (ws2_async*) as;
-    int result, err;
+    int result;
 
-    TRACE ( "async %p\n", wsa );
+    TRACE( "(%p %p %lx)\n", wsa, iosb, status );
 
-    if ( wsa->async.iosb->u.Status != STATUS_PENDING )
+    switch (status)
     {
-        TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
-        return;
-    }
+    case STATUS_ALERTED:
+        if (iosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", iosb->u.Status);
+        /* check to see if the data is ready (non-blocking) */
+        result = WS2_send( wsa->fd, wsa->iovec, wsa->n_iovecs,
+                           wsa->addr, wsa->addrlen.val, wsa->flags );
 
-    result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
-                        wsa->addr, wsa->addrlen.val, wsa->flags );
-
-    if (result >= 0)
-    {
-        wsa->async.iosb->u.Status = STATUS_SUCCESS;
-        wsa->async.iosb->Information = result;
-        TRACE ( "sent %d bytes\n", result );
-        _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
+        if (result >= 0)
+        {
+            iosb->u.Status = STATUS_SUCCESS;
+            iosb->Information = result;
+            TRACE( "sent %d bytes\n", result );
+            _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
+        }
+        else
+        {
+            int err = wsaErrno();
+            if ( err == WSAEINTR )
+            {
+                iosb->u.Status = STATUS_PENDING;
+                _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
+                TRACE( "still pending\n" );
+            }
+            else
+            {
+                /* We set the status to a winsock error code and check for that
+                   later in NtStatusToWSAError () */
+                iosb->u.Status = err;
+                TRACE( "Error: %x\n", err );
+            }
+        }
+        if (iosb->u.Status == STATUS_PENDING)
+            ws2_queue_async(wsa, iosb);
+        else
+            ws2_async_terminate(wsa, iosb);
+        break;
+    default:
+        FIXME( "status: %ld\n", status );
+        iosb->u.Status = status;
+        ws2_async_terminate(wsa, iosb);
         return;
     }
 
-    err = wsaErrno ();
-    if ( err == WSAEINTR )
-    {
-        wsa->async.iosb->u.Status = STATUS_PENDING;
-        _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
-        TRACE ( "still pending\n" );
-    }
-    else
-    {
-        /* We set the status to a winsock error code and check for that
-           later in NtStatusToWSAError () */
-        wsa->async.iosb->u.Status = err;
-        TRACE ( "Error: %x\n", err );
-    }
 }
 
 /***********************************************************************
@@ -1253,28 +1284,33 @@ static void WS2_async_send ( async_private *as )
  *
  * Handler for shutdown() operations on overlapped sockets.
  */
-static void WS2_async_shutdown ( async_private *as )
+static void WINAPI WS2_async_shutdown( void* as, PIO_STATUS_BLOCK iosb, ULONG status )
 {
     ws2_async* wsa = (ws2_async*) as;
     int err = 1;
 
-    TRACE ( "async %p %d\n", wsa, wsa->async.type );
-    switch ( wsa->async.type )
+    TRACE( "async %p %d\n", wsa, wsa->mode );
+    switch (status)
     {
-    case ASYNC_TYPE_READ:
-        err = shutdown ( wsa->async.fd, 0 );
-        break;
-    case ASYNC_TYPE_WRITE:
-        err = shutdown ( wsa->async.fd, 1 );
+    case STATUS_ALERTED:
+        switch ( wsa->mode )
+        {
+        case ws2m_sd_read:   err = shutdown( wsa->fd, 0 );  break;
+        case ws2m_sd_write:  err = shutdown( wsa->fd, 1 );  break;
+        default: ERR("invalid mode: %d\n", wsa->mode );
+        }
+        iosb->u.Status = err ? wsaErrno() : STATUS_SUCCESS;
+        if (iosb->u.Status == STATUS_PENDING)
+            ws2_queue_async(wsa, iosb);
+        else
+            ws2_async_terminate(wsa, iosb);
         break;
     default:
-        ERR ("invalid type: %d\n", wsa->async.type );
+        iosb->u.Status = status;
+        ws2_async_terminate(wsa, iosb);
+        break;
     }
 
-    if ( err )
-        wsa->async.iosb->u.Status = wsaErrno ();
-    else
-        wsa->async.iosb->u.Status = STATUS_SUCCESS;
 }
 
 /***********************************************************************
@@ -1282,43 +1318,44 @@ static void WS2_async_shutdown ( async_private *as )
  *
  * Helper function for WS_shutdown() on overlapped sockets.
  */
-static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
+static int WS2_register_async_shutdown( SOCKET s, int fd, enum ws2_mode mode )
 {
     struct ws2_async *wsa;
     int ret, err = WSAEFAULT;
     DWORD dwflags = 0;
     int len = 0;
-    LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
+    LPWSAOVERLAPPED ovl = HeapAlloc(GetProcessHeap(), 0, sizeof( WSAOVERLAPPED ));
+    IO_STATUS_BLOCK *iosb;
 
-    TRACE ("s %d fd %d type %d\n", s, fd, type);
+    TRACE("s %d fd %d mode %d\n", s, fd, mode);
     if (!ovl)
         goto out;
 
-    ovl->hEvent = WSACreateEvent ();
-    if ( ovl->hEvent == WSA_INVALID_EVENT  )
+    ovl->hEvent = WSACreateEvent();
+    if ( ovl->hEvent == WSA_INVALID_EVENT )
         goto out_free;
 
-    wsa = WS2_make_async ( s, fd, type, NULL, 0,
-                           &dwflags, NULL, &len, ovl, NULL );
+    wsa = WS2_make_async( s, fd, mode, NULL, 0,
+                          &dwflags, NULL, &len, ovl, NULL, &iosb );
     if ( !wsa )
         goto out_close;
 
     /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
     wsa->user_overlapped = NULL;
-    wsa->async.func = WS2_async_shutdown;
-    if ( (ret = register_new_async ( &wsa->async )) )
+    if ( (ret = ws2_queue_async( wsa, iosb )) )
     {
-        err = NtStatusToWSAError ( ret );
+        err = NtStatusToWSAError( ret );
         goto out;
     }
     /* Try immediate completion */
-    while ( WaitForSingleObjectEx ( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
+    while ( WaitForSingleObjectEx( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
     return 0;
 
 out_close:
-    WSACloseEvent ( ovl->hEvent );
+    WSACloseEvent( ovl->hEvent );
 out_free:
-    HeapFree ( GetProcessHeap(), 0, ovl );
+    HeapFree( GetProcessHeap(), 0, iosb );
+    HeapFree( GetProcessHeap(), 0, ovl );
 out:
     return err;
 }
@@ -1503,13 +1540,13 @@ connect_success:
 /***********************************************************************
  *              WSAConnect             (WS2_32.30)
  */
-int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
-                        LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
-                        LPQOS lpSQOS, LPQOS lpGQOS )
+int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
+                       LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
+                       LPQOS lpSQOS, LPQOS lpGQOS )
 {
     if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
-        FIXME ("unsupported parameters!\n");
-    return WS_connect ( s, name, namelen );
+        FIXME("unsupported parameters!\n");
+    return WS_connect( s, name, namelen );
 }
 
 
@@ -1849,15 +1886,15 @@ char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
  *
  *   FIXME:  Only SIO_GET_INTERFACE_LIST option implemented.
  */
-INT WINAPI WSAIoctl (SOCKET s,
-                     DWORD   dwIoControlCode,
-                     LPVOID  lpvInBuffer,
-                     DWORD   cbInBuffer,
-                     LPVOID  lpbOutBuffer,
-                     DWORD   cbOutBuffer,
-                     LPDWORD lpcbBytesReturned,
-                     LPWSAOVERLAPPED lpOverlapped,
-                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+INT WINAPI WSAIoctl(SOCKET s,
+                    DWORD   dwIoControlCode,
+                    LPVOID  lpvInBuffer,
+                    DWORD   cbInBuffer,
+                    LPVOID  lpbOutBuffer,
+                    DWORD   cbOutBuffer,
+                    LPDWORD lpcbBytesReturned,
+                    LPWSAOVERLAPPED lpOverlapped,
+                    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
 {
    int fd = get_sock_fd( s, 0, NULL );
 
@@ -1874,7 +1911,7 @@ INT WINAPI WSAIoctl (SOCKET s,
            INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
            DWORD size, numInt, apiReturn;
 
-           TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
+           TRACE("-> SIO_GET_INTERFACE_LIST request\n");
 
            if (!lpbOutBuffer)
            {
@@ -1910,7 +1947,7 @@ INT WINAPI WSAIoctl (SOCKET s,
                         HeapFree(GetProcessHeap(),0,table);
                         release_sock_fd( s, fd );
                         WSASetLastError(WSAEFAULT);
-                        return (SOCKET_ERROR);
+                        return SOCKET_ERROR;
                      }
                      for (ptr = table, numInt = 0; ptr;
                       ptr = ptr->Next, intArray++, numInt++)
@@ -1923,11 +1960,11 @@ INT WINAPI WSAIoctl (SOCKET s,
                         ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
                         if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
                         {
-                           ERR ("Error obtaining status flags for socket!\n");
+                           ERR("Error obtaining status flags for socket!\n");
                            HeapFree(GetProcessHeap(),0,table);
                            release_sock_fd( s, fd );
                            WSASetLastError(WSAEINVAL);
-                           return (SOCKET_ERROR);
+                           return SOCKET_ERROR;
                         }
                         else
                         {
@@ -1969,11 +2006,11 @@ INT WINAPI WSAIoctl (SOCKET s,
                   }
                   else
                   {
-                     ERR ("Unable to get interface table!\n");
+                     ERR("Unable to get interface table!\n");
                      release_sock_fd( s, fd );
                      HeapFree(GetProcessHeap(),0,table);
                      WSASetLastError(WSAEINVAL);
-                     return (SOCKET_ERROR);
+                     return SOCKET_ERROR;
                   }
                   HeapFree(GetProcessHeap(),0,table);
                }
@@ -1981,15 +2018,15 @@ INT WINAPI WSAIoctl (SOCKET s,
                {
                   release_sock_fd( s, fd );
                   WSASetLastError(WSAEINVAL);
-                  return (SOCKET_ERROR);
+                  return SOCKET_ERROR;
                }
            }
            else
            {
-               ERR ("Unable to get interface table!\n");
+               ERR("Unable to get interface table!\n");
                release_sock_fd( s, fd );
                WSASetLastError(WSAEINVAL);
-               return (SOCKET_ERROR);
+               return SOCKET_ERROR;
            }
            /* Calculate the size of the array being returned */
            *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
@@ -2006,12 +2043,12 @@ INT WINAPI WSAIoctl (SOCKET s,
        WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
        release_sock_fd( s, fd );
        WSASetLastError(WSAEOPNOTSUPP);
-       return (SOCKET_ERROR);
+       return SOCKET_ERROR;
    }
 
    /* Function executed with no errors */
    release_sock_fd( s, fd );
-   return (0);
+   return 0;
 }
 
 
@@ -2130,7 +2167,7 @@ int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
     wsabuf.len = len;
     wsabuf.buf = buf;
 
-    if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
+    if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
         return SOCKET_ERROR;
     else
         return n;
@@ -2140,7 +2177,7 @@ int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
  *		recvfrom		(WS2_32.17)
  */
 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
-                                struct WS_sockaddr *from, int *fromlen)
+                       struct WS_sockaddr *from, int *fromlen)
 {
     DWORD n, dwFlags = flags;
     WSABUF wsabuf;
@@ -2148,7 +2185,7 @@ int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
     wsabuf.len = len;
     wsabuf.buf = buf;
 
-    if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
+    if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
         return SOCKET_ERROR;
     else
         return n;
@@ -2222,7 +2259,7 @@ int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
     wsabuf.len = len;
     wsabuf.buf = (char*) buf;
 
-    if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
+    if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
         return SOCKET_ERROR;
     else
         return n;
@@ -2236,8 +2273,8 @@ INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
                     LPWSAOVERLAPPED lpOverlapped,
                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
 {
-    return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
-                       NULL, 0, lpOverlapped, lpCompletionRoutine );
+    return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
+                      NULL, 0, lpOverlapped, lpCompletionRoutine );
 }
 
 /***********************************************************************
@@ -2245,7 +2282,7 @@ INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
  */
 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
 {
-    return WS_shutdown ( s, SD_SEND );
+    return WS_shutdown( s, SD_SEND );
 }
 
 
@@ -2262,19 +2299,20 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
     int n, fd, err = WSAENOTSOCK, flags, ret;
     struct iovec* iovec;
     struct ws2_async *wsa;
+    IO_STATUS_BLOCK* iosb;
 
-    TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
-           s, lpBuffers, dwBufferCount, dwFlags,
-           to, tolen, lpOverlapped, lpCompletionRoutine);
+    TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
+          s, lpBuffers, dwBufferCount, dwFlags,
+          to, tolen, lpOverlapped, lpCompletionRoutine);
 
     fd = get_sock_fd( s, GENERIC_WRITE, &flags );
-    TRACE ( "fd=%d, flags=%x\n", fd, flags );
+    TRACE( "fd=%d, flags=%x\n", fd, flags );
 
     if ( fd == -1 ) return SOCKET_ERROR;
 
     if (flags & FD_FLAG_SEND_SHUTDOWN)
     {
-        WSASetLastError ( WSAESHUTDOWN );
+        WSASetLastError( WSAESHUTDOWN );
         goto err_close;
     }
 
@@ -2284,7 +2322,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
         goto err_close;
     }
 
-    iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
+    iovec = HeapAlloc(GetProcessHeap(), 0, dwBufferCount * sizeof(struct iovec) );
 
     if ( !iovec )
     {
@@ -2300,37 +2338,37 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
 
     if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
     {
-        wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
-                               &dwFlags, (struct WS_sockaddr*) to, &tolen,
-                               lpOverlapped, lpCompletionRoutine );
+        wsa = WS2_make_async( s, fd, ws2m_write, iovec, dwBufferCount,
+                              &dwFlags, (struct WS_sockaddr*) to, &tolen,
+                              lpOverlapped, lpCompletionRoutine, &iosb );
         if ( !wsa )
         {
             err = WSAEFAULT;
             goto err_free;
         }
 
-        if ( ( ret = register_new_async ( &wsa->async )) )
+        if ( ( ret = ws2_queue_async( wsa, iosb ) ) )
         {
-            err = NtStatusToWSAError ( ret );
+            err = NtStatusToWSAError( ret );
 
             if ( !lpOverlapped )
-                HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
-            HeapFree ( GetProcessHeap(), 0, wsa );
+                HeapFree( GetProcessHeap(), 0, iosb );
+            HeapFree( GetProcessHeap(), 0, wsa );
             goto err_free;
         }
 
         /* Try immediate completion */
-        if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
+        if ( lpOverlapped )
         {
-            if  ( WSAGetOverlappedResult ( s, lpOverlapped,
-                                           lpNumberOfBytesSent, FALSE, &dwFlags) )
+            if  ( WSAGetOverlappedResult( s, lpOverlapped,
+                                          lpNumberOfBytesSent, FALSE, &dwFlags) )
                 return 0;
 
-            if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
+            if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
                 goto error;
         }
 
-        WSASetLastError ( WSA_IO_PENDING );
+        WSASetLastError( WSA_IO_PENDING );
         return SOCKET_ERROR;
     }
 
@@ -2344,31 +2382,31 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
         }
     }
 
-    n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
+    n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
     if ( n == -1 )
     {
         err = wsaErrno();
         if ( err == WSAEWOULDBLOCK )
-            _enable_event (SOCKET2HANDLE(s), FD_WRITE, 0, 0);
+            _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
         goto err_free;
     }
 
     TRACE(" -> %i bytes\n", n);
     *lpNumberOfBytesSent = n;
 
-    HeapFree ( GetProcessHeap(), 0, iovec );
+    HeapFree( GetProcessHeap(), 0, iovec );
     release_sock_fd( s, fd );
     return 0;
 
 err_free:
-    HeapFree ( GetProcessHeap(), 0, iovec );
+    HeapFree( GetProcessHeap(), 0, iovec );
 
 err_close:
     release_sock_fd( s, fd );
 
 error:
-    WARN (" -> ERROR %d\n", err);
-    WSASetLastError (err);
+    WARN(" -> ERROR %d\n", err);
+    WSASetLastError(err);
     return SOCKET_ERROR;
 }
 
@@ -2384,7 +2422,7 @@ int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
     wsabuf.len = len;
     wsabuf.buf = (char*) buf;
 
-    if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
+    if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
         return SOCKET_ERROR;
     else
         return n;
@@ -2460,7 +2498,6 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
 		
 		/* Returning 0 is better for now than returning a SOCKET_ERROR */
 		return 0;
-		break;
 	    default:
 		FIXME("opt_name:%x\n", optname);
 		return SOCKET_ERROR;
@@ -2587,13 +2624,13 @@ int WINAPI WS_shutdown(SOCKET s, int how)
         case SD_BOTH:
         default:
             fd0 = fd;
-            fd1 = get_sock_fd ( s, 0, NULL );
+            fd1 = get_sock_fd( s, 0, NULL );
             break;
         }
 
         if ( fd0 != -1 )
         {
-            err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
+            err = WS2_register_async_shutdown( s, fd0, ws2m_sd_read );
             if ( err )
             {
                 release_sock_fd( s, fd0 );
@@ -2602,7 +2639,7 @@ int WINAPI WS_shutdown(SOCKET s, int how)
         }
         if ( fd1 != -1 )
         {
-            err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
+            err = WS2_register_async_shutdown( s, fd1, ws2m_sd_write );
             if ( err )
             {
                 release_sock_fd( s, fd1 );
@@ -2614,7 +2651,7 @@ int WINAPI WS_shutdown(SOCKET s, int how)
     {
         if ( shutdown( fd, how ) )
         {
-            err = wsaErrno ();
+            err = wsaErrno();
             release_sock_fd( s, fd );
             goto error;
         }
@@ -2627,7 +2664,7 @@ int WINAPI WS_shutdown(SOCKET s, int how)
 
 error:
     _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
-    WSASetLastError ( err );
+    WSASetLastError( err );
     return SOCKET_ERROR;
 }
 
@@ -2638,8 +2675,8 @@ SOCKET WINAPI WS_socket(int af, int type, int protocol)
 {
     TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
 
-    return WSASocketA ( af, type, protocol, NULL, 0,
-                        get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
+    return WSASocketA( af, type, protocol, NULL, 0,
+                       get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
 }
 
 
@@ -2913,34 +2950,40 @@ int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
 /**********************************************************************
  *      WSAGetOverlappedResult (WS2_32.40)
  */
-BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
-                                     LPDWORD lpcbTransfer, BOOL fWait,
-                                     LPDWORD lpdwFlags )
+BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
+                                    LPDWORD lpcbTransfer, BOOL fWait,
+                                    LPDWORD lpdwFlags )
 {
     DWORD r;
 
-    TRACE ( "socket %04x ovl %p trans %p, wait %d flags %p\n",
-            s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
+    TRACE( "socket %04x ovl %p trans %p, wait %d flags %p\n",
+           s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
 
-    if ( !(lpOverlapped && lpOverlapped->hEvent) )
+    if ( lpOverlapped == NULL )
     {
-        ERR ( "Invalid pointer\n" );
-        WSASetLastError (WSA_INVALID_PARAMETER);
+        ERR( "Invalid pointer\n" );
+        WSASetLastError(WSA_INVALID_PARAMETER);
         return FALSE;
     }
 
     if ( fWait )
     {
-        while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
+        if (lpOverlapped->hEvent)
+            while ( WaitForSingleObjectEx(lpOverlapped->hEvent, 
+                                          INFINITE, TRUE) == STATUS_USER_APC );
+        else /* busy loop */
+            while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
+                Sleep( 10 );
+
     }
     else if ( lpOverlapped->Internal == STATUS_PENDING )
     {
         /* Wait in order to give APCs a chance to run. */
         /* This is cheating, so we must set the event again in case of success -
            it may be a non-manual reset event. */
-        while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
-        if ( r == WAIT_OBJECT_0 )
-            NtSetEvent ( lpOverlapped->hEvent, NULL );
+        while ( (r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
+        if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
+            NtSetEvent( lpOverlapped->hEvent, NULL );
     }
 
     if ( lpcbTransfer )
@@ -2954,11 +2997,11 @@ BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
     case STATUS_SUCCESS:
         return TRUE;
     case STATUS_PENDING:
-        WSASetLastError ( WSA_IO_INCOMPLETE );
-        if (fWait) ERR ("PENDING status after waiting!\n");
+        WSASetLastError( WSA_IO_INCOMPLETE );
+        if (fWait) ERR("PENDING status after waiting!\n");
         return FALSE;
     default:
-        WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
+        WSASetLastError( NtStatusToWSAError( lpOverlapped->Internal ));
         return FALSE;
     }
 }
@@ -3267,7 +3310,7 @@ static int list_dup(char** l_src, char** l_to, int item_size)
        p += count;
    }
    l_to[i] = NULL;
-   return (p - (char *)l_to);
+   return p - (char *)l_to;
 }
 
 /* ----- hostent */
@@ -3453,13 +3496,13 @@ UINT wsaHerrno(int loc_errno)
 /***********************************************************************
  *		WSARecv			(WS2_32.67)
  */
-int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
-		    LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
-		    LPWSAOVERLAPPED lpOverlapped,
-		    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
+                   LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
+                   LPWSAOVERLAPPED lpOverlapped,
+                   LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
 {
-    return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
-                        NULL, NULL, lpOverlapped, lpCompletionRoutine);
+    return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
+                       NULL, NULL, lpOverlapped, lpCompletionRoutine);
 }
 
 /***********************************************************************
@@ -3475,6 +3518,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
     int n, fd, err = WSAENOTSOCK, flags, ret;
     struct iovec* iovec;
     struct ws2_async *wsa;
+    IO_STATUS_BLOCK* iosb;
 
     TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
           s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
@@ -3482,17 +3526,17 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
           lpOverlapped, lpCompletionRoutine);
 
     fd = get_sock_fd( s, GENERIC_READ, &flags );
-    TRACE ( "fd=%d, flags=%x\n", fd, flags );
+    TRACE( "fd=%d, flags=%x\n", fd, flags );
 
     if (fd == -1) return SOCKET_ERROR;
 
     if (flags & FD_FLAG_RECV_SHUTDOWN)
     {
-        WSASetLastError ( WSAESHUTDOWN );
+        WSASetLastError( WSAESHUTDOWN );
         goto err_close;
     }
 
-    iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
+    iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
     if ( !iovec )
     {
         err = WSAEFAULT;
@@ -3507,9 +3551,9 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
 
     if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
     {
-        wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
-                               lpFlags, lpFrom, lpFromlen,
-                               lpOverlapped, lpCompletionRoutine );
+        wsa = WS2_make_async( s, fd, ws2m_read, iovec, dwBufferCount,
+                              lpFlags, lpFrom, lpFromlen,
+                              lpOverlapped, lpCompletionRoutine, &iosb );
 
         if ( !wsa )
         {
@@ -3517,28 +3561,28 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
             goto err_free;
         }
 
-        if ( ( ret = register_new_async ( &wsa->async )) )
+        if ( ( ret = ws2_queue_async( wsa, iosb )) )
         {
-            err = NtStatusToWSAError ( ret );
+            err = NtStatusToWSAError( ret );
 
             if ( !lpOverlapped )
-                HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
-            HeapFree ( GetProcessHeap(), 0, wsa );
+                HeapFree( GetProcessHeap(), 0, iosb );
+            HeapFree( GetProcessHeap(), 0, wsa );
             goto err_free;
         }
 
         /* Try immediate completion */
-        if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
+        if ( lpOverlapped )
         {
-            if  ( WSAGetOverlappedResult ( s, lpOverlapped,
+            if  ( WSAGetOverlappedResult( s, lpOverlapped,
                                            lpNumberOfBytesRecvd, FALSE, lpFlags) )
                 return 0;
 
-            if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
+            if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
                 goto error;
         }
 
-        WSASetLastError ( WSA_IO_PENDING );
+        WSASetLastError( WSA_IO_PENDING );
         return SOCKET_ERROR;
     }
 
@@ -3555,7 +3599,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
         }
     }
 
-    n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
+    n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
     if ( n == -1 )
     {
         err = wsaErrno();
@@ -3565,21 +3609,21 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
     TRACE(" -> %i bytes\n", n);
     *lpNumberOfBytesRecvd = n;
 
-    HeapFree (GetProcessHeap(), 0, iovec);
+    HeapFree(GetProcessHeap(), 0, iovec);
     release_sock_fd( s, fd );
     _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
 
     return 0;
 
 err_free:
-    HeapFree (GetProcessHeap(), 0, iovec);
+    HeapFree(GetProcessHeap(), 0, iovec);
 
 err_close:
     release_sock_fd( s, fd );
 
 error:
     WARN(" -> ERROR %d\n", err);
-    WSASetLastError ( err );
+    WSASetLastError( err );
     return SOCKET_ERROR;
 }
 
@@ -3656,14 +3700,14 @@ SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
                                addr = memcpy(addr, &src_addr, (*addrlen > size) ?  size : *addrlen );
                        return cs;
                case CF_DEFER:
-                       SERVER_START_REQ ( set_socket_deferred )
+                       SERVER_START_REQ( set_socket_deferred )
                        {
-                           req->handle = SOCKET2HANDLE (s);
-                           req->deferred = SOCKET2HANDLE (cs);
+                           req->handle = SOCKET2HANDLE(s);
+                           req->deferred = SOCKET2HANDLE(cs);
                            if ( !wine_server_call_err ( req ) )
                            {
-                               SetLastError ( WSATRY_AGAIN );
-                               WS_closesocket ( cs );
+                               SetLastError( WSATRY_AGAIN );
+                               WS_closesocket( cs );
                            }
                        }
                        SERVER_END_REQ;
diff --git a/include/async.h b/include/async.h
deleted file mode 100644
index eae7ee7e9c888e889217d5c42b3e438d6dc0b0eb..0000000000000000000000000000000000000000
--- a/include/async.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Structures and static functions for handling asynchronous I/O.
- *
- * Copyright (C) 2002 Mike McCormack,  Martin Wilck
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * This file declares static functions.
- * It should only be included by those source files that implement async I/O requests.
- */
-
-#ifndef __WINE_ASYNC_H
-#define __WINE_ASYNC_H
-
-#include <thread.h>
-#include <ntstatus.h>
-#include <wine/server.h>
-#include <winternl.h>
-
-struct async_private;
-
-typedef void (*async_handler)(struct async_private *ovp);
-typedef void (CALLBACK *async_call_completion_func)(ULONG_PTR data);
-typedef DWORD (*async_get_count)(const struct async_private *ovp);
-typedef void (*async_cleanup)(struct async_private *ovp);
-
-typedef struct async_ops
-{
-    async_get_count             get_count;
-    async_call_completion_func  call_completion;
-    async_cleanup               cleanup;
-} async_ops;
-
-typedef struct async_private
-{
-    struct async_ops*   ops;
-    HANDLE              handle;
-    HANDLE              event;
-    int                 fd;
-    async_handler       func;
-    int                 type;
-    IO_STATUS_BLOCK*    iosb;
-    struct async_private* next;
-    struct async_private* prev;
-} async_private;
-
-/* All functions declared static for Dll separation purposes */
-static void CALLBACK call_user_apc( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 )
-{
-    PAPCFUNC func = (PAPCFUNC)arg1;
-    func( arg2 );
-}
-
-inline static void finish_async( async_private *ovp )
-{
-    if (ovp->prev)
-        ovp->prev->next = ovp->next;
-    else
-        NtCurrentTeb()->pending_list = ovp->next;
-
-    if (ovp->next)
-        ovp->next->prev = ovp->prev;
-
-    ovp->next = ovp->prev = NULL;
-
-    wine_server_release_fd( ovp->handle, ovp->fd );
-    if ( ovp->event != INVALID_HANDLE_VALUE )
-        NtSetEvent( ovp->event, NULL );
-
-    if ( ovp->ops->call_completion )
-        NtQueueApcThread( GetCurrentThread(), call_user_apc, 
-                          (ULONG_PTR)ovp->ops->call_completion, (ULONG_PTR)ovp, 0 );
-    else
-        ovp->ops->cleanup( ovp );
-}
-
-inline static NTSTATUS __register_async( async_private *ovp, const DWORD status )
-{
-    NTSTATUS    ret;
-
-    SERVER_START_REQ( register_async )
-    {
-        req->handle = ovp->handle;
-        req->overlapped = ovp;
-        req->type = ovp->type;
-        req->count = ovp->ops->get_count( ovp );
-        req->status = status;
-        ret = wine_server_call( req );
-    }
-    SERVER_END_REQ;
-
-    if (ret) ovp->iosb->u.Status = ret;
-
-    if ( ovp->iosb->u.Status != STATUS_PENDING )
-        finish_async(ovp);
-
-    return ret;
-}
-
-inline static NTSTATUS register_old_async( async_private *ovp )
-{
-    return __register_async(ovp, ovp->iosb->u.Status);
-}
-
-inline static NTSTATUS register_new_async( async_private *ovp )
-{
-    ovp->iosb->u.Status = STATUS_PENDING;
-
-    ovp->next = NtCurrentTeb()->pending_list;
-    ovp->prev = NULL;
-    if ( ovp->next ) ovp->next->prev = ovp;
-    NtCurrentTeb()->pending_list = ovp;
-
-    return __register_async( ovp, STATUS_PENDING );
-}
-
-inline static NTSTATUS cancel_async( async_private *ovp )
-{
-     /* avoid multiple cancellations */
-     if ( ovp->iosb->u.Status != STATUS_PENDING )
-          return STATUS_SUCCESS;
-     ovp->iosb->u.Status = STATUS_CANCELLED;
-     return __register_async( ovp, STATUS_CANCELLED );
-}
-
-#endif /* __WINE_ASYNC_H */
diff --git a/include/thread.h b/include/thread.h
index ed0bc815893264e4becd8ad0e59c9561374260f3..636de6576110d15b34c89b635187da19898e2c2e 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -112,7 +112,7 @@ typedef struct _TEB
     int          wait_fd[2];     /* --3 214 fd for sleeping server requests */
     struct debug_info *debug_info;        /* --3 21c Info for debugstr functions */
     void        *pthread_data;   /* --3 220 Data for pthread emulation */
-    struct async_private *pending_list;   /* --3 224 list of pending async operations */
+    DWORD        num_async_io;   /* --3 224 number of pending async I/O in the server */
     void        *driver_data;    /* --3 228 Graphics driver private data */
     DWORD        dpmi_vif;       /* --3 22c Protected mode virtual interrupt flag */
     DWORD        vm86_pending;   /* --3 230 Data for vm86 mode */
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index f7753920a7a6dbd0c3386b8603e804b3767bdfaf..2cc4897b406bd5e8d92a0689673908c80a2ac517 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -2282,21 +2282,33 @@ struct register_async_request
     struct request_header __header;
     obj_handle_t handle;
     int          type;
-    void*        overlapped;
+    void*        io_apc;
+    void*        io_sb;
+    void*        io_user;
     int          count;
-    unsigned int status;
 };
 struct register_async_reply
 {
     struct reply_header __header;
 };
-#define ASYNC_TYPE_NONE  0x00
 #define ASYNC_TYPE_READ  0x01
 #define ASYNC_TYPE_WRITE 0x02
 #define ASYNC_TYPE_WAIT  0x03
 
 
 
+struct cancel_async_request
+{
+    struct request_header __header;
+    obj_handle_t handle;
+};
+struct cancel_async_reply
+{
+    struct reply_header __header;
+};
+
+
+
 struct create_named_pipe_request
 {
     struct request_header __header;
@@ -3274,6 +3286,7 @@ enum request
     REQ_get_serial_info,
     REQ_set_serial_info,
     REQ_register_async,
+    REQ_cancel_async,
     REQ_create_named_pipe,
     REQ_open_named_pipe,
     REQ_connect_named_pipe,
@@ -3460,6 +3473,7 @@ union generic_request
     struct get_serial_info_request get_serial_info_request;
     struct set_serial_info_request set_serial_info_request;
     struct register_async_request register_async_request;
+    struct cancel_async_request cancel_async_request;
     struct create_named_pipe_request create_named_pipe_request;
     struct open_named_pipe_request open_named_pipe_request;
     struct connect_named_pipe_request connect_named_pipe_request;
@@ -3644,6 +3658,7 @@ union generic_reply
     struct get_serial_info_reply get_serial_info_reply;
     struct set_serial_info_reply set_serial_info_reply;
     struct register_async_reply register_async_reply;
+    struct cancel_async_reply cancel_async_reply;
     struct create_named_pipe_reply create_named_pipe_reply;
     struct open_named_pipe_reply open_named_pipe_reply;
     struct connect_named_pipe_reply connect_named_pipe_reply;
@@ -3697,6 +3712,6 @@ union generic_reply
     struct set_global_windows_reply set_global_windows_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 153
+#define SERVER_PROTOCOL_VERSION 154
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/Makefile.in b/server/Makefile.in
index 0fb042da3885ace91e06f92c3e5d4ae3070999db..dd19f904ae61bad66401008b89d19bed696f0bd3 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -6,7 +6,6 @@ VPATH     = @srcdir@
 MODULE    = none
 
 C_SRCS = \
-	async.c \
 	atom.c \
 	change.c \
 	class.c \
diff --git a/server/async.c b/server/async.c
deleted file mode 100644
index 338f0d1e4fe9dd82aefcb643f0258eb984abd276..0000000000000000000000000000000000000000
--- a/server/async.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Server-side support for async i/o operations
- *
- * Copyright (C) 1998 Alexandre Julliard
- * Copyright (C) 2000 Mike McCormack
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "config.h"
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-
-#include "handle.h"
-#include "file.h"
-#include "thread.h"
-#include "request.h"
-
-#include "async.h"
-
-void destroy_async( struct async *async )
-{
-    struct async_queue *aq = async->q;
-
-    /*fprintf(stderr,"destroyed async %p\n",async->overlapped); */
-
-    if(async->timeout)
-        remove_timeout_user(async->timeout);
-    async->timeout = NULL;
-
-    if(async->prev)
-        async->prev->next = async->next;
-    else
-        aq->head = async->next;
-
-    if(async->next)
-        async->next->prev = async->prev;
-    else
-        aq->tail = async->prev;
-
-    async->q = NULL;
-    async->next = NULL;
-    async->prev = NULL;
-    release_object( async->thread );
-    free(async);
-}
-
-void async_notify(struct async *async, int status)
-{
-    /* fprintf(stderr,"notifying %p!\n",async->overlapped); */
-    async->status = status;
-    thread_queue_apc(async->thread, NULL, NULL, APC_ASYNC_IO, 1,
-                     async->overlapped, (void *)status, NULL );
-}
-
-void destroy_async_queue( struct async_queue *q )
-{
-    while(q->head)
-    {
-        async_notify(q->head, STATUS_CANCELLED);
-        destroy_async(q->head);
-    }
-}
-
-struct async *find_async(struct async_queue *q, struct thread *thread, void *overlapped)
-{
-    struct async *async;
-
-    /* fprintf(stderr,"find_async: %p\n",overlapped); */
-
-    if(!q)
-        return NULL;
-
-    for(async = q->head; async; async = async->next)
-        if((async->overlapped==overlapped) && (async->thread == thread))
-             return async;
-
-    return NULL;
-}
-
-void async_insert(struct async_queue *q, struct async *async)
-{
-    async->q = q;
-    async->prev = q->tail;
-    async->next = NULL;
-
-    if(q->tail)
-        q->tail->next = async;
-    else
-        q->head = async;
-
-    q->tail = async;
-}
-
-static void async_callback(void *private)
-{
-    struct async *async = (struct async *)private;
-
-    /* fprintf(stderr,"%p timeout out\n",async->overlapped); */
-    async->timeout = NULL;
-    async_notify(async, STATUS_TIMEOUT);
-    destroy_async(async);
-}
-
-struct async *create_async(struct object *obj, struct thread *thread,
-                           void *overlapped)
-{
-    struct async *async = (struct async *) malloc(sizeof(struct async));
-    if(!async)
-    {
-        set_error(STATUS_NO_MEMORY);
-        return NULL;
-    }
-
-    async->obj = obj;
-    async->thread = (struct thread *)grab_object(thread);
-    async->overlapped = overlapped;
-    async->next = NULL;
-    async->prev = NULL;
-    async->q = NULL;
-    async->status = STATUS_PENDING;
-    async->timeout = NULL;
-
-    return async;
-}
-
-void async_add_timeout(struct async *async, int timeout)
-{
-    if(timeout)
-    {
-        gettimeofday( &async->when, 0 );
-        add_timeout( &async->when, timeout );
-        async->timeout = add_timeout_user( &async->when, async_callback, async );
-    }
-}
diff --git a/server/async.h b/server/async.h
deleted file mode 100644
index 31df5abb4e047f73ea72db927598cd060bba8c65..0000000000000000000000000000000000000000
--- a/server/async.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Async i/o definitions
- *
- * Copyright (C) 2000 Mike McCormack
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _SERVER_ASYNC_
-#define _SERVER_ASYNC_
-
-#include <sys/time.h>
-#include "object.h"
-
-struct async_queue;
-
-struct async
-{
-    struct object       *obj;
-    struct thread       *thread;
-    void                *overlapped;
-    unsigned int         status;
-    struct timeval       when;
-    struct timeout_user *timeout;
-    struct async        *next,*prev;
-    struct async_queue  *q;
-};
-
-struct async_queue
-{
-    struct async        *head;
-    struct async        *tail;
-};
-
-void destroy_async( struct async *async );
-void destroy_async_queue( struct async_queue *q );
-void async_notify(struct async *async, int status);
-struct async *find_async(struct async_queue *q, struct thread *thread, void *overlapped);
-void async_insert(struct async_queue *q, struct async *async);
-struct async *create_async(struct object *obj, struct thread *thread,
-                           void *overlapped);
-void async_add_timeout(struct async *async, int timeout);
-static inline void init_async_queue(struct async_queue *q)
-{
-    q->head = q->tail = NULL;
-}
-
-#define IS_READY(q) (((q).head) && ((q).head->status==STATUS_PENDING))
-
-#endif /* _SERVER_ASYNC_ */
-
diff --git a/server/fd.c b/server/fd.c
index e29c6cf85a67fdb93be91c7b52f02765e4b10371..f43c4a95b7b1ffaf03b8ee40e22241a204a06ec8 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -979,6 +979,89 @@ void unlock_fd( struct fd *fd, file_pos_t start, file_pos_t count )
 }
 
 
+/****************************************************************/
+/* asynchronous operations support */
+
+struct async
+{
+    struct fd           *fd;
+    struct thread       *thread;
+    void                *apc;
+    void                *user;
+    void                *sb;
+    struct timeval       when;
+    struct timeout_user *timeout;
+    struct async        *next;
+    struct async       **head;
+};
+
+/* cb for timeout on an async request */
+static void async_callback(void *private)
+{
+    struct async *async = (struct async *)private;
+
+    /* fprintf(stderr, "async timeout out %p\n", async); */
+    async->timeout = NULL;
+    async_terminate( async, STATUS_TIMEOUT );
+}
+
+/* create an async on a given queue of a fd */
+struct async *create_async(struct fd *fd, struct thread *thread,
+                           int timeout, struct async **head, 
+                           void *io_apc, void *io_user, void* io_sb)
+{
+    struct async *async = mem_alloc( sizeof(struct async) );
+    struct async **p;
+
+    if (!async) return NULL;
+
+    async->fd = fd;
+    async->thread = (struct thread *)grab_object(thread);
+    async->apc = io_apc;
+    async->user = io_user;
+    async->sb = io_sb;
+    async->head = head;
+    async->next = NULL;
+
+    for (p = head; *p; p = &(*p)->next);
+    *p = async;
+
+    if (timeout)
+    {
+        gettimeofday( &async->when, 0 );
+        add_timeout( &async->when, timeout );
+        async->timeout = add_timeout_user( &async->when, async_callback, async );
+    }
+    else async->timeout = NULL;
+
+    return async;
+}
+
+/* notifies client thread of new status of its async request */
+/* destroys the server side of it */
+void async_terminate( struct async *async, int status )
+{
+    struct async** p;
+
+    thread_queue_apc( async->thread, NULL, async->apc, APC_ASYNC_IO,
+                      1, async->user, async->sb, (void *)status );
+
+    if (async->timeout) remove_timeout_user( async->timeout );
+    async->timeout = NULL;
+
+    for (p = async->head; *p; p = &(*p)->next)
+    {
+        if (*p == async)
+        {
+            *p = async->next;
+            break;
+        }
+    }
+
+    release_object( async->thread );
+    free( async );
+}
+
 /****************************************************************/
 /* file descriptor functions */
 
@@ -1309,7 +1392,14 @@ int no_get_file_info( struct fd *fd )
 }
 
 /* default queue_async() routine */
-void no_queue_async( struct fd *fd, void* ptr, unsigned int status, int type, int count )
+void no_queue_async( struct fd *fd, void* apc, void* user, void* io_sb, 
+                     int type, int count)
+{
+    set_error( STATUS_OBJECT_TYPE_MISMATCH );
+}
+
+/* default cancel_async() routine */
+void no_cancel_async( struct fd *fd )
 {
     set_error( STATUS_OBJECT_TYPE_MISMATCH );
 }
@@ -1338,7 +1428,7 @@ DECL_HANDLER(flush_file)
     if (fd)
     {
         fd->fd_ops->flush( fd, &event );
-        if( event )
+        if ( event )
         {
             reply->event = alloc_handle( current->process, event, SYNCHRONIZE, 0 );
         }
@@ -1372,26 +1462,41 @@ DECL_HANDLER(register_async)
 {
     struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
 
-/*
- * The queue_async method must do the following:
- *
- * 1. Get the async_queue for the request of given type.
- * 2. Call find_async() to look for the specific client request in the queue (=> NULL if not found).
- * 3. If status is STATUS_PENDING:
- *      a) If no async request found in step 2 (new request): call create_async() to initialize one.
- *      b) Set request's status to STATUS_PENDING.
- *      c) If the "queue" field of the async request is NULL: call async_insert() to put it into the queue.
- *    Otherwise:
- *      If the async request was found in step 2, destroy it by calling destroy_async().
- * 4. Carry out any operations necessary to adjust the object's poll events
- *    Usually: set_elect_events (obj, obj->ops->get_poll_events()).
- *
- * See also the implementations in file.c, serial.c, and sock.c.
-*/
+    /*
+     * The queue_async method must do the following:
+     *
+     * 1. Get the async_queue for the request of given type.
+     * 2. Create a new asynchronous request for the selected queue
+     * 3. Carry out any operations necessary to adjust the object's poll events
+     *    Usually: set_elect_events (obj, obj->ops->get_poll_events()).
+     * 4. When the async request is triggered, then send back (with a proper APC)
+     *    the trigger (STATUS_ALERTED) to the thread that posted the request. 
+     *    async_destroy() is to be called: it will both notify the sender about
+     *    the trigger and destroy the request by itself
+     * See also the implementations in file.c, serial.c, and sock.c.
+     */
 
     if (fd)
     {
-        fd->fd_ops->queue_async( fd, req->overlapped, req->status, req->type, req->count );
+        fd->fd_ops->queue_async( fd, req->io_apc, req->io_user, req->io_sb, 
+                                 req->type, req->count );
         release_object( fd );
     }
 }
+
+/* cancels all async I/O */
+DECL_HANDLER(cancel_async)
+{
+    struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
+    if (fd)
+    {
+        /* Note: we don't kill the queued APC_ASYNC_IO on this thread because
+         * NtCancelIoFile() will force the pending APC to be run. Since, 
+         * Windows only guarantees that the current thread will have no async 
+         * operation on the current fd when NtCancelIoFile returns, this shall
+         * do the work.
+         */
+        fd->fd_ops->cancel_async( fd );
+        release_object( fd );
+    }        
+}
diff --git a/server/file.c b/server/file.c
index 352932fc26e0d3c65a7661e507c99c94aacdd8ad..2b7fb2e654d79c187a65c741432722be6157ba9b 100644
--- a/server/file.c
+++ b/server/file.c
@@ -50,7 +50,6 @@
 #include "handle.h"
 #include "thread.h"
 #include "request.h"
-#include "async.h"
 
 struct file
 {
@@ -58,8 +57,8 @@ struct file
     struct fd          *fd;         /* file descriptor for this file */
     unsigned int        access;     /* file access (GENERIC_READ/WRITE) */
     unsigned int        options;    /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */
-    struct async_queue  read_q;
-    struct async_queue  write_q;
+    struct async       *read_q;
+    struct async       *write_q;
 };
 
 static void file_dump( struct object *obj, int verbose );
@@ -70,7 +69,8 @@ static int file_get_poll_events( struct fd *fd );
 static void file_poll_event( struct fd *fd, int event );
 static int file_flush( struct fd *fd, struct event **event );
 static int file_get_info( struct fd *fd );
-static void file_queue_async( struct fd *fd, void *ptr, unsigned int status, int type, int count );
+static void file_queue_async( struct fd *fd, void *apc, void *user, void* iosb, int type, int count );
+static void file_cancel_async( struct fd *fd );
 
 static const struct object_ops file_ops =
 {
@@ -90,7 +90,8 @@ static const struct fd_ops file_fd_ops =
     file_poll_event,              /* poll_event */
     file_flush,                   /* flush */
     file_get_info,                /* get_file_info */
-    file_queue_async              /* queue_async */
+    file_queue_async,             /* queue_async */
+    file_cancel_async             /* cancel_async */
 };
 
 static inline int is_overlapped( const struct file *file )
@@ -141,6 +142,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
     case FILE_OVERWRITE:    flags = O_TRUNC; break;
     default:                set_error( STATUS_INVALID_PARAMETER ); goto error;
     }
+
     switch(access & (GENERIC_READ | GENERIC_WRITE))
     {
     case 0: break;
@@ -160,8 +162,7 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int
     file->options    = options;
     if (is_overlapped( file ))
     {
-        init_async_queue (&file->read_q);
-        init_async_queue (&file->write_q);
+        file->read_q = file->write_q = NULL;
     }
 
     /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
@@ -236,14 +237,14 @@ static void file_poll_event( struct fd *fd, int event )
     assert( file->obj.ops == &file_ops );
     if (is_overlapped( file ))
     {
-        if( IS_READY(file->read_q) && (POLLIN & event) )
+        if ( file->read_q && (POLLIN & event) )
         {
-            async_notify(file->read_q.head, STATUS_ALERTED);
+            async_terminate( file->read_q, STATUS_ALERTED );
             return;
         }
-        if( IS_READY(file->write_q) && (POLLOUT & event) )
+        if ( file->write_q && (POLLOUT & event) )
         {
-            async_notify(file->write_q.head, STATUS_ALERTED);
+            async_terminate( file->write_q, STATUS_ALERTED );
             return;
         }
     }
@@ -266,56 +267,51 @@ static int file_get_info( struct fd *fd )
     else return 0;
 }
 
-static void file_queue_async(struct fd *fd, void *ptr, unsigned int status, int type, int count)
+static void file_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
+                              int type, int count )
 {
     struct file *file = get_fd_user( fd );
-    struct async *async;
-    struct async_queue *q;
+    struct async **head;
+    int events;
 
     assert( file->obj.ops == &file_ops );
 
     if (!is_overlapped( file ))
     {
-        set_error ( STATUS_INVALID_HANDLE );
+        set_error( STATUS_INVALID_HANDLE );
         return;
     }
 
-    switch(type)
+    switch (type)
     {
     case ASYNC_TYPE_READ:
-        q = &file->read_q;
+        head = &file->read_q;
         break;
     case ASYNC_TYPE_WRITE:
-        q = &file->write_q;
+        head = &file->write_q;
         break;
     default:
         set_error( STATUS_INVALID_PARAMETER );
         return;
     }
 
-    async = find_async ( q, current, ptr );
-
-    if ( status == STATUS_PENDING )
-    {
-        int events;
+    if (!create_async( fd, current, 0, head, apc, user, iosb ))
+        return;
 
-        if ( !async )
-            async = create_async ( &file->obj, current, ptr );
-        if ( !async )
-            return;
+    /* Check if the new pending request can be served immediately */
+    events = check_fd_events( fd, file_get_poll_events( fd ) );
+    if (events) file_poll_event( fd, events );
 
-        async->status = STATUS_PENDING;
-        if ( !async->q )
-            async_insert( q, async );
+    set_fd_events( fd, file_get_poll_events( fd ));
+}
 
-        /* Check if the new pending request can be served immediately */
-        events = check_fd_events( fd, file_get_poll_events( fd ) );
-        if (events) file_poll_event ( fd, events );
-    }
-    else if ( async ) destroy_async ( async );
-    else set_error ( STATUS_INVALID_PARAMETER );
+static void file_cancel_async( struct fd *fd )
+{
+    struct file *file = get_fd_user( fd );
+    assert( file->obj.ops == &file_ops );
 
-    set_fd_events( fd, file_get_poll_events( fd ));
+    async_terminate_queue( &file->read_q, STATUS_CANCELLED );
+    async_terminate_queue( &file->write_q, STATUS_CANCELLED );
 }
 
 static struct fd *file_get_fd( struct object *obj )
@@ -332,8 +328,8 @@ static void file_destroy( struct object *obj )
 
     if (is_overlapped( file ))
     {
-        destroy_async_queue (&file->read_q);
-        destroy_async_queue (&file->write_q);
+        async_terminate_queue( &file->read_q, STATUS_CANCELLED );
+        async_terminate_queue( &file->write_q, STATUS_CANCELLED );
     }
     if (file->fd) release_object( file->fd );
 }
diff --git a/server/file.h b/server/file.h
index 80f936f59505f822bf9928415c65649142f70db1..7f535945e5f8588227167b1c5d58ab7582dcca1c 100644
--- a/server/file.h
+++ b/server/file.h
@@ -38,8 +38,10 @@ struct fd_ops
     int  (*flush)(struct fd *, struct event **);
     /* get file information */
     int  (*get_file_info)(struct fd *);
-    /* queue an async operation - see register_async handler in async.c*/
-    void (*queue_async)(struct fd *, void* ptr, unsigned int status, int type, int count);
+    /* queue an async operation */
+    void (*queue_async)(struct fd *, void* apc, void* user, void* io_sb, int type, int count);
+    /* cancel an async operation */
+    void (*cancel_async)(struct fd *);
 };
 
 /* file descriptor functions */
@@ -65,7 +67,8 @@ extern int default_fd_signaled( struct object *obj, struct thread *thread );
 extern void default_poll_event( struct fd *fd, int event );
 extern int no_flush( struct fd *fd, struct event **event );
 extern int no_get_file_info( struct fd *fd );
-extern void no_queue_async( struct fd *fd, void* ptr, unsigned int status, int type, int count );
+extern void no_queue_async( struct fd *fd, void* apc, void* user, void* io_sb, int type, int count);
+extern void no_cancel_async( struct fd *fd );
 extern void main_loop(void);
 
 inline static struct fd *get_obj_fd( struct object *obj ) { return obj->ops->get_fd( obj ); }
@@ -107,4 +110,14 @@ extern void sigio_callback(void);
 extern int is_serial_fd( struct fd *fd );
 extern struct object *create_serial( struct fd *fd, unsigned int options );
 
+/* async I/O functions */
+extern struct async *create_async( struct fd *fd, struct thread *thread, int timeout,
+                                   struct async **head, void *, void *, void *);
+extern void async_terminate( struct async *async, int status );
+
+static inline void async_terminate_queue( struct async **head, int status )
+{
+    while (*head) async_terminate( *head, status );
+}
+
 #endif  /* __WINE_SERVER_FILE_H */
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 85c81885a0767cbeb456df953deb99303e926763..d945199dc42327b47077f04a685e9dc8cfa42068 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -151,7 +151,8 @@ static const struct fd_ops pipe_server_fd_ops =
     default_poll_event,           /* poll_event */
     pipe_server_flush,            /* flush */
     pipe_end_get_info,            /* get_file_info */
-    no_queue_async                /* queue_async */
+    no_queue_async,               /* queue_async */
+    no_cancel_async,              /* cancel_async */
 };
 
 /* client end functions */
@@ -178,7 +179,8 @@ static const struct fd_ops pipe_client_fd_ops =
     default_poll_event,           /* poll_event */
     pipe_client_flush,            /* flush */
     pipe_end_get_info,            /* get_file_info */
-    no_queue_async                /* queue_async */
+    no_queue_async,               /* queue_async */
+    no_cancel_async               /* cancel_async */
 };
 
 static void named_pipe_dump( struct object *obj, int verbose )
diff --git a/server/process.c b/server/process.c
index 1c04ba712bcf1dd1fdf81720e3e9c06adae993e1..fc69e507232f5ad378faf8dec9aefb3d17584464 100644
--- a/server/process.c
+++ b/server/process.c
@@ -76,7 +76,8 @@ static const struct fd_ops process_fd_ops =
     process_poll_event,          /* poll_event */
     no_flush,                    /* flush */
     no_get_file_info,            /* get_file_info */
-    no_queue_async               /* queue_async */
+    no_queue_async,              /* queue_async */
+    no_cancel_async              /* cancel async */
 };
 
 /* process startup info */
diff --git a/server/protocol.def b/server/protocol.def
index 0cfd8c5bb2610440adf48de8614200ba102f3cd4..6873faa392ce3d6c2dec99e3ae078be2ce99c5a7 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1615,20 +1615,26 @@ enum message_type
 #define SERIALINFO_SET_ERROR     0x04
 
 
-/* Create / reschedule an async I/O */
+/* Create an async I/O */
 @REQ(register_async)
-    obj_handle_t handle;  /* handle to comm port, socket or file */
-    int          type;
-    void*        overlapped;
-    int          count;
-    unsigned int status;
+    obj_handle_t handle;        /* handle to comm port, socket or file */
+    int          type;          /* type of queue to look after */
+    void*        io_apc;        /* APC routine to queue upon end of async */
+    void*        io_sb;         /* I/O status block (unique across all async on this handle) */
+    void*        io_user;       /* data to pass back to caller */
+    int          count;         /* count - usually # of bytes to be read/written */
 @END
-#define ASYNC_TYPE_NONE  0x00
 #define ASYNC_TYPE_READ  0x01
 #define ASYNC_TYPE_WRITE 0x02
 #define ASYNC_TYPE_WAIT  0x03
 
 
+/* Cancel all async op on a fd */
+@REQ(cancel_async)
+    obj_handle_t handle;        /* handle to comm port, socket or file */
+@END
+
+
 /* Create a named pipe */
 @REQ(create_named_pipe)
     unsigned int   openmode;
diff --git a/server/request.c b/server/request.c
index 6bba18063bc4450f9be2d838b6adb1f2da424159..c7ac8bef720eddb583742dc9e9253f6d0ea5296f 100644
--- a/server/request.c
+++ b/server/request.c
@@ -100,7 +100,8 @@ static const struct fd_ops master_socket_fd_ops =
     master_socket_poll_event,      /* poll_event */
     no_flush,                      /* flush */
     no_get_file_info,              /* get_file_info */
-    no_queue_async                 /* queue_async */
+    no_queue_async,                /* queue_async */
+    no_cancel_async                /* cancel_async */
 };
 
 
diff --git a/server/request.h b/server/request.h
index 0a2319f2f7abaeea1f93948fdd8daca3e7e2ef66..2b779196966f4a8848aea200005c9ead85c3e546 100644
--- a/server/request.h
+++ b/server/request.h
@@ -231,6 +231,7 @@ DECL_HANDLER(kill_win_timer);
 DECL_HANDLER(get_serial_info);
 DECL_HANDLER(set_serial_info);
 DECL_HANDLER(register_async);
+DECL_HANDLER(cancel_async);
 DECL_HANDLER(create_named_pipe);
 DECL_HANDLER(open_named_pipe);
 DECL_HANDLER(connect_named_pipe);
@@ -416,6 +417,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_get_serial_info,
     (req_handler)req_set_serial_info,
     (req_handler)req_register_async,
+    (req_handler)req_cancel_async,
     (req_handler)req_create_named_pipe,
     (req_handler)req_open_named_pipe,
     (req_handler)req_connect_named_pipe,
diff --git a/server/serial.c b/server/serial.c
index c368a2b61066ce99b7185c811f9f039c074ee1d6..f24cfed351c28c5fb02e9872044cb23ceb1757da 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -53,7 +53,6 @@
 #include "handle.h"
 #include "thread.h"
 #include "request.h"
-#include "async.h"
 
 static void serial_dump( struct object *obj, int verbose );
 static struct fd *serial_get_fd( struct object *obj );
@@ -63,7 +62,8 @@ static int serial_get_poll_events( struct fd *fd );
 static void serial_poll_event( struct fd *fd, int event );
 static int serial_get_info( struct fd *fd );
 static int serial_flush( struct fd *fd, struct event **event );
-static void serial_queue_async(struct fd *fd, void *ptr, unsigned int status, int type, int count);
+static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb, int type, int count );
+static void serial_cancel_async( struct fd *fd );
 
 struct serial
 {
@@ -83,9 +83,9 @@ struct serial
 
     struct termios      original;
 
-    struct async_queue  read_q;
-    struct async_queue  write_q;
-    struct async_queue  wait_q;
+    struct async       *read_q;
+    struct async       *write_q;
+    struct async       *wait_q;
 
     /* FIXME: add dcb, comm status, handler module, sharing */
 };
@@ -108,7 +108,8 @@ static const struct fd_ops serial_fd_ops =
     serial_poll_event,            /* poll_event */
     serial_flush,                 /* flush */
     serial_get_info,              /* get_file_info */
-    serial_queue_async            /* queue_async */
+    serial_queue_async,           /* queue_async */
+    serial_cancel_async           /* cancel_async */
 };
 
 /* check if the given fd is a serial port */
@@ -144,9 +145,7 @@ struct object *create_serial( struct fd *fd, unsigned int options )
     serial->writeconst   = 0;
     serial->eventmask    = 0;
     serial->commerror    = 0;
-    init_async_queue(&serial->read_q);
-    init_async_queue(&serial->write_q);
-    init_async_queue(&serial->wait_q);
+    serial->read_q = serial->write_q = serial->wait_q = NULL;
     if (!(serial->fd = create_anonymous_fd( &serial_fd_ops, unix_fd, &serial->obj )))
     {
         release_object( serial );
@@ -165,9 +164,9 @@ static void serial_destroy( struct object *obj)
 {
     struct serial *serial = (struct serial *)obj;
 
-    destroy_async_queue(&serial->read_q);
-    destroy_async_queue(&serial->write_q);
-    destroy_async_queue(&serial->wait_q);
+    async_terminate_queue( &serial->read_q, STATUS_CANCELLED );
+    async_terminate_queue( &serial->write_q, STATUS_CANCELLED );
+    async_terminate_queue( &serial->wait_q, STATUS_CANCELLED );
     if (serial->fd) release_object( serial->fd );
 }
 
@@ -189,12 +188,9 @@ static int serial_get_poll_events( struct fd *fd )
     int events = 0;
     assert( serial->obj.ops == &serial_ops );
 
-    if(IS_READY(serial->read_q))
-        events |= POLLIN;
-    if(IS_READY(serial->write_q))
-        events |= POLLOUT;
-    if(IS_READY(serial->wait_q))
-        events |= POLLIN;
+    if (serial->read_q)  events |= POLLIN;
+    if (serial->write_q) events |= POLLOUT;
+    if (serial->wait_q)  events |= POLLIN;
 
     /* fprintf(stderr,"poll events are %04x\n",events); */
 
@@ -225,39 +221,40 @@ static void serial_poll_event(struct fd *fd, int event)
 
     /* fprintf(stderr,"Poll event %02x\n",event); */
 
-    if(IS_READY(serial->read_q) && (POLLIN & event) )
-        async_notify(serial->read_q.head,STATUS_ALERTED);
+    if (serial->read_q && (POLLIN & event) )
+        async_terminate( serial->read_q, STATUS_ALERTED );
 
-    if(IS_READY(serial->write_q) && (POLLOUT & event) )
-        async_notify(serial->write_q.head,STATUS_ALERTED);
+    if (serial->write_q && (POLLOUT & event) )
+        async_terminate( serial->write_q, STATUS_ALERTED );
 
-    if(IS_READY(serial->wait_q) && (POLLIN & event) )
-        async_notify(serial->wait_q.head,STATUS_ALERTED);
+    if (serial->wait_q && (POLLIN & event) )
+        async_terminate( serial->wait_q, STATUS_ALERTED );
 
     set_fd_events( fd, serial_get_poll_events(fd) );
 }
 
-static void serial_queue_async(struct fd *fd, void *ptr, unsigned int status, int type, int count)
+static void serial_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
+                                int type, int count )
 {
     struct serial *serial = get_fd_user( fd );
-    struct async_queue *q;
-    struct async *async;
+    struct async **head;
     int timeout;
+    int events;
 
     assert(serial->obj.ops == &serial_ops);
 
-    switch(type)
+    switch (type)
     {
     case ASYNC_TYPE_READ:
-        q = &serial->read_q;
+        head = &serial->read_q;
         timeout = serial->readconst + serial->readmult*count;
         break;
     case ASYNC_TYPE_WAIT:
-        q = &serial->wait_q;
+        head = &serial->wait_q;
         timeout = 0;
         break;
     case ASYNC_TYPE_WRITE:
-        q = &serial->write_q;
+        head = &serial->write_q;
         timeout = serial->writeconst + serial->writemult*count;
         break;
     default:
@@ -265,37 +262,29 @@ static void serial_queue_async(struct fd *fd, void *ptr, unsigned int status, in
         return;
     }
 
-    async = find_async ( q, current, ptr );
+    if (!create_async( fd, current, timeout, head, apc, user, iosb ))
+        return;
 
-    if ( status == STATUS_PENDING )
+    /* Check if the new pending request can be served immediately */
+    events = check_fd_events( fd, serial_get_poll_events( fd ) );
+    if (events)
     {
-        int events;
-
-        if ( !async )
-            async = create_async ( &serial->obj, current, ptr );
-        if ( !async )
-            return;
+        /* serial_poll_event() calls set_select_events() */
+        serial_poll_event( fd, events );
+        return;
+    }
 
-        async->status = STATUS_PENDING;
-        if(!async->q)
-        {
-            async_add_timeout(async,timeout);
-            async_insert(q, async);
-        }
+    set_fd_events( fd, serial_get_poll_events( fd ) );
+}
 
-        /* Check if the new pending request can be served immediately */
-        events = check_fd_events( fd, serial_get_poll_events( fd ) );
-        if (events)
-        {
-            /* serial_poll_event() calls set_select_events() */
-            serial_poll_event( fd, events );
-            return;
-        }
-    }
-    else if ( async ) destroy_async ( async );
-    else set_error ( STATUS_INVALID_PARAMETER );
+static void serial_cancel_async( struct fd *fd )
+{
+    struct serial *serial = get_fd_user( fd );
+    assert(serial->obj.ops == &serial_ops);
 
-    set_fd_events ( fd, serial_get_poll_events( fd ) );
+    async_terminate_queue( &serial->read_q, STATUS_CANCELLED );
+    async_terminate_queue( &serial->write_q, STATUS_CANCELLED );
+    async_terminate_queue( &serial->wait_q, STATUS_CANCELLED );
 }
 
 static int serial_flush( struct fd *fd, struct event **event )
@@ -338,7 +327,7 @@ DECL_HANDLER(set_serial_info)
     if ((serial = get_serial_obj( current->process, req->handle, 0 )))
     {
         /* timeouts */
-        if(req->flags & SERIALINFO_SET_TIMEOUTS)
+        if (req->flags & SERIALINFO_SET_TIMEOUTS)
         {
             serial->readinterval = req->readinterval;
             serial->readconst    = req->readconst;
@@ -348,21 +337,17 @@ DECL_HANDLER(set_serial_info)
         }
 
         /* event mask */
-        if(req->flags & SERIALINFO_SET_MASK)
+        if (req->flags & SERIALINFO_SET_MASK)
         {
             serial->eventmask = req->eventmask;
-            if(!serial->eventmask)
+            if (!serial->eventmask)
             {
-                while(serial->wait_q.head)
-                {
-                    async_notify(serial->wait_q.head, STATUS_SUCCESS);
-                    destroy_async(serial->wait_q.head);
-                }
+                async_terminate_queue( &serial->wait_q, STATUS_SUCCESS );
             }
         }
 
         /* comm port error status */
-        if(req->flags & SERIALINFO_SET_ERROR)
+        if (req->flags & SERIALINFO_SET_ERROR)
         {
             serial->commerror = req->commerror;
         }
diff --git a/server/signal.c b/server/signal.c
index 99d9b82dc08a70e9f17c8c1315c4f871e772b100..0fe7df3f654c5a8620c66ffd84cc923f68c92b0a 100644
--- a/server/signal.c
+++ b/server/signal.c
@@ -71,7 +71,8 @@ static const struct fd_ops handler_fd_ops =
     handler_poll_event,       /* poll_event */
     no_flush,                 /* flush */
     no_get_file_info,         /* get_file_info */
-    no_queue_async            /* queue_async */
+    no_queue_async,           /* queue_async */
+    no_cancel_async           /* cancel_async */
 };
 
 static struct handler *handler_sighup;
diff --git a/server/sock.c b/server/sock.c
index fa911e9cd4891d31853274c99807f5b316940b05..9a4ae794224a050703dfd4368c9bcee95382121e 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -56,7 +56,6 @@
 #include "thread.h"
 #include "request.h"
 #include "user.h"
-#include "async.h"
 
 /* To avoid conflicts with the Unix socket headers. Plus we only need a few
  * macros anyway.
@@ -81,9 +80,9 @@ struct sock
     unsigned int        message;     /* message to send */
     obj_handle_t        wparam;      /* message wparam (socket handle) */
     int                 errors[FD_MAX_EVENTS]; /* event errors */
-    struct sock*        deferred;    /* socket that waits for a deferred accept */
-    struct async_queue  read_q;      /* Queue for asynchronous reads */
-    struct async_queue  write_q;     /* Queue for asynchronous writes */
+    struct sock        *deferred;    /* socket that waits for a deferred accept */
+    struct async       *read_q;      /* Queue for asynchronous reads */
+    struct async       *write_q;     /* Queue for asynchronous writes */
 };
 
 static void sock_dump( struct object *obj, int verbose );
@@ -94,7 +93,8 @@ static void sock_destroy( struct object *obj );
 static int sock_get_poll_events( struct fd *fd );
 static void sock_poll_event( struct fd *fd, int event );
 static int sock_get_info( struct fd *fd );
-static void sock_queue_async( struct fd *fd, void *ptr, unsigned int status, int type, int count );
+static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb, int type, int count );
+static void sock_cancel_async( struct fd *fd );
 
 static int sock_get_error( int err );
 static void sock_set_error(void);
@@ -117,7 +117,8 @@ static const struct fd_ops sock_fd_ops =
     sock_poll_event,              /* poll_event */
     no_flush,                     /* flush */
     sock_get_info,                /* get_file_info */
-    sock_queue_async              /* queue_async */
+    sock_queue_async,             /* queue_async */
+    sock_cancel_async             /* cancel_async */
 };
 
 
@@ -150,48 +151,48 @@ typedef enum {
 
 static sock_shutdown_t sock_shutdown_type = SOCK_SHUTDOWN_ERROR;
 
-static sock_shutdown_t sock_check_pollhup (void)
+static sock_shutdown_t sock_check_pollhup(void)
 {
     sock_shutdown_t ret = SOCK_SHUTDOWN_ERROR;
     int fd[2], n;
     struct pollfd pfd;
     char dummy;
 
-    if ( socketpair ( AF_UNIX, SOCK_STREAM, 0, fd ) ) goto out;
-    if ( shutdown ( fd[0], 1 ) ) goto out;
+    if ( socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) ) goto out;
+    if ( shutdown( fd[0], 1 ) ) goto out;
 
     pfd.fd = fd[1];
     pfd.events = POLLIN;
     pfd.revents = 0;
 
-    n = poll ( &pfd, 1, 0 );
+    n = poll( &pfd, 1, 0 );
     if ( n != 1 ) goto out; /* error or timeout */
     if ( pfd.revents & POLLHUP )
         ret = SOCK_SHUTDOWN_POLLHUP;
     else if ( pfd.revents & POLLIN &&
-              read ( fd[1], &dummy, 1 ) == 0 )
+              read( fd[1], &dummy, 1 ) == 0 )
         ret = SOCK_SHUTDOWN_EOF;
 
 out:
-    close ( fd[0] );
-    close ( fd[1] );
+    close( fd[0] );
+    close( fd[1] );
     return ret;
 }
 
 void sock_init(void)
 {
-    sock_shutdown_type = sock_check_pollhup ();
+    sock_shutdown_type = sock_check_pollhup();
 
     switch ( sock_shutdown_type )
     {
     case SOCK_SHUTDOWN_EOF:
-        if (debug_level) fprintf ( stderr, "sock_init: shutdown() causes EOF\n" );
+        if (debug_level) fprintf( stderr, "sock_init: shutdown() causes EOF\n" );
         break;
     case SOCK_SHUTDOWN_POLLHUP:
-        if (debug_level) fprintf ( stderr, "sock_init: shutdown() causes POLLHUP\n" );
+        if (debug_level) fprintf( stderr, "sock_init: shutdown() causes POLLHUP\n" );
         break;
     default:
-        fprintf ( stderr, "sock_init: ERROR in sock_check_pollhup()\n" );
+        fprintf( stderr, "sock_init: ERROR in sock_check_pollhup()\n" );
         sock_shutdown_type = SOCK_SHUTDOWN_EOF;
     }
 }
@@ -217,13 +218,13 @@ static int sock_reselect( struct sock *sock )
 
 /* After POLLHUP is received, the socket will no longer be in the main select loop.
    This function is used to signal pending events nevertheless */
-static void sock_try_event ( struct sock *sock, int event )
+static void sock_try_event( struct sock *sock, int event )
 {
     event = check_fd_events( sock->fd, event );
     if (event)
     {
-        if ( debug_level ) fprintf ( stderr, "sock_try_event: %x\n", event );
-        sock_poll_event ( sock->fd, event );
+        if ( debug_level ) fprintf( stderr, "sock_try_event: %x\n", event );
+        sock_poll_event( sock->fd, event );
     }
 }
 
@@ -236,16 +237,16 @@ static void sock_wake_up( struct sock *sock, int pollev )
 
     if ( sock->flags & WSA_FLAG_OVERLAPPED )
     {
-        if( pollev & (POLLIN|POLLPRI) && IS_READY( sock->read_q ) )
+        if ( pollev & (POLLIN|POLLPRI) && sock->read_q )
         {
-            if (debug_level) fprintf ( stderr, "activating read queue for socket %p\n", sock );
-            async_notify( sock->read_q.head, STATUS_ALERTED );
+            if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock );
+            async_terminate( sock->read_q, STATUS_ALERTED );
             async_active = 1;
         }
-        if( pollev & POLLOUT && IS_READY( sock->write_q ) )
+        if ( pollev & POLLOUT && sock->write_q )
         {
-            if (debug_level) fprintf ( stderr, "activating write queue for socket %p\n", sock );
-            async_notify( sock->write_q.head, STATUS_ALERTED );
+            if (debug_level) fprintf( stderr, "activating write queue for socket %p\n", sock );
+            async_terminate( sock->write_q, STATUS_ALERTED );
             async_active = 1;
         }
     }
@@ -315,8 +316,8 @@ static void sock_poll_event( struct fd *fd, int event )
             if (debug_level)
                 fprintf(stderr, "socket %p connection failure\n", sock);
         }
-    } else
-    if (sock->state & FD_WINE_LISTENING)
+    }
+    else if (sock->state & FD_WINE_LISTENING)
     {
         /* listening */
         if (event & POLLIN)
@@ -333,7 +334,8 @@ static void sock_poll_event( struct fd *fd, int event )
             sock->errors[FD_ACCEPT_BIT] = sock_error( fd );
             sock->hmask |= FD_ACCEPT;
         }
-    } else
+    }
+    else
     {
         /* normal data flow */
         if ( sock->type == SOCK_STREAM && ( event & POLLIN ) )
@@ -364,7 +366,7 @@ static void sock_poll_event( struct fd *fd, int event )
                 else
                 {
                     if ( debug_level )
-                        fprintf ( stderr, "recv error on socket %p: %d\n", sock, errno );
+                        fprintf( stderr, "recv error on socket %p: %d\n", sock, errno );
                     event = POLLERR;
                 }
             }
@@ -418,7 +420,7 @@ static void sock_poll_event( struct fd *fd, int event )
     if ( sock->pmask & FD_CLOSE || event & (POLLERR|POLLHUP) )
     {
         if ( debug_level )
-            fprintf ( stderr, "removing socket %p from select loop\n", sock );
+            fprintf( stderr, "removing socket %p from select loop\n", sock );
         set_fd_events( sock->fd, -1 );
     }
     else
@@ -464,9 +466,9 @@ static int sock_get_poll_events( struct fd *fd )
         /* listening, wait for readable */
         return (sock->hmask & FD_ACCEPT) ? 0 : POLLIN;
 
-    if (mask & (FD_READ) || (sock->flags & WSA_FLAG_OVERLAPPED && IS_READY (sock->read_q)))
+    if (mask & (FD_READ) || (sock->flags & WSA_FLAG_OVERLAPPED && sock->read_q))
         ev |= POLLIN | POLLPRI;
-    if (mask & FD_WRITE || (sock->flags & WSA_FLAG_OVERLAPPED && IS_READY (sock->write_q)))
+    if (mask & FD_WRITE || (sock->flags & WSA_FLAG_OVERLAPPED && sock->write_q))
         ev |= POLLOUT;
     /* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */
     if ( sock->type == SOCK_STREAM && ( sock->mask & ~sock->hmask & FD_CLOSE) )
@@ -479,7 +481,7 @@ static int sock_get_info( struct fd *fd )
 {
     int flags = FD_FLAG_AVAILABLE;
     struct sock *sock = get_fd_user( fd );
-    assert ( sock->obj.ops == &sock_ops );
+    assert( sock->obj.ops == &sock_ops );
 
     if (sock->flags & WSA_FLAG_OVERLAPPED) flags |= FD_FLAG_OVERLAPPED;
     if ( sock->type != SOCK_STREAM || sock->state & FD_WINE_CONNECTED )
@@ -490,62 +492,57 @@ static int sock_get_info( struct fd *fd )
     return flags;
 }
 
-static void sock_queue_async(struct fd *fd, void *ptr, unsigned int status, int type, int count)
+static void sock_queue_async( struct fd *fd, void *apc, void *user, void *iosb,
+                              int type, int count )
 {
     struct sock *sock = get_fd_user( fd );
-    struct async_queue *q;
-    struct async *async;
+    struct async **head;
     int pollev;
-
+    
     assert( sock->obj.ops == &sock_ops );
 
     if ( !(sock->flags & WSA_FLAG_OVERLAPPED) )
     {
-        set_error ( STATUS_INVALID_HANDLE );
+        set_error( STATUS_INVALID_HANDLE );
         return;
     }
 
-    switch( type )
+    switch (type)
     {
     case ASYNC_TYPE_READ:
-        q = &sock->read_q;
+        head = &sock->read_q;
         sock->hmask &= ~FD_CLOSE;
         break;
     case ASYNC_TYPE_WRITE:
-        q = &sock->write_q;
+        head = &sock->write_q;
         break;
     default:
         set_error( STATUS_INVALID_PARAMETER );
         return;
     }
 
-    async = find_async ( q, current, ptr );
-
-    if ( status == STATUS_PENDING )
+    if ( ( !( sock->state & FD_READ ) && type == ASYNC_TYPE_READ  ) ||
+         ( !( sock->state & FD_WRITE ) && type == ASYNC_TYPE_WRITE ) )
     {
-        if ( ( !( sock->state & FD_READ ) && type == ASYNC_TYPE_READ  ) ||
-             ( !( sock->state & FD_WRITE ) && type == ASYNC_TYPE_WRITE ) )
-        {
-            set_error ( STATUS_PIPE_DISCONNECTED );
-            if ( async ) destroy_async ( async );
-        }
-        else
-        {
-            if ( !async )
-                async = create_async ( &sock->obj, current, ptr );
-            if ( !async )
-                return;
-
-            async->status = STATUS_PENDING;
-            if ( !async->q )
-                async_insert ( q, async );
-        }
+        set_error( STATUS_PIPE_DISCONNECTED );
+    }
+    else
+    {
+        if (!create_async( fd, current, 0, head, apc, user, iosb ))
+            return;
     }
-    else if ( async ) destroy_async ( async );
-    else set_error ( STATUS_INVALID_PARAMETER );
 
-    pollev = sock_reselect ( sock );
-    if ( pollev ) sock_try_event ( sock, pollev );
+    pollev = sock_reselect( sock );
+    if ( pollev ) sock_try_event( sock, pollev );
+}
+
+static void sock_cancel_async( struct fd *fd )
+{
+    struct sock *sock = get_fd_user( fd );
+    assert( sock->obj.ops == &sock_ops );
+
+    async_terminate_queue( &sock->read_q, STATUS_CANCELLED );
+    async_terminate_queue( &sock->write_q, STATUS_CANCELLED );
 }
 
 static struct fd *sock_get_fd( struct object *obj )
@@ -562,12 +559,12 @@ static void sock_destroy( struct object *obj )
     /* FIXME: special socket shutdown stuff? */
 
     if ( sock->deferred )
-        release_object ( sock->deferred );
+        release_object( sock->deferred );
 
     if ( sock->flags & WSA_FLAG_OVERLAPPED )
     {
-        destroy_async_queue ( &sock->read_q );
-        destroy_async_queue ( &sock->write_q );
+        async_terminate_queue( &sock->read_q, STATUS_CANCELLED );
+        async_terminate_queue( &sock->write_q, STATUS_CANCELLED );
     }
     if (sock->event) release_object( sock->event );
     if (sock->fd) release_object( sock->fd );
@@ -582,7 +579,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
     sockfd = socket( family, type, protocol );
     if (debug_level)
         fprintf(stderr,"socket(%d,%d,%d)=%d\n",family,type,protocol,sockfd);
-    if (sockfd == -1) {
+    if (sockfd == -1)
+    {
         sock_set_error();
         return NULL;
     }
@@ -612,8 +610,7 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
     }
     if (sock->flags & WSA_FLAG_OVERLAPPED)
     {
-        init_async_queue (&sock->read_q);
-        init_async_queue (&sock->write_q);
+        sock->read_q = sock->write_q = NULL;
     }
     sock_reselect( sock );
     clear_error();
@@ -634,10 +631,13 @@ static struct sock *accept_socket( obj_handle_t handle )
     if (!sock)
     	return NULL;
 
-    if ( sock->deferred ) {
+    if ( sock->deferred )
+    {
         acceptsock = sock->deferred;
         sock->deferred = NULL;
-    } else {
+    }
+    else
+    {
 
         /* Try to accept(2). We can't be safe that this an already connected socket
          * or that accept() is allowed on it. In those cases we will get -1/errno
@@ -645,7 +645,8 @@ static struct sock *accept_socket( obj_handle_t handle )
          */
         slen = sizeof(saddr);
         acceptfd = accept( get_unix_fd(sock->fd), &saddr, &slen);
-        if (acceptfd==-1) {
+        if (acceptfd==-1)
+        {
             sock_set_error();
             release_object( sock );
             return NULL;
@@ -683,8 +684,7 @@ static struct sock *accept_socket( obj_handle_t handle )
         }
         if ( acceptsock->flags & WSA_FLAG_OVERLAPPED )
         {
-            init_async_queue ( &acceptsock->read_q );
-            init_async_queue ( &acceptsock->write_q );
+            acceptsock->read_q = acceptsock->write_q = NULL;
         }
     }
     clear_error();
@@ -700,62 +700,62 @@ static int sock_get_error( int err )
 {
     switch (err)
     {
-        case EINTR:             return WSAEINTR; break;
-        case EBADF:             return WSAEBADF; break;
+        case EINTR:             return WSAEINTR;
+        case EBADF:             return WSAEBADF;
         case EPERM:
-        case EACCES:            return WSAEACCES; break;
-        case EFAULT:            return WSAEFAULT; break;
-        case EINVAL:            return WSAEINVAL; break;
-        case EMFILE:            return WSAEMFILE; break;
-        case EWOULDBLOCK:       return WSAEWOULDBLOCK; break;
-        case EINPROGRESS:       return WSAEINPROGRESS; break;
-        case EALREADY:          return WSAEALREADY; break;
-        case ENOTSOCK:          return WSAENOTSOCK; break;
-        case EDESTADDRREQ:      return WSAEDESTADDRREQ; break;
-        case EMSGSIZE:          return WSAEMSGSIZE; break;
-        case EPROTOTYPE:        return WSAEPROTOTYPE; break;
-        case ENOPROTOOPT:       return WSAENOPROTOOPT; break;
-        case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT; break;
-        case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT; break;
-        case EOPNOTSUPP:        return WSAEOPNOTSUPP; break;
-        case EPFNOSUPPORT:      return WSAEPFNOSUPPORT; break;
-        case EAFNOSUPPORT:      return WSAEAFNOSUPPORT; break;
-        case EADDRINUSE:        return WSAEADDRINUSE; break;
-        case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL; break;
-        case ENETDOWN:          return WSAENETDOWN; break;
-        case ENETUNREACH:       return WSAENETUNREACH; break;
-        case ENETRESET:         return WSAENETRESET; break;
-        case ECONNABORTED:      return WSAECONNABORTED; break;
+        case EACCES:            return WSAEACCES;
+        case EFAULT:            return WSAEFAULT;
+        case EINVAL:            return WSAEINVAL;
+        case EMFILE:            return WSAEMFILE;
+        case EWOULDBLOCK:       return WSAEWOULDBLOCK;
+        case EINPROGRESS:       return WSAEINPROGRESS;
+        case EALREADY:          return WSAEALREADY;
+        case ENOTSOCK:          return WSAENOTSOCK;
+        case EDESTADDRREQ:      return WSAEDESTADDRREQ;
+        case EMSGSIZE:          return WSAEMSGSIZE;
+        case EPROTOTYPE:        return WSAEPROTOTYPE;
+        case ENOPROTOOPT:       return WSAENOPROTOOPT;
+        case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
+        case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
+        case EOPNOTSUPP:        return WSAEOPNOTSUPP;
+        case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
+        case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
+        case EADDRINUSE:        return WSAEADDRINUSE;
+        case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
+        case ENETDOWN:          return WSAENETDOWN;
+        case ENETUNREACH:       return WSAENETUNREACH;
+        case ENETRESET:         return WSAENETRESET;
+        case ECONNABORTED:      return WSAECONNABORTED;
         case EPIPE:
-        case ECONNRESET:        return WSAECONNRESET; break;
-        case ENOBUFS:           return WSAENOBUFS; break;
-        case EISCONN:           return WSAEISCONN; break;
-        case ENOTCONN:          return WSAENOTCONN; break;
-        case ESHUTDOWN:         return WSAESHUTDOWN; break;
-        case ETOOMANYREFS:      return WSAETOOMANYREFS; break;
-        case ETIMEDOUT:         return WSAETIMEDOUT; break;
-        case ECONNREFUSED:      return WSAECONNREFUSED; break;
-        case ELOOP:             return WSAELOOP; break;
-        case ENAMETOOLONG:      return WSAENAMETOOLONG; break;
-        case EHOSTDOWN:         return WSAEHOSTDOWN; break;
-        case EHOSTUNREACH:      return WSAEHOSTUNREACH; break;
-        case ENOTEMPTY:         return WSAENOTEMPTY; break;
+        case ECONNRESET:        return WSAECONNRESET;
+        case ENOBUFS:           return WSAENOBUFS;
+        case EISCONN:           return WSAEISCONN;
+        case ENOTCONN:          return WSAENOTCONN;
+        case ESHUTDOWN:         return WSAESHUTDOWN;
+        case ETOOMANYREFS:      return WSAETOOMANYREFS;
+        case ETIMEDOUT:         return WSAETIMEDOUT;
+        case ECONNREFUSED:      return WSAECONNREFUSED;
+        case ELOOP:             return WSAELOOP;
+        case ENAMETOOLONG:      return WSAENAMETOOLONG;
+        case EHOSTDOWN:         return WSAEHOSTDOWN;
+        case EHOSTUNREACH:      return WSAEHOSTUNREACH;
+        case ENOTEMPTY:         return WSAENOTEMPTY;
 #ifdef EPROCLIM
-        case EPROCLIM:          return WSAEPROCLIM; break;
+        case EPROCLIM:          return WSAEPROCLIM;
 #endif
 #ifdef EUSERS
-        case EUSERS:            return WSAEUSERS; break;
+        case EUSERS:            return WSAEUSERS;
 #endif
 #ifdef EDQUOT
-        case EDQUOT:            return WSAEDQUOT; break;
+        case EDQUOT:            return WSAEDQUOT;
 #endif
 #ifdef ESTALE
-        case ESTALE:            return WSAESTALE; break;
+        case ESTALE:            return WSAESTALE;
 #endif
 #ifdef EREMOTE
-        case EREMOTE:           return WSAEREMOTE; break;
+        case EREMOTE:           return WSAEREMOTE;
 #endif
-    default: errno=err; perror("sock_set_error"); return WSAEFAULT; break;
+    default: errno=err; perror("sock_set_error"); return WSAEFAULT;
     }
 }
 
@@ -814,7 +814,7 @@ DECL_HANDLER(set_socket_event)
     if (debug_level && sock->event) fprintf(stderr, "event ptr: %p\n", sock->event);
 
     pollev = sock_reselect( sock );
-    if ( pollev ) sock_try_event ( sock, pollev );
+    if ( pollev ) sock_try_event( sock, pollev );
 
     if (sock->mask)
         sock->state |= FD_WINE_NONBLOCKING;
@@ -885,7 +885,7 @@ DECL_HANDLER(enable_socket_event)
     if ( sock->type != SOCK_STREAM ) sock->state &= ~STREAM_FLAG_MASK;
 
     pollev = sock_reselect( sock );
-    if ( pollev ) sock_try_event ( sock, pollev );
+    if ( pollev ) sock_try_event( sock, pollev );
 
     release_object( &sock->obj );
 }
@@ -898,17 +898,17 @@ DECL_HANDLER(set_socket_deferred)
                                        GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
     if ( !sock )
     {
-        set_error ( WSAENOTSOCK );
+        set_error( WSAENOTSOCK );
         return;
     }
     acceptsock = (struct sock*)get_handle_obj( current->process,req->deferred,
                                                GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
     if ( !acceptsock )
     {
-        release_object ( sock );
-        set_error ( WSAENOTSOCK );
+        release_object( sock );
+        set_error( WSAENOTSOCK );
         return;
     }
     sock->deferred = acceptsock;
-    release_object ( sock );
+    release_object( sock );
 }
diff --git a/server/thread.c b/server/thread.c
index ced318977e889d1b65b23eda200ad17ced7051a5..64e2ad5c5556b067ae8d6167f8f46a4025178439 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -100,7 +100,8 @@ static const struct fd_ops thread_fd_ops =
     thread_poll_event,          /* poll_event */
     no_flush,                   /* flush */
     no_get_file_info,           /* get_file_info */
-    no_queue_async              /* queue_async */
+    no_queue_async,             /* queue_async */
+    no_cancel_async             /* cancel_async */
 };
 
 static struct thread *first_thread;
diff --git a/server/trace.c b/server/trace.c
index bcba1d1444f99d4a35a3264984c5423c47345a0c..38d4c894dad78ac32c2dc7bd941360532d18b069 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1948,9 +1948,15 @@ static void dump_register_async_request( const struct register_async_request *re
 {
     fprintf( stderr, " handle=%p,", req->handle );
     fprintf( stderr, " type=%d,", req->type );
-    fprintf( stderr, " overlapped=%p,", req->overlapped );
-    fprintf( stderr, " count=%d,", req->count );
-    fprintf( stderr, " status=%08x", req->status );
+    fprintf( stderr, " io_apc=%p,", req->io_apc );
+    fprintf( stderr, " io_sb=%p,", req->io_sb );
+    fprintf( stderr, " io_user=%p,", req->io_user );
+    fprintf( stderr, " count=%d", req->count );
+}
+
+static void dump_cancel_async_request( const struct cancel_async_request *req )
+{
+    fprintf( stderr, " handle=%p", req->handle );
 }
 
 static void dump_create_named_pipe_request( const struct create_named_pipe_request *req )
@@ -2730,6 +2736,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_get_serial_info_request,
     (dump_func)dump_set_serial_info_request,
     (dump_func)dump_register_async_request,
+    (dump_func)dump_cancel_async_request,
     (dump_func)dump_create_named_pipe_request,
     (dump_func)dump_open_named_pipe_request,
     (dump_func)dump_connect_named_pipe_request,
@@ -2912,6 +2919,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_get_serial_info_reply,
     (dump_func)0,
     (dump_func)0,
+    (dump_func)0,
     (dump_func)dump_create_named_pipe_reply,
     (dump_func)dump_open_named_pipe_reply,
     (dump_func)0,
@@ -3094,6 +3102,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "get_serial_info",
     "set_serial_info",
     "register_async",
+    "cancel_async",
     "create_named_pipe",
     "open_named_pipe",
     "connect_named_pipe",