- Need a "cleanup" method.
- calling the "call_completion" method unconditionally in finish_async
  (introduced by me) was wrong, because the thread may never be in an
  alertable wait state -> call it only if user completion function is present.
- We need two constant "ops" objects, one with and one without call_completion
  method (the event field may NOT be used to determine whether the completion
  must be called or not).

diff --git a/files/file.c b/files/file.c
index d698bf6..582ef8f 100644
--- a/files/file.c
+++ b/files/file.c
@@ -88,13 +88,24 @@
 static DWORD fileio_get_async_count (const async_private *ovp);
 static void fileio_set_async_status (async_private *ovp, const DWORD status);
 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_status,       /* get_status */
     fileio_set_async_status,       /* set_status */
     fileio_get_async_count,        /* get_count */
-    fileio_call_completion_func    /* call_completion */
+    fileio_call_completion_func,   /* call_completion */
+    fileio_async_cleanup           /* cleanup */
+};
+
+static async_ops fileio_nocomp_async_ops =
+{
+    fileio_get_async_status,       /* get_status */
+    fileio_set_async_status,       /* set_status */
+    fileio_get_async_count,        /* get_count */
+    NULL,                          /* call_completion */
+    fileio_async_cleanup           /* cleanup */
 };
 
 typedef struct async_fileio
@@ -128,12 +139,16 @@
     async_fileio *ovp = (async_fileio*) data;
     TRACE ("data: %p\n", ovp);
 
-    if (ovp->completion_func)
-        ovp->completion_func(ovp->lpOverlapped->Internal,
-                             ovp->lpOverlapped->InternalHigh,
-                             ovp->lpOverlapped);
+    ovp->completion_func( ovp->lpOverlapped->Internal,
+                          ovp->lpOverlapped->InternalHigh,
+                          ovp->lpOverlapped );
 
-    HeapFree(GetProcessHeap(), 0, ovp);
+    fileio_async_cleanup ( &ovp->async );
+}
+
+static void fileio_async_cleanup ( struct async_private *ovp )
+{
+    HeapFree ( GetProcessHeap(), 0, ovp );
 }
 
 /***********************************************************************
@@ -1478,6 +1493,8 @@
 {
     async_fileio *ovp;
     int fd;
+    int flags;
+    enum fd_type type;
 
     TRACE("file %d to buf %p num %ld %p func %p\n",
 	  hFile, buffer, bytesToRead, overlapped, lpCompletionRoutine);
@@ -1489,10 +1506,11 @@
         return FALSE;
     }
 
-    fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
-    if(fd<0)
+    fd = FILE_GetUnixHandleType ( hFile, GENERIC_READ, &type, &flags);
+    if ( fd < 0 )
     {
-        TRACE("Couldn't get FD\n");
+        WARN ( "Couldn't get FD\n" );
+        SetLastError ( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
 
@@ -1501,11 +1519,10 @@
     {
         TRACE("HeapAlloc Failed\n");
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        close(fd);
-        return FALSE;
+        goto error;
     }
 
-    ovp->async.ops = &fileio_async_ops;
+    ovp->async.ops = ( lpCompletionRoutine ? &fileio_async_ops : &fileio_nocomp_async_ops );
     ovp->async.handle = hFile;
     ovp->async.fd = fd;
     ovp->async.type = ASYNC_TYPE_READ;
@@ -1517,6 +1534,11 @@
     ovp->buffer = buffer;
 
     return !register_new_async (&ovp->async);
+
+error:
+    close (fd);
+    return FALSE;
+
 }
 
 /***********************************************************************
@@ -1710,6 +1732,8 @@
 {
     async_fileio *ovp;
     int fd;
+    int flags;
+    enum fd_type type;
 
     TRACE("file %d to buf %p num %ld %p func %p stub\n",
 	  hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine);
@@ -1720,7 +1744,7 @@
         return FALSE;
     }
 
-    fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
+    fd = FILE_GetUnixHandleType ( hFile, GENERIC_WRITE, &type, &flags );
     if ( fd < 0 )
     {
         TRACE( "Couldn't get FD\n" );
@@ -1732,8 +1756,7 @@
     {
         TRACE("HeapAlloc Failed\n");
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        close (fd);
-        return FALSE;
+        goto error;
     }
 
     ovp->async.ops = &fileio_async_ops;
@@ -1748,6 +1771,10 @@
     ovp->completion_func = lpCompletionRoutine;
 
     return !register_new_async (&ovp->async);
+
+error:
+    close (fd);
+    return FALSE;
 }
 
 /***********************************************************************