- move async activation into the server
- implement async queues

diff --git a/files/file.c b/files/file.c
index 995ae3e..b3ef897 100644
--- a/files/file.c
+++ b/files/file.c
@@ -1248,12 +1248,34 @@
 
 
 /***********************************************************************
+ *              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 @@
  *  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 @@
     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 @@
 			 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 @@
         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 @@
     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 @@
         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 @@
  *  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 @@
 			 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 @@
     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 @@
         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);