A few optimizations in the process startup requests now that Winelib
apps are started differently from Unix ones.

diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index ddc2afd..1f44452 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -214,7 +214,7 @@
     handle_t     phandle;
     void*        tid;
     handle_t     thandle;
-    handle_t     event;
+    int          success;
 };
 
 
@@ -258,7 +258,6 @@
     struct reply_header __header;
     int          create_flags;
     unsigned int server_start;
-    handle_t     info;
     size_t       info_size;
     handle_t     exe_file;
     handle_t     hstdin;
@@ -271,8 +270,6 @@
 struct get_startup_info_request
 {
     struct request_header __header;
-    handle_t     info;
-    int          close;
 };
 struct get_startup_info_reply
 {
@@ -3198,6 +3195,6 @@
     struct get_window_properties_reply get_window_properties_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 79
+#define SERVER_PROTOCOL_VERSION 80
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/memory/environ.c b/memory/environ.c
index da2ab4b..8fa917a 100644
--- a/memory/environ.c
+++ b/memory/environ.c
@@ -201,8 +201,7 @@
  *
  * Fill the startup info structure from the server.
  */
-ENVDB *ENV_InitStartupInfo( handle_t info_handle, size_t info_size,
-                            char *main_exe_name, size_t main_exe_size )
+ENVDB *ENV_InitStartupInfo( size_t info_size, char *main_exe_name, size_t main_exe_size )
 {
     startup_info_t info;
     void *data;
@@ -217,8 +216,6 @@
 
     SERVER_START_REQ( get_startup_info )
     {
-        req->info = info_handle;
-        req->close = TRUE;
         wine_server_set_reply( req, data, info_size );
         wine_server_call( req );
         info_size = wine_server_reply_size( reply );
diff --git a/scheduler/process.c b/scheduler/process.c
index e611b55..2d83fbc 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -118,8 +118,8 @@
 static unsigned int server_startticks;
 
 /* memory/environ.c */
-extern struct _ENVDB *ENV_InitStartupInfo( handle_t info_handle, size_t info_size,
-                                           char *main_exe_name, size_t main_exe_size );
+extern struct _ENVDB *ENV_InitStartupInfo( size_t info_size, char *main_exe_name,
+                                           size_t main_exe_size );
 extern BOOL ENV_BuildCommandLine( char **argv );
 extern STARTUPINFOA current_startupinfo;
 
@@ -358,7 +358,6 @@
 {
     BOOL ret;
     size_t info_size = 0;
-    handle_t info = 0;
 
     /* store the program name */
     argv0 = argv[0];
@@ -384,7 +383,6 @@
             main_exe_file     = reply->exe_file;
             main_create_flags = reply->create_flags;
             info_size         = reply->info_size;
-            info              = reply->info;
             server_startticks = reply->server_start;
             current_startupinfo.hStdInput   = reply->hstdin;
             current_startupinfo.hStdOutput  = reply->hstdout;
@@ -420,12 +418,12 @@
     PTHREAD_init_done();
 
     /* Copy the parent environment */
-    if (!(current_process.env_db = ENV_InitStartupInfo( info, info_size,
-                                                        main_exe_name, sizeof(main_exe_name) )))
+    if (!(current_process.env_db = ENV_InitStartupInfo( info_size, main_exe_name,
+                                                        sizeof(main_exe_name) )))
         return FALSE;
 
     /* Parse command line arguments */
-    OPTIONS_ParseOptions( !info ? argv : NULL );
+    OPTIONS_ParseOptions( !info_size ? argv : NULL );
 
     ret = MAIN_MainInit();
 
@@ -891,8 +889,7 @@
                             BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
                             LPPROCESS_INFORMATION info, LPCSTR unixdir )
 {
-    BOOL ret;
-    HANDLE load_done_evt = 0;
+    BOOL ret, success = FALSE;
     HANDLE process_info;
     startup_info_t startup_info;
 
@@ -965,48 +962,33 @@
 
     /* wait for the new process info to be ready */
 
-    ret = TRUE;  /* pretend success even if we don't get the new process info */
-    if (WaitForSingleObject( process_info, 2000 ) == STATUS_WAIT_0)
+    WaitForSingleObject( process_info, INFINITE );
+    SERVER_START_REQ( get_new_process_info )
     {
-        SERVER_START_REQ( get_new_process_info )
+        req->info     = process_info;
+        req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
+        req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle);
+        if ((ret = !wine_server_call_err( req )))
         {
-            req->info     = process_info;
-            req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
-            req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle);
-            if ((ret = !wine_server_call_err( req )))
-            {
-                info->dwProcessId = (DWORD)reply->pid;
-                info->dwThreadId  = (DWORD)reply->tid;
-                info->hProcess    = reply->phandle;
-                info->hThread     = reply->thandle;
-                load_done_evt     = reply->event;
-            }
+            info->dwProcessId = (DWORD)reply->pid;
+            info->dwThreadId  = (DWORD)reply->tid;
+            info->hProcess    = reply->phandle;
+            info->hThread     = reply->thandle;
+            success           = reply->success;
         }
-        SERVER_END_REQ;
+    }
+    SERVER_END_REQ;
+
+    if (ret && !success)  /* new process failed to start */
+    {
+        DWORD exitcode;
+        if (GetExitCodeProcess( info->hProcess, &exitcode )) SetLastError( exitcode );
+        CloseHandle( info->hThread );
+        CloseHandle( info->hProcess );
+        ret = FALSE;
     }
     CloseHandle( process_info );
-    if (!ret) return FALSE;
-
-    /* Wait until process is initialized (or initialization failed) */
-    if (load_done_evt)
-    {
-        DWORD res;
-        HANDLE handles[2];
-
-        handles[0] = info->hProcess;
-        handles[1] = load_done_evt;
-        res = WaitForMultipleObjects( 2, handles, FALSE, INFINITE );
-        CloseHandle( load_done_evt );
-        if (res == STATUS_WAIT_0)  /* the process died */
-        {
-            DWORD exitcode;
-            if (GetExitCodeProcess( info->hProcess, &exitcode )) SetLastError( exitcode );
-            CloseHandle( info->hThread );
-            CloseHandle( info->hProcess );
-            return FALSE;
-        }
-    }
-    return TRUE;
+    return ret;
 }
 
 
diff --git a/server/debugger.c b/server/debugger.c
index fa2c080..dcf7e0f 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -427,7 +427,7 @@
     struct thread *thread;
 
     if (process->debugger) goto error;  /* already being debugged */
-    if (process->init_event) goto error;  /* still starting up */
+    if (!is_process_init_done( process )) goto error;  /* still starting up */
     if (!process->thread_list) goto error;  /* no thread running in the process */
 
     /* make sure we don't create a debugging loop */
@@ -470,7 +470,7 @@
         goto error;  /* not currently debugged, or debugged by another debugger */
     if (!debugger->debug_ctx ) goto error; /* should be a debugger */
     /* init should be done, otherwise wouldn't be attached */
-    assert(!process->init_event);
+    assert(is_process_init_done(process));
 
     suspend_process( process );
     /* send continue indication for all events */
diff --git a/server/process.c b/server/process.c
index 55cd67e..9368a81 100644
--- a/server/process.c
+++ b/server/process.c
@@ -74,9 +74,12 @@
 
 /* process startup info */
 
+enum startup_state { STARTUP_IN_PROGRESS, STARTUP_DONE, STARTUP_ABORTED };
+
 struct startup_info
 {
     struct object       obj;          /* object header */
+    enum startup_state  state;        /* child process startup state */
     int                 inherit_all;  /* inherit all handles from parent */
     int                 use_handles;  /* use stdio handles */
     int                 create_flags; /* creation flags */
@@ -113,6 +116,16 @@
 };
 
 
+/* set the state of the process startup info */
+static void set_process_startup_state( struct process *process, enum startup_state state )
+{
+    if (!process->startup_info) return;
+    process->startup_info->state = state;
+    wake_up( &process->startup_info->obj, 0 );
+    release_object( process->startup_info );
+    process->startup_info = NULL;
+}
+
 /* set the console and stdio handles for a newly created process */
 static int set_process_console( struct process *process, struct thread *parent_thread,
                                 struct startup_info *info, struct init_process_reply *reply )
@@ -122,7 +135,7 @@
         /* let the process init do the allocation */
         return 1;
     }
-    else if (parent_thread && !(process->create_flags & DETACHED_PROCESS))
+    else if (info && !(process->create_flags & DETACHED_PROCESS))
     {
         /* FIXME: some better error checking should be done...
          * like if hConOut and hConIn are console handles, then they should be on the same
@@ -131,7 +144,7 @@
         inherit_console( parent_thread, process,
                          (info->inherit_all || info->use_handles) ? info->hstdin : 0 );
     }
-    if (parent_thread)
+    if (info)
     {
         if (!info->inherit_all && !info->use_handles)
         {
@@ -193,7 +206,7 @@
     process->suspend         = 0;
     process->create_flags    = 0;
     process->console         = NULL;
-    process->init_event      = NULL;
+    process->startup_info    = NULL;
     process->idle_event      = NULL;
     process->queue           = NULL;
     process->atom_table      = NULL;
@@ -201,6 +214,7 @@
     process->exe.next        = NULL;
     process->exe.prev        = NULL;
     process->exe.file        = NULL;
+    process->exe.base        = NULL;
     process->exe.dbg_offset  = 0;
     process->exe.dbg_size    = 0;
     process->exe.namelen     = 0;
@@ -210,9 +224,6 @@
     if ((process->next = first_process) != NULL) process->next->prev = process;
     first_process = process;
 
-    /* create the init done event */
-    if (!(process->init_event = create_event( NULL, 0, 1, 0 ))) goto error;
-
     /* create the main thread */
     if (pipe( request_pipe ) == -1)
     {
@@ -245,12 +256,7 @@
     {
         parent = parent_thread->process;
         info = parent_thread->info;
-        if (!info)
-        {
-            fatal_protocol_error( current, "init_process: parent but no info\n" );
-            return NULL;
-        }
-        if (info->thread)
+        if (info && info->thread)
         {
             fatal_protocol_error( current, "init_process: called twice?\n" );
             return NULL;
@@ -262,7 +268,7 @@
     process->create_flags = info ? info->create_flags : 0;
 
     /* create the handle table */
-    if (parent && info->inherit_all)
+    if (info && info->inherit_all)
         process->handles = copy_handle_table( process, parent );
     else
         process->handles = alloc_handle_table( process, 0 );
@@ -270,7 +276,7 @@
 
     /* retrieve the main exe file */
     reply->exe_file = 0;
-    if (parent && info->exe_file)
+    if (info && info->exe_file)
     {
         process->exe.file = (struct file *)grab_object( info->exe_file );
         if (!(reply->exe_file = alloc_handle( process, process->exe.file, GENERIC_READ, 0 )))
@@ -285,7 +291,7 @@
         /* 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 && parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS))
+        else if (parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS))
             set_process_debugger( process, parent->debugger );
     }
 
@@ -297,7 +303,6 @@
         reply->info_size = info->data_size;
         info->process = (struct process *)grab_object( process );
         info->thread  = (struct thread *)grab_object( current );
-        wake_up( &info->obj, 0 );
     }
     reply->create_flags = process->create_flags;
     reply->server_start = server_start_ticks;
@@ -312,12 +317,13 @@
 
     /* we can't have a thread remaining */
     assert( !process->thread_list );
+
+    set_process_startup_state( process, STARTUP_ABORTED );
     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;
-    if (process->init_event) release_object( process->init_event );
     if (process->idle_event) release_object( process->idle_event );
     if (process->queue) release_object( process->queue );
     if (process->atom_table) release_object( process->atom_table );
@@ -371,17 +377,16 @@
     struct startup_info *info = (struct startup_info *)obj;
     assert( obj->ops == &startup_info_ops );
 
-    fprintf( stderr, "Startup info flags=%x in=%d out=%d err=%d\n",
-             info->create_flags, info->hstdin, info->hstdout, info->hstderr );
+    fprintf( stderr, "Startup info flags=%x in=%d out=%d err=%d state=%d\n",
+             info->create_flags, info->hstdin, info->hstdout, info->hstderr, info->state );
 }
 
 static int startup_info_signaled( struct object *obj, struct thread *thread )
 {
     struct startup_info *info = (struct startup_info *)obj;
-    return (info->thread != NULL);
+    return info->state != STARTUP_IN_PROGRESS;
 }
 
-
 /* get a process from an id (and increment the refcount) */
 struct process *get_process_from_id( void *id )
 {
@@ -490,6 +495,7 @@
         if (dll->filename) free( dll->filename );
         free( dll );
     }
+    set_process_startup_state( process, STARTUP_ABORTED );
     if (process->exe.file) release_object( process->exe.file );
     process->exe.file = NULL;
     wake_up( &process->obj, 0 );
@@ -776,6 +782,7 @@
 
     /* build the startup info for a new process */
     if (!(info = alloc_object( &startup_info_ops, -1 ))) return;
+    info->state        = STARTUP_IN_PROGRESS;
     info->inherit_all  = req->inherit_all;
     info->use_handles  = req->use_handles;
     info->create_flags = req->create_flags;
@@ -807,8 +814,6 @@
 {
     struct startup_info *info;
 
-    reply->event = 0;
-
     if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
                                                        0, &startup_info_ops )))
     {
@@ -818,9 +823,7 @@
                                        PROCESS_ALL_ACCESS, req->pinherit );
         reply->thandle = alloc_handle( current->process, info->thread,
                                        THREAD_ALL_ACCESS, req->tinherit );
-        if (info->process->init_event)
-            reply->event = alloc_handle( current->process, info->process->init_event,
-                                       EVENT_ALL_ACCESS, 0 );
+        reply->success = (info->state == STARTUP_DONE);
         release_object( info );
     }
     else
@@ -829,6 +832,7 @@
         reply->tid     = 0;
         reply->phandle = 0;
         reply->thandle = 0;
+        reply->success = 0;
     }
 }
 
@@ -837,19 +841,15 @@
 {
     struct startup_info *info;
 
-    if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
-                                                       0, &startup_info_ops )))
+    if ((info = current->process->startup_info))
     {
         size_t size = info->data_size;
         if (size > get_reply_max_size()) size = get_reply_max_size();
-        if (req->close)
-        {
-            set_reply_data_ptr( info->data, size );
-            info->data = NULL;
-            close_handle( current->process, req->info, NULL );
-        }
-        else set_reply_data( info->data, size );
-        release_object( info );
+
+        /* we return the data directly without making a copy so this can only be called once */
+        set_reply_data_ptr( info->data, size );
+        info->data = NULL;
+        info->data_size = 0;
     }
 }
 
@@ -857,21 +857,19 @@
 /* initialize a new process */
 DECL_HANDLER(init_process)
 {
-    struct startup_info *info;
-
-    reply->info = 0;
-    reply->info_size = 0;
     if (!current->unix_pid)
     {
         fatal_protocol_error( current, "init_process: init_thread not called yet\n" );
         return;
     }
-    current->process->ldt_copy  = req->ldt_copy;
-    if ((info = init_process( req->ppid, reply )))
+    if (current->process->startup_info)
     {
-        reply->info = alloc_handle( current->process, info, 0, FALSE );
-        release_object( info );
+        fatal_protocol_error( current, "init_process: called twice\n" );
+        return;
     }
+    reply->info_size = 0;
+    current->process->ldt_copy = req->ldt_copy;
+    current->process->startup_info = init_process( req->ppid, reply );
 }
 
 /* signal the end of the process initialization */
@@ -880,9 +878,14 @@
     struct file *file = NULL;
     struct process *process = current->process;
 
-    if (!process->init_event)
+    if (is_process_init_done(process))
     {
-        fatal_protocol_error( current, "init_process_done: no event\n" );
+        fatal_protocol_error( current, "init_process_done: called twice\n" );
+        return;
+    }
+    if (!req->module)
+    {
+        fatal_protocol_error( current, "init_process_done: module base address cannot be 0\n" );
         return;
     }
     process->exe.base = req->module;
@@ -896,10 +899,9 @@
     if ((process->exe.namelen = get_req_data_size()))
         process->exe.filename = memdup( get_req_data(), process->exe.namelen );
 
-    generate_startup_debug_events( current->process, req->entry );
-    set_event( process->init_event );
-    release_object( process->init_event );
-    process->init_event = NULL;
+    generate_startup_debug_events( process, req->entry );
+    set_process_startup_state( process, STARTUP_DONE );
+
     if (req->gui) process->idle_event = create_event( NULL, 0, 1, 0 );
     if (current->suspend + current->process->suspend > 0) stop_thread( current );
     reply->debugged = (current->process->debugger != 0);
@@ -1018,7 +1020,7 @@
         dll->dbg_size   = req->dbg_size;
         dll->name       = req->name;
         /* only generate event if initialization is done */
-        if (!current->process->init_event)
+        if (is_process_init_done( current->process ))
             generate_debug_event( current, LOAD_DLL_DEBUG_EVENT, dll );
     }
     if (file) release_object( file );
diff --git a/server/process.h b/server/process.h
index 3e84c09..81a18e2 100644
--- a/server/process.h
+++ b/server/process.h
@@ -25,6 +25,7 @@
 
 struct msg_queue;
 struct atom_table;
+struct startup_info;
 
 /* process structures */
 
@@ -60,7 +61,7 @@
     int                  suspend;         /* global process suspend count */
     int                  create_flags;    /* process creation flags */
     struct console_input*console;         /* console input */
-    struct event        *init_event;      /* event for init done */
+    struct startup_info *startup_info;    /* startup info while init is in progress */
     struct event        *idle_event;      /* event for input idle */
     struct msg_queue    *queue;           /* main message queue */
     struct atom_table   *atom_table;      /* pointer to local atom table */
@@ -106,6 +107,7 @@
 extern struct process_snapshot *process_snap( int *count );
 extern struct module_snapshot *module_snap( struct process *process, int *count );
 
-static inline void *get_process_id( struct process *process ) { return process; }
+inline static void *get_process_id( struct process *process ) { return process; }
+inline static int is_process_init_done( struct process *process ) { return process->exe.base != 0; }
 
 #endif  /* __WINE_SERVER_PROCESS_H */
diff --git a/server/protocol.def b/server/protocol.def
index e1d49c3..7222b7e 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -220,7 +220,7 @@
     handle_t     phandle;      /* process handle (in the current process) */
     void*        tid;          /* thread id */
     handle_t     thandle;      /* thread handle (in the current process) */
-    handle_t     event;        /* event handle to signal startup */
+    int          success;      /* did the process start successfully? */
 @END
 
 
@@ -248,7 +248,6 @@
 @REPLY
     int          create_flags; /* creation flags */
     unsigned int server_start; /* server start time (GetTickCount) */
-    handle_t     info;         /* handle to startup info */
     size_t       info_size;    /* total size of startup info */
     handle_t     exe_file;     /* file handle for main exe */
     handle_t     hstdin;       /* handle for stdin */
@@ -259,8 +258,6 @@
 
 /* Retrieve the new process startup info */
 @REQ(get_startup_info)
-    handle_t     info;         /* handle to startup info */
-    int          close;        /* should we close the handle at the same time? */
 @REPLY
     VARARG(info,startup_info); /* startup information */
 @END
diff --git a/server/ptrace.c b/server/ptrace.c
index b66f02a..7aa0c88 100644
--- a/server/ptrace.c
+++ b/server/ptrace.c
@@ -177,7 +177,7 @@
 void stop_thread( struct thread *thread )
 {
     /* can't stop a thread while initialisation is in progress */
-    if (!thread->unix_pid || thread->process->init_event) return;
+    if (!thread->unix_pid || !is_process_init_done(thread->process)) return;
     /* first try to attach to it */
     if (!thread->attached)
         if (attach_thread( thread )) return;  /* this will have stopped it */
@@ -206,7 +206,7 @@
         return 1;
     }
     /* can't stop a thread while initialisation is in progress */
-    if (!thread->unix_pid || thread->process->init_event) goto error;
+    if (!thread->unix_pid || !is_process_init_done(thread->process)) goto error;
     thread->suspend++;
     if (attach_thread( thread )) return 1;
     thread->suspend--;
diff --git a/server/trace.c b/server/trace.c
index d957856..f610d04 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -376,7 +376,7 @@
     fprintf( stderr, " phandle=%d,", req->phandle );
     fprintf( stderr, " tid=%p,", req->tid );
     fprintf( stderr, " thandle=%d,", req->thandle );
-    fprintf( stderr, " event=%d", req->event );
+    fprintf( stderr, " success=%d", req->success );
 }
 
 static void dump_new_thread_request( const struct new_thread_request *req )
@@ -407,7 +407,6 @@
 {
     fprintf( stderr, " create_flags=%d,", req->create_flags );
     fprintf( stderr, " server_start=%08x,", req->server_start );
-    fprintf( stderr, " info=%d,", req->info );
     fprintf( stderr, " info_size=%d,", req->info_size );
     fprintf( stderr, " exe_file=%d,", req->exe_file );
     fprintf( stderr, " hstdin=%d,", req->hstdin );
@@ -417,8 +416,6 @@
 
 static void dump_get_startup_info_request( const struct get_startup_info_request *req )
 {
-    fprintf( stderr, " info=%d,", req->info );
-    fprintf( stderr, " close=%d", req->close );
 }
 
 static void dump_get_startup_info_reply( const struct get_startup_info_reply *req )