server: Simplify process creation.

Pass the socket for the new process from the parent through the
environment.
Perform initialisations during the new_process request.
diff --git a/server/process.c b/server/process.c
index 0c71540..231eb2f 100644
--- a/server/process.c
+++ b/server/process.c
@@ -94,17 +94,11 @@
 struct startup_info
 {
     struct object       obj;          /* object header */
-    struct list         entry;        /* entry in list of startup infos */
-    int                 inherit_all;  /* inherit all handles from parent */
-    unsigned int        create_flags; /* creation flags */
-    int                 unix_pid;     /* Unix pid of new process */
     obj_handle_t        hstdin;       /* handle for stdin */
     obj_handle_t        hstdout;      /* handle for stdout */
     obj_handle_t        hstderr;      /* handle for stderr */
     struct file        *exe_file;     /* file handle for main exe */
-    struct thread      *owner;        /* owner thread (the one that created the new process) */
     struct process     *process;      /* created process */
-    struct thread      *thread;       /* created thread */
     size_t              data_size;    /* size of startup data */
     void               *data;         /* data for startup info */
 };
@@ -130,8 +124,6 @@
 };
 
 
-static struct list startup_info_list = LIST_INIT(startup_info_list);
-
 struct ptid_entry
 {
     void        *ptr;   /* entry ptr */
@@ -226,13 +218,18 @@
 }
 
 /* create a new process and its main thread */
-struct thread *create_process( int fd )
+/* if the function fails the fd is closed */
+struct thread *create_process( int fd, struct thread *parent_thread, int inherit_all )
 {
     struct process *process;
     struct thread *thread = NULL;
     int request_pipe[2];
 
-    if (!(process = alloc_object( &process_ops ))) goto error;
+    if (!(process = alloc_object( &process_ops )))
+    {
+        close( fd );
+        goto error;
+    }
     process->parent          = NULL;
     process->debugger        = NULL;
     process->handles         = NULL;
@@ -261,9 +258,24 @@
     gettimeofday( &process->start_time, NULL );
     list_add_head( &process_list, &process->entry );
 
-    if (!(process->id = process->group_id = alloc_ptid( process ))) goto error;
+    if (!(process->id = process->group_id = alloc_ptid( process )))
+    {
+        close( fd );
+        goto error;
+    }
     if (!(process->msg_fd = create_anonymous_fd( &process_fd_ops, fd, &process->obj ))) goto error;
 
+    /* create the handle table */
+    if (!parent_thread) process->handles = alloc_handle_table( process, 0 );
+    else
+    {
+        struct process *parent = parent_thread->process;
+        process->parent = (struct process *)grab_object( parent );
+        process->handles = inherit_all ? copy_handle_table( process, parent )
+                                       : alloc_handle_table( process, 0 );
+    }
+    if (!process->handles) goto error;
+
     /* create the main thread */
     if (pipe( request_pipe ) == -1)
     {
@@ -290,82 +302,13 @@
     return NULL;
 }
 
-/* find the startup info for a given Unix process */
-inline static struct startup_info *find_startup_info( int unix_pid )
-{
-    struct list *ptr;
-
-    LIST_FOR_EACH( ptr, &startup_info_list )
-    {
-        struct startup_info *info = LIST_ENTRY( ptr, struct startup_info, entry );
-        if (info->unix_pid == unix_pid) return info;
-    }
-    return NULL;
-}
-
 /* initialize the current process and fill in the request */
 size_t init_process( struct thread *thread )
 {
     struct process *process = thread->process;
-    struct thread *parent_thread = NULL;
-    struct process *parent = NULL;
-    struct startup_info *info;
-
-    if (process->startup_info) return process->startup_info->data_size;  /* already initialized */
-
-    if ((info = find_startup_info( thread->unix_pid )))
-    {
-        if (info->thread) return info->data_size;  /* already initialized */
-
-        info->thread  = (struct thread *)grab_object( thread );
-        info->process = (struct process *)grab_object( process );
-        process->startup_info = (struct startup_info *)grab_object( info );
-
-        parent_thread = info->owner;
-        parent = parent_thread->process;
-        process->parent = (struct process *)grab_object( parent );
-
-        /* set the process flags */
-        process->create_flags = info->create_flags;
-
-        if (info->inherit_all) process->handles = copy_handle_table( process, parent );
-    }
-
-    /* create the handle table */
-    if (!process->handles) process->handles = alloc_handle_table( process, 0 );
-    if (!process->handles)
-    {
-        set_error( STATUS_NO_MEMORY );
-        return 0;
-    }
-
-    /* connect to the window station */
-    connect_process_winstation( process, parent_thread );
+    struct startup_info *info = process->startup_info;
 
     if (!info) return 0;
-
-    /* thread will be actually suspended in init_done */
-    if (info->create_flags & CREATE_SUSPENDED) thread->suspend++;
-
-    /* set the process console */
-    if (!(info->create_flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE)))
-    {
-        /* 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_thread, process, info->inherit_all ? info->hstdin : 0 );
-    }
-
-    /* attach to the debugger if requested */
-    if (process->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
-        set_process_debugger( process, parent_thread );
-    else if (parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS))
-        set_process_debugger( process, parent->debugger );
-
-    if (!(process->create_flags & CREATE_NEW_PROCESS_GROUP))
-        process->group_id = parent->group_id;
-
     return info->data_size;
 }
 
@@ -426,12 +369,9 @@
 {
     struct startup_info *info = (struct startup_info *)obj;
     assert( obj->ops == &startup_info_ops );
-    list_remove( &info->entry );
     if (info->data) free( info->data );
     if (info->exe_file) release_object( info->exe_file );
     if (info->process) release_object( info->process );
-    if (info->thread) release_object( info->thread );
-    if (info->owner) release_object( info->owner );
 }
 
 static void startup_info_dump( struct object *obj, int verbose )
@@ -439,8 +379,8 @@
     struct startup_info *info = (struct startup_info *)obj;
     assert( obj->ops == &startup_info_ops );
 
-    fprintf( stderr, "Startup info flags=%x in=%p out=%p err=%p\n",
-             info->create_flags, info->hstdin, info->hstdout, info->hstderr );
+    fprintf( stderr, "Startup info in=%p out=%p err=%p\n",
+             info->hstdin, info->hstdout, info->hstderr );
 }
 
 static int startup_info_signaled( struct object *obj, struct thread *thread )
@@ -792,20 +732,30 @@
 DECL_HANDLER(new_process)
 {
     struct startup_info *info;
+    struct thread *thread;
+    struct process *process;
+    struct process *parent = current->process;
+    int socket_fd = thread_get_inflight_fd( current, req->socket_fd );
+
+    if (socket_fd == -1)
+    {
+        set_error( STATUS_INVALID_PARAMETER );
+        return;
+    }
+    if (fcntl( socket_fd, F_SETFL, O_NONBLOCK ) == -1)
+    {
+        set_error( STATUS_INVALID_HANDLE );
+        close( socket_fd );
+        return;
+    }
 
     /* build the startup info for a new process */
     if (!(info = alloc_object( &startup_info_ops ))) return;
-    list_add_head( &startup_info_list, &info->entry );
-    info->inherit_all  = req->inherit_all;
-    info->create_flags = req->create_flags;
-    info->unix_pid     = req->unix_pid;
     info->hstdin       = req->hstdin;
     info->hstdout      = req->hstdout;
     info->hstderr      = req->hstderr;
     info->exe_file     = NULL;
-    info->owner        = (struct thread *)grab_object( current );
     info->process      = NULL;
-    info->thread       = NULL;
     info->data_size    = get_req_data_size();
     info->data         = NULL;
 
@@ -814,7 +764,56 @@
         goto done;
 
     if (!(info->data = memdup( get_req_data(), info->data_size ))) goto done;
+
+    if (!(thread = create_process( socket_fd, current, req->inherit_all ))) goto done;
+    process = thread->process;
+    process->create_flags = req->create_flags;
+    process->startup_info = (struct startup_info *)grab_object( info );
+
+    /* connect to the window station */
+    connect_process_winstation( process, current );
+
+    /* thread will be actually suspended in init_done */
+    if (req->create_flags & CREATE_SUSPENDED) thread->suspend++;
+
+    /* set the process console */
+    if (!(req->create_flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE)))
+    {
+        /* 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( current, process, req->inherit_all ? req->hstdin : 0 );
+    }
+
+    if (!req->inherit_all && !(req->create_flags & CREATE_NEW_CONSOLE))
+    {
+        info->hstdin  = duplicate_handle( parent, req->hstdin, process,
+                                          0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
+        info->hstdout = duplicate_handle( parent, req->hstdout, process,
+                                          0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
+        info->hstderr = duplicate_handle( parent, req->hstderr, process,
+                                          0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
+        /* some handles above may have been invalid; this is not an error */
+        if (get_error() == STATUS_INVALID_HANDLE ||
+            get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error();
+    }
+
+    /* attach to the debugger if requested */
+    if (req->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
+        set_process_debugger( process, current );
+    else if (parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS))
+        set_process_debugger( process, parent->debugger );
+
+    if (!(req->create_flags & CREATE_NEW_PROCESS_GROUP))
+        process->group_id = parent->group_id;
+
+    info->process = (struct process *)grab_object( process );
     reply->info = alloc_handle( current->process, info, SYNCHRONIZE, 0 );
+    reply->pid = get_process_id( process );
+    reply->tid = get_thread_id( thread );
+    reply->phandle = alloc_handle( parent, process, req->process_access, req->process_attr );
+    reply->thandle = alloc_handle( parent, thread, req->thread_access, req->thread_attr );
 
  done:
     release_object( info );
@@ -828,23 +827,10 @@
     if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
                                                        0, &startup_info_ops )))
     {
-        reply->pid = get_process_id( info->process );
-        reply->tid = get_thread_id( info->thread );
-        reply->phandle = alloc_handle( current->process, info->process,
-                                       req->process_access, req->process_attr );
-        reply->thandle = alloc_handle( current->process, info->thread,
-                                       req->thread_access, req->thread_attr );
         reply->success = is_process_init_done( info->process );
+        reply->exit_code = info->process->exit_code;
         release_object( info );
     }
-    else
-    {
-        reply->pid     = 0;
-        reply->tid     = 0;
-        reply->phandle = 0;
-        reply->thandle = 0;
-        reply->success = 0;
-    }
 }
 
 /* Retrieve the new process startup info */
@@ -859,25 +845,9 @@
     if (info->exe_file &&
         !(reply->exe_file = alloc_handle( process, info->exe_file, GENERIC_READ, 0 ))) return;
 
-    if (!info->inherit_all && !(info->create_flags & CREATE_NEW_CONSOLE))
-    {
-        struct process *parent_process = info->owner->process;
-        reply->hstdin  = duplicate_handle( parent_process, info->hstdin, process,
-                                           0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
-        reply->hstdout = duplicate_handle( parent_process, info->hstdout, process,
-                                           0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
-        reply->hstderr = duplicate_handle( parent_process, info->hstderr, process,
-                                           0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
-        /* some handles above may have been invalid; this is not an error */
-        if (get_error() == STATUS_INVALID_HANDLE ||
-            get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error();
-    }
-    else
-    {
-        reply->hstdin  = info->hstdin;
-        reply->hstdout = info->hstdout;
-        reply->hstderr = info->hstderr;
-    }
+    reply->hstdin  = info->hstdin;
+    reply->hstdout = info->hstdout;
+    reply->hstderr = info->hstderr;
 
     /* we return the data directly without making a copy so this can only be called once */
     size = info->data_size;
diff --git a/server/process.h b/server/process.h
index baf2632..e5289da 100644
--- a/server/process.h
+++ b/server/process.h
@@ -102,7 +102,7 @@
 extern unsigned int alloc_ptid( void *ptr );
 extern void free_ptid( unsigned int id );
 extern void *get_ptid_entry( unsigned int id );
-extern struct thread *create_process( int fd );
+extern struct thread *create_process( int fd, struct thread *parent_thread, int inherit_all );
 extern size_t init_process( struct thread *thread );
 extern struct thread *get_process_first_thread( struct process *process );
 extern struct process *get_process_from_id( process_id_t id );
diff --git a/server/protocol.def b/server/protocol.def
index 663f910..eab3115 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -205,33 +205,34 @@
 
 /* Create a new process from the context of the parent */
 @REQ(new_process)
-    int          inherit_all;  /* inherit all handles from parent */
-    unsigned int create_flags; /* creation flags */
-    int          unix_pid;     /* Unix pid of new process */
-    obj_handle_t exe_file;     /* file handle for main exe */
-    obj_handle_t hstdin;       /* handle for stdin */
-    obj_handle_t hstdout;      /* handle for stdout */
-    obj_handle_t hstderr;      /* handle for stderr */
-    VARARG(info,startup_info); /* startup information */
-    VARARG(env,unicode_str);   /* environment for new process */
+    int          inherit_all;    /* inherit all handles from parent */
+    unsigned int create_flags;   /* creation flags */
+    int          socket_fd;      /* file descriptor for process socket */
+    obj_handle_t exe_file;       /* file handle for main exe */
+    obj_handle_t hstdin;         /* handle for stdin */
+    obj_handle_t hstdout;        /* handle for stdout */
+    obj_handle_t hstderr;        /* handle for stderr */
+    unsigned int process_access; /* access rights for process object */
+    unsigned int process_attr;   /* attributes for process object */
+    unsigned int thread_access;  /* access rights for thread object */
+    unsigned int thread_attr;    /* attributes for thread object */
+    VARARG(info,startup_info);   /* startup information */
+    VARARG(env,unicode_str);     /* environment for new process */
 @REPLY
-    obj_handle_t info;         /* new process info handle */
+    obj_handle_t info;           /* new process info handle */
+    process_id_t pid;            /* process id */
+    obj_handle_t phandle;        /* process handle (in the current process) */
+    thread_id_t  tid;            /* thread id */
+    obj_handle_t thandle;        /* thread handle (in the current process) */
 @END
 
 
 /* Retrieve information about a newly started process */
 @REQ(get_new_process_info)
     obj_handle_t info;           /* info handle returned from new_process_request */
-    unsigned int process_access; /* access rights for process object */
-    unsigned int process_attr;   /* attributes for process object */
-    unsigned int thread_access;  /* access rights for thread object */
-    unsigned int thread_attr;    /* attributes for thread object */
 @REPLY
-    process_id_t pid;          /* process id */
-    obj_handle_t phandle;      /* process handle (in the current process) */
-    thread_id_t  tid;          /* thread id */
-    obj_handle_t thandle;      /* thread handle (in the current process) */
     int          success;      /* did the process start successfully? */
+    int          exit_code;    /* process exit code if failed */
 @END
 
 
diff --git a/server/request.c b/server/request.c
index a78916e..260fc62 100644
--- a/server/request.c
+++ b/server/request.c
@@ -508,7 +508,7 @@
             sock->timeout = NULL;
         }
         fcntl( client, F_SETFL, O_NONBLOCK );
-        create_process( client );
+        create_process( client, NULL, 0 );
     }
 }
 
diff --git a/server/trace.c b/server/trace.c
index 24e0c6e..b5e40b8 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -606,11 +606,15 @@
 {
     fprintf( stderr, " inherit_all=%d,", req->inherit_all );
     fprintf( stderr, " create_flags=%08x,", req->create_flags );
-    fprintf( stderr, " unix_pid=%d,", req->unix_pid );
+    fprintf( stderr, " socket_fd=%d,", req->socket_fd );
     fprintf( stderr, " exe_file=%p,", req->exe_file );
     fprintf( stderr, " hstdin=%p,", req->hstdin );
     fprintf( stderr, " hstdout=%p,", req->hstdout );
     fprintf( stderr, " hstderr=%p,", req->hstderr );
+    fprintf( stderr, " process_access=%08x,", req->process_access );
+    fprintf( stderr, " process_attr=%08x,", req->process_attr );
+    fprintf( stderr, " thread_access=%08x,", req->thread_access );
+    fprintf( stderr, " thread_attr=%08x,", req->thread_attr );
     fprintf( stderr, " info=" );
     dump_varargs_startup_info( cur_size );
     fputc( ',', stderr );
@@ -620,25 +624,22 @@
 
 static void dump_new_process_reply( const struct new_process_reply *req )
 {
-    fprintf( stderr, " info=%p", req->info );
+    fprintf( stderr, " info=%p,", req->info );
+    fprintf( stderr, " pid=%04x,", req->pid );
+    fprintf( stderr, " phandle=%p,", req->phandle );
+    fprintf( stderr, " tid=%04x,", req->tid );
+    fprintf( stderr, " thandle=%p", req->thandle );
 }
 
 static void dump_get_new_process_info_request( const struct get_new_process_info_request *req )
 {
-    fprintf( stderr, " info=%p,", req->info );
-    fprintf( stderr, " process_access=%08x,", req->process_access );
-    fprintf( stderr, " process_attr=%08x,", req->process_attr );
-    fprintf( stderr, " thread_access=%08x,", req->thread_access );
-    fprintf( stderr, " thread_attr=%08x", req->thread_attr );
+    fprintf( stderr, " info=%p", req->info );
 }
 
 static void dump_get_new_process_info_reply( const struct get_new_process_info_reply *req )
 {
-    fprintf( stderr, " pid=%04x,", req->pid );
-    fprintf( stderr, " phandle=%p,", req->phandle );
-    fprintf( stderr, " tid=%04x,", req->tid );
-    fprintf( stderr, " thandle=%p,", req->thandle );
-    fprintf( stderr, " success=%d", req->success );
+    fprintf( stderr, " success=%d,", req->success );
+    fprintf( stderr, " exit_code=%d", req->exit_code );
 }
 
 static void dump_new_thread_request( const struct new_thread_request *req )