diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c index f682ca1452f..d760b658cff 100644 --- a/dlls/kernel32/console.c +++ b/dlls/kernel32/console.c @@ -1809,6 +1809,7 @@ HANDLE WINAPI CreateConsoleScreenBuffer(DWORD dwDesiredAccess, DWORD dwShareMode req->access = dwDesiredAccess; req->attributes = (sa && sa->bInheritHandle) ? OBJ_INHERIT : 0; req->share = dwShareMode; + req->fd = -1; if (!wine_server_call_err( req )) ret = console_handle_map( wine_server_ptr_handle( reply->handle_out )); } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 3b0a5833743..77c13e85df4 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1654,7 +1654,7 @@ struct create_console_output_request unsigned int access; unsigned int attributes; unsigned int share; - char __pad_28[4]; + int fd; }; struct create_console_output_reply { @@ -5506,6 +5506,6 @@ union generic_reply struct set_cursor_reply set_cursor_reply; }; -#define SERVER_PROTOCOL_VERSION 405 +#define SERVER_PROTOCOL_VERSION 406 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/programs/wineconsole/wineconsole.c b/programs/wineconsole/wineconsole.c index 384230387b1..52edfb3aa15 100644 --- a/programs/wineconsole/wineconsole.c +++ b/programs/wineconsole/wineconsole.c @@ -612,6 +612,7 @@ static struct inner_data* WINECON_Init(HINSTANCE hInst, DWORD pid, LPCWSTR appna req->access = GENERIC_WRITE|GENERIC_READ; req->attributes = 0; req->share = FILE_SHARE_READ|FILE_SHARE_WRITE; + req->fd = -1; ret = !wine_server_call_err( req ); data->hConOut = wine_server_ptr_handle( reply->handle_out ); } diff --git a/server/console.c b/server/console.c index 9d844915451..905cc5014ab 100644 --- a/server/console.c +++ b/server/console.c @@ -143,10 +143,12 @@ struct screen_buffer 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 @@ static const struct object_ops screen_buffer_ops = 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 @@ static void generate_sb_initial_events( struct console_input *console_input ) 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 @@ static struct screen_buffer *create_console_output( struct console_input *consol 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 @@ static void screen_buffer_destroy( struct object *obj ) } } } + 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 @@ DECL_HANDLER(open_console) } 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 @@ DECL_HANDLER(create_console_output) { 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 diff --git a/server/protocol.def b/server/protocol.def index 7ed3886bca1..ceebba13009 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1295,6 +1295,7 @@ struct console_renderer_event unsigned int access; /* wanted access rights */ unsigned int attributes; /* object attributes */ unsigned int share; /* sharing credentials */ + int fd; /* for bare consoles, fd the screen-buffer is attached to */ @REPLY obj_handle_t handle_out; /* handle to the screen buffer */ @END diff --git a/server/request.h b/server/request.h index 1f90278b3a5..b16dbe9a6b2 100644 --- a/server/request.h +++ b/server/request.h @@ -1011,6 +1011,7 @@ C_ASSERT( FIELD_OFFSET(struct create_console_output_request, handle_in) == 12 ); C_ASSERT( FIELD_OFFSET(struct create_console_output_request, access) == 16 ); C_ASSERT( FIELD_OFFSET(struct create_console_output_request, attributes) == 20 ); C_ASSERT( FIELD_OFFSET(struct create_console_output_request, share) == 24 ); +C_ASSERT( FIELD_OFFSET(struct create_console_output_request, fd) == 28 ); C_ASSERT( sizeof(struct create_console_output_request) == 32 ); C_ASSERT( FIELD_OFFSET(struct create_console_output_reply, handle_out) == 8 ); C_ASSERT( sizeof(struct create_console_output_reply) == 16 ); diff --git a/server/trace.c b/server/trace.c index 8c2418c07fb..c7c12f63038 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1704,6 +1704,7 @@ static void dump_create_console_output_request( const struct create_console_outp fprintf( stderr, ", access=%08x", req->access ); fprintf( stderr, ", attributes=%08x", req->attributes ); fprintf( stderr, ", share=%08x", req->share ); + fprintf( stderr, ", fd=%d", req->fd ); } static void dump_create_console_output_reply( const struct create_console_output_reply *req )