New console code based on Win32 windows.
diff --git a/server/process.c b/server/process.c
index b3196a9..f02f5b7 100644
--- a/server/process.c
+++ b/server/process.c
@@ -26,6 +26,7 @@
#include "process.h"
#include "thread.h"
#include "request.h"
+#include "console.h"
/* process structure */
@@ -101,12 +102,18 @@
{
if (process->create_flags & CREATE_NEW_CONSOLE)
{
- if (!alloc_console( process )) return 0;
+ /* let the process init do the allocation */
+ return 1;
}
else if (parent && !(process->create_flags & DETACHED_PROCESS))
{
- if (parent->console_in) process->console_in = grab_object( parent->console_in );
- if (parent->console_out) process->console_out = grab_object( parent->console_out );
+ /* FIXME: some better error checking should be done...
+ * like if hConOut and hConIn are console handles, then they should be on the same
+ * physical console
+ */
+ inherit_console( parent, process,
+ (info->inherit_all || (info->start_flags & STARTF_USESTDHANDLES)) ?
+ info->hstdin : 0 );
}
if (parent)
{
@@ -129,13 +136,20 @@
}
else
{
- /* no parent, use handles to the console for stdio */
- req->hstdin = alloc_handle( process, process->console_in,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
- req->hstdout = alloc_handle( process, process->console_out,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
- req->hstderr = alloc_handle( process, process->console_out,
- GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
+ if (process->console)
+ {
+ req->hstdin = alloc_handle( process, process->console,
+ GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
+ req->hstdout = alloc_handle( process, process->console->active,
+ GENERIC_READ | GENERIC_WRITE, 1 );
+ req->hstderr = alloc_handle( process, process->console->active,
+ GENERIC_READ | GENERIC_WRITE, 1 );
+ }
+ else
+ {
+ /* no parent, let the caller decide what to do */
+ req->hstdin = req->hstdout = req->hstderr = 0;
+ }
}
/* some handles above may have been invalid; this is not an error */
if (get_error() == STATUS_INVALID_HANDLE) clear_error();
@@ -152,6 +166,7 @@
if (!(process = alloc_object( &process_ops, fd ))) return NULL;
process->next = NULL;
process->prev = NULL;
+ process->parent = NULL;
process->thread_list = NULL;
process->debugger = NULL;
process->handles = NULL;
@@ -161,8 +176,7 @@
process->affinity = 1;
process->suspend = 0;
process->create_flags = 0;
- process->console_in = NULL;
- process->console_out = NULL;
+ process->console = NULL;
process->init_event = NULL;
process->idle_event = NULL;
process->queue = NULL;
@@ -173,6 +187,7 @@
process->exe.file = NULL;
process->exe.dbg_offset = 0;
process->exe.dbg_size = 0;
+
gettimeofday( &process->start_time, NULL );
if ((process->next = first_process) != NULL) process->next->prev = process;
first_process = process;
@@ -222,10 +237,11 @@
fatal_protocol_error( current, "init_process: called twice?\n" );
return;
}
+ process->parent = (struct process *)grab_object( parent );
}
/* set the process flags */
- process->create_flags = info ? info->create_flags : CREATE_NEW_CONSOLE;
+ process->create_flags = info ? info->create_flags : 0;
/* create the handle table */
if (parent && info->inherit_all)
@@ -288,6 +304,8 @@
/* we can't have a thread remaining */
assert( !process->thread_list );
+ if (process->console) release_object( process->console );
+ if (process->parent) release_object( process->parent );
if (process->next) process->next->prev = process->prev;
if (process->prev) process->prev->next = process->next;
else first_process = process->next;
@@ -304,9 +322,8 @@
struct process *process = (struct process *)obj;
assert( obj->ops == &process_ops );
- fprintf( stderr, "Process next=%p prev=%p console=%p/%p handles=%p\n",
- process->next, process->prev, process->console_in, process->console_out,
- process->handles );
+ fprintf( stderr, "Process next=%p prev=%p handles=%p\n",
+ process->next, process->prev, process->handles );
}
static int process_signaled( struct object *obj, struct thread *thread )
@@ -418,6 +435,25 @@
set_error( STATUS_INVALID_PARAMETER );
}
+/* kill all processes being attached to a console renderer */
+static void kill_console_processes( struct process *renderer, int exit_code )
+{
+ for (;;) /* restart from the beginning of the list every time */
+ {
+ struct process *process = first_process;
+
+ /* find the first process being attached to 'renderer' and still running */
+ while (process &&
+ (process == renderer || !process->console ||
+ process->console->renderer != renderer || !process->running_threads))
+ {
+ process = process->next;
+ }
+ if (!process) break;
+ kill_process( process, NULL, exit_code );
+ }
+}
+
/* a process has been killed (i.e. its last thread died) */
static void process_killed( struct process *process )
{
@@ -425,7 +461,13 @@
gettimeofday( &process->end_time, NULL );
if (process->handles) release_object( process->handles );
process->handles = NULL;
+
+ /* close the console attached to this process, if any */
free_console( process );
+
+ /* close the processes using process as renderer, if any */
+ kill_console_processes( process, 0 );
+
while (process->exe.next)
{
struct process_dll *dll = process->exe.next;
@@ -508,6 +550,7 @@
void kill_process( struct process *process, struct thread *skip, int exit_code )
{
struct thread *thread = process->thread_list;
+
while (thread)
{
struct thread *next = thread->proc_next;
@@ -532,6 +575,7 @@
}
}
+
/* get all information about a process */
static void get_process_info( struct process *process, struct get_process_info_request *req )
{