ntdll: Move the current directory initialization to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Alexandre Julliard 2020-06-17 16:19:38 +02:00
parent c1dc5021ac
commit df5e476487
8 changed files with 104 additions and 131 deletions

View File

@ -306,58 +306,3 @@ BOOLEAN WINAPI RtlDoesFileExists_U(LPCWSTR file_name)
RtlFreeUnicodeString( &nt_name );
return ret;
}
/******************************************************************************
* DIR_get_unix_cwd
*
* Retrieve the Unix name of the current directory; helper for wine_unix_to_nt_file_name.
* Returned value must be freed by caller.
*/
NTSTATUS DIR_get_unix_cwd( char **cwd )
{
CURDIR *curdir;
HANDLE handle;
NTSTATUS status;
ANSI_STRING name;
RtlAcquirePebLock();
if (NtCurrentTeb()->Tib.SubSystemTib) /* FIXME: hack */
curdir = &((WIN16_SUBSYSTEM_TIB *)NtCurrentTeb()->Tib.SubSystemTib)->curdir;
else
curdir = &NtCurrentTeb()->Peb->ProcessParameters->CurrentDirectory;
if (!(handle = curdir->Handle))
{
UNICODE_STRING dirW;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
if (!RtlDosPathNameToNtPathName_U( curdir->DosPath.Buffer, &dirW, NULL, NULL ))
{
status = STATUS_OBJECT_NAME_INVALID;
goto done;
}
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.Attributes = OBJ_CASE_INSENSITIVE;
attr.ObjectName = &dirW;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
status = NtOpenFile( &handle, SYNCHRONIZE, &attr, &io, 0,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT );
RtlFreeUnicodeString( &dirW );
if (status != STATUS_SUCCESS) goto done;
}
status = server_get_unix_name( handle, &name );
if (!status) *cwd = name.Buffer;
if (!curdir->Handle) NtClose( handle );
done:
RtlReleasePebLock();
return status;
}

View File

@ -574,69 +574,13 @@ char **build_envp( const WCHAR *envW )
*/
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 */
if (nt_name.Length > 6 * sizeof(WCHAR) && nt_name.Buffer[5] == ':')
{
dir->Length = nt_name.Length - 4 * sizeof(WCHAR);
memcpy( dir->Buffer, nt_name.Buffer + 4, dir->Length );
}
else /* change \??\ to \\?\ */
{
dir->Length = nt_name.Length;
memcpy( dir->Buffer, nt_name.Buffer, dir->Length );
dir->Buffer[1] = '\\';
}
RtlFreeUnicodeString( &nt_name );
}
}
unix_funcs->get_initial_directory( dir );
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 = wcslen( 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] != '\\')
{
@ -1550,6 +1494,5 @@ done:
RtlInitUnicodeString( &curdir, windows_dir );
RtlSetCurrentDirectory_U( &curdir );
}
if (!params->CurrentDirectory.Handle) chdir("/"); /* avoid locking removable devices */
set_wow64_environment( &params->Environment );
}

View File

@ -118,7 +118,6 @@ extern const struct unix_funcs *unix_funcs DECLSPEC_HIDDEN;
extern NTSTATUS FILE_GetNtStatus(void) DECLSPEC_HIDDEN;
extern NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name ) DECLSPEC_HIDDEN;
extern void init_directories(void) DECLSPEC_HIDDEN;
extern NTSTATUS DIR_get_unix_cwd( char **cwd ) DECLSPEC_HIDDEN;
extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] ) DECLSPEC_HIDDEN;
/* virtual memory */

View File

@ -854,6 +854,75 @@ NTSTATUS CDECL get_initial_environment( WCHAR **wargv[], WCHAR *env, SIZE_T *siz
}
/*************************************************************************
* get_initial_directory
*
* Get the current directory at startup.
*/
void CDECL get_initial_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 = malloc( size ))) break;
if (getcwd( cwd, size )) break;
free( 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 (!unix_to_nt_file_name( &unix_name, &nt_name ))
{
/* skip the \??\ prefix */
if (nt_name.Length > 6 * sizeof(WCHAR) && nt_name.Buffer[5] == ':')
{
dir->Length = nt_name.Length - 4 * sizeof(WCHAR);
memcpy( dir->Buffer, nt_name.Buffer + 4, dir->Length );
}
else /* change \??\ to \\?\ */
{
dir->Length = nt_name.Length;
memcpy( dir->Buffer, nt_name.Buffer, dir->Length );
dir->Buffer[1] = '\\';
}
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 : "" );
free( cwd );
chdir( "/" ); /* avoid locking removable devices */
}
/*************************************************************************
* get_unix_codepage
*

View File

@ -951,6 +951,7 @@ static struct unix_funcs unix_funcs =
fast_RtlWakeConditionVariable,
get_main_args,
get_initial_environment,
get_initial_directory,
get_paths,
get_dll_path,
get_unix_codepage,

View File

@ -481,18 +481,26 @@ static ULONG get_env_size( const RTL_USER_PROCESS_PARAMETERS *params, char **win
/***********************************************************************
* get_unix_curdir
*/
static char *get_unix_curdir( const RTL_USER_PROCESS_PARAMETERS *params )
static int get_unix_curdir( const RTL_USER_PROCESS_PARAMETERS *params )
{
UNICODE_STRING nt_name;
ANSI_STRING unix_name;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
HANDLE handle;
int fd = -1;
if (!RtlDosPathNameToNtPathName_U( params->CurrentDirectory.DosPath.Buffer, &nt_name, NULL, NULL ))
return NULL;
status = nt_to_unix_file_name( &nt_name, &unix_name, FILE_OPEN_IF, FALSE );
return -1;
InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL );
status = NtOpenFile( &handle, FILE_TRAVERSE | SYNCHRONIZE, &attr, &io,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT );
RtlFreeUnicodeString( &nt_name );
if (status && status != STATUS_NO_SUCH_FILE) return NULL;
return unix_name.Buffer;
if (status) return -1;
server_handle_to_fd( handle, FILE_TRAVERSE, &fd, NULL );
NtClose( handle );
return fd;
}
@ -519,8 +527,8 @@ static void set_stdio_fd( int stdin_fd, int stdout_fd )
/***********************************************************************
* spawn_process
*/
NTSTATUS CDECL spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd,
const char *unixdir, char *winedebug, const pe_image_info_t *pe_info )
static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd,
int unixdir, char *winedebug, const pe_image_info_t *pe_info )
{
const int is_child_64bit = (pe_info->cpu == CPU_x86_64 || pe_info->cpu == CPU_ARM64);
NTSTATUS status = STATUS_SUCCESS;
@ -548,8 +556,11 @@ NTSTATUS CDECL spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int soc
if (stdout_fd != -1) close( stdout_fd );
if (winedebug) putenv( winedebug );
if (unixdir) chdir( unixdir );
if (unixdir != -1)
{
fchdir( unixdir );
close( unixdir );
}
argv = build_argv( &params->CommandLine, 2 );
exec_wineloader( argv, socketfd, is_child_64bit,
@ -630,7 +641,7 @@ NTSTATUS CDECL exec_process( const UNICODE_STRING *cmdline, const pe_image_info_
*
* Fork and exec a new Unix binary, checking for errors.
*/
static NTSTATUS fork_and_exec( UNICODE_STRING *path, const char *unix_dir,
static NTSTATUS fork_and_exec( UNICODE_STRING *path, int unixdir,
const RTL_USER_PROCESS_PARAMETERS *params )
{
pid_t pid;
@ -681,8 +692,11 @@ static NTSTATUS fork_and_exec( UNICODE_STRING *path, const char *unix_dir,
argv = build_argv( &params->CommandLine, 0 );
envp = build_envp( params->Environment );
if (unix_dir) chdir( unix_dir );
if (unixdir != -1)
{
fchdir( unixdir );
close( unixdir );
}
execve( unix_name.Buffer, argv, envp );
}
@ -741,10 +755,10 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
HANDLE file_handle, process_info = 0, process_handle = 0, thread_handle = 0;
struct object_attributes *objattr;
data_size_t attr_len;
char *unixdir = NULL, *winedebug = NULL;
char *winedebug = NULL;
startup_info_t *startup_info = NULL;
ULONG startup_info_size, env_size;
int socketfd[2] = { -1, -1 };
int unixdir, socketfd[2] = { -1, -1 };
pe_image_info_t pe_info;
CLIENT_ID id;
HANDLE parent = 0, debug = 0, token = 0;
@ -943,9 +957,9 @@ done:
if (process_handle) NtClose( process_handle );
if (thread_handle) NtClose( thread_handle );
if (socketfd[0] != -1) close( socketfd[0] );
if (unixdir != -1) close( unixdir );
RtlFreeHeap( GetProcessHeap(), 0, startup_info );
RtlFreeHeap( GetProcessHeap(), 0, winedebug );
RtlFreeHeap( GetProcessHeap(), 0, unixdir );
return status;
}

View File

@ -85,6 +85,7 @@ int CDECL mmap_enum_reserved_areas( int (CDECL *enum_func)(void *base, SIZE_T s
int top_down ) DECLSPEC_HIDDEN;
extern void CDECL get_main_args( int *argc, char **argv[], char **envp[] ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL get_initial_environment( WCHAR **wargv[], WCHAR *env, SIZE_T *size ) DECLSPEC_HIDDEN;
extern void CDECL get_initial_directory( UNICODE_STRING *dir ) DECLSPEC_HIDDEN;
extern void CDECL get_unix_codepage( CPTABLEINFO *table ) DECLSPEC_HIDDEN;
extern void CDECL get_locales( WCHAR *sys, WCHAR *user ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zero_bits_64, SIZE_T commit_size,

View File

@ -28,7 +28,7 @@ struct ldt_copy;
struct msghdr;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 51
#define NTDLL_UNIXLIB_VERSION 52
struct unix_funcs
{
@ -259,6 +259,7 @@ struct unix_funcs
/* environment functions */
void (CDECL *get_main_args)( int *argc, char **argv[], char **envp[] );
NTSTATUS (CDECL *get_initial_environment)( WCHAR **wargv[], WCHAR *env, SIZE_T *size );
void (CDECL *get_initial_directory)( UNICODE_STRING *dir );
void (CDECL *get_paths)( const char **builddir, const char **datadir, const char **configdir );
void (CDECL *get_dll_path)( const char ***paths, SIZE_T *maxlen );
void (CDECL *get_unix_codepage)( CPTABLEINFO *table );