diff --git a/dlls/kernel/process.c b/dlls/kernel/process.c index 8df05af72dd..07851b040e3 100644 --- a/dlls/kernel/process.c +++ b/dlls/kernel/process.c @@ -64,7 +64,6 @@ typedef struct static UINT process_error_mode; -static HANDLE main_exe_file; static DWORD shutdown_flags = 0; static DWORD shutdown_priority = 0x280; static DWORD process_dword; @@ -637,28 +636,6 @@ static BOOL build_command_line( WCHAR **argv ) } -/* make sure the unicode string doesn't point beyond the end pointer */ -static inline void fix_unicode_string( UNICODE_STRING *str, char *end_ptr ) -{ - if ((char *)str->Buffer >= end_ptr) - { - str->Length = str->MaximumLength = 0; - str->Buffer = NULL; - return; - } - if ((char *)str->Buffer + str->MaximumLength > end_ptr) - { - str->MaximumLength = (end_ptr - (char *)str->Buffer) & ~(sizeof(WCHAR) - 1); - } - if (str->Length >= str->MaximumLength) - { - if (str->MaximumLength >= sizeof(WCHAR)) - str->Length = str->MaximumLength - sizeof(WCHAR); - else - str->Length = str->MaximumLength = 0; - } -} - static void version(void) { MESSAGE( "%s\n", PACKAGE_STRING ); @@ -675,87 +652,6 @@ static void usage(void) } -/*********************************************************************** - * init_user_process_params - * - * Fill the RTL_USER_PROCESS_PARAMETERS structure from the server. - */ -static BOOL init_user_process_params( RTL_USER_PROCESS_PARAMETERS *params ) -{ - BOOL ret; - void *ptr; - SIZE_T size, env_size, info_size; - HANDLE hstdin, hstdout, hstderr; - - size = info_size = params->AllocationSize; - if (!size) return TRUE; /* no parameters received from parent */ - - SERVER_START_REQ( get_startup_info ) - { - wine_server_set_reply( req, params, size ); - if ((ret = !wine_server_call( req ))) - { - info_size = wine_server_reply_size( reply ); - main_exe_file = reply->exe_file; - hstdin = reply->hstdin; - hstdout = reply->hstdout; - hstderr = reply->hstderr; - } - } - SERVER_END_REQ; - if (!ret) return ret; - - 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 ); - fix_unicode_string( ¶ms->DllPath, (char *)info_size ); - fix_unicode_string( ¶ms->ImagePathName, (char *)info_size ); - fix_unicode_string( ¶ms->CommandLine, (char *)info_size ); - fix_unicode_string( ¶ms->WindowTitle, (char *)info_size ); - fix_unicode_string( ¶ms->Desktop, (char *)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; - ptr = NULL; - if (NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, 0, &env_size, - MEM_COMMIT, PAGE_READWRITE ) != STATUS_SUCCESS) - return FALSE; - memcpy( ptr, (char *)params + params->Size, info_size - params->Size ); - params->Environment = ptr; - - /* convert value from server: - * + 0 => INVALID_HANDLE_VALUE - * + console handle needs to be mapped - */ - if (!hstdin) - hstdin = INVALID_HANDLE_VALUE; - else if (VerifyConsoleIoHandle(console_handle_map(hstdin))) - hstdin = console_handle_map(hstdin); - - if (!hstdout) - hstdout = INVALID_HANDLE_VALUE; - else if (VerifyConsoleIoHandle(console_handle_map(hstdout))) - hstdout = console_handle_map(hstdout); - - if (!hstderr) - hstderr = INVALID_HANDLE_VALUE; - else if (VerifyConsoleIoHandle(console_handle_map(hstderr))) - hstderr = console_handle_map(hstderr); - - params->hStdInput = hstdin; - params->hStdOutput = hstdout; - params->hStdError = hstderr; - - RtlNormalizeProcessParams( params ); - return TRUE; -} - - /*********************************************************************** * init_current_directory * @@ -878,6 +774,7 @@ static BOOL process_init(void) { static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2',0}; PEB *peb = NtCurrentTeb()->Peb; + RTL_USER_PROCESS_PARAMETERS *params = peb->ProcessParameters; PTHREAD_Init(); @@ -885,13 +782,11 @@ static BOOL process_init(void) setbuf(stderr,NULL); setlocale(LC_CTYPE,""); - if (!init_user_process_params( peb->ProcessParameters )) return FALSE; - kernel32_handle = GetModuleHandleW(kernel32W); LOCALE_Init(); - if (!peb->ProcessParameters->Environment) + if (!params->Environment) { /* Copy the parent environment */ if (!build_initial_environment( __wine_main_environ )) return FALSE; @@ -903,7 +798,26 @@ static BOOL process_init(void) } init_windows_dirs(); - init_current_directory( &peb->ProcessParameters->CurrentDirectory ); + init_current_directory( ¶ms->CurrentDirectory ); + + /* convert value from server: + * + 0 => INVALID_HANDLE_VALUE + * + console handle needs to be mapped + */ + if (!params->hStdInput) + params->hStdInput = INVALID_HANDLE_VALUE; + else if (VerifyConsoleIoHandle(console_handle_map(params->hStdInput))) + params->hStdInput = console_handle_map(params->hStdInput); + + if (!params->hStdOutput) + params->hStdOutput = INVALID_HANDLE_VALUE; + else if (VerifyConsoleIoHandle(console_handle_map(params->hStdOutput))) + params->hStdOutput = console_handle_map(params->hStdOutput); + + if (!params->hStdError) + params->hStdError = INVALID_HANDLE_VALUE; + else if (VerifyConsoleIoHandle(console_handle_map(params->hStdError))) + params->hStdError = console_handle_map(params->hStdError); return TRUE; } @@ -1023,7 +937,7 @@ void __wine_kernel_init(void) !get_builtin_path( exe_nameW, exeW, main_exe_name, MAX_PATH )) { MESSAGE( "wine: cannot find '%s'\n", __wine_main_argv[0] ); - ExitProcess(1); + ExitProcess( GetLastError() ); } } @@ -1031,8 +945,8 @@ void __wine_kernel_init(void) p = strrchrW( main_exe_name, '.' ); if (!p || strchrW( p, '/' ) || strchrW( p, '\\' )) strcatW( main_exe_name, dotW ); - TRACE( "starting process name=%s file=%p argv[0]=%s\n", - debugstr_w(main_exe_name), main_exe_file, debugstr_a(__wine_main_argv[0]) ); + TRACE( "starting process name=%s argv[0]=%s\n", + debugstr_w(main_exe_name), debugstr_a(__wine_main_argv[0]) ); RtlInitUnicodeString( &NtCurrentTeb()->Peb->ProcessParameters->DllPath, MODULE_get_dll_load_path(NULL) ); @@ -1054,14 +968,12 @@ void __wine_kernel_init(void) } } - if (main_exe_file) CloseHandle( main_exe_file ); - if (!module) { char msg[1024]; FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, msg, sizeof(msg), NULL ); MESSAGE( "wine: could not load %s: %s", debugstr_w(main_exe_name), msg ); - ExitProcess(1); + ExitProcess( error ); } peb->ImageBaseAddress = module; diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index aa23017b363..4143bf28cf4 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -85,6 +85,7 @@ struct builtin_load_info static struct builtin_load_info default_load_info; static struct builtin_load_info *builtin_load_info = &default_load_info; +static HANDLE main_exe_file; static UINT tls_module_count; /* number of modules with TLS directory */ static UINT tls_total_size; /* total size of TLS storage */ static const IMAGE_TLS_DIRECTORY **tls_dirs; /* array of TLS directories */ @@ -2037,6 +2038,8 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3, PEB *peb = NtCurrentTeb()->Peb; IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress ); + if (main_exe_file) NtClose( main_exe_file ); /* at this point the main module is created */ + /* allocate the modref for the main exe (if not already done) */ wm = get_modref( peb->ImageBaseAddress ); assert( wm ); @@ -2243,7 +2246,7 @@ void __wine_process_init( int argc, char *argv[] ) void (* DECLSPEC_NORETURN init_func)(void); extern mode_t FILE_umask; - thread_init(); + main_exe_file = thread_init(); /* retrieve current umask */ FILE_umask = umask(0777); diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index d50e1bdfb3b..20bd5c850c6 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -48,7 +48,7 @@ extern BOOL SIGNAL_Init(void); extern size_t get_signal_stack_total_size(void); extern void version_init( const WCHAR *appname ); extern void debug_init(void); -extern void thread_init(void); +extern HANDLE thread_init(void); /* server support */ extern time_t server_start_time; diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 760f8490afa..5bfdceef470 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -101,6 +101,94 @@ static inline void free_teb( TEB *teb ) } +/*********************************************************************** + * fix_unicode_string + * + * Make sure the unicode string doesn't point beyond the end pointer + */ +static inline void fix_unicode_string( UNICODE_STRING *str, char *end_ptr ) +{ + if ((char *)str->Buffer >= end_ptr) + { + str->Length = str->MaximumLength = 0; + str->Buffer = NULL; + return; + } + if ((char *)str->Buffer + str->MaximumLength > end_ptr) + { + str->MaximumLength = (end_ptr - (char *)str->Buffer) & ~(sizeof(WCHAR) - 1); + } + if (str->Length >= str->MaximumLength) + { + if (str->MaximumLength >= sizeof(WCHAR)) + str->Length = str->MaximumLength - sizeof(WCHAR); + else + str->Length = str->MaximumLength = 0; + } +} + + +/*********************************************************************** + * init_user_process_params + * + * Fill the RTL_USER_PROCESS_PARAMETERS structure from the server. + */ +static NTSTATUS init_user_process_params( SIZE_T info_size, HANDLE *exe_file ) +{ + void *ptr; + SIZE_T env_size; + NTSTATUS status; + RTL_USER_PROCESS_PARAMETERS *params = NULL; + + status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)¶ms, 0, &info_size, + MEM_COMMIT, PAGE_READWRITE ); + if (status != STATUS_SUCCESS) return status; + + params->AllocationSize = info_size; + peb.ProcessParameters = params; + + SERVER_START_REQ( get_startup_info ) + { + wine_server_set_reply( req, params, info_size ); + if (!(status = wine_server_call( req ))) + { + info_size = wine_server_reply_size( reply ); + *exe_file = reply->exe_file; + params->hStdInput = reply->hstdin; + params->hStdOutput = reply->hstdout; + params->hStdError = reply->hstderr; + } + } + SERVER_END_REQ; + if (status != STATUS_SUCCESS) return status; + + if (params->Size > info_size) params->Size = info_size; + + /* make sure the strings are valid */ + fix_unicode_string( ¶ms->CurrentDirectory.DosPath, (char *)info_size ); + fix_unicode_string( ¶ms->DllPath, (char *)info_size ); + fix_unicode_string( ¶ms->ImagePathName, (char *)info_size ); + fix_unicode_string( ¶ms->CommandLine, (char *)info_size ); + fix_unicode_string( ¶ms->WindowTitle, (char *)info_size ); + fix_unicode_string( ¶ms->Desktop, (char *)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; + ptr = NULL; + status = NtAllocateVirtualMemory( NtCurrentProcess(), &ptr, 0, &env_size, + MEM_COMMIT, PAGE_READWRITE ); + if (status != STATUS_SUCCESS) return status; + memcpy( ptr, (char *)params + params->Size, info_size - params->Size ); + params->Environment = ptr; + + RtlNormalizeProcessParams( params ); + return status; +} + + /*********************************************************************** * thread_init * @@ -108,11 +196,12 @@ static inline void free_teb( TEB *teb ) * * NOTES: The first allocated TEB on NT is at 0x7ffde000. */ -void thread_init(void) +HANDLE thread_init(void) { TEB *teb; void *addr; SIZE_T info_size; + HANDLE exe_file = 0; struct ntdll_thread_data *thread_data; struct ntdll_thread_regs *thread_regs; struct wine_pthread_thread_info thread_info; @@ -170,14 +259,7 @@ void thread_init(void) /* allocate user parameters */ if (info_size) { - RTL_USER_PROCESS_PARAMETERS *params = NULL; - - if (NtAllocateVirtualMemory( NtCurrentProcess(), (void **)¶ms, 0, &info_size, - MEM_COMMIT, PAGE_READWRITE ) == STATUS_SUCCESS) - { - params->AllocationSize = info_size; - NtCurrentTeb()->Peb->ProcessParameters = params; - } + init_user_process_params( info_size, &exe_file ); } else { @@ -188,6 +270,7 @@ void thread_init(void) wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms.hStdOutput ); wine_server_fd_to_handle( 2, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, ¶ms.hStdError ); } + return exe_file; }