From c4ec2108b1bc3580fd9dd8114f507d4f49902b46 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 16 Jul 2004 03:54:35 +0000 Subject: [PATCH] Pass the environment for a child process through the server instead of relying on the Unix environment. --- dlls/kernel/process.c | 99 +++++++++++++++++++++++++----------------- include/wine/server_protocol.h | 4 +- server/protocol.def | 2 + server/trace.c | 6 +++ 4 files changed, 70 insertions(+), 41 deletions(-) diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c index b0cbbcb66d5..e00cae29ab3 100644 --- a/dlls/kernel/process.c +++ b/dlls/kernel/process.c @@ -106,6 +106,7 @@ inline static int contains_path( LPCWSTR name ) inline static int is_special_env_var( const char *var ) { return (!strncmp( var, "PATH=", sizeof("PATH=")-1 ) || + !strncmp( var, "HOME=", sizeof("HOME=")-1 ) || !strncmp( var, "TEMP=", sizeof("TEMP=")-1 ) || !strncmp( var, "TMP=", sizeof("TMP=")-1 )); } @@ -690,13 +691,12 @@ static void usage(void) static RTL_USER_PROCESS_PARAMETERS *init_user_process_params( size_t info_size ) { void *ptr; - DWORD size; - NTSTATUS status; + DWORD size, env_size; RTL_USER_PROCESS_PARAMETERS *params; size = info_size; - if ((status = NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, NULL, &size, - MEM_COMMIT, PAGE_READWRITE )) != STATUS_SUCCESS) + if (NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, NULL, &size, + MEM_COMMIT, PAGE_READWRITE ) != STATUS_SUCCESS) return NULL; SERVER_START_REQ( get_startup_info ) @@ -708,8 +708,8 @@ static RTL_USER_PROCESS_PARAMETERS *init_user_process_params( size_t info_size ) SERVER_END_REQ; params = ptr; - params->Size = info_size; params->AllocationSize = size; + if (params->Size > info_size) params->Size = info_size; /* make sure the strings are valid */ fix_unicode_string( ¶ms->CurrentDirectory.DosPath, (char *)info_size ); @@ -721,6 +721,15 @@ static RTL_USER_PROCESS_PARAMETERS *init_user_process_params( size_t info_size ) fix_unicode_string( ¶ms->ShellInfo, (char *)info_size ); fix_unicode_string( ¶ms->RuntimeInfo, (char *)info_size ); + /* environment needs to be a separate memory block */ + env_size = info_size - params->Size; + if (!env_size) env_size = 1; + if (NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, NULL, &env_size, + MEM_COMMIT, PAGE_READWRITE ) != STATUS_SUCCESS) + return NULL; + memcpy( ptr, (char *)params + params->Size, info_size - params->Size ); + params->Environment = ptr; + return RtlNormalizeProcessParams( params ); } @@ -929,28 +938,30 @@ static BOOL process_init(void) LOCALE_Init(); - /* Copy the parent environment */ - if (!build_initial_environment( __wine_main_environ )) return FALSE; + if (!info_size) + { + /* Copy the parent environment */ + if (!build_initial_environment( __wine_main_environ )) return FALSE; - /* Create device symlinks */ - VOLUME_CreateDevices(); + /* Create device symlinks */ + VOLUME_CreateDevices(); - init_current_directory( ¶ms->CurrentDirectory ); + /* registry initialisation */ + SHELL_LoadRegistry(); - /* registry initialisation */ - SHELL_LoadRegistry(); + /* global boot finished, the rest is process-local */ + SERVER_START_REQ( boot_done ) + { + req->debug_level = TRACE_ON(server); + wine_server_call( req ); + } + SERVER_END_REQ; - /* global boot finished, the rest is process-local */ - SERVER_START_REQ( boot_done ) - { - req->debug_level = TRACE_ON(server); - wine_server_call( req ); + set_registry_environment(); } - SERVER_END_REQ; - - if (!info_size) set_registry_environment(); init_windows_dirs(); + init_current_directory( ¶ms->CurrentDirectory ); return TRUE; } @@ -1260,7 +1271,7 @@ static char *alloc_env_string( const char *name, const char *value ) * * Build the environment of a new child process. */ -static char **build_envp( const WCHAR *envW, char *extra_env ) +static char **build_envp( const WCHAR *envW ) { const WCHAR *end; char **envp; @@ -1273,30 +1284,26 @@ static char **build_envp( const WCHAR *envW, char *extra_env ) if (!(env = malloc( length ))) return NULL; WideCharToMultiByte( CP_UNIXCP, 0, envW, end - envW, env, length, NULL, NULL ); - if (extra_env) for (p = extra_env; *p; p += strlen(p) + 1) count++; count += 4; if ((envp = malloc( count * sizeof(*envp) ))) { char **envptr = envp; - /* first the extra strings */ - if (extra_env) - for (p = extra_env; *p; p += strlen(p) + 1) *envptr++ = alloc_env_string( "", p ); - /* then put PATH, TEMP, TMP, HOME and WINEPREFIX from the unix env */ + /* some variables must not be modified, so we get them directly from the unix env */ if ((p = getenv("PATH"))) *envptr++ = alloc_env_string( "PATH=", p ); if ((p = getenv("TEMP"))) *envptr++ = alloc_env_string( "TEMP=", p ); if ((p = getenv("TMP"))) *envptr++ = alloc_env_string( "TMP=", p ); if ((p = getenv("HOME"))) *envptr++ = alloc_env_string( "HOME=", p ); - if ((p = getenv("WINEPREFIX"))) *envptr++ = alloc_env_string( "WINEPREFIX=", p ); /* now put the Windows environment strings */ for (p = env; *p; p += strlen(p) + 1) { + if (*p == '=') continue; /* skip drive curdirs, this crashes some unix apps */ + if (!strncmp( p, "WINEPRELOADRESERVE=", sizeof("WINEPRELOADRESERVE=")-1 )) continue; if (is_special_env_var( p )) /* prefix it with "WINE" */ *envptr++ = alloc_env_string( "WINE", p ); - else if (strncmp( p, "HOME=", 5 ) && - strncmp( p, "WINEPRELOADRESERVE=", 19 ) && - strncmp( p, "WINEPREFIX=", 11 )) *envptr++ = p; + else + *envptr++ = p; } *envptr = 0; } @@ -1326,7 +1333,7 @@ static int fork_and_exec( const char *filename, const WCHAR *cmdline, if (!(pid = fork())) /* child */ { char **argv = build_argv( cmdline, 0 ); - char **envp = build_envp( env, NULL ); + char **envp = build_envp( env ); close( fd[0] ); /* Reset signals that we previously set to SIG_IGN */ @@ -1356,7 +1363,8 @@ static int fork_and_exec( const char *filename, const WCHAR *cmdline, * create_user_params */ static RTL_USER_PROCESS_PARAMETERS *create_user_params( LPCWSTR filename, LPCWSTR cmdline, - LPCWSTR cur_dir, const STARTUPINFOW *startup ) + LPCWSTR cur_dir, LPWSTR env, + const STARTUPINFOW *startup ) { RTL_USER_PROCESS_PARAMETERS *params; UNICODE_STRING image_str, cmdline_str, curdir_str, desktop, title; @@ -1376,7 +1384,7 @@ static RTL_USER_PROCESS_PARAMETERS *create_user_params( LPCWSTR filename, LPCWST status = RtlCreateProcessParameters( ¶ms, &image_str, NULL, cur_dir ? &curdir_str : NULL, - &cmdline_str, NULL, + &cmdline_str, env, startup->lpTitle ? &title : NULL, startup->lpDesktop ? &desktop : NULL, NULL, NULL ); @@ -1386,7 +1394,6 @@ static RTL_USER_PROCESS_PARAMETERS *create_user_params( LPCWSTR filename, LPCWST return NULL; } - params->Environment = NULL; /* we pass it through the Unix environment */ params->hStdInput = startup->hStdInput; params->hStdOutput = startup->hStdOutput; params->hStdError = startup->hStdError; @@ -1417,6 +1424,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW { BOOL ret, success = FALSE; HANDLE process_info; + WCHAR *env_end; RTL_USER_PROCESS_PARAMETERS *params; int startfd[2]; int execfd[2]; @@ -1425,10 +1433,16 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW char dummy = 0; char preloader_reserve[64]; - if (!env) env = GetEnvironmentStringsW(); + if (!env) RtlAcquirePebLock(); - if (!(params = create_user_params( filename, cmd_line, cur_dir, startup ))) + if (!(params = create_user_params( filename, cmd_line, cur_dir, env, startup ))) + { + if (!env) RtlReleasePebLock(); return FALSE; + } + env_end = params->Environment; + while (*env_end) env_end += strlenW(env_end) + 1; + env_end++; sprintf( preloader_reserve, "WINEPRELOADRESERVE=%lx-%lx%c", (unsigned long)res_start, (unsigned long)res_end, 0 ); @@ -1437,12 +1451,14 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW if (pipe( startfd ) == -1) { + if (!env) RtlReleasePebLock(); SetLastError( ERROR_TOO_MANY_OPEN_FILES ); RtlDestroyProcessParameters( params ); return FALSE; } if (pipe( execfd ) == -1) { + if (!env) RtlReleasePebLock(); SetLastError( ERROR_TOO_MANY_OPEN_FILES ); close( startfd[0] ); close( startfd[1] ); @@ -1456,7 +1472,6 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW if (!(pid = fork())) /* child */ { char **argv = build_argv( cmd_line, 1 ); - char **envp = build_envp( env, preloader_reserve ); close( startfd[1] ); close( execfd[0] ); @@ -1469,15 +1484,16 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW signal( SIGPIPE, SIG_DFL ); signal( SIGCHLD, SIG_DFL ); + putenv( preloader_reserve ); if (unixdir) chdir(unixdir); - if (argv && envp) + if (argv) { /* first, try for a WINELOADER environment variable */ const char *loader = getenv("WINELOADER"); - if (loader) wine_exec_wine_binary( loader, argv, envp, TRUE ); + if (loader) wine_exec_wine_binary( loader, argv, NULL, TRUE ); /* now use the standard search strategy */ - wine_exec_wine_binary( NULL, argv, envp, TRUE ); + wine_exec_wine_binary( NULL, argv, NULL, TRUE ); } err = errno; write( execfd[1], &err, sizeof(err) ); @@ -1490,6 +1506,7 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW close( execfd[1] ); if (pid == -1) { + if (!env) RtlReleasePebLock(); close( startfd[1] ); close( execfd[0] ); FILE_SetDosError(); @@ -1533,11 +1550,13 @@ static BOOL create_process( HANDLE hFile, LPCWSTR filename, LPWSTR cmd_line, LPW } 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 ); process_info = reply->info; } SERVER_END_REQ; + if (!env) RtlReleasePebLock(); RtlDestroyProcessParameters( params ); if (!ret) { diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index db99ae39985..7bcfd73bb36 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -177,6 +177,7 @@ struct new_process_request obj_handle_t hstdout; obj_handle_t hstderr; /* VARARG(info,startup_info); */ + /* VARARG(env,unicode_str); */ }; struct new_process_reply { @@ -261,6 +262,7 @@ struct get_startup_info_reply { struct reply_header __header; /* VARARG(info,startup_info); */ + /* VARARG(env,unicode_str); */ }; @@ -3626,6 +3628,6 @@ union generic_reply struct set_global_windows_reply set_global_windows_reply; }; -#define SERVER_PROTOCOL_VERSION 145 +#define SERVER_PROTOCOL_VERSION 146 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 041dc6d0fab..df2bf6850a4 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -191,6 +191,7 @@ typedef struct 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 */ @REPLY obj_handle_t info; /* new process info handle */ @END @@ -246,6 +247,7 @@ typedef struct @REQ(get_startup_info) @REPLY VARARG(info,startup_info); /* startup information */ + VARARG(env,unicode_str); /* environment */ @END diff --git a/server/trace.c b/server/trace.c index 0f293e4d37c..f9445bc2789 100644 --- a/server/trace.c +++ b/server/trace.c @@ -423,6 +423,9 @@ static void dump_new_process_request( const struct new_process_request *req ) fprintf( stderr, " hstderr=%p,", req->hstderr ); fprintf( stderr, " info=" ); dump_varargs_startup_info( cur_size ); + fputc( ',', stderr ); + fprintf( stderr, " env=" ); + dump_varargs_unicode_str( cur_size ); } static void dump_new_process_reply( const struct new_process_reply *req ) @@ -489,6 +492,9 @@ static void dump_get_startup_info_reply( const struct get_startup_info_reply *re { fprintf( stderr, " info=" ); dump_varargs_startup_info( cur_size ); + fputc( ',', stderr ); + fprintf( stderr, " env=" ); + dump_varargs_unicode_str( cur_size ); } static void dump_init_process_done_request( const struct init_process_done_request *req ) -- 2.11.4.GIT