diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c
index 4e82c1e4d28af1e09b39e14aa88bf36db9a20985..3b74114637d877e96ccf4a0ea440bd9458abbb23 100644
--- a/dlls/kernel/comm.c
+++ b/dlls/kernel/comm.c
@@ -1512,27 +1512,19 @@ 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, int events)
+static void COMM_WaitCommEventService(async_private *ovp)
 {
     LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
 
-    TRACE("overlapped %p wait complete %p <- %x\n",lpOverlapped,ovp->buffer,events);
-    if(events&POLLNVAL)
-    {
-        lpOverlapped->Internal = STATUS_HANDLES_CLOSED;
-        return;
-    }
-    if(ovp->buffer)
-    {
-        if(events&POLLIN)
+    TRACE("overlapped %p\n",lpOverlapped);
+
+    /* FIXME: detect other events */
             *ovp->buffer = EV_RXCHAR;
-    }
  
     lpOverlapped->Internal = STATUS_SUCCESS;
 }
 
 
-
 /***********************************************************************
  *             COMM_WaitCommEvent         (INTERNAL)
  *
@@ -1560,20 +1552,6 @@ static BOOL COMM_WaitCommEvent(
     lpOverlapped->Offset = 0;
     lpOverlapped->OffsetHigh = 0;
 
-    /* start an ASYNCHRONOUS WaitCommEvent */
-    SERVER_START_REQ( create_async )
-    {
-        req->file_handle = hFile;
-        req->count = 0;
-        req->type = ASYNC_TYPE_WAIT;
-
-        ret=wine_server_call_err( req );
-    }
-    SERVER_END_REQ;
-
-    if (ret)
-        return FALSE;
-  
     fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
     if(fd<0)
 	return FALSE;
@@ -1585,15 +1563,13 @@ static BOOL COMM_WaitCommEvent(
         return FALSE;
     }
     ovp->lpOverlapped = lpOverlapped;
-    ovp->timeout = 0;
-    ovp->tv.tv_sec = 0;
-    ovp->tv.tv_usec = 0;
-    ovp->event = POLLIN;
     ovp->func = COMM_WaitCommEventService;
     ovp->buffer = (char *)lpdwEvents;
     ovp->fd = fd;
     ovp->count = 0;
     ovp->completion_func = 0;                                                  
+    ovp->type = ASYNC_TYPE_WAIT;
+    ovp->handle = hFile;
   
     ovp->next = NtCurrentTeb()->pending_list;
     ovp->prev = NULL;
@@ -1601,6 +1577,21 @@ static BOOL COMM_WaitCommEvent(
         ovp->next->prev=ovp;
     NtCurrentTeb()->pending_list = ovp;
   
+    /* start an ASYNCHRONOUS WaitCommEvent */
+    SERVER_START_REQ( register_async )
+    {
+        req->handle = hFile;
+        req->overlapped = lpOverlapped;
+        req->type = ASYNC_TYPE_WAIT;
+        req->count = 0;
+        req->func = check_async_list;
+        req->status = STATUS_PENDING;
+
+        ret=wine_server_call_err(req);
+    }
+    SERVER_END_REQ;
+
+    if (!ret)
     SetLastError(ERROR_IO_PENDING);
 
     return FALSE;
diff --git a/files/file.c b/files/file.c
index 995ae3e992f8f2161f0585d70197e946ecb7dc07..b3ef8978fb4d8135b1d4dccaee3076011a4ab87d 100644
--- a/files/file.c
+++ b/files/file.c
@@ -1247,13 +1247,35 @@ BOOL WINAPI GetOverlappedResult(
 }
 
 
+/***********************************************************************
+ *              FILE_StartAsync                (INTERNAL)
+ *
+ * type==ASYNC_TYPE_NONE means cancel the indicated overlapped operation
+ * lpOverlapped==NULL means all overlappeds match
+ */
+BOOL FILE_StartAsync(HANDLE hFile, LPOVERLAPPED lpOverlapped, DWORD type, DWORD count, DWORD status)
+{
+    BOOL ret;
+    SERVER_START_REQ(register_async)
+    {
+        req->handle = hFile;
+        req->overlapped = lpOverlapped;
+        req->type = type;
+        req->count = count;
+        req->func = check_async_list;
+        req->status = status;
+        ret = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+    return !ret;
+}
+
 /***********************************************************************
  *             CancelIo                   (KERNEL32.@)
  */
 BOOL WINAPI CancelIo(HANDLE handle)
 {
-    FIXME("(%d) stub\n",handle);
-    return FALSE;
+    return FILE_StartAsync(handle, NULL, ASYNC_TYPE_NONE, 0, STATUS_CANCELLED);
 }
 
 /***********************************************************************
@@ -1262,28 +1284,12 @@ BOOL WINAPI CancelIo(HANDLE handle)
  *  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, int events)
+static void FILE_AsyncReadService(async_private *ovp)
 {
     LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
     int result, r;
 
-    TRACE("%p %p %08x\n", lpOverlapped, ovp->buffer, events );
-
-    /* if POLLNVAL, then our fd was closed or we have the wrong fd */
-    if(events&POLLNVAL)
-    {
-        ERR("fd %d invalid for %p\n",ovp->fd,ovp);
-        r = STATUS_UNSUCCESSFUL;
-        goto async_end;
-    }
-
-    /* if there are no events, it must be a timeout */
-    if(events==0)
-    {
-        TRACE("read timed out\n");
-        r = STATUS_TIMEOUT;
-        goto async_end;
-    }
+    TRACE("%p %p\n", lpOverlapped, ovp->buffer );
 
     /* check to see if the data is ready (non-blocking) */
     result = read(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
@@ -1316,41 +1322,6 @@ async_end:
     lpOverlapped->Internal = r;
 }
 
-/* flogged from wineserver */
-/* add a timeout in milliseconds to an absolute time */
-static void add_timeout( struct timeval *when, int timeout )
-{
-    if (timeout)
-    {
-        long sec = timeout / 1000;
-        if ((when->tv_usec += (timeout - 1000*sec) * 1000) >= 1000000)
-        {
-            when->tv_usec -= 1000000;
-            when->tv_sec++;
-        }
-        when->tv_sec += sec;
-    }
-}
-
-/***********************************************************************
- *              FILE_GetTimeout                (INTERNAL)
- */
-static BOOL FILE_GetTimeout(HANDLE hFile, DWORD txcount, DWORD type, int *timeout)
-{
-    BOOL ret;
-    SERVER_START_REQ(create_async)
-    {
-        req->count = txcount;
-        req->type = type;
-        req->file_handle = hFile;
-        ret = wine_server_call( req );
-        if(timeout)
-            *timeout = reply->timeout;
-    }
-    SERVER_END_REQ;
-    return !ret;
-}
-
 /***********************************************************************
  *              FILE_ReadFileEx                (INTERNAL)
  */
@@ -1359,7 +1330,7 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
 			 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
 {
     async_private *ovp;
-    int fd, timeout=0;
+    int fd;
 
     TRACE("file %d to buf %p num %ld %p func %p\n",
 	  hFile, buffer, bytesToRead, overlapped, lpCompletionRoutine);
@@ -1372,12 +1343,6 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
         return FALSE;
     }
 
-    if ( !FILE_GetTimeout(hFile, bytesToRead, ASYNC_TYPE_READ, &timeout ) )
-    {
-        TRACE("FILE_GetTimeout failed\n");
-        return FALSE;
-    }
-
     fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
     if(fd<0)
     {
@@ -1396,13 +1361,11 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
     ovp->lpOverlapped = overlapped;
     ovp->count = bytesToRead;
     ovp->completion_func = lpCompletionRoutine;
-    ovp->timeout = timeout;
-    gettimeofday(&ovp->tv,NULL);
-    add_timeout(&ovp->tv,timeout);
-    ovp->event = POLLIN;
     ovp->func = FILE_AsyncReadService;
     ovp->buffer = buffer;
     ovp->fd = fd;
+    ovp->type = ASYNC_TYPE_READ;
+    ovp->handle = hFile;
 
     /* hook this overlap into the pending async operation list */
     ovp->next = NtCurrentTeb()->pending_list;
@@ -1411,6 +1374,13 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
         ovp->next->prev = ovp;
     NtCurrentTeb()->pending_list = ovp;
 
+    if ( !FILE_StartAsync(hFile, overlapped, ASYNC_TYPE_READ, bytesToRead, STATUS_PENDING) )
+    {
+        /* FIXME: remove async_private and release memory */
+        ERR("FILE_StartAsync failed\n");
+        return FALSE;
+    }
+
     return TRUE;
 }
 
@@ -1548,28 +1518,12 @@ BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
  *  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, int events)
+static void FILE_AsyncWriteService(struct async_private *ovp)
 {
     LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
     int result, r;
 
-    TRACE("(%p %p %08x)\n",lpOverlapped,ovp->buffer,events);
-
-    /* if POLLNVAL, then our fd was closed or we have the wrong fd */
-    if(events&POLLNVAL)
-    {
-        ERR("fd %d invalid for %p\n",ovp->fd,ovp);
-        r = STATUS_UNSUCCESSFUL;
-        goto async_end;
-    }
-
-    /* if there are no events, it must be a timeout */
-    if(events==0)
-    {
-        TRACE("write timed out\n");
-        r = STATUS_TIMEOUT;
-        goto async_end;
-    }
+    TRACE("(%p %p)\n",lpOverlapped,ovp->buffer);
 
     /* write some data (non-blocking) */
     result = write(ovp->fd, &ovp->buffer[lpOverlapped->InternalHigh],
@@ -1609,7 +1563,6 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
 			 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
 {
     async_private *ovp;
-    int timeout=0;
 
     TRACE("file %d to buf %p num %ld %p func %p stub\n",
 	  hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine);
@@ -1623,9 +1576,9 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
     overlapped->Internal     = STATUS_PENDING;
     overlapped->InternalHigh = 0;
 
-    if (!FILE_GetTimeout(hFile, bytesToWrite, ASYNC_TYPE_WRITE, &timeout))
+    if (!FILE_StartAsync(hFile, overlapped, ASYNC_TYPE_WRITE, bytesToWrite, STATUS_PENDING ))
     {
-        TRACE("FILE_GetTimeout failed\n");
+        TRACE("FILE_StartAsync failed\n");
         return FALSE;
     }
 
@@ -1637,15 +1590,14 @@ BOOL WINAPI WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
         return FALSE;
     }
     ovp->lpOverlapped = overlapped;
-    ovp->timeout = timeout;
-    gettimeofday(&ovp->tv,NULL);
-    add_timeout(&ovp->tv,timeout);
-    ovp->event = POLLOUT;
     ovp->func = FILE_AsyncWriteService;
     ovp->buffer = (LPVOID) buffer;
     ovp->count = bytesToWrite;
     ovp->completion_func = lpCompletionRoutine;
     ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
+    ovp->type = ASYNC_TYPE_WRITE;
+    ovp->handle = hFile;
+
     if(ovp->fd <0)
     {
         HeapFree(GetProcessHeap(), 0, ovp);
diff --git a/include/file.h b/include/file.h
index 5efc9a5c5b6c242a39599b07ee1c647530347586..73d5ef3f7fed0dc6d2c3508b2d7084f8aee3f3b8 100644
--- a/include/file.h
+++ b/include/file.h
@@ -33,22 +33,23 @@ typedef struct
 
 /* overlapped private structure */
 struct async_private;
-typedef void (*async_handler)(struct async_private *ovp, int revents);
+typedef void (*async_handler)(struct async_private *ovp);
 typedef struct async_private
 {
      LPOVERLAPPED  lpOverlapped;
+     HANDLE        handle;
      int           fd;
-     int           timeout;
-     struct timeval tv;
-     int           event;
      char         *buffer;
      async_handler func;
      int           count;
+     int           type;
      LPOVERLAPPED_COMPLETION_ROUTINE completion_func;
      struct async_private *next;
      struct async_private *prev;
 } async_private;
 
+extern void check_async_list(LPOVERLAPPED ov, DWORD status);
+
 /* locale-independent case conversion */
 inline static char FILE_tolower( char c )
 {
@@ -80,6 +81,7 @@ extern HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing,
                                DWORD attributes, HANDLE template, BOOL fail_read_only,
                                UINT drive_type );
 extern HANDLE FILE_CreateDevice( int client_id, DWORD access, LPSECURITY_ATTRIBUTES sa );
+extern BOOL FILE_StartAsync(HANDLE handle, LPOVERLAPPED lpOverlapped, DWORD type, DWORD count, DWORD status);
 
 extern LONG WINAPI WIN16_hread(HFILE16,SEGPTR,LONG);
 
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 58cac3faf8c721dda3399f41acb12e0886ec494b..ccb317bd48527f387a1f209932c9e51566822c9d 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -2181,18 +2181,21 @@ struct set_serial_info_reply
 
 
 
-struct create_async_request
+struct register_async_request
 {
     struct request_header __header;
-    handle_t     file_handle;
-    int          count;
+    handle_t     handle;
+    void*        func;
     int          type;
+    void*        overlapped;
+    int          count;
+    unsigned int status;
 };
-struct create_async_reply
+struct register_async_reply
 {
     struct reply_header __header;
-    int          timeout;
 };
+#define ASYNC_TYPE_NONE  0x00
 #define ASYNC_TYPE_READ  0x01
 #define ASYNC_TYPE_WRITE 0x02
 #define ASYNC_TYPE_WAIT  0x03
@@ -2699,7 +2702,7 @@ enum request
     REQ_create_serial,
     REQ_get_serial_info,
     REQ_set_serial_info,
-    REQ_create_async,
+    REQ_register_async,
     REQ_create_named_pipe,
     REQ_open_named_pipe,
     REQ_connect_named_pipe,
@@ -2854,7 +2857,7 @@ union generic_request
     struct create_serial_request create_serial_request;
     struct get_serial_info_request get_serial_info_request;
     struct set_serial_info_request set_serial_info_request;
-    struct create_async_request create_async_request;
+    struct register_async_request register_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;
@@ -3007,7 +3010,7 @@ union generic_reply
     struct create_serial_reply create_serial_reply;
     struct get_serial_info_reply get_serial_info_reply;
     struct set_serial_info_reply set_serial_info_reply;
-    struct create_async_reply create_async_reply;
+    struct register_async_reply register_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;
@@ -3035,6 +3038,6 @@ union generic_reply
     struct get_window_properties_reply get_window_properties_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 66
+#define SERVER_PROTOCOL_VERSION 67
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/scheduler/synchro.c b/scheduler/synchro.c
index 5220f0e28583b2afd7baa813138367c4f1cdbb91..667837408e61ad635655482c2bf9d52ab240e286 100644
--- a/scheduler/synchro.c
+++ b/scheduler/synchro.c
@@ -36,14 +36,6 @@ inline static void get_timeout( struct timeval *when, int timeout )
     }
 }
 
-#define MAX_NUMBER_OF_FDS 20
-
-static inline int time_before( struct timeval *t1, struct timeval *t2 )
-{
-    return ((t1->tv_sec < t2->tv_sec) ||
-            ((t1->tv_sec == t2->tv_sec) && (t1->tv_usec < t2->tv_usec)));
-}
-
 static void CALLBACK call_completion_routine(ULONG_PTR data)
 {
     async_private* ovp = (async_private*)data;
@@ -85,90 +77,32 @@ static void finish_async(async_private *ovp, DWORD status)
 /***********************************************************************
  *           check_async_list
  *
- *  Create a list of fds for poll to check while waiting on the server
- *  FIXME: this loop is too large, cut into smaller functions
- *         perhaps we could share/steal some of the code in server/select.c?
+ * Process a status event from the server.
  */
-static void check_async_list(void)
-{
-    /* FIXME: should really malloc these two arrays */
-    struct pollfd fds[MAX_NUMBER_OF_FDS];
-    async_private *user[MAX_NUMBER_OF_FDS], *tmp;
-    int i, n, r, timeout;
-    async_private *ovp, *timeout_user;
-    struct timeval now;
-
-    while(1)
-    {
-        /* the first fd belongs to the server connection */
-        fds[0].events=POLLIN;
-        fds[0].revents=0;
-        fds[0].fd = NtCurrentTeb()->wait_fd[0];
-
-        ovp = NtCurrentTeb()->pending_list;
-        timeout = -1;
-        timeout_user = NULL;
-        gettimeofday(&now,NULL);
-        for(n=1; ovp && (n<MAX_NUMBER_OF_FDS); ovp = tmp)
-        {
-            tmp = ovp->next;
-
-            if(ovp->lpOverlapped->Internal!=STATUS_PENDING)
-            {
-                finish_async(ovp,STATUS_UNSUCCESSFUL);
-                continue;
-            }
-
-            if(ovp->timeout && time_before(&ovp->tv,&now))
+void check_async_list(LPOVERLAPPED overlapped, DWORD status)
             {
-                finish_async(ovp,STATUS_TIMEOUT);
-                continue;
-            }
+    async_private *ovp;
 
-            fds[n].fd=ovp->fd;
-            fds[n].events=ovp->event;
-            fds[n].revents=0;
-            user[n] = ovp;
+    /* fprintf(stderr,"overlapped %p status %x\n",overlapped,status); */
 
-            if(ovp->timeout && ( (!timeout_user) || time_before(&ovp->tv,&timeout_user->tv)))
-            {
-                timeout = (ovp->tv.tv_sec - now.tv_sec) * 1000
-                        + (ovp->tv.tv_usec - now.tv_usec) / 1000;
-                timeout_user = ovp;
-            }
-
-            n++;
-        }
-
-        /* if there aren't any active asyncs return */
-        if(n==1)
-            return;
-
-        r = poll(fds, n, timeout);
+    for(ovp = NtCurrentTeb()->pending_list; ovp; ovp = ovp->next)
+        if(ovp->lpOverlapped == overlapped)
+            break;
 
-        /* if there were any errors, return immediately */
-        if( (r<0) || (fds[0].revents==POLLNVAL) )
+    if(!ovp)
             return;
 
-        if( r==0 )
-        {
-            finish_async(timeout_user, STATUS_TIMEOUT);
-            continue;
-        }
+    if(status != STATUS_ALERTED)
+        ovp->lpOverlapped->Internal = status;
 
-        /* search for async operations that are ready */
-        for( i=1; i<n; i++)
+    if(ovp->lpOverlapped->Internal==STATUS_PENDING)
         {
-            if (fds[i].revents)
-                user[i]->func(user[i],fds[i].revents);
-
-            if(user[i]->lpOverlapped->Internal!=STATUS_PENDING)
-                finish_async(user[i],user[i]->lpOverlapped->Internal);
+        ovp->func(ovp);
+        FILE_StartAsync(ovp->handle, ovp->lpOverlapped, ovp->type, 0, ovp->lpOverlapped->Internal);
         }
 
-        if(fds[0].revents == POLLIN)
-            return;
-    }
+    if(ovp->lpOverlapped->Internal!=STATUS_PENDING)
+        finish_async(ovp,ovp->lpOverlapped->Internal);
 }
 
 
@@ -184,7 +118,6 @@ static int wait_reply( void *cookie )
     for (;;)
     {
         int ret;
-        if (NtCurrentTeb()->pending_list) check_async_list();
         ret = read( NtCurrentTeb()->wait_fd[0], &reply, sizeof(reply) );
         if (ret == sizeof(reply))
         {
diff --git a/server/async.c b/server/async.c
index 5e160004e050366b4f0081d53edfbb8beea248a9..567631ee6d9b4a2fa0f7143dc4082e3e6e88cd91 100644
--- a/server/async.c
+++ b/server/async.c
@@ -12,23 +12,168 @@
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <stdio.h>
 
 #include "handle.h"
 #include "thread.h"
 #include "request.h"
 
+#include "async.h"
 
-DECL_HANDLER(create_async)
+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;
+
+    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, async->func, APC_ASYNC, 1, 2, async->overlapped, status);
+}
+
+void destroy_async_queue( struct async_queue *q )
+{
+    while(q->head)
+    {
+        async_notify(q->head, STATUS_HANDLES_CLOSED);
+        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 *func, 
+                           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 = thread;
+    async->func = func;
+    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 );
+    }
+}
+
+DECL_HANDLER(register_async)
 {
     struct object *obj;
 
-    if (!(obj = get_handle_obj( current->process, req->file_handle, 0, NULL)) )
+    if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL)) )
         return;
 
-    /* FIXME: check if this object is allowed to do overlapped I/O */
+    if(obj->ops->queue_async)
+    {
+        struct async_queue *q = obj->ops->queue_async(obj, NULL, req->type, 0);
+        struct async *async;
+
+        async = find_async(q, current, req->overlapped);
+        if(req->status==STATUS_PENDING)
+        {
+            if(!async)
+                async = create_async(obj, current, req->func, req->overlapped);
 
-    /* FIXME: this should be a function pointer */
-    reply->timeout = get_serial_async_timeout(obj,req->type,req->count);
+            if(async)
+            {
+                async->status = req->status;
+                if(!obj->ops->queue_async(obj, async, req->type, req->count))
+                    destroy_async(async);
+            }
+        }
+        else
+        {
+            if(async)
+                destroy_async(async);
+            else
+                set_error(STATUS_INVALID_PARAMETER);
+        }
+
+        set_select_events(obj,obj->ops->get_poll_events(obj));
+    }
+    else
+        set_error(STATUS_INVALID_HANDLE);
 
     release_object(obj);
 }
+
diff --git a/server/async.h b/server/async.h
new file mode 100644
index 0000000000000000000000000000000000000000..b0225245dd22015e8cbd2c271e2e9d4e70440eb1
--- /dev/null
+++ b/server/async.h
@@ -0,0 +1,45 @@
+
+#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                *func;
+    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 *func, 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/atom.c b/server/atom.c
index 7d0b52cd0fb9cec1247bfeeb3efb3b15f83f7833..debe1867ac115986e769c2f3a5a51fa7e677662c 100644
--- a/server/atom.c
+++ b/server/atom.c
@@ -59,6 +59,7 @@ static const struct object_ops atom_table_ops =
     no_get_fd,                    /* get_fd */
     no_flush,                     /* flush */
     no_get_file_info,             /* get_file_info */
+    NULL,                         /* queue_async */
     atom_table_destroy            /* destroy */
 };
 
diff --git a/server/change.c b/server/change.c
index 1162b6a7e9602c7cb4210d1bb738a49f4c73f06d..8d3a37c3f5cbc84bb6a33d16c06edee2b12d5ee1 100644
--- a/server/change.c
+++ b/server/change.c
@@ -37,6 +37,7 @@ static const struct object_ops change_ops =
     no_get_fd,                /* get_fd */
     no_flush,                 /* flush */
     no_get_file_info,         /* get_file_info */
+    NULL,                     /* queue_async */
     no_destroy                /* destroy */
 };
 
diff --git a/server/console.c b/server/console.c
index 16fe874ddd5f2df63daa803a33e5498d02c615fd..a48e11bec67bfbd2bb356e85f9b76ad23db25330 100644
--- a/server/console.c
+++ b/server/console.c
@@ -40,6 +40,7 @@ static const struct object_ops console_input_ops =
     no_get_fd,                        /* get_fd */
     no_flush,                         /* flush */
     console_get_file_info,            /* get_file_info */
+    NULL,                             /* queue_async */
     console_input_destroy             /* destroy */
 };
 
@@ -68,6 +69,7 @@ static const struct object_ops console_input_events_ops =
     no_get_fd,                        /* get_fd */
     no_flush,                         /* flush */
     no_get_file_info,                 /* get_file_info */
+    NULL,                             /* queue_async */
     console_input_events_destroy      /* destroy */
 };
 
@@ -108,6 +110,7 @@ static const struct object_ops screen_buffer_ops =
     no_get_fd,                        /* get_fd */
     no_flush,                         /* flush */
     console_get_file_info,            /* get_file_info */
+    NULL,                             /* queue_async */
     screen_buffer_destroy             /* destroy */
 };
 
diff --git a/server/debugger.c b/server/debugger.c
index 3790292a0c1a629cd724f6658d3dc4548bc36873..e487eb0480c0c4df43ece4473e147896eb9684d9 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -58,6 +58,7 @@ static const struct object_ops debug_event_ops =
     no_get_fd,                     /* get_fd */
     no_flush,                      /* flush */
     no_get_file_info,              /* get_file_info */
+    NULL,                          /* queue_async */
     debug_event_destroy            /* destroy */
 };
 
@@ -78,6 +79,7 @@ static const struct object_ops debug_ctx_ops =
     no_get_fd,                     /* get_fd */
     no_flush,                      /* flush */
     no_get_file_info,              /* get_file_info */
+    NULL,                          /* queue_async */
     debug_ctx_destroy              /* destroy */
 };
 
diff --git a/server/device.c b/server/device.c
index 6c37c19c303f2c638f8fed80e1d9801e3ef7d092..c3601f22cda5533c507d8d804084ab1930ab6a03 100644
--- a/server/device.c
+++ b/server/device.c
@@ -44,6 +44,7 @@ static const struct object_ops device_ops =
     no_get_fd,                /* get_fd */
     no_flush,                 /* flush */
     device_get_info,          /* get_file_info */
+    NULL,                     /* queue_async */
     no_destroy                /* destroy */
 };
 
diff --git a/server/event.c b/server/event.c
index 7318aef1791685fe9999235e5c28c930d231216b..727b8ed794e8db392b6d723b521b67fb6aeec398 100644
--- a/server/event.c
+++ b/server/event.c
@@ -38,6 +38,7 @@ static const struct object_ops event_ops =
     no_get_fd,                 /* get_fd */
     no_flush,                  /* flush */
     no_get_file_info,          /* get_file_info */
+    NULL,                      /* queue_async */
     no_destroy                 /* destroy */
 };
 
diff --git a/server/file.c b/server/file.c
index ae9033c1dcffa1d517bec7670b1c6244c5bf4160..db539ea6c2ca73b434490c715e70c9a8050d6e47 100644
--- a/server/file.c
+++ b/server/file.c
@@ -65,6 +65,7 @@ static const struct object_ops file_ops =
     file_get_fd,                  /* get_fd */
     file_flush,                   /* flush */
     file_get_info,                /* get_file_info */
+    NULL,                         /* queue_async */
     file_destroy                  /* destroy */
 };
 
diff --git a/server/handle.c b/server/handle.c
index f4b004f1ce6882af6126601f439c210155fce1d8..967909207708da779745a7c29d76fcc4438b579c 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -92,6 +92,7 @@ static const struct object_ops handle_table_ops =
     no_get_fd,                       /* get_fd */
     no_flush,                        /* flush */
     no_get_file_info,                /* get_file_info */
+    NULL,                            /* queue_async */
     handle_table_destroy             /* destroy */
 };
 
diff --git a/server/mapping.c b/server/mapping.c
index 8f4508be85899ef910eda8f0332d27006e9958b2..a944d6a9fc3698e666c509f97478dbf00205bc72 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -51,6 +51,7 @@ static const struct object_ops mapping_ops =
     mapping_get_fd,              /* get_fd */
     no_flush,                    /* flush */
     mapping_get_info,            /* get_file_info */
+    NULL,                        /* queue_async */
     mapping_destroy              /* destroy */
 };
 
diff --git a/server/mutex.c b/server/mutex.c
index ee145d94591d0ad92a3909af71c648164a01915a..e27ccc193264990c29e6e25c56bc3278f6f53be3 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -42,6 +42,7 @@ static const struct object_ops mutex_ops =
     no_get_fd,                 /* get_fd */
     no_flush,                  /* flush */
     no_get_file_info,          /* get_file_info */
+    NULL,                      /* queue_async */
     mutex_destroy              /* destroy */
 };
 
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 06350396134f8b65fa2bc7cc8f07de77add5e083..309407e5b0114aab1f9694b8b510f297a6f52db9 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -80,6 +80,7 @@ static const struct object_ops named_pipe_ops =
     no_get_fd,                    /* get_fd */
     no_flush,                     /* flush */
     no_get_file_info,             /* get_file_info */
+    NULL,                         /* queue_async */
     named_pipe_destroy            /* destroy */
 };
 
@@ -101,6 +102,7 @@ static const struct object_ops pipe_user_ops =
     pipe_user_get_fd,             /* get_fd */
     no_flush,                     /* flush */
     pipe_user_get_info,           /* get_file_info */
+    NULL,                         /* queue_async */
     pipe_user_destroy             /* destroy */
 };
 
diff --git a/server/object.h b/server/object.h
index c805b51f26342a5a4c1f013d67453272c184366f..07230dadf0bf5253e8c4fc554fccdef410dc7151 100644
--- a/server/object.h
+++ b/server/object.h
@@ -22,6 +22,7 @@ struct process;
 struct file;
 struct wait_queue_entry;
 struct async;
+struct async_queue;
 
 /* operations valid on all objects */
 struct object_ops
@@ -48,6 +49,8 @@ struct object_ops
     int  (*flush)(struct object *);
     /* get file information */
     int  (*get_file_info)(struct object *,struct get_file_info_reply *);
+    /* queue an async operation */
+    struct async_queue* (*queue_async)(struct object *, struct async *async, int type, int count);
     /* destroy on refcount == 0 */
     void (*destroy)(struct object *);
 };
diff --git a/server/pipe.c b/server/pipe.c
index ddd200bbac4c22d086a4f2be314a6624f43bfffe..d1f02b174eaf2edce7980d720fdcbf352d38436f 100644
--- a/server/pipe.c
+++ b/server/pipe.c
@@ -53,6 +53,7 @@ static const struct object_ops pipe_ops =
     pipe_get_fd,                  /* get_fd */
     no_flush,                     /* flush */
     pipe_get_info,                /* get_file_info */
+    NULL,                         /* queue_async */
     pipe_destroy                  /* destroy */
 };
 
diff --git a/server/process.c b/server/process.c
index 9643aaf33dba0806115fc236651d68c210f69773..9b711080b4957ea4e5c04adaa4c8256a771bf3d8 100644
--- a/server/process.c
+++ b/server/process.c
@@ -53,6 +53,7 @@ static const struct object_ops process_ops =
     no_get_fd,                   /* get_fd */
     no_flush,                    /* flush */
     no_get_file_info,            /* get_file_info */
+    NULL,                        /* queue_async */
     process_destroy              /* destroy */
 };
 
@@ -92,6 +93,7 @@ static const struct object_ops startup_info_ops =
     no_get_fd,                     /* get_fd */
     no_flush,                      /* flush */
     no_get_file_info,              /* get_file_info */
+    NULL,                        /* queue_async */
     startup_info_destroy           /* destroy */
 };
 
diff --git a/server/protocol.def b/server/protocol.def
index 6010dac2be18a2d198436c1ba28931d149edbfa0..835b3ad31f34dc31bc0d173fdda8063b428f01cd 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1529,14 +1529,16 @@ enum message_type
 #define SERIALINFO_SET_ERROR     0x04
 
 
-/* Create an async I/O */
-@REQ(create_async)
-    handle_t     file_handle;  /* handle to comm port, socket or file */
-    int          count;
+/* Create/Destroy an async I/O */
+@REQ(register_async)
+    handle_t     handle;  /* handle to comm port, socket or file */
+    void*        func;
     int          type;
-@REPLY
-    int          timeout;
+    void*        overlapped;
+    int          count;
+    unsigned int status;
 @END
+#define ASYNC_TYPE_NONE  0x00
 #define ASYNC_TYPE_READ  0x01
 #define ASYNC_TYPE_WRITE 0x02
 #define ASYNC_TYPE_WAIT  0x03
diff --git a/server/queue.c b/server/queue.c
index 87e85a0fa6afbb2cfe3bc8ac4955789751c9d274..a639ebe21131e7b123d739864907d222d615aaff 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -112,6 +112,7 @@ static const struct object_ops msg_queue_ops =
     no_get_fd,                 /* get_fd */
     no_flush,                  /* flush */
     no_get_file_info,          /* get_file_info */
+    NULL,                      /* queue_async */
     msg_queue_destroy          /* destroy */
 };
 
diff --git a/server/registry.c b/server/registry.c
index f8e82f4fc4a36ac25b00917731b3856f9e14f7c4..902d065437d67a67421e511c19471138d4547954 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -142,6 +142,7 @@ static const struct object_ops key_ops =
     no_get_fd,               /* get_fd */
     no_flush,                /* flush */
     no_get_file_info,        /* get_file_info */
+    NULL,                    /* queue_async */
     key_destroy              /* destroy */
 };
 
diff --git a/server/request.c b/server/request.c
index 9f2b8ad5e49185400c03d3b80c3e8a2936980d32..0c79dc278a5ea3d6b52403beb06106953b093ab1 100644
--- a/server/request.c
+++ b/server/request.c
@@ -66,6 +66,7 @@ static const struct object_ops master_socket_ops =
     no_get_fd,                     /* get_fd */
     no_flush,                      /* flush */
     no_get_file_info,              /* get_file_info */
+    NULL,                          /* queue_async */
     master_socket_destroy          /* destroy */
 };
 
diff --git a/server/request.h b/server/request.h
index b1409aae054320d143f41ef772f69cbdd6c406ed..ee18ecbb7f8f3b5efcaa7d8ce47e424cb2e3728a 100644
--- a/server/request.h
+++ b/server/request.h
@@ -209,7 +209,7 @@ DECL_HANDLER(kill_win_timer);
 DECL_HANDLER(create_serial);
 DECL_HANDLER(get_serial_info);
 DECL_HANDLER(set_serial_info);
-DECL_HANDLER(create_async);
+DECL_HANDLER(register_async);
 DECL_HANDLER(create_named_pipe);
 DECL_HANDLER(open_named_pipe);
 DECL_HANDLER(connect_named_pipe);
@@ -363,7 +363,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_create_serial,
     (req_handler)req_get_serial_info,
     (req_handler)req_set_serial_info,
-    (req_handler)req_create_async,
+    (req_handler)req_register_async,
     (req_handler)req_create_named_pipe,
     (req_handler)req_open_named_pipe,
     (req_handler)req_connect_named_pipe,
diff --git a/server/semaphore.c b/server/semaphore.c
index 022fc738383046774ce2e623a0ad3be240cb65be..1ccaeea03eb36ddafedd4ac2ccb33aa85e64043f 100644
--- a/server/semaphore.c
+++ b/server/semaphore.c
@@ -38,6 +38,7 @@ static const struct object_ops semaphore_ops =
     no_get_fd,                     /* get_fd */
     no_flush,                      /* flush */
     no_get_file_info,              /* get_file_info */
+    NULL,                          /* queue_async */
     no_destroy                     /* destroy */
 };
 
diff --git a/server/serial.c b/server/serial.c
index da682bfeac4cd4d2938eddf326667e1ba2c69ebc..5a55c80416b9dd9129afc856fdd934d431dee4fb 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -2,10 +2,7 @@
  * Server-side serial port communications management
  *
  * Copyright (C) 1998 Alexandre Julliard
- * Copyright (C) 2000 Mike McCormack
- *
- * TODO:
- *  Add async read, write and WaitCommEvent handling.
+ * Copyright (C) 2000,2001 Mike McCormack
  *
  */
 
@@ -34,11 +31,15 @@
 #include "handle.h"
 #include "thread.h"
 #include "request.h"
+#include "async.h"
 
 static void serial_dump( struct object *obj, int verbose );
 static int serial_get_fd( struct object *obj );
 static int serial_get_info( struct object *obj, struct get_file_info_reply *reply );
 static int serial_get_poll_events( struct object *obj );
+static struct async_queue * serial_queue_async(struct object *obj, struct async* async, int type, int count);
+static void destroy_serial(struct object *obj);
+static void serial_poll_event( struct object *obj, int event );
 
 struct serial
 {
@@ -58,6 +59,10 @@ struct serial
 
     struct termios      original;
 
+    struct async_queue  read_q;
+    struct async_queue  write_q;
+    struct async_queue  wait_q;
+
     /* FIXME: add dcb, comm status, handler module, sharing */
 };
 
@@ -70,15 +75,14 @@ static const struct object_ops serial_ops =
     default_poll_signaled,        /* signaled */
     no_satisfied,                 /* satisfied */
     serial_get_poll_events,       /* get_poll_events */
-    default_poll_event,           /* poll_event */
+    serial_poll_event,            /* poll_event */
     serial_get_fd,                /* get_fd */
     no_flush,                     /* flush */
     serial_get_info,              /* get_file_info */
-    no_destroy                    /* destroy */
+    serial_queue_async,           /* queue_async */
+    destroy_serial                /* destroy */
 };
 
-/* SERIAL PORT functions */
-
 static struct serial *create_serial( const char *nameptr, size_t len, unsigned int access, int attributes )
 {
     struct serial *serial;
@@ -132,10 +136,22 @@ static struct serial *create_serial( const char *nameptr, size_t len, unsigned i
         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);
     }
     return serial;
 }
 
+static void destroy_serial( 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);
+}
+
 static void serial_dump( struct object *obj, int verbose )
 {
     struct serial *serial = (struct serial *)obj;
@@ -153,8 +169,16 @@ static int serial_get_poll_events( struct object *obj )
     struct serial *serial = (struct serial *)obj;
     int events = 0;
     assert( obj->ops == &serial_ops );
-    if (serial->access & GENERIC_READ) events |= POLLIN;
-    if (serial->access & GENERIC_WRITE) events |= POLLOUT;
+
+    if(IS_READY(serial->read_q))
+        events |= POLLIN;
+    if(IS_READY(serial->write_q))
+        events |= POLLOUT;
+    if(IS_READY(serial->wait_q))
+        events |= POLLIN;
+
+    /* fprintf(stderr,"poll events are %04x\n",events); */
+
     return events;
 }
 
@@ -190,25 +214,76 @@ static int serial_get_info( struct object *obj, struct get_file_info_reply *repl
     return FD_TYPE_TIMEOUT;
 }
 
-/* these function calculates the timeout for an async operation
-   on a serial port */
-int get_serial_async_timeout(struct object *obj, int type, int count)
+static void serial_poll_event(struct object *obj, int event)
 {
     struct serial *serial = (struct serial *)obj;
 
-    if(obj->ops != &serial_ops)
-        return 0;
+    /* fprintf(stderr,"Poll event %02x\n",event); */
+
+    if(IS_READY(serial->read_q) && (POLLIN & event) )
+        async_notify(serial->read_q.head,STATUS_ALERTED);
+
+    if(IS_READY(serial->write_q) && (POLLOUT & event) )
+        async_notify(serial->write_q.head,STATUS_ALERTED);
+
+    if(IS_READY(serial->wait_q) && (POLLIN & event) )
+        async_notify(serial->wait_q.head,STATUS_ALERTED);
+
+    set_select_events(obj,obj->ops->get_poll_events(obj));
+}
+
+/* 
+ * This function is an abuse of overloading that deserves some explanation.
+ *
+ * It has three purposes:
+ *
+ * 1. get the queue for a type of async operation
+ * 2. requeue an async operation
+ * 3. queue a new async operation
+ *
+ * It is overloaded so that these three functions only take one function pointer
+ *  in the object operations list.
+ *
+ * In all cases, it returns the async queue.
+ */
+static struct async_queue *serial_queue_async(struct object *obj, struct async *async, int type, int count)
+{
+    struct serial *serial = (struct serial *)obj;
+    struct async_queue *q;
+    int timeout;
+
+    assert(obj->ops == &serial_ops);
 
     switch(type)
     {
     case ASYNC_TYPE_READ:
-        return serial->readconst + serial->readmult*count;
+        q = &serial->read_q;
+        timeout = serial->readconst + serial->readmult*count;
+        break;
+    case ASYNC_TYPE_WAIT:
+        q = &serial->wait_q;
+        timeout = 0;
+        break;
     case ASYNC_TYPE_WRITE:
-        return serial->writeconst + serial->writemult*count;
+        q = &serial->write_q;
+        timeout = serial->writeconst + serial->writemult*count;
+        break;
+    default:
+        set_error(STATUS_INVALID_PARAMETER);
+        return NULL;
+    }
+
+    if(async)
+    {
+        if(!async->q)
+        {
+            async_add_timeout(async,timeout);
+            async_insert(q, async);
     }
-    return 0;
 }
 
+    return q;
+}
 
 /* create a serial */
 DECL_HANDLER(create_serial)
diff --git a/server/snapshot.c b/server/snapshot.c
index 1d73873e899b9e7ee44c0d1ccd7f83ba8918ec29..9bd05dfa120c0c12d7b850230d5605dca1e1e63d 100644
--- a/server/snapshot.c
+++ b/server/snapshot.c
@@ -50,6 +50,7 @@ static const struct object_ops snapshot_ops =
     no_get_fd,                    /* get_fd */
     no_flush,                     /* flush */
     no_get_file_info,             /* get_file_info */
+    NULL,                         /* queue_async */
     snapshot_destroy              /* destroy */
 };
 
diff --git a/server/sock.c b/server/sock.c
index a18dc6ef5ac84944d6298f5d8669519f9c783950..0cc4a3f3257c61dce817c4e6ab06a0c76e098257 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -77,6 +77,7 @@ static const struct object_ops sock_ops =
     sock_get_fd,                  /* get_fd */
     no_flush,                     /* flush */
     sock_get_info,                /* get_file_info */
+    NULL,                         /* queue_async */
     sock_destroy                  /* destroy */
 };
 
diff --git a/server/thread.c b/server/thread.c
index ff1e65273367ffe40232b020ef31f34861ed5c74..17093e352668ab12899993c59538e0bb5a2a34b5 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -76,6 +76,7 @@ static const struct object_ops thread_ops =
     no_get_fd,                  /* get_fd */
     no_flush,                   /* flush */
     no_get_file_info,           /* get_file_info */
+    NULL,                       /* queue_async */
     destroy_thread              /* destroy */
 };
 
diff --git a/server/timer.c b/server/timer.c
index fd9604af4c963d1ba8a3fd8e160ecf2e4681e2de..90e1f32f74be19268f87dc8084afa19859d087c5 100644
--- a/server/timer.c
+++ b/server/timer.c
@@ -45,6 +45,7 @@ static const struct object_ops timer_ops =
     no_get_fd,                 /* get_fd */
     no_flush,                  /* flush */
     no_get_file_info,          /* get_file_info */
+    NULL,                      /* queue_async */
     timer_destroy              /* destroy */
 };
 
diff --git a/server/trace.c b/server/trace.c
index f5098cb310ac2ad7f1b5f610be7cdcc527c59ad3..0f12a0ee3cf04c6dc05cd536038a23729795e406 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1738,16 +1738,14 @@ static void dump_set_serial_info_request( const struct set_serial_info_request *
     fprintf( stderr, " commerror=%08x", req->commerror );
 }
 
-static void dump_create_async_request( const struct create_async_request *req )
+static void dump_register_async_request( const struct register_async_request *req )
 {
-    fprintf( stderr, " file_handle=%d,", req->file_handle );
+    fprintf( stderr, " handle=%d,", req->handle );
+    fprintf( stderr, " func=%p,", req->func );
+    fprintf( stderr, " type=%d,", req->type );
+    fprintf( stderr, " overlapped=%p,", req->overlapped );
     fprintf( stderr, " count=%d,", req->count );
-    fprintf( stderr, " type=%d", req->type );
-}
-
-static void dump_create_async_reply( const struct create_async_reply *req )
-{
-    fprintf( stderr, " timeout=%d", req->timeout );
+    fprintf( stderr, " status=%08x", req->status );
 }
 
 static void dump_create_named_pipe_request( const struct create_named_pipe_request *req )
@@ -2154,7 +2152,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_create_serial_request,
     (dump_func)dump_get_serial_info_request,
     (dump_func)dump_set_serial_info_request,
-    (dump_func)dump_create_async_request,
+    (dump_func)dump_register_async_request,
     (dump_func)dump_create_named_pipe_request,
     (dump_func)dump_open_named_pipe_request,
     (dump_func)dump_connect_named_pipe_request,
@@ -2305,7 +2303,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_create_serial_reply,
     (dump_func)dump_get_serial_info_reply,
     (dump_func)0,
-    (dump_func)dump_create_async_reply,
+    (dump_func)0,
     (dump_func)dump_create_named_pipe_reply,
     (dump_func)dump_open_named_pipe_reply,
     (dump_func)0,
@@ -2456,7 +2454,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "create_serial",
     "get_serial_info",
     "set_serial_info",
-    "create_async",
+    "register_async",
     "create_named_pipe",
     "open_named_pipe",
     "connect_named_pipe",