Fetch a handle type in FILE_GetUnixHandle.

diff --git a/files/file.c b/files/file.c
index 02ff517..ff3c4b5 100644
--- a/files/file.c
+++ b/files/file.c
@@ -201,12 +201,12 @@
 
 
 /***********************************************************************
- *           FILE_GetUnixHandle
+ *           FILE_GetUnixHandleType
  *
  * Retrieve the Unix handle corresponding to a file handle.
  * Returns -1 on failure.
  */
-int FILE_GetUnixHandle( HANDLE handle, DWORD access )
+int FILE_GetUnixHandleType( HANDLE handle, DWORD access, DWORD *type )
 {
     int ret, fd = -1;
 
@@ -216,7 +216,11 @@
         {
             req->handle = handle;
             req->access = access;
-            if (!(ret = SERVER_CALL_ERR())) fd = req->fd;
+            if (!(ret = SERVER_CALL_ERR()))
+            {
+                fd = req->fd;
+                if (type) *type = req->type;
+            }
         }
         SERVER_END_REQ;
         if (ret) return -1;
@@ -234,6 +238,16 @@
     return fd;
 }
 
+/***********************************************************************
+ *           FILE_GetUnixHandle
+ *
+ * Retrieve the Unix handle corresponding to a file handle.
+ * Returns -1 on failure.
+ */
+int FILE_GetUnixHandle( HANDLE handle, DWORD access )
+{
+    return FILE_GetUnixHandleType(handle, access, NULL);
+}
 
 /*************************************************************************
  * 		FILE_OpenConsole
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index c94d2d4..bbac77a 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -570,7 +570,12 @@
     handle_t     handle;
     unsigned int access;
     int          fd;
+    int          type;
 };
+#define FD_TYPE_INVALID    0
+#define FD_TYPE_DEFAULT    1
+#define FD_TYPE_CONSOLE    2
+#define FD_TYPE_OVERLAPPED 3
 
 
 
@@ -1912,6 +1917,6 @@
     struct get_window_tree_request get_window_tree;
 };
 
-#define SERVER_PROTOCOL_VERSION 53
+#define SERVER_PROTOCOL_VERSION 54
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/console.c b/server/console.c
index 1561070..6aab563 100644
--- a/server/console.c
+++ b/server/console.c
@@ -355,17 +355,20 @@
 
 static int console_get_info( struct object *obj, struct get_file_info_request *req )
 {
-    req->type        = FILE_TYPE_CHAR;
-    req->attr        = 0;
-    req->access_time = 0;
-    req->write_time  = 0;
-    req->size_high   = 0;
-    req->size_low    = 0;
-    req->links       = 0;
-    req->index_high  = 0;
-    req->index_low   = 0;
-    req->serial      = 0;
-    return 1;
+    if (req)
+    {
+        req->type        = FILE_TYPE_CHAR;
+        req->attr        = 0;
+        req->access_time = 0;
+        req->write_time  = 0;
+        req->size_high   = 0;
+        req->size_low    = 0;
+        req->links       = 0;
+        req->index_high  = 0;
+        req->index_low   = 0;
+        req->serial      = 0;
+    }
+    return FD_TYPE_CONSOLE;
 }
 
 static void console_input_destroy( struct object *obj )
diff --git a/server/device.c b/server/device.c
index 5c19734..80c6af5 100644
--- a/server/device.c
+++ b/server/device.c
@@ -68,17 +68,21 @@
 {
     struct device *dev = (struct device *)obj;
     assert( obj->ops == &device_ops );
-    req->type        = FILE_TYPE_UNKNOWN;
-    req->attr        = dev->id;  /* hack! */
-    req->access_time = 0;
-    req->write_time  = 0;
-    req->size_high   = 0;
-    req->size_low    = 0;
-    req->links       = 0;
-    req->index_high  = 0;
-    req->index_low   = 0;
-    req->serial      = 0;
-    return 1;
+
+    if (req)
+    {
+        req->type        = FILE_TYPE_UNKNOWN;
+        req->attr        = dev->id;  /* hack! */
+        req->access_time = 0;
+        req->write_time  = 0;
+        req->size_high   = 0;
+        req->size_low    = 0;
+        req->links       = 0;
+        req->index_high  = 0;
+        req->index_low   = 0;
+        req->serial      = 0;
+    }
+    return FD_TYPE_DEFAULT;
 }
 
 /* create a device */
diff --git a/server/file.c b/server/file.c
index 8a96630..c79efa6 100644
--- a/server/file.c
+++ b/server/file.c
@@ -268,34 +268,37 @@
     struct file *file = (struct file *)obj;
     assert( obj->ops == &file_ops );
 
-    if (fstat( file->obj.fd, &st ) == -1)
+    if (req)
     {
-        file_set_error();
-        return 0;
+        if (fstat( file->obj.fd, &st ) == -1)
+        {
+            file_set_error();
+            return FD_TYPE_INVALID;
+        }
+        if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
+            S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) req->type = FILE_TYPE_CHAR;
+        else req->type = FILE_TYPE_DISK;
+        if (S_ISDIR(st.st_mode)) req->attr = FILE_ATTRIBUTE_DIRECTORY;
+        else req->attr = FILE_ATTRIBUTE_ARCHIVE;
+        if (!(st.st_mode & S_IWUSR)) req->attr |= FILE_ATTRIBUTE_READONLY;
+        req->access_time = st.st_atime;
+        req->write_time  = st.st_mtime;
+        if (S_ISDIR(st.st_mode))
+        {
+            req->size_high = 0;
+            req->size_low  = 0;
+        }
+        else
+        {
+            req->size_high = st.st_size >> 32;
+            req->size_low  = st.st_size & 0xffffffff;
+        }
+        req->links       = st.st_nlink;
+        req->index_high  = st.st_dev;
+        req->index_low   = st.st_ino;
+        req->serial      = 0; /* FIXME */
     }
-    if (S_ISCHR(st.st_mode) || S_ISFIFO(st.st_mode) ||
-        S_ISSOCK(st.st_mode) || isatty(file->obj.fd)) req->type = FILE_TYPE_CHAR;
-    else req->type = FILE_TYPE_DISK;
-    if (S_ISDIR(st.st_mode)) req->attr = FILE_ATTRIBUTE_DIRECTORY;
-    else req->attr = FILE_ATTRIBUTE_ARCHIVE;
-    if (!(st.st_mode & S_IWUSR)) req->attr |= FILE_ATTRIBUTE_READONLY;
-    req->access_time = st.st_atime;
-    req->write_time  = st.st_mtime;
-    if (S_ISDIR(st.st_mode))
-    {
-        req->size_high = 0;
-        req->size_low  = 0;
-    }
-    else
-    {
-        req->size_high = st.st_size >> 32;
-        req->size_low  = st.st_size & 0xffffffff;
-    }
-    req->links       = st.st_nlink;
-    req->index_high  = st.st_dev;
-    req->index_low   = st.st_ino;
-    req->serial      = 0; /* FIXME */
-    return 1;
+    return FD_TYPE_DEFAULT;
 }
 
 static void file_destroy( struct object *obj )
@@ -501,6 +504,7 @@
             if ((fd = obj->ops->get_fd( obj )) != -1)
                 send_client_fd( current->process, fd, req->handle );
         }
+        req->type = obj->ops->get_file_info( obj, NULL );
         release_object( obj );
     }
 }
diff --git a/server/mapping.c b/server/mapping.c
index c87c6d3..8dbe2e0 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -33,6 +33,7 @@
 };
 
 static int mapping_get_fd( struct object *obj );
+static int mapping_get_info( struct object *obj, struct get_file_info_request *req );
 static void mapping_dump( struct object *obj, int verbose );
 static void mapping_destroy( struct object *obj );
 
@@ -48,7 +49,7 @@
     NULL,                        /* poll_event */
     mapping_get_fd,              /* get_fd */
     no_flush,                    /* flush */
-    no_get_file_info,            /* get_file_info */
+    mapping_get_info,            /* get_file_info */
     mapping_destroy              /* destroy */
 };
 
@@ -309,6 +310,16 @@
     return get_mmap_fd( mapping->file );
 }
 
+static int mapping_get_info( struct object *obj, struct get_file_info_request *req )
+{
+    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, req );
+}
+
 static void mapping_destroy( struct object *obj )
 {
     struct mapping *mapping = (struct mapping *)obj;
diff --git a/server/object.c b/server/object.c
index ba2bce8..a6dd908 100644
--- a/server/object.c
+++ b/server/object.c
@@ -266,7 +266,7 @@
 int no_get_file_info( struct object *obj, struct get_file_info_request *info )
 {
     set_error( STATUS_OBJECT_TYPE_MISMATCH );
-    return 0;
+    return FD_TYPE_INVALID;
 }
 
 void no_destroy( struct object *obj )
diff --git a/server/pipe.c b/server/pipe.c
index 8ade625..d1b2d42 100644
--- a/server/pipe.c
+++ b/server/pipe.c
@@ -126,17 +126,20 @@
 
 static int pipe_get_info( struct object *obj, struct get_file_info_request *req )
 {
-    req->type        = FILE_TYPE_PIPE;
-    req->attr        = 0;
-    req->access_time = 0;
-    req->write_time  = 0;
-    req->size_high   = 0;
-    req->size_low    = 0;
-    req->links       = 0;
-    req->index_high  = 0;
-    req->index_low   = 0;
-    req->serial      = 0;
-    return 1;
+    if (req)
+    {
+        req->type        = FILE_TYPE_PIPE;
+        req->attr        = 0;
+        req->access_time = 0;
+        req->write_time  = 0;
+        req->size_high   = 0;
+        req->size_low    = 0;
+        req->links       = 0;
+        req->index_high  = 0;
+        req->index_low   = 0;
+        req->serial      = 0;
+    }
+    return FD_TYPE_DEFAULT;
 }
 
 static void pipe_destroy( struct object *obj )
diff --git a/server/protocol.def b/server/protocol.def
index 010d2ed..e519beb 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -526,7 +526,12 @@
     unsigned int access;        /* wanted access rights */
 @REPLY
     int          fd;            /* file descriptor */
+    int          type;          /* the type of file */
 @END
+#define FD_TYPE_INVALID    0
+#define FD_TYPE_DEFAULT    1
+#define FD_TYPE_CONSOLE    2
+#define FD_TYPE_OVERLAPPED 3
 
 
 /* Set a file current position */
diff --git a/server/serial.c b/server/serial.c
index 614be00..d6a1ea4 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -160,18 +160,20 @@
 
 static int serial_get_info( struct object *obj, struct get_file_info_request *req )
 {
-    assert( obj->ops == &serial_ops );
-    req->type        = FILE_TYPE_CHAR;
-    req->attr        = 0;
-    req->access_time = 0;
-    req->write_time  = 0;
-    req->size_high   = 0;
-    req->size_low    = 0;
-    req->links       = 0;
-    req->index_high  = 0;
-    req->index_low   = 0;
-    req->serial      = 0;
-    return 1;
+    if (req)
+    {
+        req->type        = FILE_TYPE_CHAR;
+        req->attr        = 0;
+        req->access_time = 0;
+        req->write_time  = 0;
+        req->size_high   = 0;
+        req->size_low    = 0;
+        req->links       = 0;
+        req->index_high  = 0;
+        req->index_low   = 0;
+        req->serial      = 0;
+    }
+    return FD_TYPE_DEFAULT;
 }
 
 /* these function calculates the timeout for an async operation
diff --git a/server/trace.c b/server/trace.c
index 66d58f9..eeb323c 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -713,7 +713,8 @@
 
 static void dump_get_handle_fd_reply( const struct get_handle_fd_request *req )
 {
-    fprintf( stderr, " fd=%d", req->fd );
+    fprintf( stderr, " fd=%d,", req->fd );
+    fprintf( stderr, " type=%d", req->type );
 }
 
 static void dump_set_file_pointer_request( const struct set_file_pointer_request *req )