From ec7bb2391d82386213ba5a2740114188e9467eca Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Fri, 12 Nov 1999 03:35:25 +0000
Subject: [PATCH] Added support for CREATE_SUSPENDED flag in CreateProcess.

---
 include/server.h    |  9 +++++++++
 loader/module.c     |  2 --
 scheduler/process.c | 23 +++++++++--------------
 server/process.c    | 26 +++++++++++++++++++++++++-
 server/process.h    |  1 +
 server/request.h    |  2 ++
 server/thread.c     |  3 ++-
 server/trace.c      |  9 +++++++++
 8 files changed, 57 insertions(+), 18 deletions(-)

diff --git a/include/server.h b/include/server.h
index 653296e6038..2eada6e8909 100644
--- a/include/server.h
+++ b/include/server.h
@@ -33,6 +33,7 @@ struct new_process_request
     IN  int          hstdin;       /* handle for stdin */
     IN  int          hstdout;      /* handle for stdout */
     IN  int          hstderr;      /* handle for stderr */
+    IN  int          event;        /* event to signal startup */
     IN  int          cmd_show;     /* main window show mode */
     IN  void*        env_ptr;      /* pointer to environment (FIXME: hack) */
     OUT void*        pid;          /* process id */
@@ -72,6 +73,13 @@ struct init_process_request
 };
 
 
+/* Signal the end of the process initialization */
+struct init_process_done_request
+{
+    IN  int          dummy;
+};
+
+
 /* Initialize a thread; called from the child after fork()/clone() */
 struct init_thread_request
 {
@@ -808,6 +816,7 @@ enum request
     REQ_NEW_THREAD,
     REQ_SET_DEBUG,
     REQ_INIT_PROCESS,
+    REQ_INIT_PROCESS_DONE,
     REQ_INIT_THREAD,
     REQ_GET_THREAD_BUFFER,
     REQ_TERMINATE_PROCESS,
diff --git a/loader/module.c b/loader/module.c
index be6a9942300..f0173231bba 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -1113,8 +1113,6 @@ BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
 
     /* Warn if unsupported features are used */
 
-    if (dwCreationFlags & CREATE_SUSPENDED)
-        FIXME_(module)("(%s,...): CREATE_SUSPENDED ignored\n", name);
     if (dwCreationFlags & DETACHED_PROCESS)
         FIXME_(module)("(%s,...): DETACHED_PROCESS ignored\n", name);
     if (dwCreationFlags & CREATE_NEW_CONSOLE)
diff --git a/scheduler/process.c b/scheduler/process.c
index b5f3b4e4641..b115863e142 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -446,9 +446,7 @@ void PROCESS_Start(void)
     PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0 );
 
     /* Signal the parent process to continue */
-    SetEvent( pdb->load_done_evt );
-    CloseHandle( pdb->load_done_evt );
-    pdb->load_done_evt = INVALID_HANDLE_VALUE;
+    server_call( REQ_INIT_PROCESS_DONE );
 
     /* Perform Win32 specific process initialization */
     if ( type == PROC_WIN32 )
@@ -523,7 +521,7 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
                      BOOL inherit, DWORD flags, STARTUPINFOA *startup,
                      PROCESS_INFORMATION *info )
 {
-    HANDLE handles[2], load_done_evt = INVALID_HANDLE_VALUE;
+    HANDLE handles[2], load_done_evt = 0;
     DWORD exitcode, size;
     BOOL alloc_stack16;
     int server_thandle;
@@ -534,13 +532,15 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
 
     if (!pdb) return NULL;
     info->hThread = info->hProcess = INVALID_HANDLE_VALUE;
-
+    if (!(load_done_evt = CreateEventA( NULL, TRUE, FALSE, NULL ))) goto error;
+    
     /* Create the process on the server side */
 
     req->inherit      = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
     req->inherit_all  = inherit;
     req->create_flags = flags;
     req->start_flags  = startup->dwFlags;
+    req->event        = load_done_evt;
     if (startup->dwFlags & STARTF_USESTDHANDLES)
     {
         req->hstdin  = startup->hStdInput;
@@ -588,17 +588,12 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
 
     /* Create the main thread */
 
-    if (!(teb = THREAD_Create( pdb, 0L, size, alloc_stack16, tsa, &server_thandle ))) 
-        goto error;
+    if (!(teb = THREAD_Create( pdb, flags & CREATE_SUSPENDED, size,
+                               alloc_stack16, tsa, &server_thandle ))) goto error;
     info->hThread     = server_thandle;
     info->dwThreadId  = (DWORD)teb->tid;
     teb->startup = PROCESS_Start;
 
-    /* Create the load-done event */
-    load_done_evt = CreateEventA( NULL, TRUE, FALSE, NULL );
-    DuplicateHandle( GetCurrentProcess(), load_done_evt,
-                     info->hProcess, &pdb->load_done_evt, 0, TRUE, DUPLICATE_SAME_ACCESS );
-
     /* Pass module to new process (FIXME: hack) */
     pdb->module = pModule->self;
     SYSDEPS_SpawnThread( teb );
@@ -634,12 +629,12 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
     } 
 
     CloseHandle( load_done_evt );
-    load_done_evt = INVALID_HANDLE_VALUE;
+    load_done_evt = 0;
 
     return pdb;
 
 error:
-    if (load_done_evt != INVALID_HANDLE_VALUE) CloseHandle( load_done_evt );
+    if (load_done_evt) CloseHandle( load_done_evt );
     if (info->hThread != INVALID_HANDLE_VALUE) CloseHandle( info->hThread );
     if (info->hProcess != INVALID_HANDLE_VALUE) CloseHandle( info->hProcess );
     PROCESS_FreePDB( pdb );
diff --git a/server/process.c b/server/process.c
index 17fa8cc4c69..f5ce22039f8 100644
--- a/server/process.c
+++ b/server/process.c
@@ -70,6 +70,7 @@ static struct process *create_process( struct process *parent, struct new_proces
     process->suspend         = 0;
     process->console_in      = NULL;
     process->console_out     = NULL;
+    process->init_event      = NULL;
     process->info            = NULL;
     gettimeofday( &process->start_time, NULL );
 
@@ -87,6 +88,13 @@ static struct process *create_process( struct process *parent, struct new_proces
     memcpy( process->info->cmdline, cmd_line, len );
     process->info->cmdline[len] = 0;
 
+    /* get the init done event */
+    if (req->event != -1)
+    {
+        if (!(process->init_event = get_event_obj( parent, req->event, EVENT_MODIFY_STATE )))
+            goto error;
+    }
+
     /* set the process console */
     if (req->create_flags & CREATE_NEW_CONSOLE)
     {
@@ -120,7 +128,6 @@ static struct process *create_process( struct process *parent, struct new_proces
 
  error:
     free_console( process );
-    if (process->info) free( process->info );
     if (process->handles) release_object( process->handles );
     release_object( process );
     return NULL;
@@ -139,6 +146,7 @@ struct process *create_initial_process(void)
     req.hstdin       = -1;
     req.hstdout      = -1;
     req.hstderr      = -1;
+    req.event        = -1;
     req.cmd_show     = 0;
     req.env_ptr      = NULL;
     if ((process = create_process( NULL, &req, "", 1 )))
@@ -165,6 +173,7 @@ static void process_destroy( struct object *obj )
     if (process->prev) process->prev->next = process->next;
     else first_process = process->next;
     if (process->info) free( process->info );
+    if (process->init_event) release_object( process->init_event );
 }
 
 /* dump a process on stdout for debugging purposes */
@@ -369,6 +378,21 @@ DECL_HANDLER(init_process)
     free( info );
 }
 
+/* signal the end of the process initialization */
+DECL_HANDLER(init_process_done)
+{
+    struct process *process = current->process;
+    if (!process->init_event)
+    {
+        fatal_protocol_error( current, "init_process_done: no event\n" );
+        return;
+    }
+    set_event( process->init_event );
+    release_object( process->init_event );
+    process->init_event = NULL;
+    if (current->suspend + current->process->suspend > 0) stop_thread( current );
+}
+
 /* open a handle to a process */
 DECL_HANDLER(open_process)
 {
diff --git a/server/process.h b/server/process.h
index b141dc98772..08edd0b0b60 100644
--- a/server/process.h
+++ b/server/process.h
@@ -34,6 +34,7 @@ struct process
     int                  suspend;         /* global process suspend count */
     struct object       *console_in;      /* console input */
     struct object       *console_out;     /* console output */
+    struct event        *init_event;      /* event for init done */
     struct new_process_request *info;     /* startup info (freed after startup) */
 };
 
diff --git a/server/request.h b/server/request.h
index c111d4dc65e..6ee07e67b6b 100644
--- a/server/request.h
+++ b/server/request.h
@@ -65,6 +65,7 @@ DECL_HANDLER(new_process);
 DECL_HANDLER(new_thread);
 DECL_HANDLER(set_debug);
 DECL_HANDLER(init_process);
+DECL_HANDLER(init_process_done);
 DECL_HANDLER(init_thread);
 DECL_HANDLER(get_thread_buffer);
 DECL_HANDLER(terminate_process);
@@ -142,6 +143,7 @@ static const struct handler {
     { (void(*)())req_new_thread, sizeof(struct new_thread_request) },
     { (void(*)())req_set_debug, sizeof(struct set_debug_request) },
     { (void(*)())req_init_process, sizeof(struct init_process_request) },
+    { (void(*)())req_init_process_done, sizeof(struct init_process_done_request) },
     { (void(*)())req_init_thread, sizeof(struct init_thread_request) },
     { (void(*)())req_get_thread_buffer, sizeof(struct get_thread_buffer_request) },
     { (void(*)())req_terminate_process, sizeof(struct terminate_process_request) },
diff --git a/server/thread.c b/server/thread.c
index 89fd690a5f4..1861fc9ebc0 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -318,7 +318,8 @@ static void detach_thread( struct thread *thread )
 /* stop a thread (at the Unix level) */
 void stop_thread( struct thread *thread )
 {
-    if (!thread->unix_pid) return;
+    /* can't stop a thread while initialisation is in progress */
+    if (!thread->unix_pid || thread->process->init_event) return;
     /* first try to attach to it */
     if (!thread->attached)
         if (attach_thread( thread )) return;  /* this will have stopped it */
diff --git a/server/trace.c b/server/trace.c
index 098b3c22690..1af1367eb32 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -52,6 +52,7 @@ static void dump_new_process_request( struct new_process_request *req )
     fprintf( stderr, " hstdin=%d,", req->hstdin );
     fprintf( stderr, " hstdout=%d,", req->hstdout );
     fprintf( stderr, " hstderr=%d,", req->hstderr );
+    fprintf( stderr, " event=%d,", req->event );
     fprintf( stderr, " cmd_show=%d,", req->cmd_show );
     fprintf( stderr, " env_ptr=%p,", req->env_ptr );
     fprintf( stderr, " cmdline=\"%s\"", req->cmdline );
@@ -96,6 +97,11 @@ static void dump_init_process_reply( struct init_process_request *req )
     fprintf( stderr, " cmdline=\"%s\"", req->cmdline );
 }
 
+static void dump_init_process_done_request( struct init_process_done_request *req )
+{
+    fprintf( stderr, " dummy=%d", req->dummy );
+}
+
 static void dump_init_thread_request( struct init_thread_request *req )
 {
     fprintf( stderr, " unix_pid=%d,", req->unix_pid );
@@ -762,6 +768,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_new_thread_request,
     (dump_func)dump_set_debug_request,
     (dump_func)dump_init_process_request,
+    (dump_func)dump_init_process_done_request,
     (dump_func)dump_init_thread_request,
     (dump_func)dump_get_thread_buffer_request,
     (dump_func)dump_terminate_process_request,
@@ -835,6 +842,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_new_thread_reply,
     (dump_func)0,
     (dump_func)dump_init_process_reply,
+    (dump_func)0,
     (dump_func)dump_init_thread_reply,
     (dump_func)0,
     (dump_func)0,
@@ -908,6 +916,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "new_thread",
     "set_debug",
     "init_process",
+    "init_process_done",
     "init_thread",
     "get_thread_buffer",
     "terminate_process",
-- 
GitLab