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/dlls/kernel/process.c b/dlls/kernel/process.c
index 911cf51..ec92bb1 100644
--- a/dlls/kernel/process.c
+++ b/dlls/kernel/process.c
@@ -31,6 +31,12 @@
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
#ifdef HAVE_SYS_PRCTL_H
# include <sys/prctl.h>
#endif
@@ -1104,6 +1110,7 @@
{
if (*p == '=') continue; /* skip drive curdirs, this crashes some unix apps */
if (!strncmp( p, "WINEPRELOADRESERVE=", sizeof("WINEPRELOADRESERVE=")-1 )) continue;
+ if (!strncmp( p, "WINESERVERSOCKET=", sizeof("WINESERVERSOCKET=")-1 )) continue;
if (is_special_env_var( p )) /* prefix it with "WINE" */
*envptr++ = alloc_env_string( "WINE", p );
else
@@ -1210,9 +1217,18 @@
if (flags & CREATE_NEW_PROCESS_GROUP) params->ConsoleFlags = 1;
if (flags & CREATE_NEW_CONSOLE) params->ConsoleHandle = (HANDLE)1; /* FIXME: cf. kernel_main.c */
- params->hStdInput = startup->hStdInput;
- params->hStdOutput = startup->hStdOutput;
- params->hStdError = startup->hStdError;
+ if (startup->dwFlags & STARTF_USESTDHANDLES)
+ {
+ params->hStdInput = startup->hStdInput;
+ params->hStdOutput = startup->hStdOutput;
+ params->hStdError = startup->hStdError;
+ }
+ else
+ {
+ params->hStdInput = GetStdHandle( STD_INPUT_HANDLE );
+ params->hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE );
+ params->hStdError = GetStdHandle( STD_ERROR_HANDLE );
+ }
params->dwX = startup->dwX;
params->dwY = startup->dwY;
params->dwXSize = startup->dwXSize;
@@ -1243,12 +1259,9 @@
WCHAR *env_end;
char *winedebug = NULL;
RTL_USER_PROCESS_PARAMETERS *params;
- int startfd[2];
- int execfd[2];
+ int socketfd[2];
pid_t pid;
int err;
- char dummy = 0;
- char preloader_reserve[64];
if (!env) RtlAcquirePebLock();
@@ -1271,96 +1284,34 @@
}
env_end++;
- sprintf( preloader_reserve, "WINEPRELOADRESERVE=%lx-%lx%c",
- (unsigned long)res_start, (unsigned long)res_end, 0 );
+ /* create the socket for the new process */
- /* create the synchronization pipes */
-
- if (pipe( startfd ) == -1)
+ if (socketpair( PF_UNIX, SOCK_STREAM, 0, socketfd ) == -1)
{
if (!env) RtlReleasePebLock();
HeapFree( GetProcessHeap(), 0, winedebug );
+ RtlDestroyProcessParameters( params );
SetLastError( ERROR_TOO_MANY_OPEN_FILES );
- RtlDestroyProcessParameters( params );
return FALSE;
}
- if (pipe( execfd ) == -1)
- {
- if (!env) RtlReleasePebLock();
- HeapFree( GetProcessHeap(), 0, winedebug );
- SetLastError( ERROR_TOO_MANY_OPEN_FILES );
- close( startfd[0] );
- close( startfd[1] );
- RtlDestroyProcessParameters( params );
- return FALSE;
- }
- fcntl( execfd[1], F_SETFD, 1 ); /* set close on exec */
-
- /* create the child process */
-
- if (!(pid = fork())) /* child */
- {
- char **argv = build_argv( cmd_line, 1 );
-
- close( startfd[1] );
- close( execfd[0] );
-
- /* wait for parent to tell us to start */
- if (read( startfd[0], &dummy, 1 ) != 1) _exit(1);
-
- close( startfd[0] );
- if (flags & (CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE | DETACHED_PROCESS)) setsid();
-
- /* Reset signals that we previously set to SIG_IGN */
- signal( SIGPIPE, SIG_DFL );
- signal( SIGCHLD, SIG_DFL );
-
- putenv( preloader_reserve );
- if (winedebug) putenv( winedebug );
- if (unixdir) chdir(unixdir);
-
- if (argv) wine_exec_wine_binary( NULL, argv, getenv("WINELOADER") );
-
- err = errno;
- write( execfd[1], &err, sizeof(err) );
- _exit(1);
- }
-
- /* this is the parent */
-
- close( startfd[0] );
- close( execfd[1] );
- HeapFree( GetProcessHeap(), 0, winedebug );
- if (pid == -1)
- {
- if (!env) RtlReleasePebLock();
- close( startfd[1] );
- close( execfd[0] );
- FILE_SetDosError();
- RtlDestroyProcessParameters( params );
- return FALSE;
- }
+ wine_server_send_fd( socketfd[1] );
+ close( socketfd[1] );
/* create the process on the server side */
SERVER_START_REQ( new_process )
{
- req->inherit_all = inherit;
- req->create_flags = flags;
- req->unix_pid = pid;
- req->exe_file = hFile;
- if (startup->dwFlags & STARTF_USESTDHANDLES)
- {
- req->hstdin = startup->hStdInput;
- req->hstdout = startup->hStdOutput;
- req->hstderr = startup->hStdError;
- }
- else
- {
- req->hstdin = GetStdHandle( STD_INPUT_HANDLE );
- req->hstdout = GetStdHandle( STD_OUTPUT_HANDLE );
- req->hstderr = GetStdHandle( STD_ERROR_HANDLE );
- }
+ req->inherit_all = inherit;
+ req->create_flags = flags;
+ req->socket_fd = socketfd[1];
+ req->exe_file = hFile;
+ req->process_access = PROCESS_ALL_ACCESS;
+ req->process_attr = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle) ? OBJ_INHERIT : 0;
+ req->thread_access = THREAD_ALL_ACCESS;
+ req->thread_attr = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle) ? OBJ_INHERIT : 0;
+ req->hstdin = params->hStdInput;
+ req->hstdout = params->hStdOutput;
+ req->hstderr = params->hStdError;
if ((flags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)) != 0)
{
@@ -1378,7 +1329,13 @@
wine_server_add_data( req, params, params->Size );
wine_server_add_data( req, params->Environment, (env_end-params->Environment)*sizeof(WCHAR) );
- ret = !wine_server_call_err( req );
+ 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;
+ }
process_info = reply->info;
}
SERVER_END_REQ;
@@ -1387,57 +1344,74 @@
RtlDestroyProcessParameters( params );
if (!ret)
{
- close( startfd[1] );
- close( execfd[0] );
+ close( socketfd[0] );
+ HeapFree( GetProcessHeap(), 0, winedebug );
return FALSE;
}
- /* tell child to start and wait for it to exec */
+ /* create the child process */
- write( startfd[1], &dummy, 1 );
- close( startfd[1] );
-
- if (read( execfd[0], &err, sizeof(err) ) > 0) /* exec failed */
+ if (!(pid = fork())) /* child */
{
- errno = err;
- FILE_SetDosError();
- close( execfd[0] );
- CloseHandle( process_info );
- return FALSE;
+ char preloader_reserve[64], socket_env[64];
+ char **argv = build_argv( cmd_line, 1 );
+
+ if (flags & (CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE | DETACHED_PROCESS)) setsid();
+
+ /* Reset signals that we previously set to SIG_IGN */
+ signal( SIGPIPE, SIG_DFL );
+ signal( SIGCHLD, SIG_DFL );
+
+ sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd[0] );
+ sprintf( preloader_reserve, "WINEPRELOADRESERVE=%lx-%lx",
+ (unsigned long)res_start, (unsigned long)res_end );
+
+ putenv( preloader_reserve );
+ putenv( socket_env );
+ if (winedebug) putenv( winedebug );
+ if (unixdir) chdir(unixdir);
+
+ if (argv) wine_exec_wine_binary( NULL, argv, getenv("WINELOADER") );
+ _exit(1);
}
- close( execfd[0] );
+
+ /* this is the parent */
+
+ close( socketfd[0] );
+ HeapFree( GetProcessHeap(), 0, winedebug );
+ if (pid == -1)
+ {
+ FILE_SetDosError();
+ goto error;
+ }
/* wait for the new process info to be ready */
WaitForSingleObject( process_info, INFINITE );
SERVER_START_REQ( get_new_process_info )
{
- req->info = process_info;
- req->process_access = PROCESS_ALL_ACCESS;
- req->process_attr = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle) ? OBJ_INHERIT : 0;
- req->thread_access = THREAD_ALL_ACCESS;
- req->thread_attr = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle) ? OBJ_INHERIT : 0;
- 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;
- success = reply->success;
- }
+ req->info = process_info;
+ wine_server_call( req );
+ success = reply->success;
+ err = reply->exit_code;
}
SERVER_END_REQ;
- if (ret && !success) /* new process failed to start */
+ if (!success)
{
- DWORD exitcode;
- if (GetExitCodeProcess( info->hProcess, &exitcode )) SetLastError( exitcode );
- CloseHandle( info->hThread );
- CloseHandle( info->hProcess );
- ret = FALSE;
+ SetLastError( err ? err : ERROR_INTERNAL_ERROR );
+ goto error;
}
CloseHandle( process_info );
- return ret;
+ return success;
+
+error:
+ CloseHandle( process_info );
+ CloseHandle( info->hProcess );
+ CloseHandle( info->hThread );
+ info->hProcess = info->hThread = 0;
+ info->dwProcessId = info->dwThreadId = 0;
+ return FALSE;
}
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index b10a391..a64bdb6 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -843,16 +843,27 @@
void server_init_process(void)
{
obj_handle_t dummy_handle;
- const char *server_dir = wine_get_server_dir();
+ const char *env_socket = getenv( "WINESERVERSOCKET" );
- if (!server_dir) /* this means the config dir doesn't exist */
+ if (env_socket)
{
- create_config_dir();
- server_dir = wine_get_server_dir();
+ fd_socket = atoi( env_socket );
+ if (fcntl( fd_socket, F_SETFD, 1 ) == -1)
+ fatal_perror( "Bad server socket %d", fd_socket );
}
+ else
+ {
+ const char *server_dir = wine_get_server_dir();
- /* connect to the server */
- fd_socket = server_connect( server_dir );
+ if (!server_dir) /* this means the config dir doesn't exist */
+ {
+ create_config_dir();
+ server_dir = wine_get_server_dir();
+ }
+
+ /* connect to the server */
+ fd_socket = server_connect( server_dir );
+ }
/* setup the signal mask */
sigemptyset( &block_set );
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 3c8f487..2755827 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -193,11 +193,15 @@
struct request_header __header;
int inherit_all;
unsigned int create_flags;
- int unix_pid;
+ int socket_fd;
obj_handle_t exe_file;
obj_handle_t hstdin;
obj_handle_t hstdout;
obj_handle_t hstderr;
+ unsigned int process_access;
+ unsigned int process_attr;
+ unsigned int thread_access;
+ unsigned int thread_attr;
/* VARARG(info,startup_info); */
/* VARARG(env,unicode_str); */
};
@@ -205,6 +209,10 @@
{
struct reply_header __header;
obj_handle_t info;
+ process_id_t pid;
+ obj_handle_t phandle;
+ thread_id_t tid;
+ obj_handle_t thandle;
};
@@ -213,19 +221,12 @@
{
struct request_header __header;
obj_handle_t info;
- unsigned int process_access;
- unsigned int process_attr;
- unsigned int thread_access;
- unsigned int thread_attr;
};
struct get_new_process_info_reply
{
struct reply_header __header;
- process_id_t pid;
- obj_handle_t phandle;
- thread_id_t tid;
- obj_handle_t thandle;
int success;
+ int exit_code;
};
@@ -4382,6 +4383,6 @@
struct query_symlink_reply query_symlink_reply;
};
-#define SERVER_PROTOCOL_VERSION 237
+#define SERVER_PROTOCOL_VERSION 238
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
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 )