Commit 412555e0 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Move fork and exec support to the Unix library.

parent 22970932
......@@ -53,6 +53,7 @@ C_SRCS = \
unix/debug.c \
unix/env.c \
unix/loader.c \
unix/process.c \
unix/server.c \
unix/signal_arm.c \
unix/signal_arm64.c \
......
......@@ -408,6 +408,14 @@ static void init_unix_codepage(void)
#endif /* __APPLE__ || __ANDROID__ */
static inline SIZE_T get_env_length( const WCHAR *env )
{
const WCHAR *end = env;
while (*end) end += wcslen(end) + 1;
return end + 1 - env;
}
/***********************************************************************
* is_special_env_var
*
......@@ -446,6 +454,122 @@ DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD dstlen )
}
/******************************************************************
* ntdll_wcstoumbs
*/
int ntdll_wcstoumbs( const WCHAR *src, DWORD srclen, char *dst, DWORD dstlen, BOOL strict )
{
DWORD i, reslen;
if (unix_table.CodePage)
{
if (unix_table.DBCSOffsets)
{
const unsigned short *uni2cp = unix_table.WideCharTable;
for (i = dstlen; srclen && i; i--, srclen--, src++)
{
unsigned short ch = uni2cp[*src];
if (ch >> 8)
{
if (strict && unix_table.DBCSOffsets[unix_table.DBCSOffsets[ch >> 8] + (ch & 0xff)] != *src)
return -1;
if (i == 1) break; /* do not output a partial char */
i--;
*dst++ = ch >> 8;
}
else
{
if (unix_table.MultiByteTable[ch] != *src) return -1;
*dst++ = (char)ch;
}
}
reslen = dstlen - i;
}
else
{
const unsigned char *uni2cp = unix_table.WideCharTable;
reslen = min( srclen, dstlen );
for (i = 0; i < reslen; i++)
{
unsigned char ch = uni2cp[src[i]];
if (strict && unix_table.MultiByteTable[ch] != src[i]) return -1;
dst[i] = ch;
}
}
}
else RtlUnicodeToUTF8N( dst, dstlen, &reslen, src, srclen * sizeof(WCHAR) );
return reslen;
}
/***********************************************************************
* 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 = malloc( 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 = malloc( 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;
}
free( env );
return envp;
}
/***********************************************************************
* set_process_name
*
......
......@@ -424,8 +424,8 @@ static NTSTATUS loader_exec( const char *loader, char **argv, int is_child_64bit
*
* 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 )
NTSTATUS 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" );
......@@ -906,7 +906,6 @@ static struct unix_funcs unix_funcs =
get_version,
get_build_id,
get_host_version,
exec_wineloader,
map_so_dll,
virtual_map_section,
virtual_get_system_info,
......@@ -925,6 +924,9 @@ static struct unix_funcs unix_funcs =
exit_thread,
exit_process,
get_thread_ldt_entry,
spawn_process,
exec_process,
fork_and_exec,
wine_server_call,
server_send_fd,
server_get_unix_fd,
......
......@@ -114,6 +114,11 @@ extern TEB * CDECL init_threading( int *nb_threads_ptr, struct ldt_copy **ldt_co
extern void CDECL DECLSPEC_NORETURN exit_thread( int status ) DECLSPEC_HIDDEN;
extern void CDECL DECLSPEC_NORETURN exit_process( int status ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_len ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd,
const char *unixdir, char *winedebug, const pe_image_info_t *pe_info ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL exec_process( const UNICODE_STRING *cmdline, const pe_image_info_t *pe_info ) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fork_and_exec( const char *unix_name, const char *unix_dir,
const RTL_USER_PROCESS_PARAMETERS *params ) DECLSPEC_HIDDEN;
extern const char *data_dir DECLSPEC_HIDDEN;
extern const char *build_dir DECLSPEC_HIDDEN;
......@@ -129,6 +134,10 @@ extern struct _KUSER_SHARED_DATA *user_shared_data DECLSPEC_HIDDEN;
extern void init_environment( int argc, char *argv[], char *envp[] ) DECLSPEC_HIDDEN;
extern DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD dstlen ) DECLSPEC_HIDDEN;
extern int ntdll_wcstoumbs( const WCHAR *src, DWORD srclen, char *dst, DWORD dstlen, BOOL strict ) DECLSPEC_HIDDEN;
extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN;
extern NTSTATUS exec_wineloader( char **argv, int socketfd, int is_child_64bit,
ULONGLONG res_start, ULONGLONG res_end ) DECLSPEC_HIDDEN;
extern unsigned int server_call_unlocked( void *req_ptr ) DECLSPEC_HIDDEN;
extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ) DECLSPEC_HIDDEN;
......
......@@ -28,7 +28,7 @@ struct ldt_copy;
struct msghdr;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 40
#define NTDLL_UNIXLIB_VERSION 41
struct unix_funcs
{
......@@ -180,10 +180,6 @@ struct unix_funcs
const char * (CDECL *get_build_id)(void);
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 */
NTSTATUS (CDECL *map_so_dll)( const IMAGE_NT_HEADERS *nt_descr, HMODULE module );
NTSTATUS (CDECL *virtual_map_section)( HANDLE handle, PVOID *addr_ptr, unsigned short zero_bits_64, SIZE_T commit_size,
......@@ -208,6 +204,12 @@ struct unix_funcs
void (CDECL *exit_thread)( int status );
void (CDECL *exit_process)( int status );
NTSTATUS (CDECL *get_thread_ldt_entry)( HANDLE handle, void *data, ULONG len, ULONG *ret_len );
NTSTATUS (CDECL *spawn_process)( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd,
const char *unixdir, char *winedebug,
const pe_image_info_t *pe_info );
NTSTATUS (CDECL *exec_process)( const UNICODE_STRING *cmdline, const pe_image_info_t *pe_info );
NTSTATUS (CDECL *fork_and_exec)( const char *unix_name, const char *unix_dir,
const RTL_USER_PROCESS_PARAMETERS *params );
/* server functions */
unsigned int (CDECL *server_call)( void *req_ptr );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment