More general approach to file descriptor types and flags.

diff --git a/files/file.c b/files/file.c
index 4dd4847..06ea389 100644
--- a/files/file.c
+++ b/files/file.c
@@ -210,7 +210,7 @@
  * Retrieve the Unix handle corresponding to a file handle.
  * Returns -1 on failure.
  */
-int FILE_GetUnixHandleType( HANDLE handle, DWORD access, DWORD *type )
+static int FILE_GetUnixHandleType( HANDLE handle, DWORD access, enum fd_type *type, DWORD *flags )
 {
     int ret, fd = -1;
 
@@ -225,6 +225,7 @@
                 fd = reply->fd;
             }
             if (type) *type = reply->type;
+            if (flags) *flags = reply->flags;
         }
         SERVER_END_REQ;
         if (ret) return -1;
@@ -250,7 +251,7 @@
  */
 int FILE_GetUnixHandle( HANDLE handle, DWORD access )
 {
-    return FILE_GetUnixHandleType(handle, access, NULL);
+    return FILE_GetUnixHandleType( handle, access, NULL, NULL );
 }
 
 /*************************************************************************
@@ -1449,7 +1450,8 @@
                         LPDWORD bytesRead, LPOVERLAPPED overlapped )
 {
     int unix_handle, result;
-    DWORD type;
+    enum fd_type type;
+    DWORD flags;
 
     TRACE("%d %p %ld %p %p\n", hFile, buffer, bytesToRead, 
           bytesRead, overlapped );
@@ -1457,11 +1459,10 @@
     if (bytesRead) *bytesRead = 0;  /* Do this before anything else */
     if (!bytesToRead) return TRUE;
 
-    unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_READ, &type );
+    unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_READ, &type, &flags );
 
-    switch (type)
+    if (flags & FD_FLAG_OVERLAPPED)
     {
-    case FD_TYPE_OVERLAPPED:
 	if (unix_handle == -1) return FALSE;
         if ( (overlapped==NULL) || NtResetEvent( overlapped->hEvent, NULL ) )
         {
@@ -1506,13 +1507,16 @@
         /* fail on return, with ERROR_IO_PENDING */
         SetLastError(ERROR_IO_PENDING);
         return FALSE;
-
-    case FD_TYPE_CONSOLE:
-	return ReadConsoleA(hFile, buffer, bytesToRead, bytesRead, NULL);
-
-    case FD_TYPE_TIMEOUT:
+    }
+    if (flags & FD_FLAG_TIMEOUT)
+    {
         close(unix_handle);
         return FILE_TimeoutRead(hFile, buffer, bytesToRead, bytesRead);
+    }
+    switch(type)
+    {
+    case FD_TYPE_CONSOLE:
+	return ReadConsoleA(hFile, buffer, bytesToRead, bytesRead, NULL);
 
     default:
 	/* normal unix files */
@@ -1668,7 +1672,8 @@
                          LPDWORD bytesWritten, LPOVERLAPPED overlapped )
 {
     int unix_handle, result;
-    DWORD type;
+    enum fd_type type;
+    DWORD flags;
 
     TRACE("%d %p %ld %p %p\n", hFile, buffer, bytesToWrite, 
           bytesWritten, overlapped );
@@ -1676,11 +1681,10 @@
     if (bytesWritten) *bytesWritten = 0;  /* Do this before anything else */
     if (!bytesToWrite) return TRUE;
 
-    unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type );
+    unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type, &flags );
 
-    switch (type)
+    if (flags & FD_FLAG_OVERLAPPED)
     {
-    case FD_TYPE_OVERLAPPED:
 	if (unix_handle == -1) return FALSE;
         if ( (overlapped==NULL) || NtResetEvent( overlapped->hEvent, NULL ) )
         {
@@ -1727,7 +1731,10 @@
         /* fail on return, with ERROR_IO_PENDING */
         SetLastError(ERROR_IO_PENDING);
         return FALSE;
+    }
 
+    switch(type)
+    {
     case FD_TYPE_CONSOLE:
 	TRACE("%d %s %ld %p %p\n", hFile, debugstr_an(buffer, bytesToWrite), bytesToWrite, 
 	      bytesWritten, overlapped );
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 6802851..03c06b5 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -730,12 +730,16 @@
     struct reply_header __header;
     int          fd;
     int          type;
+    int          flags;
 };
-#define FD_TYPE_INVALID    0
-#define FD_TYPE_DEFAULT    1
-#define FD_TYPE_CONSOLE    2
-#define FD_TYPE_OVERLAPPED 3
-#define FD_TYPE_TIMEOUT    4
+enum fd_type
+{
+    FD_TYPE_INVALID,
+    FD_TYPE_DEFAULT,
+    FD_TYPE_CONSOLE
+};
+#define FD_FLAG_OVERLAPPED 0x01
+#define FD_FLAG_TIMEOUT    0x02
 
 
 
@@ -3038,6 +3042,6 @@
     struct get_window_properties_reply get_window_properties_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 68
+#define SERVER_PROTOCOL_VERSION 69
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/console.c b/server/console.c
index 72717e7..29f76e5 100644
--- a/server/console.c
+++ b/server/console.c
@@ -25,7 +25,7 @@
 static int console_input_signaled( struct object *obj, struct thread *thread );
 
 /* common routine */
-static int console_get_file_info( struct object *obj, struct get_file_info_reply *reply );
+static int console_get_file_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 
 static const struct object_ops console_input_ops =
 {
@@ -785,7 +785,7 @@
 	     console->active, console->evt );
 }
 
-static int console_get_file_info( struct object *obj, struct get_file_info_reply *reply )
+static int console_get_file_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
 {
     if (reply)
     {
@@ -800,6 +800,7 @@
         reply->index_low   = 0;
         reply->serial      = 0;
     }
+    *flags = 0;
     return FD_TYPE_CONSOLE;
 }
 
diff --git a/server/device.c b/server/device.c
index c3601f2..872c243b 100644
--- a/server/device.c
+++ b/server/device.c
@@ -29,7 +29,7 @@
 };
 
 static void device_dump( struct object *obj, int verbose );
-static int device_get_info( struct object *obj, struct get_file_info_reply *reply );
+static int device_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 
 static const struct object_ops device_ops =
 {
@@ -65,7 +65,7 @@
     fprintf( stderr, "Device id=%08x\n", dev->id );
 }
 
-static int device_get_info( struct object *obj, struct get_file_info_reply *reply )
+static int device_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
 {
     struct device *dev = (struct device *)obj;
     assert( obj->ops == &device_ops );
@@ -83,6 +83,7 @@
         reply->index_low   = 0;
         reply->serial      = 0;
     }
+    *flags = 0;
     return FD_TYPE_DEFAULT;
 }
 
diff --git a/server/file.c b/server/file.c
index 351da8a..67805c2 100644
--- a/server/file.c
+++ b/server/file.c
@@ -53,7 +53,7 @@
 static void file_poll_event( struct object *obj, int event );
 static int file_get_fd( struct object *obj );
 static int file_flush( struct object *obj );
-static int file_get_info( struct object *obj, struct get_file_info_reply *reply );
+static int file_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 static void file_destroy( struct object *obj );
 static struct async_queue * file_queue_async(struct object *obj, struct async* async, int type, int count);
 
@@ -303,7 +303,7 @@
     return ret;
 }
 
-static int file_get_info( struct object *obj, struct get_file_info_reply *reply )
+static int file_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
 {
     struct stat st;
     struct file *file = (struct file *)obj;
@@ -339,9 +339,8 @@
         reply->index_low   = st.st_ino;
         reply->serial      = 0; /* FIXME */
     }
-
-    if (file->flags & FILE_FLAG_OVERLAPPED) return FD_TYPE_OVERLAPPED;
-
+    *flags = 0;
+    if (file->flags & FILE_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED;
     return FD_TYPE_DEFAULT;
 }
 
@@ -587,7 +586,7 @@
             if ((fd = obj->ops->get_fd( obj )) != -1)
                 send_client_fd( current->process, fd, req->handle );
         }
-        reply->type = obj->ops->get_file_info( obj, NULL );
+        reply->type = obj->ops->get_file_info( obj, NULL, &reply->flags );
         release_object( obj );
     }
 }
@@ -633,7 +632,8 @@
 
     if ((obj = get_handle_obj( current->process, req->handle, 0, NULL )))
     {
-        obj->ops->get_file_info( obj, reply );
+        int flags;
+        obj->ops->get_file_info( obj, reply, &flags );
         release_object( obj );
     }
 }
diff --git a/server/mapping.c b/server/mapping.c
index a944d6a..2d63cc5 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -34,7 +34,7 @@
 };
 
 static int mapping_get_fd( struct object *obj );
-static int mapping_get_info( struct object *obj, struct get_file_info_reply *reply );
+static int mapping_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 static void mapping_dump( struct object *obj, int verbose );
 static void mapping_destroy( struct object *obj );
 
@@ -264,9 +264,10 @@
         }
         if (!size_high && !size_low)
         {
+            int flags;
             struct get_file_info_reply reply;
             struct object *obj = (struct object *)mapping->file;
-            obj->ops->get_file_info( obj, &reply );
+            obj->ops->get_file_info( obj, &reply, &flags );
             size_high = reply.size_high;
             size_low  = ROUND_SIZE( 0, reply.size_low );
         }
@@ -312,14 +313,14 @@
     return get_mmap_fd( mapping->file );
 }
 
-static int mapping_get_info( struct object *obj, struct get_file_info_reply *reply )
+static int mapping_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
 {
     struct mapping *mapping = (struct mapping *)obj;
     struct object *file = (struct object *)mapping->file;
 
     assert( obj->ops == &mapping_ops );
     assert( file );
-    return file->ops->get_file_info( file, reply );
+    return file->ops->get_file_info( file, reply, flags );
 }
 
 static void mapping_destroy( struct object *obj )
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 309407e..bce7b23 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -87,7 +87,7 @@
 static void pipe_user_dump( struct object *obj, int verbose );
 static void pipe_user_destroy( struct object *obj);
 static int pipe_user_get_fd( struct object *obj );
-static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply );
+static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 
 static const struct object_ops pipe_user_ops =
 {
@@ -182,7 +182,7 @@
     return user->obj.fd;
 }
 
-static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply )
+static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
 {
     if (reply)
     {
@@ -197,6 +197,7 @@
         reply->index_low   = 0;
         reply->serial      = 0;
     }
+    *flags = 0;
     return FD_TYPE_DEFAULT;
 }
 
diff --git a/server/object.c b/server/object.c
index 1077006..2411eff 100644
--- a/server/object.c
+++ b/server/object.c
@@ -263,9 +263,10 @@
     return 0;
 }
 
-int no_get_file_info( struct object *obj, struct get_file_info_reply *info )
+int no_get_file_info( struct object *obj, struct get_file_info_reply *info, int *flags )
 {
     set_error( STATUS_OBJECT_TYPE_MISMATCH );
+    *flags = 0;
     return FD_TYPE_INVALID;
 }
 
diff --git a/server/object.h b/server/object.h
index 07230da..851c446 100644
--- a/server/object.h
+++ b/server/object.h
@@ -48,7 +48,7 @@
     /* flush the object buffers */
     int  (*flush)(struct object *);
     /* get file information */
-    int  (*get_file_info)(struct object *,struct get_file_info_reply *);
+    int  (*get_file_info)(struct object *,struct get_file_info_reply *, int *flags);
     /* queue an async operation */
     struct async_queue* (*queue_async)(struct object *, struct async *async, int type, int count);
     /* destroy on refcount == 0 */
@@ -92,7 +92,7 @@
 extern int no_satisfied( struct object *obj, struct thread *thread );
 extern int no_get_fd( struct object *obj );
 extern int no_flush( struct object *obj );
-extern int no_get_file_info( struct object *obj, struct get_file_info_reply *info );
+extern int no_get_file_info( struct object *obj, struct get_file_info_reply *info, int *flags );
 extern void no_destroy( struct object *obj );
 extern int default_poll_add_queue( struct object *obj, struct wait_queue_entry *entry );
 extern void default_poll_remove_queue( struct object *obj, struct wait_queue_entry *entry );
diff --git a/server/pipe.c b/server/pipe.c
index d1f02b1..5dccae2 100644
--- a/server/pipe.c
+++ b/server/pipe.c
@@ -37,7 +37,7 @@
 static void pipe_dump( struct object *obj, int verbose );
 static int pipe_get_poll_events( struct object *obj );
 static int pipe_get_fd( struct object *obj );
-static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply );
+static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 static void pipe_destroy( struct object *obj );
 
 static const struct object_ops pipe_ops =
@@ -125,7 +125,7 @@
     return pipe->obj.fd;
 }
 
-static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply )
+static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
 {
     if (reply)
     {
@@ -140,6 +140,7 @@
         reply->index_low   = 0;
         reply->serial      = 0;
     }
+    *flags = 0;
     return FD_TYPE_DEFAULT;
 }
 
diff --git a/server/protocol.def b/server/protocol.def
index 76a3cf8..6ab1f35 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -542,13 +542,17 @@
     unsigned int access;        /* wanted access rights */
 @REPLY
     int          fd;            /* file descriptor */
-    int          type;          /* the type of file */
+    int          type;          /* the type of file (see below) */
+    int          flags;         /* file read/write flags (see below) */
 @END
-#define FD_TYPE_INVALID    0
-#define FD_TYPE_DEFAULT    1
-#define FD_TYPE_CONSOLE    2
-#define FD_TYPE_OVERLAPPED 3
-#define FD_TYPE_TIMEOUT    4
+enum fd_type
+{
+    FD_TYPE_INVALID,
+    FD_TYPE_DEFAULT,
+    FD_TYPE_CONSOLE
+};
+#define FD_FLAG_OVERLAPPED 0x01
+#define FD_FLAG_TIMEOUT    0x02
 
 
 /* Set a file current position */
diff --git a/server/serial.c b/server/serial.c
index 110854a..5911876 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -35,7 +35,7 @@
 
 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_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 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);
@@ -189,7 +189,7 @@
     return serial->obj.fd;
 }
 
-static int serial_get_info( struct object *obj, struct get_file_info_reply *reply )
+static int serial_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
 {
     struct serial *serial = (struct serial *) obj;
     assert( obj->ops == &serial_ops );
@@ -208,14 +208,14 @@
         reply->serial      = 0;
     }
 
+    *flags = 0;
     if(serial->attrib & FILE_FLAG_OVERLAPPED)
-        return FD_TYPE_OVERLAPPED;
+        *flags |= FD_FLAG_OVERLAPPED;
+    else if(!((serial->readinterval == MAXDWORD) &&
+              (serial->readmult == 0) && (serial->readconst == 0)) )
+        *flags |= FD_FLAG_TIMEOUT;
 
-    if( (serial->readinterval == MAXDWORD) &&
-        (serial->readmult == 0) && (serial->readconst == 0) )
-        return FD_TYPE_DEFAULT;
-
-    return FD_TYPE_TIMEOUT;
+    return FD_TYPE_DEFAULT;
 }
 
 static void serial_poll_event(struct object *obj, int event)
diff --git a/server/sock.c b/server/sock.c
index 0cc4a3f..bc901f6 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -59,7 +59,7 @@
 static int sock_get_poll_events( struct object *obj );
 static void sock_poll_event( struct object *obj, int event );
 static int sock_get_fd( struct object *obj );
-static int sock_get_info( struct object *obj, struct get_file_info_reply *reply );
+static int sock_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 static void sock_destroy( struct object *obj );
 static int sock_get_error( int err );
 static void sock_set_error(void);
@@ -273,7 +273,7 @@
     return sock->obj.fd;
 }
 
-static int sock_get_info( struct object *obj, struct get_file_info_reply *reply )
+static int sock_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags )
 {
     if (reply)
     {
@@ -288,6 +288,7 @@
         reply->index_low   = 0;
         reply->serial      = 0;
     }
+    *flags = 0;
     return FD_TYPE_DEFAULT;
 }
 
diff --git a/server/trace.c b/server/trace.c
index d162045..79ca059 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -722,7 +722,8 @@
 static void dump_get_handle_fd_reply( const struct get_handle_fd_reply *req )
 {
     fprintf( stderr, " fd=%d,", req->fd );
-    fprintf( stderr, " type=%d", req->type );
+    fprintf( stderr, " type=%d,", req->type );
+    fprintf( stderr, " flags=%d", req->flags );
 }
 
 static void dump_set_file_pointer_request( const struct set_file_pointer_request *req )