ntdll: Move the wineloader exec support to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e619429035
commit
fb310724f6
|
@ -67,6 +67,7 @@ server_EXTRADEFS = \
|
||||||
-DDLL_TO_BINDIR=\"`$(MAKEDEP) -R ${dlldir} ${bindir}`\"
|
-DDLL_TO_BINDIR=\"`$(MAKEDEP) -R ${dlldir} ${bindir}`\"
|
||||||
|
|
||||||
unix_loader_EXTRADEFS = \
|
unix_loader_EXTRADEFS = \
|
||||||
|
-DBINDIR=\"${bindir}\" \
|
||||||
-DDLL_TO_BINDIR=\"`$(MAKEDEP) -R ${dlldir} ${bindir}`\" \
|
-DDLL_TO_BINDIR=\"`$(MAKEDEP) -R ${dlldir} ${bindir}`\" \
|
||||||
-DBIN_TO_DATADIR=\"`$(MAKEDEP) -R ${bindir} ${datadir}/wine`\"
|
-DBIN_TO_DATADIR=\"`$(MAKEDEP) -R ${bindir} ${datadir}/wine`\"
|
||||||
|
|
||||||
|
|
|
@ -1074,6 +1074,7 @@ static void set_stdio_fd( int stdin_fd, int stdout_fd )
|
||||||
static NTSTATUS spawn_loader( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd,
|
static NTSTATUS spawn_loader( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd,
|
||||||
const char *unixdir, char *winedebug, const pe_image_info_t *pe_info )
|
const char *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);
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int stdin_fd = -1, stdout_fd = -1;
|
int stdin_fd = -1, stdout_fd = -1;
|
||||||
char **argv;
|
char **argv;
|
||||||
|
@ -1103,7 +1104,8 @@ static NTSTATUS spawn_loader( const RTL_USER_PROCESS_PARAMETERS *params, int soc
|
||||||
if (winedebug) putenv( winedebug );
|
if (winedebug) putenv( winedebug );
|
||||||
if (unixdir) chdir( unixdir );
|
if (unixdir) chdir( unixdir );
|
||||||
|
|
||||||
exec_wineloader( argv, socketfd, pe_info );
|
unix_funcs->exec_wineloader( argv, socketfd, is_child_64bit,
|
||||||
|
pe_info->base, pe_info->base + pe_info->map_size );
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1533,12 +1535,14 @@ NTSTATUS restart_process( RTL_USER_PROCESS_PARAMETERS *params, NTSTATUS status )
|
||||||
|
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
|
const int is_child_64bit = (pe_info.cpu == CPU_x86_64 || pe_info.cpu == CPU_ARM64);
|
||||||
char **argv = build_argv( &strW, 2 );
|
char **argv = build_argv( &strW, 2 );
|
||||||
if (argv)
|
if (argv)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
status = exec_wineloader( argv, socketfd[0], &pe_info );
|
status = unix_funcs->exec_wineloader( argv, socketfd[0], is_child_64bit,
|
||||||
|
pe_info.base, pe_info.base + pe_info.map_size );
|
||||||
}
|
}
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
while (errno == ENOTSUP && terminate_main_thread());
|
while (errno == ENOTSUP && terminate_main_thread());
|
||||||
|
|
|
@ -121,12 +121,6 @@ static const enum cpu_type client_cpu = CPU_ARM64;
|
||||||
#error Unsupported CPU
|
#error Unsupported CPU
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(linux) || defined(__APPLE__)
|
|
||||||
static const BOOL use_preloader = TRUE;
|
|
||||||
#else
|
|
||||||
static const BOOL use_preloader = FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
|
static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
|
||||||
|
|
||||||
const char *build_dir = NULL;
|
const char *build_dir = NULL;
|
||||||
|
@ -1229,119 +1223,6 @@ int server_pipe( int fd[2] )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* preloader_exec
|
|
||||||
*/
|
|
||||||
static void preloader_exec( char **argv )
|
|
||||||
{
|
|
||||||
if (use_preloader)
|
|
||||||
{
|
|
||||||
static const char *preloader = "wine-preloader";
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (!(p = strrchr( argv[1], '/' ))) p = argv[1];
|
|
||||||
else p++;
|
|
||||||
|
|
||||||
if (strlen(p) > 2 && !strcmp( p + strlen(p) - 2, "64" )) preloader = "wine64-preloader";
|
|
||||||
argv[0] = malloc( p - argv[1] + strlen(preloader) + 1 );
|
|
||||||
memcpy( argv[0], argv[1], p - argv[1] );
|
|
||||||
strcpy( argv[0] + (p - argv[1]), preloader );
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
{
|
|
||||||
posix_spawnattr_t attr;
|
|
||||||
posix_spawnattr_init( &attr );
|
|
||||||
posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR );
|
|
||||||
posix_spawn( NULL, argv[0], NULL, &attr, argv, *_NSGetEnviron() );
|
|
||||||
posix_spawnattr_destroy( &attr );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
execv( argv[0], argv );
|
|
||||||
free( argv[0] );
|
|
||||||
}
|
|
||||||
execv( argv[1], argv + 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* exec_wineloader
|
|
||||||
*
|
|
||||||
* argv[0] and argv[1] must be reserved for the preloader and loader respectively.
|
|
||||||
*/
|
|
||||||
NTSTATUS exec_wineloader( char **argv, int socketfd, const pe_image_info_t *pe_info )
|
|
||||||
{
|
|
||||||
const int is_child_64bit = (pe_info->cpu == CPU_x86_64 || pe_info->cpu == CPU_ARM64);
|
|
||||||
const char *path, *loader = argv0;
|
|
||||||
const char *loader_env = getenv( "WINELOADER" );
|
|
||||||
char *p, preloader_reserve[64], socket_env[64];
|
|
||||||
ULONGLONG res_start = pe_info->base;
|
|
||||||
ULONGLONG res_end = pe_info->base + pe_info->map_size;
|
|
||||||
|
|
||||||
if (!is_win64 ^ !is_child_64bit)
|
|
||||||
{
|
|
||||||
/* remap WINELOADER to the alternate 32/64-bit version if necessary */
|
|
||||||
if (loader_env)
|
|
||||||
{
|
|
||||||
int len = strlen( loader_env );
|
|
||||||
char *env = malloc( sizeof("WINELOADER=") + len + 2 );
|
|
||||||
|
|
||||||
if (!env) return STATUS_NO_MEMORY;
|
|
||||||
strcpy( env, "WINELOADER=" );
|
|
||||||
strcat( env, loader_env );
|
|
||||||
if (is_child_64bit)
|
|
||||||
{
|
|
||||||
strcat( env, "64" );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len += sizeof("WINELOADER=") - 1;
|
|
||||||
if (!strcmp( env + len - 2, "64" )) env[len - 2] = 0;
|
|
||||||
}
|
|
||||||
loader = env;
|
|
||||||
putenv( env );
|
|
||||||
}
|
|
||||||
else loader = is_child_64bit ? "wine64" : "wine";
|
|
||||||
}
|
|
||||||
|
|
||||||
signal( SIGPIPE, SIG_DFL );
|
|
||||||
|
|
||||||
sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd );
|
|
||||||
sprintf( preloader_reserve, "WINEPRELOADRESERVE=%x%08x-%x%08x",
|
|
||||||
(ULONG)(res_start >> 32), (ULONG)res_start, (ULONG)(res_end >> 32), (ULONG)res_end );
|
|
||||||
|
|
||||||
putenv( preloader_reserve );
|
|
||||||
putenv( socket_env );
|
|
||||||
|
|
||||||
if (build_dir)
|
|
||||||
{
|
|
||||||
argv[1] = build_path( build_dir, is_child_64bit ? "loader/wine64" : "loader/wine" );
|
|
||||||
preloader_exec( argv );
|
|
||||||
return STATUS_INVALID_IMAGE_FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((p = strrchr( loader, '/' ))) loader = p + 1;
|
|
||||||
|
|
||||||
argv[1] = build_path( bin_dir, loader );
|
|
||||||
preloader_exec( argv );
|
|
||||||
|
|
||||||
argv[1] = getenv( "WINELOADER" );
|
|
||||||
if (argv[1]) preloader_exec( argv );
|
|
||||||
|
|
||||||
if ((path = getenv( "PATH" )))
|
|
||||||
{
|
|
||||||
for (p = strtok( strdup( path ), ":" ); p; p = strtok( NULL, ":" ))
|
|
||||||
{
|
|
||||||
argv[1] = build_path( p, loader );
|
|
||||||
preloader_exec( argv );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
argv[1] = build_path( BINDIR, loader );
|
|
||||||
preloader_exec( argv );
|
|
||||||
return STATUS_INVALID_IMAGE_FORMAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* exec_wineserver
|
* exec_wineserver
|
||||||
*
|
*
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
#ifdef HAVE_PWD_H
|
#ifdef HAVE_PWD_H
|
||||||
# include <pwd.h>
|
# include <pwd.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -50,6 +51,11 @@
|
||||||
# undef GetCurrentThread
|
# undef GetCurrentThread
|
||||||
# include <pthread.h>
|
# include <pthread.h>
|
||||||
# include <mach-o/getsect.h>
|
# include <mach-o/getsect.h>
|
||||||
|
# include <crt_externs.h>
|
||||||
|
# include <spawn.h>
|
||||||
|
# ifndef _POSIX_SPAWN_DISABLE_ASLR
|
||||||
|
# define _POSIX_SPAWN_DISABLE_ASLR 0x0100
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ntstatus.h"
|
#include "ntstatus.h"
|
||||||
|
@ -76,6 +82,14 @@ extern int __wine_main_argc;
|
||||||
extern char **__wine_main_argv;
|
extern char **__wine_main_argv;
|
||||||
extern char **__wine_main_environ;
|
extern char **__wine_main_environ;
|
||||||
|
|
||||||
|
#if defined(linux) || defined(__APPLE__)
|
||||||
|
static const BOOL use_preloader = TRUE;
|
||||||
|
#else
|
||||||
|
static const BOOL use_preloader = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
|
||||||
|
|
||||||
static int main_argc;
|
static int main_argc;
|
||||||
static char **main_argv;
|
static char **main_argv;
|
||||||
static char **main_envp;
|
static char **main_envp;
|
||||||
|
@ -344,6 +358,121 @@ static void CDECL get_dll_path( const char ***paths, SIZE_T *maxlen )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void preloader_exec( char **argv )
|
||||||
|
{
|
||||||
|
if (use_preloader)
|
||||||
|
{
|
||||||
|
static const char *preloader = "wine-preloader";
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (!(p = strrchr( argv[1], '/' ))) p = argv[1];
|
||||||
|
else p++;
|
||||||
|
|
||||||
|
if (strlen(p) > 2 && !strcmp( p + strlen(p) - 2, "64" )) preloader = "wine64-preloader";
|
||||||
|
argv[0] = malloc( p - argv[1] + strlen(preloader) + 1 );
|
||||||
|
memcpy( argv[0], argv[1], p - argv[1] );
|
||||||
|
strcpy( argv[0] + (p - argv[1]), preloader );
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
{
|
||||||
|
posix_spawnattr_t attr;
|
||||||
|
posix_spawnattr_init( &attr );
|
||||||
|
posix_spawnattr_setflags( &attr, POSIX_SPAWN_SETEXEC | _POSIX_SPAWN_DISABLE_ASLR );
|
||||||
|
posix_spawn( NULL, argv[0], NULL, &attr, argv, *_NSGetEnviron() );
|
||||||
|
posix_spawnattr_destroy( &attr );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
execv( argv[0], argv );
|
||||||
|
free( argv[0] );
|
||||||
|
}
|
||||||
|
execv( argv[1], argv + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS loader_exec( const char *loader, char **argv, int is_child_64bit )
|
||||||
|
{
|
||||||
|
char *p, *path;
|
||||||
|
|
||||||
|
if (build_dir)
|
||||||
|
{
|
||||||
|
argv[1] = build_path( build_dir, is_child_64bit ? "loader/wine64" : "loader/wine" );
|
||||||
|
preloader_exec( argv );
|
||||||
|
return STATUS_INVALID_IMAGE_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p = strrchr( loader, '/' ))) loader = p + 1;
|
||||||
|
|
||||||
|
argv[1] = build_path( bin_dir, loader );
|
||||||
|
preloader_exec( argv );
|
||||||
|
|
||||||
|
argv[1] = getenv( "WINELOADER" );
|
||||||
|
if (argv[1]) preloader_exec( argv );
|
||||||
|
|
||||||
|
if ((path = getenv( "PATH" )))
|
||||||
|
{
|
||||||
|
for (p = strtok( strdup( path ), ":" ); p; p = strtok( NULL, ":" ))
|
||||||
|
{
|
||||||
|
argv[1] = build_path( p, loader );
|
||||||
|
preloader_exec( argv );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
argv[1] = build_path( BINDIR, loader );
|
||||||
|
preloader_exec( argv );
|
||||||
|
return STATUS_INVALID_IMAGE_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* exec_wineloader
|
||||||
|
*
|
||||||
|
* argv[0] and argv[1] must be reserved for the preloader and loader respectively.
|
||||||
|
*/
|
||||||
|
static NTSTATUS CDECL exec_wineloader( char **argv, int socketfd, int is_child_64bit,
|
||||||
|
ULONGLONG res_start, ULONGLONG res_end )
|
||||||
|
{
|
||||||
|
const char *loader = argv0;
|
||||||
|
const char *loader_env = getenv( "WINELOADER" );
|
||||||
|
char preloader_reserve[64], socket_env[64];
|
||||||
|
|
||||||
|
if (!is_win64 ^ !is_child_64bit)
|
||||||
|
{
|
||||||
|
/* remap WINELOADER to the alternate 32/64-bit version if necessary */
|
||||||
|
if (loader_env)
|
||||||
|
{
|
||||||
|
int len = strlen( loader_env );
|
||||||
|
char *env = malloc( sizeof("WINELOADER=") + len + 2 );
|
||||||
|
|
||||||
|
if (!env) return STATUS_NO_MEMORY;
|
||||||
|
strcpy( env, "WINELOADER=" );
|
||||||
|
strcat( env, loader_env );
|
||||||
|
if (is_child_64bit)
|
||||||
|
{
|
||||||
|
strcat( env, "64" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len += sizeof("WINELOADER=") - 1;
|
||||||
|
if (!strcmp( env + len - 2, "64" )) env[len - 2] = 0;
|
||||||
|
}
|
||||||
|
loader = env;
|
||||||
|
putenv( env );
|
||||||
|
}
|
||||||
|
else loader = is_child_64bit ? "wine64" : "wine";
|
||||||
|
}
|
||||||
|
|
||||||
|
signal( SIGPIPE, SIG_DFL );
|
||||||
|
|
||||||
|
sprintf( socket_env, "WINESERVERSOCKET=%u", socketfd );
|
||||||
|
sprintf( preloader_reserve, "WINEPRELOADRESERVE=%x%08x-%x%08x",
|
||||||
|
(ULONG)(res_start >> 32), (ULONG)res_start, (ULONG)(res_end >> 32), (ULONG)res_end );
|
||||||
|
|
||||||
|
putenv( preloader_reserve );
|
||||||
|
putenv( socket_env );
|
||||||
|
|
||||||
|
return loader_exec( loader, argv, is_child_64bit );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* map_so_dll
|
* map_so_dll
|
||||||
*
|
*
|
||||||
|
@ -619,6 +748,7 @@ static struct unix_funcs unix_funcs =
|
||||||
get_version,
|
get_version,
|
||||||
get_build_id,
|
get_build_id,
|
||||||
get_host_version,
|
get_host_version,
|
||||||
|
exec_wineloader,
|
||||||
map_so_dll,
|
map_so_dll,
|
||||||
mmap_add_reserved_area,
|
mmap_add_reserved_area,
|
||||||
mmap_remove_reserved_area,
|
mmap_remove_reserved_area,
|
||||||
|
|
|
@ -36,6 +36,10 @@ struct unix_funcs
|
||||||
const char * (CDECL *get_build_id)(void);
|
const char * (CDECL *get_build_id)(void);
|
||||||
void (CDECL *get_host_version)( const char **sysname, const char **release );
|
void (CDECL *get_host_version)( const char **sysname, const char **release );
|
||||||
|
|
||||||
|
/* loader functions */
|
||||||
|
NTSTATUS (CDECL *exec_wineloader)( char **argv, int socketfd, int is_child_64bit,
|
||||||
|
ULONGLONG res_start, ULONGLONG res_end );
|
||||||
|
|
||||||
/* virtual memory functions */
|
/* virtual memory functions */
|
||||||
NTSTATUS (CDECL *map_so_dll)( const IMAGE_NT_HEADERS *nt_descr, HMODULE module );
|
NTSTATUS (CDECL *map_so_dll)( const IMAGE_NT_HEADERS *nt_descr, HMODULE module );
|
||||||
void (CDECL *mmap_add_reserved_area)( void *addr, SIZE_T size );
|
void (CDECL *mmap_add_reserved_area)( void *addr, SIZE_T size );
|
||||||
|
|
Loading…
Reference in New Issue