ntdll: Set the Wine paths environment variables from the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-06-24 09:21:48 +02:00
parent 36e55720b6
commit 438abad27c
8 changed files with 105 additions and 186 deletions

View file

@ -60,24 +60,6 @@ static inline SIZE_T get_env_length( const WCHAR *env )
}
/***********************************************************************
* is_special_env_var
*
* Check if an environment variable needs to be handled specially when
* passed through the Unix environment (i.e. prefixed with "WINE").
*/
static inline BOOL is_special_env_var( const char *var )
{
return (!strncmp( var, "PATH=", sizeof("PATH=")-1 ) ||
!strncmp( var, "PWD=", sizeof("PWD=")-1 ) ||
!strncmp( var, "HOME=", sizeof("HOME=")-1 ) ||
!strncmp( var, "TEMP=", sizeof("TEMP=")-1 ) ||
!strncmp( var, "TMP=", sizeof("TMP=")-1 ) ||
!strncmp( var, "QT_", sizeof("QT_")-1 ) ||
!strncmp( var, "VK_", sizeof("VK_")-1 ));
}
/***********************************************************************
* set_env_var
*/
@ -86,8 +68,12 @@ static void set_env_var( WCHAR **env, const WCHAR *name, const WCHAR *val )
UNICODE_STRING nameW, valW;
RtlInitUnicodeString( &nameW, name );
RtlInitUnicodeString( &valW, val );
RtlSetEnvironmentVariable( env, &nameW, &valW );
if (val)
{
RtlInitUnicodeString( &valW, val );
RtlSetEnvironmentVariable( env, &nameW, &valW );
}
else RtlSetEnvironmentVariable( env, &nameW, NULL );
}
@ -322,24 +308,6 @@ static void set_additional_environment( WCHAR **env )
}
/* set an environment variable for one of the wine path variables */
static void set_wine_path_variable( WCHAR **env, const WCHAR *name, const char *unix_path )
{
UNICODE_STRING nt_name, var_name;
ANSI_STRING unix_name;
RtlInitUnicodeString( &var_name, name );
if (unix_path)
{
RtlInitAnsiString( &unix_name, unix_path );
if (wine_unix_to_nt_file_name( &unix_name, &nt_name )) return;
RtlSetEnvironmentVariable( env, &var_name, &nt_name );
RtlFreeUnicodeString( &nt_name );
}
else RtlSetEnvironmentVariable( env, &var_name, NULL );
}
/***********************************************************************
* set_wow64_environment
*
@ -366,12 +334,6 @@ static void set_wow64_environment( WCHAR **env )
static const WCHAR commonfilesW[] = {'C','o','m','m','o','n','P','r','o','g','r','a','m','F','i','l','e','s',0};
static const WCHAR commonfiles86W[] = {'C','o','m','m','o','n','P','r','o','g','r','a','m','F','i','l','e','s','(','x','8','6',')',0};
static const WCHAR commonw6432W[] = {'C','o','m','m','o','n','P','r','o','g','r','a','m','W','6','4','3','2',0};
static const WCHAR winedlldirW[] = {'W','I','N','E','D','L','L','D','I','R','%','u',0};
static const WCHAR winehomedirW[] = {'W','I','N','E','H','O','M','E','D','I','R',0};
static const WCHAR winedatadirW[] = {'W','I','N','E','D','A','T','A','D','I','R',0};
static const WCHAR winebuilddirW[] = {'W','I','N','E','B','U','I','L','D','D','I','R',0};
static const WCHAR wineusernameW[] = {'W','I','N','E','U','S','E','R','N','A','M','E',0};
static const WCHAR wineconfigdirW[] = {'W','I','N','E','C','O','N','F','I','G','D','I','R',0};
WCHAR buf[256];
UNICODE_STRING arch_strW = { sizeof(archW) - sizeof(WCHAR), sizeof(archW), archW };
@ -379,47 +341,23 @@ static void set_wow64_environment( WCHAR **env )
UNICODE_STRING valW = { 0, sizeof(buf), buf };
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
const char *p;
const char *home = getenv( "HOME" );
const char *name = getenv( "USER" );
const char **dll_paths;
SIZE_T dll_path_maxlen;
WCHAR *val;
HANDLE hkey;
DWORD i;
SIZE_T size = 1024;
WCHAR *ptr, *val, *p;
if (!home || !name)
for (;;)
{
struct passwd *pwd = getpwuid( getuid() );
if (pwd)
{
if (!home) home = pwd->pw_dir;
if (!name) name = pwd->pw_name;
}
if (!(ptr = RtlAllocateHeap( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) break;
if (!unix_funcs->get_dynamic_environment( ptr, &size )) break;
RtlFreeHeap( GetProcessHeap(), 0, ptr );
}
/* set the Wine paths */
set_wine_path_variable( env, winedatadirW, data_dir );
set_wine_path_variable( env, winehomedirW, home );
set_wine_path_variable( env, winebuilddirW, build_dir );
set_wine_path_variable( env, wineconfigdirW, config_dir );
unix_funcs->get_dll_path( &dll_paths, &dll_path_maxlen );
for (i = 0; dll_paths[i]; i++)
for (p = ptr; *p; p += wcslen(p) + 1)
{
NTDLL_swprintf( buf, winedlldirW, i );
set_wine_path_variable( env, buf, dll_paths[i] );
if ((val = wcschr( p, '=' ))) *val++ = 0;
set_env_var( env, p, val );
if (val) p = val;
}
NTDLL_swprintf( buf, winedlldirW, i );
set_wine_path_variable( env, buf, NULL );
/* set user name */
if (!name) name = "wine";
if ((p = strrchr( name, '/' ))) name = p + 1;
if ((p = strrchr( name, '\\' ))) name = p + 1;
ntdll_umbstowcs( name, strlen(name) + 1, buf, ARRAY_SIZE(buf) );
set_env_var( env, wineusernameW, buf );
RtlFreeHeap( GetProcessHeap(), 0, ptr );
/* set the PROCESSOR_ARCHITECTURE variable */
@ -500,73 +438,6 @@ static WCHAR *build_initial_environment( WCHAR **wargv[] )
}
/***********************************************************************
* build_envp
*
* Build the environment of a new child process.
*/
char **build_envp( const WCHAR *envW )
{
static const char * const unix_vars[] = { "PATH", "TEMP", "TMP", "HOME" };
char **envp;
char *env, *p;
int count = 1, length, lenW;
unsigned int i;
lenW = get_env_length( envW );
if (!(env = RtlAllocateHeap( GetProcessHeap(), 0, lenW * 3 ))) return NULL;
length = ntdll_wcstoumbs( envW, lenW, env, lenW * 3, FALSE );
for (p = env; *p; p += strlen(p) + 1, count++)
if (is_special_env_var( p )) length += 4; /* prefix it with "WINE" */
for (i = 0; i < ARRAY_SIZE( unix_vars ); i++)
{
if (!(p = getenv(unix_vars[i]))) continue;
length += strlen(unix_vars[i]) + strlen(p) + 2;
count++;
}
if ((envp = RtlAllocateHeap( GetProcessHeap(), 0, count * sizeof(*envp) + length )))
{
char **envptr = envp;
char *dst = (char *)(envp + count);
/* some variables must not be modified, so we get them directly from the unix env */
for (i = 0; i < ARRAY_SIZE( unix_vars ); i++)
{
if (!(p = getenv( unix_vars[i] ))) continue;
*envptr++ = strcpy( dst, unix_vars[i] );
strcat( dst, "=" );
strcat( dst, p );
dst += strlen(dst) + 1;
}
/* 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 (!strncmp( p, "WINELOADERNOEXEC=", sizeof("WINELOADERNOEXEC=")-1 )) continue;
if (!strncmp( p, "WINESERVERSOCKET=", sizeof("WINESERVERSOCKET=")-1 )) continue;
if (is_special_env_var( p )) /* prefix it with "WINE" */
{
*envptr++ = strcpy( dst, "WINE" );
strcat( dst, p );
}
else
{
*envptr++ = strcpy( dst, p );
}
dst += strlen(dst) + 1;
}
*envptr = 0;
}
RtlFreeHeap( GetProcessHeap(), 0, env );
return envp;
}
/***********************************************************************
* get_current_directory
*

View file

@ -70,13 +70,9 @@ extern void heap_set_debug_flags( HANDLE handle ) DECLSPEC_HIDDEN;
extern void init_unix_codepage(void) DECLSPEC_HIDDEN;
extern void init_locale( HMODULE module ) DECLSPEC_HIDDEN;
extern void init_user_process_params( SIZE_T data_size ) DECLSPEC_HIDDEN;
extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN;
extern NTSTATUS restart_process( RTL_USER_PROCESS_PARAMETERS *params, NTSTATUS status ) DECLSPEC_HIDDEN;
/* server support */
extern const char *build_dir DECLSPEC_HIDDEN;
extern const char *data_dir DECLSPEC_HIDDEN;
extern const char *config_dir DECLSPEC_HIDDEN;
extern BOOL is_wow64 DECLSPEC_HIDDEN;
extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
data_size_t *ret_len ) DECLSPEC_HIDDEN;

View file

@ -36,10 +36,6 @@
#include "wine/debug.h"
#include "ntdll_misc.h"
const char *build_dir = NULL;
const char *data_dir = NULL;
const char *config_dir = NULL;
BOOL is_wow64 = FALSE;
/***********************************************************************

View file

@ -136,7 +136,6 @@ TEB *thread_init( SIZE_T *info_size )
*/
peb->SessionId = 1;
unix_funcs->get_paths( &build_dir, &data_dir, &config_dir );
NtQueryInformationProcess( GetCurrentProcess(), ProcessWow64Information, &val, sizeof(val), NULL );
is_wow64 = !!val;
return teb;

View file

@ -841,6 +841,88 @@ NTSTATUS CDECL get_initial_environment( WCHAR **wargv[], WCHAR *env, SIZE_T *siz
}
/* append a variable to the environment */
static void append_env( WCHAR *env, SIZE_T *pos, const char *name, const WCHAR *value )
{
SIZE_T i = *pos;
while (*name) env[i++] = (unsigned char)*name++;
if (value)
{
env[i++] = '=';
while (*value) env[i++] = *value++;
}
env[i++] = 0;
*pos = i;
}
/* set an environment variable for one of the wine path variables */
static void add_path_var( WCHAR *env, SIZE_T *pos, const char *name, const char *path )
{
UNICODE_STRING nt_name;
ANSI_STRING unix_name;
if (!path) append_env( env, pos, name, NULL );
else
{
RtlInitAnsiString( &unix_name, path );
if (unix_to_nt_file_name( &unix_name, &nt_name )) return;
append_env( env, pos, name, nt_name.Buffer );
RtlFreeUnicodeString( &nt_name );
}
}
/*************************************************************************
* get_dynamic_environment
*
* Get the environment variables that can differ between processes.
*/
NTSTATUS CDECL get_dynamic_environment( WCHAR *env, SIZE_T *size )
{
SIZE_T alloc, pos = 0;
WCHAR *buffer;
DWORD i;
WCHAR buf[256];
char dlldir[22];
NTSTATUS status = STATUS_SUCCESS;
alloc = 20 * 6; /* 6 variable names */
if (data_dir) alloc += strlen( data_dir ) + 9;
if (home_dir) alloc += strlen( home_dir ) + 9;
if (build_dir) alloc += strlen( build_dir ) + 9;
if (config_dir) alloc += strlen( config_dir ) + 9;
if (user_name) alloc += strlen( user_name );
for (i = 0; dll_paths[i]; i++) alloc += 20 + strlen( dll_paths[i] ) + 9;
if (!(buffer = malloc( alloc * sizeof(WCHAR) ))) return STATUS_NO_MEMORY;
pos = 0;
add_path_var( buffer, &pos, "WINEDATADIR", data_dir );
add_path_var( buffer, &pos, "WINEHOMEDIR", home_dir );
add_path_var( buffer, &pos, "WINEBUILDDIR", build_dir );
add_path_var( buffer, &pos, "WINECONFIGDIR", config_dir );
for (i = 0; dll_paths[i]; i++)
{
sprintf( dlldir, "WINEDLLDIR%u", i );
add_path_var( buffer, &pos, dlldir, dll_paths[i] );
}
sprintf( dlldir, "WINEDLLDIR%u", i );
append_env( buffer, &pos, dlldir, NULL );
ntdll_umbstowcs( user_name, strlen(user_name) + 1, buf, ARRAY_SIZE(buf) );
append_env( buffer, &pos, "WINEUSERNAME", buf );
assert( pos <= alloc );
if (pos < *size)
{
memcpy( env, buffer, pos * sizeof(WCHAR) );
env[pos] = 0;
}
else status = STATUS_BUFFER_TOO_SMALL;
*size = pos + 1;
return status;
}
/*************************************************************************
* get_initial_directory
*

View file

@ -120,13 +120,13 @@ static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
static char *argv0;
static const char *bin_dir;
static const char *dll_dir;
static const char **dll_paths;
static SIZE_T dll_path_maxlen;
const char *home_dir = NULL;
const char *data_dir = NULL;
const char *build_dir = NULL;
const char *config_dir = NULL;
const char **dll_paths = NULL;
const char *user_name = NULL;
HMODULE ntdll_module = NULL;
@ -400,31 +400,6 @@ void CDECL get_host_version( const char **sysname, const char **release )
}
/*************************************************************************
* get_paths
*
* Return the various configuration paths.
*/
static void CDECL get_paths( const char **builddir, const char **datadir, const char **configdir )
{
*builddir = build_dir;
*datadir = data_dir;
*configdir = config_dir;
}
/*************************************************************************
* get_dll_path
*
* Return the various configuration paths.
*/
static void CDECL get_dll_path( const char ***paths, SIZE_T *maxlen )
{
*paths = dll_paths;
*maxlen = dll_path_maxlen;
}
static void preloader_exec( char **argv )
{
if (use_preloader)
@ -1491,9 +1466,8 @@ static struct unix_funcs unix_funcs =
fast_RtlSleepConditionVariableCS,
fast_RtlWakeConditionVariable,
get_initial_environment,
get_dynamic_environment,
get_initial_directory,
get_paths,
get_dll_path,
get_unix_codepage,
get_locales,
get_version,

View file

@ -96,6 +96,7 @@ int CDECL mmap_is_in_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
int CDECL mmap_enum_reserved_areas( int (CDECL *enum_func)(void *base, SIZE_T size, void *arg), void *arg,
int top_down ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL get_initial_environment( WCHAR **wargv[], WCHAR *env, SIZE_T *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_unix_codepage( CPTABLEINFO *table ) DECLSPEC_HIDDEN;
extern void CDECL get_locales( WCHAR *sys, WCHAR *user ) DECLSPEC_HIDDEN;
@ -129,6 +130,7 @@ extern const char *data_dir DECLSPEC_HIDDEN;
extern const char *build_dir DECLSPEC_HIDDEN;
extern const char *config_dir DECLSPEC_HIDDEN;
extern const char *user_name DECLSPEC_HIDDEN;
extern const char **dll_paths DECLSPEC_HIDDEN;
extern HMODULE ntdll_module DECLSPEC_HIDDEN;
extern USHORT *uctable DECLSPEC_HIDDEN;
extern USHORT *lctable DECLSPEC_HIDDEN;

View file

@ -28,7 +28,7 @@ struct ldt_copy;
struct msghdr;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 60
#define NTDLL_UNIXLIB_VERSION 61
struct unix_funcs
{
@ -285,9 +285,8 @@ struct unix_funcs
/* environment functions */
NTSTATUS (CDECL *get_initial_environment)( WCHAR **wargv[], WCHAR *env, SIZE_T *size );
NTSTATUS (CDECL *get_dynamic_environment)( 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 );
void (CDECL *get_locales)( WCHAR *sys, WCHAR *user );
const char * (CDECL *get_version)(void);