Commit 5b4f3e8d authored by Alexandre Julliard's avatar Alexandre Julliard

Rewrote Unix process launching to allow passing startup information to

Winelib apps. Improved handling of execve() failures.
parent 045d81f1
......@@ -148,8 +148,9 @@ extern DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset );
void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value );
extern DWORD WINAPI MapProcessHandle( HANDLE handle );
/* scheduler/environ.c */
extern BOOL ENV_InheritEnvironment( LPCSTR env );
/* memory/environ.c */
extern BOOL ENV_BuildEnvironment(void);
extern BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env );
extern void ENV_FreeEnvironment( PDB *pdb );
/* scheduler/process.c */
......@@ -161,6 +162,10 @@ extern PDB *PROCESS_Create( struct _NE_MODULE *pModule, HFILE hFile,
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
BOOL inherit, DWORD flags,
STARTUPINFOA *startup, PROCESS_INFORMATION *info );
extern BOOL PROCESS_CreateUnixProcess( LPCSTR filename, LPCSTR cmd_line, LPCSTR env,
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
LPPROCESS_INFORMATION info );
extern void PROCESS_FreePDB( PDB *pdb );
extern void PROCESS_WalkProcess( void );
......
......@@ -104,8 +104,6 @@ typedef struct
/* Create a new process from the context of the parent */
struct new_process_request
{
IN int pinherit; /* process handle inherit flag */
IN int tinherit; /* thread handle inherit flag */
IN int inherit_all; /* inherit all handles from parent */
IN int create_flags; /* creation flags */
IN int start_flags; /* flags from startup info */
......@@ -114,13 +112,22 @@ struct new_process_request
IN int hstdout; /* handle for stdout */
IN int hstderr; /* handle for stderr */
IN int cmd_show; /* main window show mode */
IN void* env_ptr; /* pointer to environment (FIXME: hack) */
IN int alloc_fd; /* create the fd pair right now? */
};
/* Wait for the new process to start */
struct wait_process_request
{
IN int pinherit; /* process handle inherit flag */
IN int tinherit; /* thread handle inherit flag */
IN int timeout; /* wait timeout */
IN int cancel; /* cancel the process creation? */
OUT void* pid; /* process id */
OUT int phandle; /* process handle (in the current process) */
OUT void* tid; /* thread id */
OUT int thandle; /* thread handle (in the current process) */
OUT int event; /* event handle to signal startup */
IN char cmdline[1]; /* command line */
};
......@@ -146,14 +153,13 @@ struct init_process_request
{
IN void* ldt_copy; /* addr of LDT copy */
IN void* ldt_flags; /* addr of LDT flags */
IN int ppid; /* parent Unix pid */
OUT int start_flags; /* flags from startup info */
OUT int exe_file; /* file handle for main exe */
OUT int hstdin; /* handle for stdin */
OUT int hstdout; /* handle for stdout */
OUT int hstderr; /* handle for stderr */
OUT int cmd_show; /* main window show mode */
OUT void* env_ptr; /* pointer to environment (FIXME: hack) */
OUT char cmdline[1]; /* command line */
};
......@@ -1142,6 +1148,7 @@ struct get_atom_name_request
enum request
{
REQ_NEW_PROCESS,
REQ_WAIT_PROCESS,
REQ_NEW_THREAD,
REQ_BOOT_DONE,
REQ_INIT_PROCESS,
......@@ -1246,7 +1253,7 @@ enum request
REQ_NB_REQUESTS
};
#define SERVER_PROTOCOL_VERSION 9
#define SERVER_PROTOCOL_VERSION 10
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */
......
......@@ -119,9 +119,8 @@ typedef struct _TEB
/* scheduler/thread.c */
extern TEB *THREAD_CreateInitialThread( struct _PDB *pdb, int server_fd );
extern TEB *THREAD_Create( struct _PDB *pdb, void *pid, void *tid, int fd,
DWORD stack_size, BOOL alloc_stack16 );
extern TEB *THREAD_Init( struct _PDB *pdb );
extern TEB *THREAD_Create( struct _PDB *pdb, int fd, DWORD stack_size, BOOL alloc_stack16 );
extern TEB *THREAD_InitStack( TEB *teb, struct _PDB *pdb, DWORD stack_size, BOOL alloc_stack16 );
extern BOOL THREAD_IsWin16( TEB *thdb );
extern TEB *THREAD_IdToTEB( DWORD id );
......
......@@ -62,8 +62,6 @@ DEFAULT_DEBUG_CHANNEL(server);
*/
BOOL MAIN_MainInit( int argc, char *argv[], BOOL win32 )
{
char szGraphicsDriver[MAX_PATH];
/* store the program name */
argv0 = argv[0];
......@@ -94,15 +92,6 @@ BOOL MAIN_MainInit( int argc, char *argv[], BOOL win32 )
/* Initialize module loadorder */
if (!MODULE_InitLoadOrder()) return FALSE;
/* Initialize KERNEL */
if (!LoadLibraryA( "KERNEL32" )) return FALSE;
if (PROFILE_GetWineIniString( "Wine", "GraphicsDriver",
"x11drv", szGraphicsDriver, sizeof(szGraphicsDriver)))
{
if (!LoadLibraryA( szGraphicsDriver )) return FALSE;
}
return TRUE;
}
......
......@@ -684,60 +684,6 @@ BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
return ret;
}
/**********************************************************************
* MODULE_CreateUnixProcess
*/
static BOOL MODULE_CreateUnixProcess( LPCSTR filename, LPCSTR lpCmdLine,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInfo )
{
const char *argv[256], **argptr;
char *cmdline = NULL;
char *p;
const char *unixfilename = filename;
DOS_FULL_NAME full_name;
/* Build argument list */
argptr = argv;
p = cmdline = strdup(lpCmdLine);
if (strchr(filename, '/') || strchr(filename, ':') || strchr(filename, '\\'))
{
if ( DOSFS_GetFullName( filename, TRUE, &full_name ) )
unixfilename = full_name.long_name;
}
while (1)
{
while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
if (!*p) break;
*argptr++ = p;
while (*p && *p != ' ' && *p != '\t') p++;
}
*argptr++ = 0;
/* overwrite program name gotten from tidy_cmd */
argv[0] = unixfilename;
/* Fork and execute */
if ( !fork() )
{
/* Note: don't use Wine routines here, as this process
has not been correctly initialized! */
execvp( argv[0], (char**)argv );
exit( 1 );
}
/* Fake success return value */
memset( lpProcessInfo, '\0', sizeof( *lpProcessInfo ) );
lpProcessInfo->hProcess = INVALID_HANDLE_VALUE;
lpProcessInfo->hThread = INVALID_HANDLE_VALUE;
if (cmdline) free(cmdline);
SetLastError( ERROR_SUCCESS );
return TRUE;
}
/***********************************************************************
* WinExec16 (KERNEL.166)
......@@ -1027,7 +973,10 @@ BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
{
CloseHandle( hFile );
/* FIXME: Try Unix executable only when appropriate! */
retv = MODULE_CreateUnixProcess( name, tidy_cmdline, lpStartupInfo, lpProcessInfo );
retv = PROCESS_CreateUnixProcess( name, tidy_cmdline, lpEnvironment,
lpProcessAttributes, lpThreadAttributes,
bInheritHandles, dwCreationFlags,
lpStartupInfo, lpProcessInfo );
goto done;
}
......
......@@ -67,7 +67,7 @@ static LPCSTR ENV_FindVariable( LPCSTR env, LPCSTR name, INT len )
*
* Build the environment for the initial process
*/
static BOOL ENV_BuildEnvironment( PDB *pdb )
BOOL ENV_BuildEnvironment(void)
{
extern char **environ;
LPSTR p, *e;
......@@ -81,7 +81,7 @@ static BOOL ENV_BuildEnvironment( PDB *pdb )
/* Now allocate the environment */
if (!(p = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
pdb->env_db->environ = p;
PROCESS_Current()->env_db->environ = p;
/* And fill it with the Unix environment */
......@@ -104,20 +104,11 @@ static BOOL ENV_BuildEnvironment( PDB *pdb )
* Make a process inherit the environment from its parent or from an
* explicit environment.
*/
BOOL ENV_InheritEnvironment( LPCSTR env )
BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env )
{
DWORD size;
LPCSTR src;
LPSTR dst;
PDB *pdb = PROCESS_Current();
/* FIXME: should lock the parent environment */
if (!env)
{
if (!pdb->parent) /* initial process */
return ENV_BuildEnvironment( pdb );
env = pdb->parent->env_db->environ;
}
/* Compute the environment size */
......
......@@ -42,6 +42,13 @@ void MAIN_EmulatorRun( void )
char startProg[256], defProg[256];
int i, tasks = 0;
MSG msg;
char szGraphicsDriver[MAX_PATH];
if (PROFILE_GetWineIniString( "Wine", "GraphicsDriver",
"x11drv", szGraphicsDriver, sizeof(szGraphicsDriver)))
{
if (!LoadLibraryA( szGraphicsDriver )) return FALSE;
}
/* Load system DLLs into the initial process (and initialize them) */
if ( !LoadLibrary16("GDI.EXE" ) || !LoadLibraryA("GDI32.DLL" )
......@@ -102,6 +109,12 @@ int main( int argc, char *argv[] )
/* Initialize everything */
if (!MAIN_MainInit( argc, argv, FALSE )) return 1;
if (!THREAD_InitStack( NtCurrentTeb(), PROCESS_Current(), 0, TRUE )) return 1;
SIGNAL_Init(); /* reinitialize signal stack */
/* Initialize KERNEL */
if (!LoadLibraryA( "KERNEL32" )) return FALSE;
/* Create initial task */
if ( !(pModule = NE_GetPtr( GetModuleHandle16( "KERNEL" ) )) ) return 1;
if ( !TASK_Create( pModule, FALSE ) ) return 1;
......
......@@ -85,6 +85,8 @@ static BOOL THREAD_InitTEB( TEB *teb, PDB *pdb )
teb->process = pdb;
teb->exit_code = STILL_ACTIVE;
teb->socket = -1;
teb->stack_top = (void *)~0UL;
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
teb->StaticUnicodeString.Buffer = (PWSTR)teb->StaticUnicodeBuffer;
teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, SEGMENT_DATA, TRUE, FALSE );
......@@ -194,20 +196,17 @@ error:
/***********************************************************************
* THREAD_CreateInitialThread
* THREAD_Init
*
* Create the initial thread.
* Setup the initial thread.
*
* NOTES: The first allocated TEB on NT is at 0x7ffde000.
*/
TEB *THREAD_CreateInitialThread( PDB *pdb, int server_fd )
TEB *THREAD_Init( struct _PDB *pdb )
{
if (!THREAD_InitTEB( &initial_teb, pdb )) return NULL;
SYSDEPS_SetCurThread( &initial_teb );
initial_teb.socket = server_fd;
if (CLIENT_InitThread()) return NULL;
return THREAD_InitStack( &initial_teb, pdb, 0, TRUE );
return &initial_teb;
}
......@@ -215,15 +214,12 @@ TEB *THREAD_CreateInitialThread( PDB *pdb, int server_fd )
* THREAD_Create
*
*/
TEB *THREAD_Create( PDB *pdb, void *pid, void *tid, int fd,
DWORD stack_size, BOOL alloc_stack16 )
TEB *THREAD_Create( PDB *pdb, int fd, DWORD stack_size, BOOL alloc_stack16 )
{
TEB *teb;
if ((teb = THREAD_InitStack( NULL, pdb, stack_size, alloc_stack16 )))
{
teb->pid = pid;
teb->tid = tid;
teb->socket = fd;
fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
TRACE("(%p) succeeded\n", teb);
......@@ -266,14 +262,15 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
struct new_thread_request *req = get_req_buffer();
int socket, handle = -1;
TEB *teb;
void *tid;
req->suspend = ((flags & CREATE_SUSPENDED) != 0);
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
if (server_call_fd( REQ_NEW_THREAD, -1, &socket )) return 0;
handle = req->handle;
tid = req->tid;
if (!(teb = THREAD_Create( PROCESS_Current(), (void *)GetCurrentProcessId(),
req->tid, socket, stack, TRUE )))
if (!(teb = THREAD_Create( PROCESS_Current(), socket, stack, TRUE )))
{
close( socket );
return 0;
......@@ -282,7 +279,7 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
teb->entry_point = start;
teb->entry_arg = param;
teb->startup = THREAD_Start;
if (id) *id = (DWORD)teb->tid;
if (id) *id = (DWORD)tid;
if (SYSDEPS_SpawnThread( teb ) == -1)
{
CloseHandle( handle );
......
......@@ -48,7 +48,6 @@ struct process
struct process_dll exe; /* main exe file */
void *ldt_copy; /* pointer to LDT copy in client addr space */
void *ldt_flags; /* pointer to LDT flags in client addr space */
struct new_process_request *info; /* startup info (freed after startup) */
};
struct process_snapshot
......@@ -67,9 +66,7 @@ struct module_snapshot
/* process functions */
extern struct thread *create_process( int fd, struct process *parent,
struct new_process_request *req,
const char *cmd_line, size_t len );
extern struct thread *create_process( int fd );
extern struct process *get_process_from_id( void *id );
extern struct process *get_process_from_handle( int handle, unsigned int access );
extern int process_set_debugger( struct process *process, struct thread *thread );
......
......@@ -289,7 +289,7 @@ static void master_socket_poll_event( struct object *obj, int event )
struct sockaddr_un dummy;
int len = sizeof(dummy);
int client = accept( master_socket->obj.fd, (struct sockaddr *) &dummy, &len );
if (client != -1) create_process( client, NULL, NULL, "", 1 );
if (client != -1) create_process( client );
}
}
......
......@@ -71,6 +71,7 @@ static inline size_t get_req_strlenW( const void *req, const WCHAR *str )
/* ### make_requests begin ### */
DECL_HANDLER(new_process);
DECL_HANDLER(wait_process);
DECL_HANDLER(new_thread);
DECL_HANDLER(boot_done);
DECL_HANDLER(init_process);
......@@ -179,6 +180,7 @@ typedef void (*req_handler)( void *req );
static const req_handler req_handlers[REQ_NB_REQUESTS] =
{
(req_handler)req_new_process,
(req_handler)req_wait_process,
(req_handler)req_new_thread,
(req_handler)req_boot_done,
(req_handler)req_init_process,
......
......@@ -116,7 +116,7 @@ static int alloc_client_buffer( struct thread *thread )
}
/* create a new thread */
struct thread *create_thread( int fd, struct process *process, int suspend )
struct thread *create_thread( int fd, struct process *process )
{
struct thread *thread;
......@@ -131,6 +131,7 @@ struct thread *create_thread( int fd, struct process *process, int suspend )
thread->mutex = NULL;
thread->debug_ctx = NULL;
thread->debug_event = NULL;
thread->info = NULL;
thread->wait = NULL;
thread->apc = NULL;
thread->apc_count = 0;
......@@ -143,7 +144,7 @@ struct thread *create_thread( int fd, struct process *process, int suspend )
thread->prev = NULL;
thread->priority = THREAD_PRIORITY_NORMAL;
thread->affinity = 1;
thread->suspend = (suspend != 0);
thread->suspend = 0;
thread->buffer = (void *)-1;
thread->last_req = REQ_GET_THREAD_BUFFER;
thread->process = (struct process *)grab_object( process );
......@@ -194,6 +195,7 @@ static void destroy_thread( struct object *obj )
if (thread->prev) thread->prev->next = thread->next;
else first_thread = thread->next;
if (thread->apc) free( thread->apc );
if (thread->info) release_object( thread->info );
if (thread->buffer != (void *)-1) munmap( thread->buffer, MAX_REQUEST_LENGTH );
if (thread->pass_fd != -1) close( thread->pass_fd );
}
......@@ -625,8 +627,9 @@ DECL_HANDLER(new_thread)
if (socketpair( AF_UNIX, SOCK_STREAM, 0, sock ) != -1)
{
if ((thread = create_thread( sock[0], current->process, req->suspend )))
if ((thread = create_thread( sock[0], current->process )))
{
if (req->suspend) thread->suspend++;
req->tid = thread;
if ((req->handle = alloc_handle( current->process, thread,
THREAD_ALL_ACCESS, req->inherit )) != -1)
......
......@@ -21,6 +21,7 @@ struct thread_apc;
struct mutex;
struct debug_ctx;
struct debug_event;
struct startup_info;
enum run_state
{
......@@ -40,6 +41,7 @@ struct thread
struct mutex *mutex; /* list of currently owned mutexes */
struct debug_ctx *debug_ctx; /* debugger context if this thread is a debugger */
struct debug_event *debug_event; /* debug event being sent to debugger */
struct startup_info*info; /* startup info for child process */
struct thread_wait *wait; /* current wait condition if sleeping */
struct thread_apc *apc; /* list of async procedure calls */
int apc_count; /* number of outstanding APCs */
......@@ -72,7 +74,7 @@ extern struct thread *current;
/* thread functions */
extern struct thread *create_thread( int fd, struct process *process, int suspend );
extern struct thread *create_thread( int fd, struct process *process );
extern struct thread *get_thread_from_id( void *id );
extern struct thread *get_thread_from_handle( int handle, unsigned int access );
extern struct thread *get_thread_from_pid( int pid );
......
......@@ -215,8 +215,6 @@ typedef void (*dump_func)( const void *req );
static void dump_new_process_request( const struct new_process_request *req )
{
fprintf( stderr, " pinherit=%d,", req->pinherit );
fprintf( stderr, " tinherit=%d,", req->tinherit );
fprintf( stderr, " inherit_all=%d,", req->inherit_all );
fprintf( stderr, " create_flags=%d,", req->create_flags );
fprintf( stderr, " start_flags=%d,", req->start_flags );
......@@ -225,12 +223,18 @@ static void dump_new_process_request( const struct new_process_request *req )
fprintf( stderr, " hstdout=%d,", req->hstdout );
fprintf( stderr, " hstderr=%d,", req->hstderr );
fprintf( stderr, " cmd_show=%d,", req->cmd_show );
fprintf( stderr, " env_ptr=%p,", req->env_ptr );
fprintf( stderr, " cmdline=" );
dump_string( req, req->cmdline );
fprintf( stderr, " alloc_fd=%d", req->alloc_fd );
}
static void dump_wait_process_request( const struct wait_process_request *req )
{
fprintf( stderr, " pinherit=%d,", req->pinherit );
fprintf( stderr, " tinherit=%d,", req->tinherit );
fprintf( stderr, " timeout=%d,", req->timeout );
fprintf( stderr, " cancel=%d", req->cancel );
}
static void dump_new_process_reply( const struct new_process_request *req )
static void dump_wait_process_reply( const struct wait_process_request *req )
{
fprintf( stderr, " pid=%p,", req->pid );
fprintf( stderr, " phandle=%d,", req->phandle );
......@@ -259,7 +263,8 @@ static void dump_boot_done_request( const struct boot_done_request *req )
static void dump_init_process_request( const struct init_process_request *req )
{
fprintf( stderr, " ldt_copy=%p,", req->ldt_copy );
fprintf( stderr, " ldt_flags=%p", req->ldt_flags );
fprintf( stderr, " ldt_flags=%p,", req->ldt_flags );
fprintf( stderr, " ppid=%d", req->ppid );
}
static void dump_init_process_reply( const struct init_process_request *req )
......@@ -269,10 +274,7 @@ static void dump_init_process_reply( const struct init_process_request *req )
fprintf( stderr, " hstdin=%d,", req->hstdin );
fprintf( stderr, " hstdout=%d,", req->hstdout );
fprintf( stderr, " hstderr=%d,", req->hstderr );
fprintf( stderr, " cmd_show=%d,", req->cmd_show );
fprintf( stderr, " env_ptr=%p,", req->env_ptr );
fprintf( stderr, " cmdline=" );
dump_string( req, req->cmdline );
fprintf( stderr, " cmd_show=%d", req->cmd_show );
}
static void dump_init_process_done_request( const struct init_process_done_request *req )
......@@ -1326,6 +1328,7 @@ static void dump_get_atom_name_reply( const struct get_atom_name_request *req )
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request,
(dump_func)dump_wait_process_request,
(dump_func)dump_new_thread_request,
(dump_func)dump_boot_done_request,
(dump_func)dump_init_process_request,
......@@ -1430,7 +1433,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
};
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_reply,
(dump_func)0,
(dump_func)dump_wait_process_reply,
(dump_func)dump_new_thread_reply,
(dump_func)0,
(dump_func)dump_init_process_reply,
......@@ -1536,6 +1540,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
static const char * const req_names[REQ_NB_REQUESTS] = {
"new_process",
"wait_process",
"new_thread",
"boot_done",
"init_process",
......
......@@ -1533,7 +1533,7 @@ DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
return 0;
}
pdb = PROCESS_IdToPDB( pid );
if (!(pdb = PROCESS_IdToPDB( pid ))) return 0;
/* check whether we are waiting for a win32 process or the win16 subsystem */
if ( pdb->flags & PDB32_WIN16_PROC ) {
......
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