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;
......
......@@ -5,6 +5,8 @@
*/
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
......@@ -44,31 +46,6 @@ static PDB *PROCESS_First = &initial_pdb;
/***********************************************************************
* PROCESS_WalkProcess
*/
void PROCESS_WalkProcess(void)
{
PDB *pdb;
char *name;
pdb = PROCESS_First;
MESSAGE( " pid PDB #th modref module \n" );
while(pdb)
{
if (pdb == &initial_pdb)
name = "initial PDB";
else
name = (pdb->exe_modref) ? pdb->exe_modref->filename : "";
MESSAGE( " %8p %8p %5d %8p %s\n", pdb->server_pid, pdb,
pdb->threads, pdb->exe_modref, name);
pdb = pdb->next;
}
return;
}
/***********************************************************************
* PROCESS_IdToPDB
*
* Convert a process id to a PDB, making sure it is valid.
......@@ -210,27 +187,15 @@ void PROCESS_CallUserSignalProc( UINT uCode, HMODULE hModule )
static BOOL PROCESS_CreateEnvDB(void)
{
struct init_process_request *req = get_req_buffer();
STARTUPINFOA *startup;
ENVDB *env_db;
char cmd_line[4096];
PDB *pdb = PROCESS_Current();
/* Allocate the env DB */
if (!(env_db = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ENVDB) )))
return FALSE;
pdb->env_db = env_db;
InitializeCriticalSection( &env_db->section );
/* Allocate and fill the startup info */
if (!(startup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(STARTUPINFOA) )))
return FALSE;
env_db->startup_info = startup;
ENVDB *env_db = pdb->env_db;
STARTUPINFOA *startup = env_db->startup_info;
/* Retrieve startup info from the server */
req->ldt_copy = ldt_copy;
req->ldt_flags = ldt_flags_copy;
req->ppid = getppid();
if (server_call( REQ_INIT_PROCESS )) return FALSE;
pdb->exe_file = req->exe_file;
startup->dwFlags = req->start_flags;
......@@ -238,16 +203,6 @@ static BOOL PROCESS_CreateEnvDB(void)
env_db->hStdin = startup->hStdInput = req->hstdin;
env_db->hStdout = startup->hStdOutput = req->hstdout;
env_db->hStderr = startup->hStdError = req->hstderr;
lstrcpynA( cmd_line, req->cmdline, sizeof(cmd_line) );
/* Copy the parent environment */
if (!ENV_InheritEnvironment( req->env_ptr )) return FALSE;
/* Copy the command line */
if (!(pdb->env_db->cmd_line = HEAP_strdupA( GetProcessHeap(), 0, cmd_line )))
return FALSE;
return TRUE;
}
......@@ -277,7 +232,8 @@ void PROCESS_FreePDB( PDB *pdb )
*/
static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
{
PDB *pdb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PDB) );
PDB *pdb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(PDB) + sizeof(ENVDB) + sizeof(STARTUPINFOA) );
if (!pdb) return NULL;
pdb->exit_code = STILL_ACTIVE;
......@@ -291,6 +247,11 @@ static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
pdb->next = PROCESS_First;
pdb->winver = 0xffff; /* to be determined */
pdb->main_queue = INVALID_HANDLE_VALUE16;
pdb->env_db = (ENVDB *)(pdb + 1);
pdb->env_db->startup_info = (STARTUPINFOA *)(pdb->env_db + 1);
InitializeCriticalSection( &pdb->env_db->section );
PROCESS_First = pdb;
return pdb;
}
......@@ -303,10 +264,6 @@ BOOL PROCESS_Init( BOOL win32 )
{
struct init_process_request *req;
TEB *teb;
int server_fd;
/* Start the server */
server_fd = CLIENT_InitServer();
/* Fill the initial process structure */
initial_pdb.exit_code = STILL_ACTIVE;
......@@ -320,12 +277,31 @@ BOOL PROCESS_Init( BOOL win32 )
initial_pdb.winver = 0xffff; /* to be determined */
initial_pdb.main_queue = INVALID_HANDLE_VALUE16;
initial_envdb.startup_info = &initial_startup;
teb = THREAD_Init( &initial_pdb );
/* Setup the server connection */
teb->socket = CLIENT_InitServer();
if (CLIENT_InitThread()) return FALSE;
/* Initialize virtual memory management */
if (!VIRTUAL_Init()) return FALSE;
/* Create the initial thread structure and socket pair */
if (!(teb = THREAD_CreateInitialThread( &initial_pdb, server_fd ))) return FALSE;
/* Retrieve startup info from the server */
req = get_req_buffer();
req->ldt_copy = ldt_copy;
req->ldt_flags = ldt_flags_copy;
req->ppid = getppid();
if (server_call( REQ_INIT_PROCESS )) return FALSE;
initial_pdb.exe_file = req->exe_file;
initial_startup.dwFlags = req->start_flags;
initial_startup.wShowWindow = req->cmd_show;
initial_envdb.hStdin = initial_startup.hStdInput = req->hstdin;
initial_envdb.hStdout = initial_startup.hStdOutput = req->hstdout;
initial_envdb.hStderr = initial_startup.hStdError = req->hstderr;
initial_envdb.cmd_line = "";
/* Initialize signal handling */
if (!SIGNAL_Init()) return FALSE;
/* Remember TEB selector of initial process for emergency use */
SYSLEVEL_EmergencyTeb = teb->teb_sel;
......@@ -342,24 +318,8 @@ BOOL PROCESS_Init( BOOL win32 )
initial_pdb.idle_event = CreateEventA ( NULL, TRUE, FALSE, NULL );
initial_pdb.idle_event = ConvertToGlobalHandle ( initial_pdb.idle_event );
/* Initialize signal handling */
if (!SIGNAL_Init()) return FALSE;
/* Retrieve startup info from the server */
req = get_req_buffer();
req->ldt_copy = ldt_copy;
req->ldt_flags = ldt_flags_copy;
if (server_call( REQ_INIT_PROCESS )) return FALSE;
initial_pdb.exe_file = req->exe_file;
initial_startup.dwFlags = req->start_flags;
initial_startup.wShowWindow = req->cmd_show;
initial_envdb.hStdin = initial_startup.hStdInput = req->hstdin;
initial_envdb.hStdout = initial_startup.hStdOutput = req->hstdout;
initial_envdb.hStderr = initial_startup.hStdError = req->hstderr;
initial_envdb.cmd_line = "";
/* Copy the parent environment */
if (!ENV_InheritEnvironment( NULL )) return FALSE;
if (!ENV_BuildEnvironment()) return FALSE;
/* Create the SEGPTR heap */
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
......@@ -373,6 +333,33 @@ BOOL PROCESS_Init( BOOL win32 )
/***********************************************************************
* load_system_dlls
*
* Load system DLLs into the initial process (and initialize them)
*/
static int load_system_dlls(void)
{
char driver[MAX_PATH];
if (!LoadLibraryA( "KERNEL32" )) return 0;
PROFILE_GetWineIniString( "Wine", "GraphicsDriver", "x11drv", driver, sizeof(driver) );
if (!LoadLibraryA( driver ))
{
MESSAGE( "Could not load graphics driver '%s'\n", driver );
return 0;
}
if (!LoadLibraryA("GDI32.DLL")) return 0;
if (!LoadLibrary16("GDI.EXE")) return 0;
if (!LoadLibrary16("USER.EXE")) return 0;
if (!LoadLibraryA("USER32.DLL")) return 0;
return 1;
}
/***********************************************************************
* start_process
*
* Startup routine of a new Win32 process. Runs on the new process stack.
......@@ -409,13 +396,8 @@ static void start_process(void)
if (pdb->flags & PDB32_CONSOLE_PROC) AllocConsole();
/* Load system DLLs into the initial process (and initialize them) */
if (!LoadLibraryA( "KERNEL32" )) goto error;
if (!LoadLibraryA( "x11drv" )) goto error;
if ( !LoadLibrary16("GDI.EXE" ) || !LoadLibraryA("GDI32.DLL" )
|| !LoadLibrary16("USER.EXE") || !LoadLibraryA("USER32.DLL"))
goto error;
/* Load the system dlls */
if (!load_system_dlls()) goto error;
/* Get pointers to USER routines called by KERNEL */
THUNK_InitCallout();
......@@ -548,6 +530,250 @@ void PROCESS_InitWinelib( int argc, char *argv[] )
/***********************************************************************
* build_argv
*
* Build an argv array from a command-line.
* The command-line is modified to insert nulls.
*/
static char **build_argv( char *cmdline, char *argv0 )
{
char **argv;
int count = 1;
char *p = cmdline;
while (*p)
{
while (*p && isspace(*p)) p++;
if (!*p) break;
count++;
while (*p && !isspace(*p)) p++;
}
if (argv0) count++;
if ((argv = malloc( count * sizeof(*argv) )))
{
char **argvptr = argv;
if (argv0) *argvptr++ = argv0;
p = cmdline;
while (*p)
{
while (*p && isspace(*p)) *p++ = 0;
if (!*p) break;
*argvptr++ = p;
while (*p && !isspace(*p)) p++;
}
*argvptr = 0;
}
return argv;
}
/***********************************************************************
* build_envp
*
* Build the environment of a new child process.
*/
static char **build_envp( const char *env )
{
const char *p;
char **envp;
int count;
for (p = env, count = 0; *p; count++) p += strlen(p) + 1;
count += 3;
if ((envp = malloc( count * sizeof(*envp) )))
{
extern char **environ;
char **envptr = envp;
char **unixptr = environ;
/* first put PATH, HOME and WINEPREFIX from the unix env */
for (unixptr = environ; unixptr && *unixptr; unixptr++)
if (!memcmp( *unixptr, "PATH=", 5 ) ||
!memcmp( *unixptr, "HOME=", 5 ) ||
!memcmp( *unixptr, "WINEPREFIX=", 11 )) *envptr++ = *unixptr;
/* now put the Windows environment strings */
for (p = env; *p; p += strlen(p) + 1)
{
if (memcmp( p, "PATH=", 5 ) &&
memcmp( p, "HOME=", 5 ) &&
memcmp( p, "WINEPREFIX=", 11 )) *envptr++ = (char *)p;
}
*envptr = 0;
}
return envp;
}
/***********************************************************************
* find_wine_binary
*
* Locate the Wine binary to exec for a new Win32 process.
*/
static void exec_wine_binary( char **argv, char **envp )
{
const char *path, *pos, *ptr;
/* first try bin directory */
argv[0] = BINDIR "/wine";
execve( argv[0], argv, envp );
/* now try the path of argv0 of the current binary */
if (!(argv[0] = malloc( strlen(argv0) + 6 ))) return;
if ((ptr = strrchr( argv0, '/' )))
{
memcpy( argv[0], argv0, ptr - argv0 );
strcpy( argv[0] + (ptr - argv0), "/wine" );
execve( argv[0], argv, envp );
}
free( argv[0] );
/* now search in the Unix path */
if ((path = getenv( "PATH" )))
{
if (!(argv[0] = malloc( strlen(path) + 6 ))) return;
pos = path;
for (;;)
{
while (*pos == ':') pos++;
if (!*pos) break;
if (!(ptr = strchr( pos, ':' ))) ptr = pos + strlen(pos);
memcpy( argv[0], pos, ptr - pos );
strcpy( argv[0] + (ptr - pos), "/wine" );
execve( argv[0], argv, envp );
pos = ptr;
}
}
free( argv[0] );
/* finally try the current directory */
argv[0] = "./wine";
execve( argv[0], argv, envp );
}
/***********************************************************************
* fork_and_exec
*
* Fork and exec a new Unix process, checking for errors.
*/
static int fork_and_exec( const char *filename, const char *cmdline, const char *env )
{
int fd[2];
int pid, err;
if (pipe(fd) == -1)
{
FILE_SetDosError();
return -1;
}
fcntl( fd[1], F_SETFD, 1 ); /* set close on exec */
if (!(pid = fork())) /* child */
{
char **argv = build_argv( (char *)cmdline, NULL );
char **envp = build_envp( env );
close( fd[0] );
if (argv && envp) execve( filename, argv, envp );
err = errno;
write( fd[1], &err, sizeof(err) );
_exit(1);
}
close( fd[1] );
if ((pid != -1) && (read( fd[0], &err, sizeof(err) ) > 0)) /* exec failed */
{
errno = err;
pid = -1;
}
if (pid == -1) FILE_SetDosError();
close( fd[0] );
return pid;
}
/***********************************************************************
* PROCESS_CreateUnixProcess
*/
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 )
{
int pid;
const char *unixfilename = filename;
DOS_FULL_NAME full_name;
HANDLE load_done_evt = -1;
struct new_process_request *req = get_req_buffer();
struct wait_process_request *wait_req = get_req_buffer();
info->hThread = info->hProcess = INVALID_HANDLE_VALUE;
if (DOSFS_GetFullName( filename, TRUE, &full_name )) unixfilename = full_name.long_name;
/* create the process on the server side */
req->inherit_all = inherit;
req->create_flags = flags;
req->start_flags = startup->dwFlags;
req->exe_file = -1;
if (startup->dwFlags & STARTF_USESTDHANDLES)
{
req->hstdin = startup->hStdInput;
req->hstdout = startup->hStdOutput;
req->hstderr = startup->hStdError;
}
else
{
req->hstdin = GetStdHandle( STD_INPUT_HANDLE );
req->hstdout = GetStdHandle( STD_OUTPUT_HANDLE );
req->hstderr = GetStdHandle( STD_ERROR_HANDLE );
}
req->cmd_show = startup->wShowWindow;
req->alloc_fd = 0;
if (server_call( REQ_NEW_PROCESS )) return FALSE;
/* fork and execute */
pid = fork_and_exec( unixfilename, cmd_line, env ? env : GetEnvironmentStringsA() );
wait_req->cancel = (pid == -1);
wait_req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
wait_req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle);
wait_req->timeout = 2000;
if (server_call( REQ_WAIT_PROCESS ) || (pid == -1)) goto error;
info->dwProcessId = (DWORD)wait_req->pid;
info->dwThreadId = (DWORD)wait_req->tid;
info->hProcess = wait_req->phandle;
info->hThread = wait_req->thandle;
load_done_evt = wait_req->event;
/* Wait until process is initialized (or initialization failed) */
if (load_done_evt != -1)
{
DWORD res;
HANDLE handles[2];
handles[0] = info->hProcess;
handles[1] = load_done_evt;
res = WaitForMultipleObjects( 2, handles, FALSE, INFINITE );
CloseHandle( load_done_evt );
if (res == STATUS_WAIT_0) /* the process died */
{
DWORD exitcode;
if (GetExitCodeProcess( info->hProcess, &exitcode )) SetLastError( exitcode );
CloseHandle( info->hThread );
CloseHandle( info->hProcess );
return FALSE;
}
}
return TRUE;
error:
if (load_done_evt != -1) CloseHandle( load_done_evt );
if (info->hThread != INVALID_HANDLE_VALUE) CloseHandle( info->hThread );
if (info->hProcess != INVALID_HANDLE_VALUE) CloseHandle( info->hProcess );
return FALSE;
}
/***********************************************************************
* PROCESS_Start
*
* Startup routine of a new process. Called in the context of the new process.
......@@ -691,6 +917,7 @@ PDB *PROCESS_Create( NE_MODULE *pModule, HFILE hFile, LPCSTR cmd_line, LPCSTR en
BOOL alloc_stack16;
int fd = -1;
struct new_process_request *req = get_req_buffer();
struct wait_process_request *wait_req = get_req_buffer();
TEB *teb = NULL;
PDB *parent = PROCESS_Current();
PDB *pdb = PROCESS_CreatePDB( parent, inherit );
......@@ -698,10 +925,11 @@ PDB *PROCESS_Create( NE_MODULE *pModule, HFILE hFile, LPCSTR cmd_line, LPCSTR en
if (!pdb) return NULL;
info->hThread = info->hProcess = INVALID_HANDLE_VALUE;
if (!(pdb->env_db->cmd_line = HEAP_strdupA( GetProcessHeap(), 0, cmd_line ))) goto error;
if (!ENV_InheritEnvironment( pdb, env ? env : GetEnvironmentStringsA() )) goto error;
/* Create the process on the server side */
req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle);
req->inherit_all = 2 /*inherit*/; /* HACK! */
req->create_flags = flags;
req->start_flags = startup->dwFlags;
......@@ -719,15 +947,8 @@ PDB *PROCESS_Create( NE_MODULE *pModule, HFILE hFile, LPCSTR cmd_line, LPCSTR en
req->hstderr = GetStdHandle( STD_ERROR_HANDLE );
}
req->cmd_show = startup->wShowWindow;
req->env_ptr = (void*)env; /* FIXME: hack */
lstrcpynA( req->cmdline, cmd_line, server_remaining(req->cmdline) );
req->alloc_fd = 1;
if (server_call_fd( REQ_NEW_PROCESS, -1, &fd )) goto error;
pdb->server_pid = req->pid;
info->hProcess = req->phandle;
info->dwProcessId = (DWORD)req->pid;
info->hThread = req->thandle;
info->dwThreadId = (DWORD)req->tid;
load_done_evt = req->event;
if (pModule->module32) /* Win32 process */
{
......@@ -752,13 +973,26 @@ PDB *PROCESS_Create( NE_MODULE *pModule, HFILE hFile, LPCSTR cmd_line, LPCSTR en
/* Create the main thread */
if (!(teb = THREAD_Create( pdb, req->pid, req->tid, fd, size, alloc_stack16 ))) goto error;
teb->startup = PROCESS_Start;
fd = -1; /* don't close it */
if ((teb = THREAD_Create( pdb, fd, size, alloc_stack16 )))
{
teb->startup = PROCESS_Start;
fd = -1; /* don't close it */
/* Pass module to new process (FIXME: hack) */
pdb->module = pModule->self;
SYSDEPS_SpawnThread( teb );
}
/* Pass module to new process (FIXME: hack) */
pdb->module = pModule->self;
SYSDEPS_SpawnThread( teb );
wait_req->cancel = !teb;
wait_req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
wait_req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle);
wait_req->timeout = 2000;
if (server_call( REQ_WAIT_PROCESS ) || !teb) goto error;
info->dwProcessId = (DWORD)wait_req->pid;
info->dwThreadId = (DWORD)wait_req->tid;
info->hProcess = wait_req->phandle;
info->hThread = wait_req->thandle;
load_done_evt = wait_req->event;
/* Wait until process is initialized (or initialization failed) */
handles[0] = info->hProcess;
......
......@@ -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 );
......
......@@ -55,47 +55,54 @@ static const struct object_ops process_ops =
process_destroy /* destroy */
};
/* set the process creation info */
static int set_creation_info( struct process *process, struct new_process_request *req,
const char *cmd_line, size_t len )
{
if (!(process->info = mem_alloc( sizeof(*process->info) + len ))) return 0;
if (req)
{
/* copy the request structure */
memcpy( process->info, req, sizeof(*req) );
}
else /* no request, use defaults */
{
req = process->info;
req->pinherit = 0;
req->tinherit = 0;
req->inherit_all = 0;
req->create_flags = CREATE_NEW_CONSOLE;
req->start_flags = STARTF_USESTDHANDLES;
req->exe_file = -1;
req->hstdin = -1;
req->hstdout = -1;
req->hstderr = -1;
req->cmd_show = 0;
req->env_ptr = NULL;
}
memcpy( process->info->cmdline, cmd_line, len );
process->info->cmdline[len] = 0;
process->create_flags = process->info->create_flags;
return 1;
}
/* process startup info */
struct startup_info
{
struct object obj; /* object header */
int inherit_all; /* inherit all handles from parent */
int create_flags; /* creation flags */
int start_flags; /* flags from startup info */
int exe_file; /* file handle for main exe */
int hstdin; /* handle for stdin */
int hstdout; /* handle for stdout */
int hstderr; /* handle for stderr */
int cmd_show; /* main window show mode */
struct process *process; /* created process */
struct thread *thread; /* created thread */
};
static void startup_info_dump( struct object *obj, int verbose );
static int startup_info_signaled( struct object *obj, struct thread *thread );
static void startup_info_destroy( struct object *obj );
static const struct object_ops startup_info_ops =
{
sizeof(struct startup_info), /* size */
startup_info_dump, /* dump */
add_queue, /* add_queue */
remove_queue, /* remove_queue */
startup_info_signaled, /* signaled */
no_satisfied, /* satisfied */
NULL, /* get_poll_events */
NULL, /* poll_event */
no_read_fd, /* get_read_fd */
no_write_fd, /* get_write_fd */
no_flush, /* flush */
no_get_file_info, /* get_file_info */
startup_info_destroy /* destroy */
};
/* set the console and stdio handles for a newly created process */
static int set_process_console( struct process *process, struct process *parent )
static int set_process_console( struct process *process, struct process *parent,
struct startup_info *info, struct init_process_request *req )
{
struct new_process_request *info = process->info;
if (process->create_flags & CREATE_NEW_CONSOLE)
{
if (!alloc_console( process )) return 0;
}
else if (!(process->create_flags & DETACHED_PROCESS))
else if (parent && !(process->create_flags & DETACHED_PROCESS))
{
if (parent->console_in) process->console_in = grab_object( parent->console_in );
if (parent->console_out) process->console_out = grab_object( parent->console_out );
......@@ -105,31 +112,35 @@ static int set_process_console( struct process *process, struct process *parent
if (!info->inherit_all && !(info->start_flags & STARTF_USESTDHANDLES))
{
/* duplicate the handle from the parent into this process */
info->hstdin = duplicate_handle( parent, info->hstdin, process,
0, TRUE, DUPLICATE_SAME_ACCESS );
info->hstdout = duplicate_handle( parent, info->hstdout, process,
0, TRUE, DUPLICATE_SAME_ACCESS );
info->hstderr = duplicate_handle( parent, info->hstderr, process,
0, TRUE, DUPLICATE_SAME_ACCESS );
req->hstdin = duplicate_handle( parent, info->hstdin, process,
0, TRUE, DUPLICATE_SAME_ACCESS );
req->hstdout = duplicate_handle( parent, info->hstdout, process,
0, TRUE, DUPLICATE_SAME_ACCESS );
req->hstderr = duplicate_handle( parent, info->hstderr, process,
0, TRUE, DUPLICATE_SAME_ACCESS );
}
else
{
req->hstdin = info->hstdin;
req->hstdout = info->hstdout;
req->hstderr = info->hstderr;
}
}
else
{
/* no parent, use handles to the console for stdio */
info->hstdin = alloc_handle( process, process->console_in,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
info->hstdout = alloc_handle( process, process->console_out,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
info->hstderr = alloc_handle( process, process->console_out,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
req->hstdin = alloc_handle( process, process->console_in,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
req->hstdout = alloc_handle( process, process->console_out,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
req->hstderr = alloc_handle( process, process->console_out,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
}
return 1;
}
/* create a new process and its main thread */
struct thread *create_process( int fd, struct process *parent,
struct new_process_request *req,
const char *cmd_line, size_t len )
struct thread *create_process( int fd )
{
struct process *process;
struct thread *thread = NULL;
......@@ -153,7 +164,6 @@ struct thread *create_process( int fd, struct process *parent,
process->console_in = NULL;
process->console_out = NULL;
process->init_event = NULL;
process->info = NULL;
process->ldt_copy = NULL;
process->ldt_flags = NULL;
process->exe.next = NULL;
......@@ -165,52 +175,97 @@ struct thread *create_process( int fd, struct process *parent,
if ((process->next = first_process) != NULL) process->next->prev = process;
first_process = process;
/* copy the request structure */
if (!set_creation_info( process, req, cmd_line, len )) goto error;
/* create the main thread */
if (!(thread = create_thread( fd, process ))) goto error;
/* create the init done event */
if (!(process->init_event = create_event( NULL, 0, 1, 0 ))) goto error;
add_process_thread( process, thread );
release_object( process );
return thread;
error:
if (thread) release_object( thread );
release_object( process );
return NULL;
}
/* initialize the current process and fill in the request */
static void init_process( int ppid, struct init_process_request *req )
{
struct process *process = current->process;
struct thread *parent_thread = get_thread_from_pid( ppid );
struct process *parent = NULL;
struct startup_info *info = NULL;
if (process->info->inherit_all == 2) /* HACK! */
if (parent_thread)
{
parent = parent_thread->process;
info = parent_thread->info;
if (!info)
{
fatal_protocol_error( current, "init_process: parent but no info\n" );
return;
}
if (info->thread)
{
fatal_protocol_error( current, "init_process: called twice?\n" );
return;
}
}
/* set the process flags */
process->create_flags = info ? info->create_flags : CREATE_NEW_CONSOLE;
/* create the handle table */
if (parent && info->inherit_all == 2) /* HACK! */
process->handles = grab_object( parent->handles );
else if (process->info->inherit_all)
else if (parent && info->inherit_all)
process->handles = copy_handle_table( process, parent );
else
process->handles = alloc_handle_table( process, 0 );
if (!process->handles) goto error;
/* retrieve the main exe file */
if (process->info->exe_file != -1)
req->exe_file = -1;
if (parent && info->exe_file != -1)
{
if (!(process->exe.file = get_file_obj( parent, process->info->exe_file,
GENERIC_READ ))) goto error;
process->info->exe_file = -1;
if (!(process->exe.file = get_file_obj( parent, info->exe_file, GENERIC_READ )))
goto error;
if ((req->exe_file = alloc_handle( process, process->exe.file, GENERIC_READ, 0 )) == -1)
goto error;
}
/* create the main thread */
if (!(thread = create_thread( fd, process, (process->create_flags & CREATE_SUSPENDED) != 0)))
goto error;
/* create the init done event */
if (!(process->init_event = create_event( NULL, 0, 1, 0 ))) goto error;
/* set the process console */
if (!set_process_console( process, parent )) goto error;
if (!set_process_console( process, parent, info, req )) goto error;
/* attach to the debugger if requested */
if (process->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
set_process_debugger( process, current );
else if (parent && parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS))
set_process_debugger( process, parent->debugger );
if (parent)
{
/* attach to the debugger if requested */
if (process->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
set_process_debugger( process, parent_thread );
else if (parent && parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS))
set_process_debugger( process, parent->debugger );
}
add_process_thread( process, thread );
release_object( process );
return thread;
/* thread will be actually suspended in init_done */
if (process->create_flags & CREATE_SUSPENDED) current->suspend++;
if (info)
{
req->start_flags = info->start_flags;
req->cmd_show = info->cmd_show;
info->process = (struct process *)grab_object( process );
info->thread = (struct thread *)grab_object( current );
wake_up( &info->obj, 0 );
}
else
{
req->start_flags = STARTF_USESTDHANDLES;
req->cmd_show = 0;
}
error:
close( fd );
free_console( process );
if (process->handles) release_object( process->handles );
if (thread) release_object( thread );
release_object( process );
return NULL;
}
/* destroy a process when its refcount is 0 */
......@@ -224,7 +279,6 @@ static void process_destroy( struct object *obj )
if (process->next) process->next->prev = process->prev;
if (process->prev) process->prev->next = process->next;
else first_process = process->next;
if (process->info) free( process->info );
if (process->init_event) release_object( process->init_event );
if (process->exe.file) release_object( process->exe.file );
}
......@@ -247,6 +301,57 @@ static int process_signaled( struct object *obj, struct thread *thread )
}
static void startup_info_destroy( struct object *obj )
{
struct startup_info *info = (struct startup_info *)obj;
assert( obj->ops == &startup_info_ops );
if (info->process) release_object( info->process );
if (info->thread) release_object( info->thread );
}
static void startup_info_dump( struct object *obj, int verbose )
{
struct startup_info *info = (struct startup_info *)obj;
assert( obj->ops == &startup_info_ops );
fprintf( stderr, "Startup info flags=%x in=%d out=%d err=%d\n",
info->start_flags, info->hstdin, info->hstdout, info->hstderr );
}
static int startup_info_signaled( struct object *obj, struct thread *thread )
{
struct startup_info *info = (struct startup_info *)obj;
return (info->thread != NULL);
}
/* build a reply for the wait_process request */
static void build_wait_process_reply( struct thread *thread, struct object *obj, int signaled )
{
struct wait_process_request *req = get_req_ptr( thread );
if (obj)
{
struct startup_info *info = (struct startup_info *)obj;
assert( obj->ops == &startup_info_ops );
req->pid = get_process_id( info->process );
req->tid = get_thread_id( info->thread );
req->phandle = alloc_handle( thread->process, info->process,
PROCESS_ALL_ACCESS, req->pinherit );
req->thandle = alloc_handle( thread->process, info->thread,
THREAD_ALL_ACCESS, req->tinherit );
if (info->process->init_event)
req->event = alloc_handle( thread->process, info->process->init_event,
EVENT_ALL_ACCESS, 0 );
else
req->event = -1;
/* FIXME: set_error */
}
release_object( thread->info );
thread->info = NULL;
}
/* get a process from an id (and increment the refcount) */
struct process *get_process_from_id( void *id )
{
......@@ -314,7 +419,7 @@ static void process_killed( struct process *process )
{
assert( !process->thread_list );
gettimeofday( &process->end_time, NULL );
release_object( process->handles );
if (process->handles) release_object( process->handles );
process->handles = NULL;
free_console( process );
while (process->exe.next)
......@@ -594,83 +699,83 @@ struct module_snapshot *module_snap( struct process *process, int *count )
/* create a new process */
DECL_HANDLER(new_process)
{
size_t len = get_req_strlen( req, req->cmdline );
struct thread *thread;
struct startup_info *info;
int sock[2];
int event = -1, phandle = -1;
req->phandle = -1;
req->thandle = -1;
req->event = -1;
req->pid = NULL;
req->tid = NULL;
if (socketpair( AF_UNIX, SOCK_STREAM, 0, sock ) == -1)
if (current->info)
{
file_set_error();
fatal_protocol_error( current, "new_process: another process is being created\n" );
return;
}
if (!(thread = create_process( sock[0], current->process, req, req->cmdline, len )))
goto error;
/* build the startup info for a new process */
if (!(info = alloc_object( &startup_info_ops, -1 ))) return;
info->inherit_all = req->inherit_all;
info->create_flags = req->create_flags;
info->start_flags = req->start_flags;
info->exe_file = req->exe_file;
info->hstdin = req->hstdin;
info->hstdout = req->hstdout;
info->hstderr = req->hstderr;
info->cmd_show = req->cmd_show;
info->process = NULL;
info->thread = NULL;
if ((event = alloc_handle( current->process, thread->process->init_event,
EVENT_ALL_ACCESS, 0 )) == -1)
goto error;
if ((phandle = alloc_handle( current->process, thread->process,
PROCESS_ALL_ACCESS, req->pinherit )) == -1)
goto error;
if ((req->thandle = alloc_handle( current->process, thread,
THREAD_ALL_ACCESS, req->tinherit )) == -1)
goto error;
/* thread object will be released when the thread gets killed */
set_reply_fd( current, sock[1] );
req->pid = get_process_id( thread->process );
req->tid = get_thread_id( thread );
req->phandle = phandle;
req->event = event;
return;
if (req->alloc_fd)
{
if (socketpair( AF_UNIX, SOCK_STREAM, 0, sock ) == -1)
{
file_set_error();
release_object( info );
return;
}
if (!create_process( sock[0] ))
{
release_object( info );
close( sock[1] );
return;
}
/* thread object will be released when the thread gets killed */
set_reply_fd( current, sock[1] );
}
current->info = info;
}
error:
if (phandle != -1) close_handle( current->process, phandle );
if (event != -1) close_handle( current->process, event );
if (thread) release_object( thread );
close( sock[1] );
/* Wait for the new process to start */
DECL_HANDLER(wait_process)
{
if (!current->info)
{
fatal_protocol_error( current, "wait_process: no process is being created\n" );
return;
}
req->pid = 0;
req->tid = 0;
req->phandle = -1;
req->thandle = -1;
if (req->cancel)
{
release_object( current->info );
current->info = NULL;
}
else
{
struct object *obj = &current->info->obj;
sleep_on( 1, &obj, SELECT_TIMEOUT, req->timeout, build_wait_process_reply );
}
}
/* initialize a new process */
DECL_HANDLER(init_process)
{
struct new_process_request *info;
if (!current->unix_pid)
{
fatal_protocol_error( current, "init_process: init_thread not called yet\n" );
return;
}
if (!(info = current->process->info))
{
fatal_protocol_error( current, "init_process: called twice\n" );
return;
}
current->process->ldt_copy = req->ldt_copy;
current->process->ldt_flags = req->ldt_flags;
current->process->info = NULL;
req->exe_file = -1;
req->start_flags = info->start_flags;
req->hstdin = info->hstdin;
req->hstdout = info->hstdout;
req->hstderr = info->hstderr;
req->cmd_show = info->cmd_show;
req->env_ptr = info->env_ptr;
strcpy( req->cmdline, info->cmdline );
if (current->process->exe.file)
req->exe_file = alloc_handle( current->process, current->process->exe.file,
GENERIC_READ, 0 );
free( info );
init_process( req->ppid, req );
}
/* signal the end of the process initialization */
......
......@@ -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