diff --git a/files/file.c b/files/file.c
index e0b8b4920e46f25bb86f91c49401d908eb96caa5..65b264c9b2f4d23034762a9af4280ca8a5178add 100644
--- a/files/file.c
+++ b/files/file.c
@@ -115,6 +115,7 @@ typedef struct async_fileio
     LPOVERLAPPED_COMPLETION_ROUTINE  completion_func;
     char                             *buffer;
     int                              count;
+    enum fd_type                     fd_type;
 } async_fileio;
 
 static DWORD fileio_get_async_status (const struct async_private *ovp)
@@ -208,6 +209,42 @@ int FILE_strncasecmp( const char *str1, const char *str2, int len )
 }
 
 
+/***********************************************************************
+ *           FILE_GetNtStatus(void)
+ *
+ * Retrieve the Nt Status code from errno.
+ * Try to be consistent with FILE_SetDosError().
+ */
+DWORD FILE_GetNtStatus(void)
+{
+    int err = errno;
+    DWORD nt;
+    TRACE ( "errno = %d\n", errno );
+    switch ( err )
+    {
+    case EAGAIN:       nt = STATUS_SHARING_VIOLATION;       break;
+    case EBADF:        nt = STATUS_INVALID_HANDLE;          break;
+    case ENOSPC:       nt = STATUS_DISK_FULL;               break;
+    case EPERM:
+    case EROFS:
+    case EACCES:       nt = STATUS_ACCESS_DENIED;           break;
+    case ENOENT:       nt = STATUS_SHARING_VIOLATION;       break;
+    case EISDIR:       nt = STATUS_FILE_IS_A_DIRECTORY;     break;
+    case EMFILE:
+    case ENFILE:       nt = STATUS_NO_MORE_FILES;           break;
+    case EINVAL:
+    case ENOTEMPTY:    nt = STATUS_DIRECTORY_NOT_EMPTY;     break;
+    case EPIPE:        nt = STATUS_PIPE_BROKEN;             break;
+    case ENOEXEC:      /* ?? */
+    case ESPIPE:       /* ?? */
+    case EEXIST:       /* ?? */
+    default:
+        FIXME ( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
+        nt = STATUS_UNSUCCESSFUL;
+    }
+    return nt;
+}
+
 /***********************************************************************
  *           FILE_SetDosError
  *
@@ -1460,10 +1497,15 @@ static void FILE_AsyncReadService(async_private *ovp)
 
     /* check to see if the data is ready (non-blocking) */
 
-    result = pread (ovp->fd, &fileio->buffer[already], fileio->count - already,
-                    OVERLAPPED_OFFSET (lpOverlapped) + already);
-    if ((result < 0) && (errno == ESPIPE))
+    if ( fileio->fd_type == FD_TYPE_SOCKET )
         result = read (ovp->fd, &fileio->buffer[already], fileio->count - already);
+    else
+    {
+        result = pread (ovp->fd, &fileio->buffer[already], fileio->count - already,
+                        OVERLAPPED_OFFSET (lpOverlapped) + already);
+        if ((result < 0) && (errno == ESPIPE))
+            result = read (ovp->fd, &fileio->buffer[already], fileio->count - already);
+    }
 
     if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
     {
@@ -1475,18 +1517,17 @@ static void FILE_AsyncReadService(async_private *ovp)
     /* check to see if the transfer is complete */
     if(result<0)
     {
-        TRACE("read returned errno %d\n",errno);
-        r = STATUS_UNSUCCESSFUL;
+        r = FILE_GetNtStatus ();
         goto async_end;
     }
 
     lpOverlapped->InternalHigh += result;
     TRACE("read %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,fileio->count);
 
-    if(lpOverlapped->InternalHigh < fileio->count)
-        r = STATUS_PENDING;
-    else
+    if(lpOverlapped->InternalHigh >= fileio->count || fileio->fd_type == FD_TYPE_SOCKET )
         r = STATUS_SUCCESS;
+    else
+        r = STATUS_PENDING;
 
 async_end:
     lpOverlapped->Internal = r;
@@ -1545,6 +1586,7 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
     ovp->count = bytesToRead;
     ovp->completion_func = lpCompletionRoutine;
     ovp->buffer = buffer;
+    ovp->fd_type = type;
 
     return !register_new_async (&ovp->async);
 
@@ -1684,10 +1726,15 @@ static void FILE_AsyncWriteService(struct async_private *ovp)
 
     /* write some data (non-blocking) */
 
-    result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
-                    OVERLAPPED_OFFSET (lpOverlapped) + already);
-    if ((result < 0) && (errno == ESPIPE))
+    if ( fileio->fd_type == FD_TYPE_SOCKET )
         result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
+    else
+    {
+        result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
+                    OVERLAPPED_OFFSET (lpOverlapped) + already);
+        if ((result < 0) && (errno == ESPIPE))
+            result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);
+    }
 
     if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
     {
@@ -1698,7 +1745,7 @@ static void FILE_AsyncWriteService(struct async_private *ovp)
     /* check to see if the transfer is complete */
     if(result<0)
     {
-        r = STATUS_UNSUCCESSFUL;
+        r = FILE_GetNtStatus ();
         goto async_end;
     }
 
@@ -1728,8 +1775,8 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
     int flags;
     enum fd_type type;
 
-    TRACE("file %d to buf %p num %ld %p func %p stub\n",
-	  hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine);
+    TRACE("file %d to buf %p num %ld %p func %p handle %d\n",
+	  hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine, hEvent);
 
     if (overlapped == NULL)
     {
@@ -1767,6 +1814,7 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
     ovp->buffer = (LPVOID) buffer;
     ovp->count = bytesToWrite;
     ovp->completion_func = lpCompletionRoutine;
+    ovp->fd_type = type;
 
     return !register_new_async (&ovp->async);
 
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index f6d5d4aba5671befc82fd28b3e77958b15452c38..ddc2afde23290226ada0bd0f2d1bb2882fa9b8e2 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -791,6 +791,7 @@ enum fd_type
     FD_TYPE_INVALID,
     FD_TYPE_DEFAULT,
     FD_TYPE_CONSOLE,
+    FD_TYPE_SOCKET,
     FD_TYPE_SMB
 };
 #define FD_FLAG_OVERLAPPED         0x01
diff --git a/server/protocol.def b/server/protocol.def
index e75373eaefde512a20f9ed050e3d0aa7aac66649..e1d49c31646801e0dd269dc47b964d38d3fd67a4 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -608,6 +608,7 @@ enum fd_type
     FD_TYPE_INVALID,
     FD_TYPE_DEFAULT,
     FD_TYPE_CONSOLE,
+    FD_TYPE_SOCKET,
     FD_TYPE_SMB
 };
 #define FD_FLAG_OVERLAPPED         0x01
diff --git a/server/sock.c b/server/sock.c
index 06db1aca4c087e316264aa16dda387a55f12c144..d8362afcccd1e6a05d7c19ab4a03f8dd9a939543 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -421,7 +421,7 @@ static int sock_get_info( struct object *obj, struct get_file_info_reply *reply,
     if (sock->flags & WSA_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED;
     if ( !(sock->state & FD_READ ) )  *flags |= FD_FLAG_RECV_SHUTDOWN;
     if ( !(sock->state & FD_WRITE ) ) *flags |= FD_FLAG_SEND_SHUTDOWN;
-    return FD_TYPE_DEFAULT;
+    return FD_TYPE_SOCKET;
 }
 
 static void sock_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count)