server: Allow a screen buffer to be attached to a given fd (for bare consoles).
diff --git a/server/console.c b/server/console.c
index 9d84491..905cc50 100644
--- a/server/console.c
+++ b/server/console.c
@@ -143,10 +143,12 @@
     unsigned short        attr;          /* default attribute for screen buffer */
     rectangle_t           win;           /* current visible window on the screen buffer *
 					  * as seen in wineconsole */
+    struct fd            *fd;            /* for bare console, attached output fd */
 };
 
 static void screen_buffer_dump( struct object *obj, int verbose );
 static void screen_buffer_destroy( struct object *obj );
+static struct fd *screen_buffer_get_fd( struct object *obj );
 
 static const struct object_ops screen_buffer_ops =
 {
@@ -158,7 +160,7 @@
     NULL,                             /* signaled */
     NULL,                             /* satisfied */
     no_signal,                        /* signal */
-    no_get_fd,                        /* get_fd */
+    screen_buffer_get_fd,             /* get_fd */
     default_fd_map_access,            /* map_access */
     default_get_sd,                   /* get_sd */
     default_set_sd,                   /* set_sd */
@@ -395,7 +397,7 @@
     console_input_events_append( console_input->evt, &evt );
 }
 
-static struct screen_buffer *create_console_output( struct console_input *console_input )
+static struct screen_buffer *create_console_output( struct console_input *console_input, int fd )
 {
     struct screen_buffer *screen_buffer;
     int	i;
@@ -416,6 +418,18 @@
     screen_buffer->win.right      = screen_buffer->max_width - 1;
     screen_buffer->win.top        = 0;
     screen_buffer->win.bottom     = screen_buffer->max_height - 1;
+    if (fd == -1)
+        screen_buffer->fd = NULL;
+    else
+    {
+        if (!(screen_buffer->fd = create_anonymous_fd( &console_fd_ops, fd, &screen_buffer->obj,
+                                                       FILE_SYNCHRONOUS_IO_NONALERT )))
+        {
+            release_object( screen_buffer );
+            return NULL;
+        }
+        allow_fd_caching(screen_buffer->fd);
+    }
 
     list_add_head( &screen_buffer_list, &screen_buffer->entry );
 
@@ -1136,9 +1150,17 @@
             }
         }
     }
+    if (screen_buffer->fd) release_object( screen_buffer->fd );
     free( screen_buffer->data );
 }
 
+static struct fd *screen_buffer_get_fd( struct object *obj )
+{
+    struct screen_buffer *screen_buffer = (struct screen_buffer*)obj;
+    assert( obj->ops == &screen_buffer_ops );
+    return screen_buffer->fd ? (struct fd*)grab_object( screen_buffer->fd ) : NULL;
+}
+
 /* write data into a screen buffer */
 static int write_console_output( struct screen_buffer *screen_buffer, data_size_t size,
                                  const void* data, enum char_info_mode mode,
@@ -1468,8 +1490,8 @@
     }
     else if (req->from == (obj_handle_t)1)
     {
-         if (current->process->console && current->process->console->active)
-             obj = grab_object( (struct object*)current->process->console->active );
+        if (current->process->console && current->process->console->active)
+            obj = grab_object( (struct object*)current->process->console->active );
     }
     else if ((obj = get_handle_obj( current->process, req->from,
                                     FILE_READ_PROPERTIES|FILE_WRITE_PROPERTIES, &console_input_ops )))
@@ -1575,10 +1597,24 @@
 {
     struct console_input*	console;
     struct screen_buffer*	screen_buffer;
+    int                         fd;
 
-    if (!(console = console_input_get( req->handle_in, FILE_WRITE_PROPERTIES ))) return;
+    if (req->fd != -1)
+    {
+        if ((fd = thread_get_inflight_fd( current, req->fd )) == -1)
+        {
+            set_error( STATUS_INVALID_HANDLE ); /* FIXME */
+            return;
+        }
+    }
+    else fd = -1;
+    if (!(console = console_input_get( req->handle_in, FILE_WRITE_PROPERTIES )))
+    {
+        close(fd);
+        return;
+    }
 
-    screen_buffer = create_console_output( console );
+    screen_buffer = create_console_output( console, fd );
     if (screen_buffer)
     {
         /* FIXME: should store sharing and test it when opening the CONOUT$ device