diff --git a/dlls/ntdll/env.c b/dlls/ntdll/env.c index 92cd3bd0d11..8c9023c313f 100644 --- a/dlls/ntdll/env.c +++ b/dlls/ntdll/env.c @@ -1168,44 +1168,41 @@ wait: */ void init_user_process_params(void) { - WCHAR *src, *load_path, *dummy; - SIZE_T info_size, env_size, data_size = 0; - startup_info_t *info = NULL; - RTL_USER_PROCESS_PARAMETERS *params = NULL; - UNICODE_STRING curdir, dllpath, imagepath, cmdline, title, desktop, shellinfo, runtime; + WCHAR *env, *load_path, *dummy; + SIZE_T env_size; + RTL_USER_PROCESS_PARAMETERS *new_params, *params = NtCurrentTeb()->Peb->ProcessParameters; + UNICODE_STRING curdir, dllpath, cmdline; WCHAR **wargv; - unix_funcs->get_startup_info( NULL, &data_size, &info_size ); - if (!data_size) + if (!params->DllPath.MaximumLength) /* not inherited from parent process */ { - RTL_USER_PROCESS_PARAMETERS initial_params = {0}; - WCHAR *env, curdir_buffer[MAX_PATH]; + WCHAR curdir_buffer[MAX_PATH]; - NtCurrentTeb()->Peb->ProcessParameters = &initial_params; - initial_params.Environment = build_initial_environment( &wargv ); + params->Environment = build_initial_environment( &wargv ); curdir.Buffer = curdir_buffer; curdir.MaximumLength = sizeof(curdir_buffer); get_current_directory( &curdir ); - initial_params.CurrentDirectory.DosPath = curdir; - get_image_path( wargv[0], &initial_params.ImagePathName ); - wargv[0] = initial_params.ImagePathName.Buffer; + params->CurrentDirectory.DosPath = curdir; + get_image_path( wargv[0], ¶ms->ImagePathName ); + wargv[0] = params->ImagePathName.Buffer; build_command_line( wargv, &cmdline ); - LdrGetDllPath( initial_params.ImagePathName.Buffer, 0, &load_path, &dummy ); + LdrGetDllPath( params->ImagePathName.Buffer, 0, &load_path, &dummy ); RtlInitUnicodeString( &dllpath, load_path ); - env = initial_params.Environment; - initial_params.Environment = NULL; /* avoid copying it */ - if (RtlCreateProcessParametersEx( ¶ms, &initial_params.ImagePathName, &dllpath, &curdir, - &cmdline, NULL, &initial_params.ImagePathName, NULL, NULL, NULL, + env = params->Environment; + params->Environment = NULL; /* avoid copying it */ + if (RtlCreateProcessParametersEx( &new_params, ¶ms->ImagePathName, &dllpath, &curdir, + &cmdline, NULL, ¶ms->ImagePathName, NULL, NULL, NULL, PROCESS_PARAMS_FLAG_NORMALIZED )) return; - params->Environment = env; - NtCurrentTeb()->Peb->ProcessParameters = params; - RtlFreeUnicodeString( &initial_params.ImagePathName ); + new_params->Environment = env; + NtCurrentTeb()->Peb->ProcessParameters = new_params; + RtlFreeUnicodeString( ¶ms->ImagePathName ); RtlFreeUnicodeString( &cmdline ); RtlReleasePath( load_path ); + params = new_params; unix_funcs->get_initial_console( params ); params->wShowWindow = 1; /* SW_SHOWNORMAL */ @@ -1213,54 +1210,16 @@ void init_user_process_params(void) goto done; } - if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, data_size ))) return; - - if (unix_funcs->get_startup_info( info, &data_size, &info_size )) goto done; - - src = (WCHAR *)(info + 1); - get_unicode_string( &curdir, &src, info->curdir_len ); - get_unicode_string( &dllpath, &src, info->dllpath_len ); - get_unicode_string( &imagepath, &src, info->imagepath_len ); - get_unicode_string( &cmdline, &src, info->cmdline_len ); - get_unicode_string( &title, &src, info->title_len ); - get_unicode_string( &desktop, &src, info->desktop_len ); - get_unicode_string( &shellinfo, &src, info->shellinfo_len ); - get_unicode_string( &runtime, &src, info->runtime_len ); - - runtime.MaximumLength = runtime.Length; /* runtime info isn't a real string */ - - if (RtlCreateProcessParametersEx( ¶ms, &imagepath, &dllpath, &curdir, &cmdline, NULL, - &title, &desktop, &shellinfo, &runtime, - PROCESS_PARAMS_FLAG_NORMALIZED )) - goto done; - - NtCurrentTeb()->Peb->ProcessParameters = params; - params->DebugFlags = info->debug_flags; - params->ConsoleHandle = wine_server_ptr_handle( info->console ); - params->ConsoleFlags = info->console_flags; - params->hStdInput = wine_server_ptr_handle( info->hstdin ); - params->hStdOutput = wine_server_ptr_handle( info->hstdout ); - params->hStdError = wine_server_ptr_handle( info->hstderr ); - params->dwX = info->x; - params->dwY = info->y; - params->dwXSize = info->xsize; - params->dwYSize = info->ysize; - params->dwXCountChars = info->xchars; - params->dwYCountChars = info->ychars; - params->dwFillAttribute = info->attribute; - params->dwFlags = info->flags; - params->wShowWindow = info->show; - /* environment needs to be a separate memory block */ - env_size = data_size - info_size; - if ((params->Environment = RtlAllocateHeap( GetProcessHeap(), 0, max( env_size, sizeof(WCHAR) )))) + env_size = params->EnvironmentSize; + if ((env = RtlAllocateHeap( GetProcessHeap(), 0, max( env_size, sizeof(WCHAR) )))) { - if (env_size) memcpy( params->Environment, (char *)info + info_size, env_size ); - else params->Environment[0] = 0; + if (env_size) memcpy( env, params->Environment, env_size ); + else env[0] = 0; + params->Environment = env; } done: - RtlFreeHeap( GetProcessHeap(), 0, info ); if (RtlSetCurrentDirectory_U( ¶ms->CurrentDirectory.DosPath )) { MESSAGE("wine: could not open working directory %s, starting in the Windows directory.\n", diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c index cb2915c1a35..b7d0a0db05b 100644 --- a/dlls/ntdll/unix/env.c +++ b/dlls/ntdll/unix/env.c @@ -1163,32 +1163,6 @@ static void add_path_var( WCHAR *env, SIZE_T *pos, const char *name, const char } -/************************************************************************* - * get_startup_info - * - * Get the startup information from the server. - */ -NTSTATUS CDECL get_startup_info( startup_info_t *info, SIZE_T *total_size, SIZE_T *info_size ) -{ - NTSTATUS status; - - if (*total_size < startup_info_size) - { - *total_size = startup_info_size; - return STATUS_BUFFER_TOO_SMALL; - } - SERVER_START_REQ( get_startup_info ) - { - wine_server_set_reply( req, info, *total_size ); - status = wine_server_call( req ); - *total_size = wine_server_reply_size( reply ); - *info_size = reply->info_size; - } - SERVER_END_REQ; - return status; -} - - /************************************************************************* * get_dynamic_environment * @@ -1375,6 +1349,130 @@ void CDECL get_locales( WCHAR *sys, WCHAR *user ) } +static inline void copy_unicode_string( WCHAR **src, WCHAR **dst, UNICODE_STRING *str, UINT len ) +{ + str->Buffer = *dst; + str->Length = len; + str->MaximumLength = len + sizeof(WCHAR); + memcpy( *dst, *src, len ); + (*dst)[len / sizeof(WCHAR)] = 0; + *src += len / sizeof(WCHAR); + *dst += len / sizeof(WCHAR) + 1; +} + + +/************************************************************************* + * build_initial_params + * + * Build process parameters from scratch, for processes without a parent. + */ +static RTL_USER_PROCESS_PARAMETERS *build_initial_params(void) +{ + RTL_USER_PROCESS_PARAMETERS *params = NULL; + SIZE_T size; + NTSTATUS status; + + size = sizeof(*params); + + status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)¶ms, 0, &size, + MEM_COMMIT, PAGE_READWRITE ); + assert( !status ); + + params->AllocationSize = size; + params->Size = size; + params->Flags = PROCESS_PARAMS_FLAG_NORMALIZED; + params->wShowWindow = 1; /* SW_SHOWNORMAL */ + return params; +} + + +/************************************************************************* + * init_startup_info + */ +void init_startup_info(void) +{ + WCHAR *src, *dst; + NTSTATUS status; + SIZE_T size, info_size, env_size; + RTL_USER_PROCESS_PARAMETERS *params = NULL; + startup_info_t *info; + + if (!startup_info_size) + { + NtCurrentTeb()->Peb->ProcessParameters = build_initial_params(); + return; + } + + info = malloc( startup_info_size ); + + SERVER_START_REQ( get_startup_info ) + { + wine_server_set_reply( req, info, startup_info_size ); + status = wine_server_call( req ); + info_size = reply->info_size; + env_size = wine_server_reply_size( reply ) - info_size; + } + SERVER_END_REQ; + assert( !status ); + + size = (sizeof(*params) + + MAX_PATH * sizeof(WCHAR) /* curdir */ + + info->dllpath_len + sizeof(WCHAR) + + info->imagepath_len + sizeof(WCHAR) + + info->cmdline_len + sizeof(WCHAR) + + info->title_len + sizeof(WCHAR) + + info->desktop_len + sizeof(WCHAR) + + info->shellinfo_len + sizeof(WCHAR) + + info->runtime_len + sizeof(WCHAR) + + env_size); + + status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)¶ms, 0, &size, + MEM_COMMIT, PAGE_READWRITE ); + assert( !status ); + + params->AllocationSize = size; + params->Size = size; + params->Flags = PROCESS_PARAMS_FLAG_NORMALIZED; + params->EnvironmentSize = env_size; + params->DebugFlags = info->debug_flags; + params->ConsoleHandle = wine_server_ptr_handle( info->console ); + params->ConsoleFlags = info->console_flags; + params->hStdInput = wine_server_ptr_handle( info->hstdin ); + params->hStdOutput = wine_server_ptr_handle( info->hstdout ); + params->hStdError = wine_server_ptr_handle( info->hstderr ); + params->dwX = info->x; + params->dwY = info->y; + params->dwXSize = info->xsize; + params->dwYSize = info->ysize; + params->dwXCountChars = info->xchars; + params->dwYCountChars = info->ychars; + params->dwFillAttribute = info->attribute; + params->dwFlags = info->flags; + params->wShowWindow = info->show; + + src = (WCHAR *)(info + 1); + dst = (WCHAR *)(params + 1); + + /* curdir is special */ + copy_unicode_string( &src, &dst, ¶ms->CurrentDirectory.DosPath, info->curdir_len ); + params->CurrentDirectory.DosPath.MaximumLength = MAX_PATH * sizeof(WCHAR); + dst = params->CurrentDirectory.DosPath.Buffer + MAX_PATH; + + copy_unicode_string( &src, &dst, ¶ms->DllPath, info->dllpath_len ); + copy_unicode_string( &src, &dst, ¶ms->ImagePathName, info->imagepath_len ); + copy_unicode_string( &src, &dst, ¶ms->CommandLine, info->cmdline_len ); + copy_unicode_string( &src, &dst, ¶ms->WindowTitle, info->title_len ); + copy_unicode_string( &src, &dst, ¶ms->Desktop, info->desktop_len ); + copy_unicode_string( &src, &dst, ¶ms->ShellInfo, info->shellinfo_len ); + copy_unicode_string( &src, &dst, ¶ms->RuntimeInfo, info->runtime_len ); + params->RuntimeInfo.MaximumLength = params->RuntimeInfo.Length; /* runtime info isn't a real string */ + params->Environment = dst; + memcpy( dst, src, env_size ); + free( info ); + NtCurrentTeb()->Peb->ProcessParameters = params; +} + + /************************************************************************** * NtGetNlsSectionPtr (NTDLL.@) */ diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index b82bc10485b..ceb447eb907 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1608,7 +1608,6 @@ static struct unix_funcs unix_funcs = ntdll_sqrt, ntdll_tan, get_initial_environment, - get_startup_info, get_dynamic_environment, get_initial_console, get_initial_directory, @@ -1644,6 +1643,7 @@ static void start_main_thread(void) virtual_map_user_shared_data(); init_cpu_info(); init_files(); + init_startup_info(); NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 ); load_ntdll(); load_libwine(); diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index af8a14a8c65..299519691bd 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -100,7 +100,6 @@ extern NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL get_initial_environment( WCHAR **wargv[], WCHAR *env, SIZE_T *size ) DECLSPEC_HIDDEN; -extern NTSTATUS CDECL get_startup_info( startup_info_t *info, SIZE_T *total_size, SIZE_T *info_size ) DECLSPEC_HIDDEN; extern NTSTATUS CDECL get_dynamic_environment( WCHAR *env, SIZE_T *size ) DECLSPEC_HIDDEN; extern void CDECL get_initial_directory( UNICODE_STRING *dir ) DECLSPEC_HIDDEN; extern void CDECL get_initial_console( RTL_USER_PROCESS_PARAMETERS *params ) DECLSPEC_HIDDEN; @@ -138,6 +137,7 @@ extern struct ldt_copy __wine_ldt_copy DECLSPEC_HIDDEN; #endif extern void init_environment( int argc, char *argv[], char *envp[] ) DECLSPEC_HIDDEN; +extern void init_startup_info(void) DECLSPEC_HIDDEN; extern DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD dstlen ) DECLSPEC_HIDDEN; extern int ntdll_wcstoumbs( const WCHAR *src, DWORD srclen, char *dst, DWORD dstlen, BOOL strict ) DECLSPEC_HIDDEN; extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index ed78d08559a..1b344cdc11e 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -27,7 +27,7 @@ struct _DISPATCHER_CONTEXT; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 108 +#define NTDLL_UNIXLIB_VERSION 109 struct unix_funcs { @@ -72,7 +72,6 @@ struct unix_funcs /* environment functions */ NTSTATUS (CDECL *get_initial_environment)( WCHAR **wargv[], WCHAR *env, SIZE_T *size ); - NTSTATUS (CDECL *get_startup_info)( startup_info_t *info, SIZE_T *total_size, SIZE_T *info_size ); NTSTATUS (CDECL *get_dynamic_environment)( WCHAR *env, SIZE_T *size ); void (CDECL *get_initial_console)( RTL_USER_PROCESS_PARAMETERS *params ); void (CDECL *get_initial_directory)( UNICODE_STRING *dir );