kernel32: Move current directory initialization to ntdll.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Alexandre Julliard 2019-10-22 09:58:32 +02:00
parent e4595a0ce8
commit 305b5a44c5
2 changed files with 89 additions and 76 deletions

View File

@ -1085,78 +1085,6 @@ static BOOL build_command_line( WCHAR **argv )
}
/***********************************************************************
* init_current_directory
*
* Initialize the current directory from the Unix cwd or the parent info.
*/
static void init_current_directory( CURDIR *cur_dir )
{
UNICODE_STRING dir_str;
const char *pwd;
char *cwd;
int size;
/* if we received a cur dir from the parent, try this first */
if (cur_dir->DosPath.Length)
{
if (RtlSetCurrentDirectory_U( &cur_dir->DosPath ) == STATUS_SUCCESS) goto done;
}
/* now try to get it from the Unix cwd */
for (size = 256; ; size *= 2)
{
if (!(cwd = HeapAlloc( GetProcessHeap(), 0, size ))) break;
if (getcwd( cwd, size )) break;
HeapFree( GetProcessHeap(), 0, cwd );
if (errno == ERANGE) continue;
cwd = NULL;
break;
}
/* try to use PWD if it is valid, so that we don't resolve symlinks */
pwd = getenv( "PWD" );
if (cwd)
{
struct stat st1, st2;
if (!pwd || stat( pwd, &st1 ) == -1 ||
(!stat( cwd, &st2 ) && (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)))
pwd = cwd;
}
if (pwd)
{
ANSI_STRING unix_name;
UNICODE_STRING nt_name;
RtlInitAnsiString( &unix_name, pwd );
if (!wine_unix_to_nt_file_name( &unix_name, &nt_name ))
{
UNICODE_STRING dos_path;
/* skip the \??\ prefix, nt_name is 0 terminated */
RtlInitUnicodeString( &dos_path, nt_name.Buffer + 4 );
RtlSetCurrentDirectory_U( &dos_path );
RtlFreeUnicodeString( &nt_name );
}
}
if (!cur_dir->DosPath.Length) /* still not initialized */
{
MESSAGE("Warning: could not find DOS drive for current working directory '%s', "
"starting in the Windows directory.\n", cwd ? cwd : "" );
RtlInitUnicodeString( &dir_str, DIR_Windows );
RtlSetCurrentDirectory_U( &dir_str );
}
HeapFree( GetProcessHeap(), 0, cwd );
done:
TRACE( "starting in %s %p\n", debugstr_w( cur_dir->DosPath.Buffer ), cur_dir->Handle );
}
/***********************************************************************
* init_windows_dirs
*/
@ -1405,7 +1333,6 @@ void * CDECL __wine_kernel_init(void)
}
init_windows_dirs();
init_current_directory( &params->CurrentDirectory );
set_process_name( __wine_main_argc, __wine_main_argv );
set_library_wargv( __wine_main_argv );

View File

@ -21,7 +21,12 @@
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@ -41,6 +46,8 @@ static WCHAR empty[] = {0};
static const UNICODE_STRING empty_str = { 0, sizeof(empty), empty };
static const UNICODE_STRING null_str = { 0, 0, NULL };
static const WCHAR windows_dir[] = {'C',':','\\','w','i','n','d','o','w','s',0};
static inline SIZE_T get_env_length( const WCHAR *env )
{
const WCHAR *end = env;
@ -48,6 +55,77 @@ static inline SIZE_T get_env_length( const WCHAR *env )
return end + 1 - env;
}
/***********************************************************************
* get_current_directory
*
* Initialize the current directory from the Unix cwd.
*/
static void get_current_directory( UNICODE_STRING *dir )
{
const char *pwd;
char *cwd;
int size;
dir->Length = 0;
/* try to get it from the Unix cwd */
for (size = 1024; ; size *= 2)
{
if (!(cwd = RtlAllocateHeap( GetProcessHeap(), 0, size ))) break;
if (getcwd( cwd, size )) break;
RtlFreeHeap( GetProcessHeap(), 0, cwd );
if (errno == ERANGE) continue;
cwd = NULL;
break;
}
/* try to use PWD if it is valid, so that we don't resolve symlinks */
pwd = getenv( "PWD" );
if (cwd)
{
struct stat st1, st2;
if (!pwd || stat( pwd, &st1 ) == -1 ||
(!stat( cwd, &st2 ) && (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)))
pwd = cwd;
}
if (pwd)
{
ANSI_STRING unix_name;
UNICODE_STRING nt_name;
RtlInitAnsiString( &unix_name, pwd );
if (!wine_unix_to_nt_file_name( &unix_name, &nt_name ))
{
/* skip the \??\ prefix */
dir->Length = nt_name.Length - 4 * sizeof(WCHAR);
memcpy( dir->Buffer, nt_name.Buffer + 4, dir->Length );
RtlFreeUnicodeString( &nt_name );
}
}
if (!dir->Length) /* still not initialized */
{
MESSAGE("Warning: could not find DOS drive for current working directory '%s', "
"starting in the Windows directory.\n", cwd ? cwd : "" );
dir->Length = strlenW( windows_dir ) * sizeof(WCHAR);
memcpy( dir->Buffer, windows_dir, dir->Length );
}
RtlFreeHeap( GetProcessHeap(), 0, cwd );
/* add trailing backslash */
if (dir->Buffer[dir->Length / sizeof(WCHAR) - 1] != '\\')
{
dir->Buffer[dir->Length / sizeof(WCHAR)] = '\\';
dir->Length += sizeof(WCHAR);
}
dir->Buffer[dir->Length / sizeof(WCHAR)] = 0;
}
/******************************************************************************
* NtQuerySystemEnvironmentValue [NTDLL.@]
*/
@ -554,7 +632,7 @@ void init_user_process_params( SIZE_T data_size )
WCHAR *src;
SIZE_T info_size, env_size;
NTSTATUS status;
startup_info_t *info;
startup_info_t *info = NULL;
RTL_USER_PROCESS_PARAMETERS *params = NULL;
UNICODE_STRING curdir, dllpath, imagepath, cmdline, title, desktop, shellinfo, runtime;
@ -566,6 +644,8 @@ void init_user_process_params( SIZE_T data_size )
return;
NtCurrentTeb()->Peb->ProcessParameters = params;
get_current_directory( &params->CurrentDirectory.DosPath );
if (isatty(0) || isatty(1) || isatty(2))
params->ConsoleHandle = (HANDLE)2; /* see kernel32/kernel_private.h */
if (!isatty(0))
@ -575,7 +655,7 @@ void init_user_process_params( SIZE_T data_size )
if (!isatty(2))
wine_server_fd_to_handle( 2, GENERIC_WRITE|SYNCHRONIZE, OBJ_INHERIT, &params->hStdError );
params->wShowWindow = 1; /* SW_SHOWNORMAL */
return;
goto done;
}
if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, data_size ))) return;
@ -603,7 +683,6 @@ void init_user_process_params( SIZE_T data_size )
get_unicode_string( &shellinfo, &src, info->shellinfo_len );
get_unicode_string( &runtime, &src, info->runtime_len );
curdir.MaximumLength = MAX_PATH * sizeof(WCHAR); /* current directory needs more space */
runtime.MaximumLength = runtime.Length; /* runtime info isn't a real string */
if (RtlCreateProcessParametersEx( &params, &imagepath, &dllpath, &curdir, &cmdline, NULL,
@ -637,6 +716,13 @@ void init_user_process_params( SIZE_T data_size )
done:
RtlFreeHeap( GetProcessHeap(), 0, info );
if (RtlSetCurrentDirectory_U( &params->CurrentDirectory.DosPath ))
{
MESSAGE("wine: could not open working directory %s, starting in the Windows directory.\n",
debugstr_w( params->CurrentDirectory.DosPath.Buffer ));
RtlInitUnicodeString( &curdir, windows_dir );
RtlSetCurrentDirectory_U( &curdir );
}
}