[PATCH 1/9] [Server]: enhanced the console input object so that it doesn't require a wineconsole to be running
Eric Pouech
eric.pouech at orange.fr
Mon Aug 30 15:18:44 CDT 2010
A+
---
include/wine/server_protocol.h | 2
programs/wineconsole/wineconsole.c | 1
server/console.c | 153 ++++++++++++++++++++++++++++++------
server/debugger.c | 8 +-
server/protocol.def | 1
server/request.h | 3 -
server/trace.c | 1
7 files changed, 139 insertions(+), 30 deletions(-)
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 0c43ecf..c35aab3 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1412,6 +1412,8 @@ struct alloc_console_request
unsigned int access;
unsigned int attributes;
process_id_t pid;
+ int input_fd;
+ char __pad_28[4];
};
struct alloc_console_reply
{
diff --git a/programs/wineconsole/wineconsole.c b/programs/wineconsole/wineconsole.c
index 5acb9ad..3842303 100644
--- a/programs/wineconsole/wineconsole.c
+++ b/programs/wineconsole/wineconsole.c
@@ -596,6 +596,7 @@ static struct inner_data* WINECON_Init(HINSTANCE hInst, DWORD pid, LPCWSTR appna
req->access = GENERIC_READ | GENERIC_WRITE;
req->attributes = 0;
req->pid = pid;
+ req->input_fd = -1;
ret = !wine_server_call_err( req );
data->hConIn = wine_server_ptr_handle( reply->handle_in );
diff --git a/server/console.c b/server/console.c
index d44ad41..9d84491 100644
--- a/server/console.c
+++ b/server/console.c
@@ -28,6 +28,9 @@
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -62,10 +65,13 @@ struct console_input
int output_cp; /* console output codepage */
user_handle_t win; /* window handle if backend supports it */
struct event *event; /* event to wait on for input queue */
+ struct fd *fd; /* for bare console, attached input fd */
+ struct termios termios; /* for bare console, saved termio info */
};
static void console_input_dump( struct object *obj, int verbose );
static void console_input_destroy( struct object *obj );
+static struct fd *console_input_get_fd( struct object *obj );
static const struct object_ops console_input_ops =
{
@@ -77,7 +83,7 @@ static const struct object_ops console_input_ops =
NULL, /* signaled */
no_satisfied, /* satisfied */
no_signal, /* signal */
- no_get_fd, /* get_fd */
+ console_input_get_fd, /* get_fd */
default_fd_map_access, /* map_access */
default_get_sd, /* get_sd */
default_set_sd, /* set_sd */
@@ -162,10 +168,36 @@ static const struct object_ops screen_buffer_ops =
screen_buffer_destroy /* destroy */
};
+static enum server_fd_type console_get_fd_type( struct fd *fd );
+
+static const struct fd_ops console_fd_ops =
+{
+ default_fd_get_poll_events, /* get_poll_events */
+ default_poll_event, /* poll_event */
+ no_flush, /* flush */
+ console_get_fd_type, /* get_fd_type */
+ default_fd_ioctl, /* ioctl */
+ default_fd_queue_async, /* queue_async */
+ default_fd_reselect_async, /* reselect_async */
+ default_fd_cancel_async /* cancel_async */
+};
+
static struct list screen_buffer_list = LIST_INIT(screen_buffer_list);
static const char_info_t empty_char_info = { ' ', 0x000f }; /* white on black space */
+static struct fd *console_input_get_fd( struct object* obj )
+{
+ struct console_input *console_input = (struct console_input*)obj;
+ assert( obj->ops == &console_input_ops );
+ return console_input->fd ? (struct fd*)grab_object( console_input->fd ) : NULL;
+}
+
+static enum server_fd_type console_get_fd_type( struct fd *fd )
+{
+ return FD_TYPE_CHAR;
+}
+
/* dumps the renderer events of a console */
static void console_input_events_dump( struct object *obj, int verbose )
{
@@ -197,7 +229,8 @@ static void console_input_events_append( struct console_input_events* evts,
{
int collapsed = FALSE;
- /* to be done even when evt has been generated by the rendere ? */
+ if (!evts) return;
+ /* to be done even when evt has been generated by the renderer ? */
/* try to collapse evt into current queue's events */
if (evts->num_used)
@@ -255,7 +288,7 @@ static struct console_input_events *create_console_input_events(void)
return evt;
}
-static struct object *create_console_input( struct thread* renderer )
+static struct object *create_console_input( struct thread* renderer, int fd )
{
struct console_input *console_input;
@@ -267,7 +300,7 @@ static struct object *create_console_input( struct thread* renderer )
console_input->active = NULL;
console_input->recnum = 0;
console_input->records = NULL;
- console_input->evt = create_console_input_events();
+ console_input->evt = renderer ? create_console_input_events() : NULL;
console_input->title = NULL;
console_input->history_size = 50;
console_input->history = calloc( console_input->history_size, sizeof(WCHAR*) );
@@ -278,12 +311,50 @@ static struct object *create_console_input( struct thread* renderer )
console_input->output_cp = 0;
console_input->win = 0;
console_input->event = create_event( NULL, NULL, 0, 1, 0, NULL );
+ console_input->fd = NULL;
- if (!console_input->history || !console_input->evt || !console_input->event)
+ if (!console_input->history || (renderer && !console_input->evt) || !console_input->event)
{
release_object( console_input );
return NULL;
}
+ if (fd != -1) /* bare console */
+ {
+ struct termios term;
+
+ if (!(console_input->fd = create_anonymous_fd( &console_fd_ops, fd, &console_input->obj,
+ FILE_SYNCHRONOUS_IO_NONALERT )))
+ {
+ release_object( console_input );
+ return NULL;
+ }
+ if (tcgetattr(fd, &term) < 0)
+ {
+ release_object( console_input );
+ set_error( STATUS_INVALID_HANDLE );
+ return NULL;
+ }
+ console_input->termios = term;
+ term.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
+ term.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ term.c_cflag &= ~(CSIZE | PARENB);
+ term.c_cflag |= CS8;
+ /* FIXME: we should actually disable output processing here
+ * and let kernel32/console.c do the job (with support of enable/disable of
+ * processed output)
+ */
+ /* term.c_oflag &= ~(OPOST); */
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+ if (tcsetattr(fd, TCSANOW, &term) < 0)
+ {
+ release_object( console_input );
+ set_error( STATUS_INVALID_HANDLE );
+ return NULL;
+ }
+ allow_fd_caching( console_input->fd );
+ }
+
return &console_input->obj;
}
@@ -374,10 +445,10 @@ int free_console( struct process *process )
{
struct console_input* console = process->console;
- if (!console || !console->renderer) return 0;
+ if (!console) return 0;
process->console = NULL;
- if (--console->num_proc == 0)
+ if (--console->num_proc == 0 && console->renderer)
{
/* all processes have terminated... tell the renderer to terminate too */
struct console_renderer_event evt;
@@ -424,7 +495,6 @@ void inherit_console(struct thread *parent_thread, struct process *process, obj_
/* otherwise, if parent has a console, attach child to this console */
if (!done && parent->console)
{
- assert(parent->console->renderer);
process->console = (struct console_input*)grab_object( parent->console );
process->console->num_proc++;
}
@@ -444,7 +514,6 @@ static struct console_input* console_input_get( obj_handle_t handle, unsigned ac
access, &console_input_ops );
else if (current->process->console)
{
- assert( current->process->console->renderer );
console = (struct console_input *)grab_object( current->process->console );
}
@@ -1020,9 +1089,17 @@ static void console_input_destroy( struct object *obj )
if (curr->input == console_in) curr->input = NULL;
}
- release_object( console_in->evt );
- console_in->evt = NULL;
+ if (console_in->evt)
+ {
+ release_object( console_in->evt );
+ console_in->evt = NULL;
+ }
release_object( console_in->event );
+ if (console_in->fd)
+ {
+ tcsetattr(get_unix_fd(console_in->fd), TCSANOW, &console_in->termios);
+ release_object( console_in->fd );
+ }
for (i = 0; i < console_in->history_size; i++)
free( console_in->history[i] );
@@ -1295,35 +1372,58 @@ DECL_HANDLER(alloc_console)
obj_handle_t in = 0;
obj_handle_t evt = 0;
struct process *process;
+ struct thread *renderer;
struct console_input *console;
+ int fd;
- if (req->pid)
- {
- if (!(process = get_process_from_id( req->pid ))) return;
- }
- else
+ switch (req->pid)
{
+ case 0:
+ /* renderer is current, console to be attached to parent process */
+ renderer = current;
if (!(process = current->process->parent))
{
set_error( STATUS_ACCESS_DENIED );
return;
}
grab_object( process );
+ break;
+ case 0xffffffff:
+ /* no renderer, console to be attached to current process */
+ renderer = NULL;
+ process = current->process;
+ grab_object( process );
+ break;
+ default:
+ /* renderer is current, console to be attached to req->pid */
+ renderer = current;
+ if (!(process = get_process_from_id( req->pid ))) return;
}
if (process != current->process && process->console)
+ {
set_error( STATUS_ACCESS_DENIED );
- else if ((console = (struct console_input*)create_console_input( current )))
+ goto the_end;
+ }
+ if (req->input_fd != -1)
+ {
+ if ((fd = thread_get_inflight_fd( current, req->input_fd )) == -1)
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ goto the_end;
+ }
+ }
+ else fd = -1;
+
+ if ((console = (struct console_input*)create_console_input( renderer, fd )))
{
if ((in = alloc_handle( current->process, console, req->access, req->attributes )))
{
- if ((evt = alloc_handle( current->process, console->evt, SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, 0 )))
+ if (!console->evt ||
+ (evt = alloc_handle( current->process, console->evt, SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, 0 )))
{
- if (process != current->process)
- {
- process->console = (struct console_input*)grab_object( console );
- console->num_proc++;
- }
+ process->console = (struct console_input*)grab_object( console );
+ console->num_proc++;
reply->handle_in = in;
reply->event = evt;
release_object( console );
@@ -1363,13 +1463,12 @@ DECL_HANDLER(open_console)
reply->handle = 0;
if (!req->from)
{
- if (current->process->console && current->process->console->renderer)
+ if (current->process->console)
obj = grab_object( (struct object*)current->process->console );
}
else if (req->from == (obj_handle_t)1)
{
- if (current->process->console && current->process->console->renderer &&
- 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,
@@ -1608,7 +1707,7 @@ DECL_HANDLER(get_console_wait_event)
{
struct console_input* console = NULL;
- if (current->process->console && current->process->console->renderer)
+ if (current->process->console)
console = (struct console_input*)grab_object( (struct object*)current->process->console );
else enum_processes(cgwe_enum, &console);
diff --git a/server/debugger.c b/server/debugger.c
index f76b44c..74c59f2 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -426,8 +426,12 @@ static int debugger_attach( struct process *process, struct thread *debugger )
if (list_empty( &process->thread_list )) goto error; /* no thread running in the process */
/* don't let a debugger debug its console... won't work */
- if (debugger->process->console && console_get_renderer(debugger->process->console)->process == process)
- goto error;
+ if (debugger->process->console)
+ {
+ struct thread *renderer = console_get_renderer(debugger->process->console);
+ if (renderer && renderer->process == process)
+ goto error;
+ }
suspend_process( process );
if (!set_process_debugger( process, debugger ))
diff --git a/server/protocol.def b/server/protocol.def
index 5f1a8f9..2ebca95 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1130,6 +1130,7 @@ enum server_fd_type
unsigned int access; /* wanted access rights */
unsigned int attributes; /* object attributes */
process_id_t pid; /* pid of process which shall be attached to the console */
+ int input_fd; /* if pid=-1 (bare console to current process), fd for input */
@REPLY
obj_handle_t handle_in; /* handle to console input */
obj_handle_t event; /* handle to renderer events change notification */
diff --git a/server/request.h b/server/request.h
index 7897673..ca406e1 100644
--- a/server/request.h
+++ b/server/request.h
@@ -949,7 +949,8 @@ C_ASSERT( sizeof(struct set_socket_deferred_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct alloc_console_request, access) == 12 );
C_ASSERT( FIELD_OFFSET(struct alloc_console_request, attributes) == 16 );
C_ASSERT( FIELD_OFFSET(struct alloc_console_request, pid) == 20 );
-C_ASSERT( sizeof(struct alloc_console_request) == 24 );
+C_ASSERT( FIELD_OFFSET(struct alloc_console_request, input_fd) == 24 );
+C_ASSERT( sizeof(struct alloc_console_request) == 32 );
C_ASSERT( FIELD_OFFSET(struct alloc_console_reply, handle_in) == 8 );
C_ASSERT( FIELD_OFFSET(struct alloc_console_reply, event) == 12 );
C_ASSERT( sizeof(struct alloc_console_reply) == 16 );
diff --git a/server/trace.c b/server/trace.c
index 944d939..443321a 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1582,6 +1582,7 @@ static void dump_alloc_console_request( const struct alloc_console_request *req
fprintf( stderr, " access=%08x", req->access );
fprintf( stderr, ", attributes=%08x", req->attributes );
fprintf( stderr, ", pid=%04x", req->pid );
+ fprintf( stderr, ", input_fd=%d", req->input_fd );
}
static void dump_alloc_console_reply( const struct alloc_console_reply *req )
More information about the wine-patches
mailing list