Rewrote Unix process launching to allow passing startup information to
Winelib apps. Improved handling of execve() failures.
This commit is contained in:
parent
045d81f16c
commit
5b4f3e8d6d
|
@ -148,8 +148,9 @@ extern DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset );
|
||||||
void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value );
|
void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value );
|
||||||
extern DWORD WINAPI MapProcessHandle( HANDLE handle );
|
extern DWORD WINAPI MapProcessHandle( HANDLE handle );
|
||||||
|
|
||||||
/* scheduler/environ.c */
|
/* memory/environ.c */
|
||||||
extern BOOL ENV_InheritEnvironment( LPCSTR env );
|
extern BOOL ENV_BuildEnvironment(void);
|
||||||
|
extern BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env );
|
||||||
extern void ENV_FreeEnvironment( PDB *pdb );
|
extern void ENV_FreeEnvironment( PDB *pdb );
|
||||||
|
|
||||||
/* scheduler/process.c */
|
/* scheduler/process.c */
|
||||||
|
@ -161,6 +162,10 @@ extern PDB *PROCESS_Create( struct _NE_MODULE *pModule, HFILE hFile,
|
||||||
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
||||||
BOOL inherit, DWORD flags,
|
BOOL inherit, DWORD flags,
|
||||||
STARTUPINFOA *startup, PROCESS_INFORMATION *info );
|
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_FreePDB( PDB *pdb );
|
||||||
extern void PROCESS_WalkProcess( void );
|
extern void PROCESS_WalkProcess( void );
|
||||||
|
|
||||||
|
|
|
@ -104,8 +104,6 @@ typedef struct
|
||||||
/* Create a new process from the context of the parent */
|
/* Create a new process from the context of the parent */
|
||||||
struct new_process_request
|
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 inherit_all; /* inherit all handles from parent */
|
||||||
IN int create_flags; /* creation flags */
|
IN int create_flags; /* creation flags */
|
||||||
IN int start_flags; /* flags from startup info */
|
IN int start_flags; /* flags from startup info */
|
||||||
|
@ -114,13 +112,22 @@ struct new_process_request
|
||||||
IN int hstdout; /* handle for stdout */
|
IN int hstdout; /* handle for stdout */
|
||||||
IN int hstderr; /* handle for stderr */
|
IN int hstderr; /* handle for stderr */
|
||||||
IN int cmd_show; /* main window show mode */
|
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 void* pid; /* process id */
|
||||||
OUT int phandle; /* process handle (in the current process) */
|
OUT int phandle; /* process handle (in the current process) */
|
||||||
OUT void* tid; /* thread id */
|
OUT void* tid; /* thread id */
|
||||||
OUT int thandle; /* thread handle (in the current process) */
|
OUT int thandle; /* thread handle (in the current process) */
|
||||||
OUT int event; /* event handle to signal startup */
|
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_copy; /* addr of LDT copy */
|
||||||
IN void* ldt_flags; /* addr of LDT flags */
|
IN void* ldt_flags; /* addr of LDT flags */
|
||||||
|
IN int ppid; /* parent Unix pid */
|
||||||
OUT int start_flags; /* flags from startup info */
|
OUT int start_flags; /* flags from startup info */
|
||||||
OUT int exe_file; /* file handle for main exe */
|
OUT int exe_file; /* file handle for main exe */
|
||||||
OUT int hstdin; /* handle for stdin */
|
OUT int hstdin; /* handle for stdin */
|
||||||
OUT int hstdout; /* handle for stdout */
|
OUT int hstdout; /* handle for stdout */
|
||||||
OUT int hstderr; /* handle for stderr */
|
OUT int hstderr; /* handle for stderr */
|
||||||
OUT int cmd_show; /* main window show mode */
|
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
|
enum request
|
||||||
{
|
{
|
||||||
REQ_NEW_PROCESS,
|
REQ_NEW_PROCESS,
|
||||||
|
REQ_WAIT_PROCESS,
|
||||||
REQ_NEW_THREAD,
|
REQ_NEW_THREAD,
|
||||||
REQ_BOOT_DONE,
|
REQ_BOOT_DONE,
|
||||||
REQ_INIT_PROCESS,
|
REQ_INIT_PROCESS,
|
||||||
|
@ -1246,7 +1253,7 @@ enum request
|
||||||
REQ_NB_REQUESTS
|
REQ_NB_REQUESTS
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 9
|
#define SERVER_PROTOCOL_VERSION 10
|
||||||
|
|
||||||
/* ### make_requests end ### */
|
/* ### make_requests end ### */
|
||||||
/* Everything above this line is generated automatically by tools/make_requests */
|
/* Everything above this line is generated automatically by tools/make_requests */
|
||||||
|
|
|
@ -119,9 +119,8 @@ typedef struct _TEB
|
||||||
|
|
||||||
|
|
||||||
/* scheduler/thread.c */
|
/* scheduler/thread.c */
|
||||||
extern TEB *THREAD_CreateInitialThread( struct _PDB *pdb, int server_fd );
|
extern TEB *THREAD_Init( struct _PDB *pdb );
|
||||||
extern TEB *THREAD_Create( struct _PDB *pdb, void *pid, void *tid, int fd,
|
extern TEB *THREAD_Create( struct _PDB *pdb, int fd, DWORD stack_size, BOOL alloc_stack16 );
|
||||||
DWORD stack_size, BOOL alloc_stack16 );
|
|
||||||
extern TEB *THREAD_InitStack( TEB *teb, struct _PDB *pdb, 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 BOOL THREAD_IsWin16( TEB *thdb );
|
||||||
extern TEB *THREAD_IdToTEB( DWORD id );
|
extern TEB *THREAD_IdToTEB( DWORD id );
|
||||||
|
|
|
@ -62,8 +62,6 @@ DEFAULT_DEBUG_CHANNEL(server);
|
||||||
*/
|
*/
|
||||||
BOOL MAIN_MainInit( int argc, char *argv[], BOOL win32 )
|
BOOL MAIN_MainInit( int argc, char *argv[], BOOL win32 )
|
||||||
{
|
{
|
||||||
char szGraphicsDriver[MAX_PATH];
|
|
||||||
|
|
||||||
/* store the program name */
|
/* store the program name */
|
||||||
argv0 = argv[0];
|
argv0 = argv[0];
|
||||||
|
|
||||||
|
@ -94,15 +92,6 @@ BOOL MAIN_MainInit( int argc, char *argv[], BOOL win32 )
|
||||||
/* Initialize module loadorder */
|
/* Initialize module loadorder */
|
||||||
if (!MODULE_InitLoadOrder()) return FALSE;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -684,60 +684,6 @@ BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
|
||||||
return ret;
|
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)
|
* WinExec16 (KERNEL.166)
|
||||||
|
@ -1027,7 +973,10 @@ BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
|
||||||
{
|
{
|
||||||
CloseHandle( hFile );
|
CloseHandle( hFile );
|
||||||
/* FIXME: Try Unix executable only when appropriate! */
|
/* 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;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ static LPCSTR ENV_FindVariable( LPCSTR env, LPCSTR name, INT len )
|
||||||
*
|
*
|
||||||
* Build the environment for the initial process
|
* Build the environment for the initial process
|
||||||
*/
|
*/
|
||||||
static BOOL ENV_BuildEnvironment( PDB *pdb )
|
BOOL ENV_BuildEnvironment(void)
|
||||||
{
|
{
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
LPSTR p, *e;
|
LPSTR p, *e;
|
||||||
|
@ -81,7 +81,7 @@ static BOOL ENV_BuildEnvironment( PDB *pdb )
|
||||||
/* Now allocate the environment */
|
/* Now allocate the environment */
|
||||||
|
|
||||||
if (!(p = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
|
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 */
|
/* 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
|
* Make a process inherit the environment from its parent or from an
|
||||||
* explicit environment.
|
* explicit environment.
|
||||||
*/
|
*/
|
||||||
BOOL ENV_InheritEnvironment( LPCSTR env )
|
BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env )
|
||||||
{
|
{
|
||||||
DWORD size;
|
DWORD size;
|
||||||
LPCSTR src;
|
LPCSTR src;
|
||||||
LPSTR dst;
|
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 */
|
/* Compute the environment size */
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,13 @@ void MAIN_EmulatorRun( void )
|
||||||
char startProg[256], defProg[256];
|
char startProg[256], defProg[256];
|
||||||
int i, tasks = 0;
|
int i, tasks = 0;
|
||||||
MSG msg;
|
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) */
|
/* Load system DLLs into the initial process (and initialize them) */
|
||||||
if ( !LoadLibrary16("GDI.EXE" ) || !LoadLibraryA("GDI32.DLL" )
|
if ( !LoadLibrary16("GDI.EXE" ) || !LoadLibraryA("GDI32.DLL" )
|
||||||
|
@ -102,6 +109,12 @@ int main( int argc, char *argv[] )
|
||||||
/* Initialize everything */
|
/* Initialize everything */
|
||||||
if (!MAIN_MainInit( argc, argv, FALSE )) return 1;
|
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 */
|
/* Create initial task */
|
||||||
if ( !(pModule = NE_GetPtr( GetModuleHandle16( "KERNEL" ) )) ) return 1;
|
if ( !(pModule = NE_GetPtr( GetModuleHandle16( "KERNEL" ) )) ) return 1;
|
||||||
if ( !TASK_Create( pModule, FALSE ) ) return 1;
|
if ( !TASK_Create( pModule, FALSE ) ) return 1;
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -43,31 +45,6 @@ static STARTUPINFOA initial_startup;
|
||||||
static PDB *PROCESS_First = &initial_pdb;
|
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
|
* PROCESS_IdToPDB
|
||||||
*
|
*
|
||||||
|
@ -210,27 +187,15 @@ void PROCESS_CallUserSignalProc( UINT uCode, HMODULE hModule )
|
||||||
static BOOL PROCESS_CreateEnvDB(void)
|
static BOOL PROCESS_CreateEnvDB(void)
|
||||||
{
|
{
|
||||||
struct init_process_request *req = get_req_buffer();
|
struct init_process_request *req = get_req_buffer();
|
||||||
STARTUPINFOA *startup;
|
|
||||||
ENVDB *env_db;
|
|
||||||
char cmd_line[4096];
|
|
||||||
PDB *pdb = PROCESS_Current();
|
PDB *pdb = PROCESS_Current();
|
||||||
|
ENVDB *env_db = pdb->env_db;
|
||||||
/* Allocate the env DB */
|
STARTUPINFOA *startup = env_db->startup_info;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* Retrieve startup info from the server */
|
/* Retrieve startup info from the server */
|
||||||
|
|
||||||
req->ldt_copy = ldt_copy;
|
req->ldt_copy = ldt_copy;
|
||||||
req->ldt_flags = ldt_flags_copy;
|
req->ldt_flags = ldt_flags_copy;
|
||||||
|
req->ppid = getppid();
|
||||||
if (server_call( REQ_INIT_PROCESS )) return FALSE;
|
if (server_call( REQ_INIT_PROCESS )) return FALSE;
|
||||||
pdb->exe_file = req->exe_file;
|
pdb->exe_file = req->exe_file;
|
||||||
startup->dwFlags = req->start_flags;
|
startup->dwFlags = req->start_flags;
|
||||||
|
@ -238,16 +203,6 @@ static BOOL PROCESS_CreateEnvDB(void)
|
||||||
env_db->hStdin = startup->hStdInput = req->hstdin;
|
env_db->hStdin = startup->hStdInput = req->hstdin;
|
||||||
env_db->hStdout = startup->hStdOutput = req->hstdout;
|
env_db->hStdout = startup->hStdOutput = req->hstdout;
|
||||||
env_db->hStderr = startup->hStdError = req->hstderr;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -277,7 +232,8 @@ void PROCESS_FreePDB( PDB *pdb )
|
||||||
*/
|
*/
|
||||||
static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
|
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;
|
if (!pdb) return NULL;
|
||||||
pdb->exit_code = STILL_ACTIVE;
|
pdb->exit_code = STILL_ACTIVE;
|
||||||
|
@ -291,6 +247,11 @@ static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
|
||||||
pdb->next = PROCESS_First;
|
pdb->next = PROCESS_First;
|
||||||
pdb->winver = 0xffff; /* to be determined */
|
pdb->winver = 0xffff; /* to be determined */
|
||||||
pdb->main_queue = INVALID_HANDLE_VALUE16;
|
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;
|
PROCESS_First = pdb;
|
||||||
return pdb;
|
return pdb;
|
||||||
}
|
}
|
||||||
|
@ -303,10 +264,6 @@ BOOL PROCESS_Init( BOOL win32 )
|
||||||
{
|
{
|
||||||
struct init_process_request *req;
|
struct init_process_request *req;
|
||||||
TEB *teb;
|
TEB *teb;
|
||||||
int server_fd;
|
|
||||||
|
|
||||||
/* Start the server */
|
|
||||||
server_fd = CLIENT_InitServer();
|
|
||||||
|
|
||||||
/* Fill the initial process structure */
|
/* Fill the initial process structure */
|
||||||
initial_pdb.exit_code = STILL_ACTIVE;
|
initial_pdb.exit_code = STILL_ACTIVE;
|
||||||
|
@ -320,12 +277,31 @@ BOOL PROCESS_Init( BOOL win32 )
|
||||||
initial_pdb.winver = 0xffff; /* to be determined */
|
initial_pdb.winver = 0xffff; /* to be determined */
|
||||||
initial_pdb.main_queue = INVALID_HANDLE_VALUE16;
|
initial_pdb.main_queue = INVALID_HANDLE_VALUE16;
|
||||||
initial_envdb.startup_info = &initial_startup;
|
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 */
|
/* Initialize virtual memory management */
|
||||||
if (!VIRTUAL_Init()) return FALSE;
|
if (!VIRTUAL_Init()) return FALSE;
|
||||||
|
|
||||||
/* Create the initial thread structure and socket pair */
|
/* Retrieve startup info from the server */
|
||||||
if (!(teb = THREAD_CreateInitialThread( &initial_pdb, server_fd ))) return FALSE;
|
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 */
|
/* Remember TEB selector of initial process for emergency use */
|
||||||
SYSLEVEL_EmergencyTeb = teb->teb_sel;
|
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 = CreateEventA ( NULL, TRUE, FALSE, NULL );
|
||||||
initial_pdb.idle_event = ConvertToGlobalHandle ( initial_pdb.idle_event );
|
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 */
|
/* Copy the parent environment */
|
||||||
if (!ENV_InheritEnvironment( NULL )) return FALSE;
|
if (!ENV_BuildEnvironment()) return FALSE;
|
||||||
|
|
||||||
/* Create the SEGPTR heap */
|
/* Create the SEGPTR heap */
|
||||||
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
|
if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
|
||||||
|
@ -372,6 +332,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
|
* start_process
|
||||||
*
|
*
|
||||||
|
@ -409,13 +396,8 @@ static void start_process(void)
|
||||||
|
|
||||||
if (pdb->flags & PDB32_CONSOLE_PROC) AllocConsole();
|
if (pdb->flags & PDB32_CONSOLE_PROC) AllocConsole();
|
||||||
|
|
||||||
/* Load system DLLs into the initial process (and initialize them) */
|
/* Load the system dlls */
|
||||||
if (!LoadLibraryA( "KERNEL32" )) goto error;
|
if (!load_system_dlls()) goto error;
|
||||||
if (!LoadLibraryA( "x11drv" )) goto error;
|
|
||||||
|
|
||||||
if ( !LoadLibrary16("GDI.EXE" ) || !LoadLibraryA("GDI32.DLL" )
|
|
||||||
|| !LoadLibrary16("USER.EXE") || !LoadLibraryA("USER32.DLL"))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* Get pointers to USER routines called by KERNEL */
|
/* Get pointers to USER routines called by KERNEL */
|
||||||
THUNK_InitCallout();
|
THUNK_InitCallout();
|
||||||
|
@ -547,6 +529,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
|
* PROCESS_Start
|
||||||
*
|
*
|
||||||
|
@ -691,6 +917,7 @@ PDB *PROCESS_Create( NE_MODULE *pModule, HFILE hFile, LPCSTR cmd_line, LPCSTR en
|
||||||
BOOL alloc_stack16;
|
BOOL alloc_stack16;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
struct new_process_request *req = get_req_buffer();
|
struct new_process_request *req = get_req_buffer();
|
||||||
|
struct wait_process_request *wait_req = get_req_buffer();
|
||||||
TEB *teb = NULL;
|
TEB *teb = NULL;
|
||||||
PDB *parent = PROCESS_Current();
|
PDB *parent = PROCESS_Current();
|
||||||
PDB *pdb = PROCESS_CreatePDB( parent, inherit );
|
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;
|
if (!pdb) return NULL;
|
||||||
info->hThread = info->hProcess = INVALID_HANDLE_VALUE;
|
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 */
|
/* 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->inherit_all = 2 /*inherit*/; /* HACK! */
|
||||||
req->create_flags = flags;
|
req->create_flags = flags;
|
||||||
req->start_flags = startup->dwFlags;
|
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->hstderr = GetStdHandle( STD_ERROR_HANDLE );
|
||||||
}
|
}
|
||||||
req->cmd_show = startup->wShowWindow;
|
req->cmd_show = startup->wShowWindow;
|
||||||
req->env_ptr = (void*)env; /* FIXME: hack */
|
req->alloc_fd = 1;
|
||||||
lstrcpynA( req->cmdline, cmd_line, server_remaining(req->cmdline) );
|
|
||||||
if (server_call_fd( REQ_NEW_PROCESS, -1, &fd )) goto error;
|
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 */
|
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 */
|
/* Create the main thread */
|
||||||
|
|
||||||
if (!(teb = THREAD_Create( pdb, req->pid, req->tid, fd, size, alloc_stack16 ))) goto error;
|
if ((teb = THREAD_Create( pdb, fd, size, alloc_stack16 )))
|
||||||
teb->startup = PROCESS_Start;
|
{
|
||||||
fd = -1; /* don't close it */
|
teb->startup = PROCESS_Start;
|
||||||
|
fd = -1; /* don't close it */
|
||||||
|
|
||||||
/* Pass module to new process (FIXME: hack) */
|
/* Pass module to new process (FIXME: hack) */
|
||||||
pdb->module = pModule->self;
|
pdb->module = pModule->self;
|
||||||
SYSDEPS_SpawnThread( teb );
|
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) */
|
/* Wait until process is initialized (or initialization failed) */
|
||||||
handles[0] = info->hProcess;
|
handles[0] = info->hProcess;
|
||||||
|
|
|
@ -85,6 +85,8 @@ static BOOL THREAD_InitTEB( TEB *teb, PDB *pdb )
|
||||||
teb->process = pdb;
|
teb->process = pdb;
|
||||||
teb->exit_code = STILL_ACTIVE;
|
teb->exit_code = STILL_ACTIVE;
|
||||||
teb->socket = -1;
|
teb->socket = -1;
|
||||||
|
teb->stack_top = (void *)~0UL;
|
||||||
|
|
||||||
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
|
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
|
||||||
teb->StaticUnicodeString.Buffer = (PWSTR)teb->StaticUnicodeBuffer;
|
teb->StaticUnicodeString.Buffer = (PWSTR)teb->StaticUnicodeBuffer;
|
||||||
teb->teb_sel = SELECTOR_AllocBlock( teb, 0x1000, SEGMENT_DATA, TRUE, FALSE );
|
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.
|
* 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;
|
if (!THREAD_InitTEB( &initial_teb, pdb )) return NULL;
|
||||||
SYSDEPS_SetCurThread( &initial_teb );
|
SYSDEPS_SetCurThread( &initial_teb );
|
||||||
initial_teb.socket = server_fd;
|
return &initial_teb;
|
||||||
|
|
||||||
if (CLIENT_InitThread()) return NULL;
|
|
||||||
return THREAD_InitStack( &initial_teb, pdb, 0, TRUE );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,15 +214,12 @@ TEB *THREAD_CreateInitialThread( PDB *pdb, int server_fd )
|
||||||
* THREAD_Create
|
* THREAD_Create
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
TEB *THREAD_Create( PDB *pdb, void *pid, void *tid, int fd,
|
TEB *THREAD_Create( PDB *pdb, int fd, DWORD stack_size, BOOL alloc_stack16 )
|
||||||
DWORD stack_size, BOOL alloc_stack16 )
|
|
||||||
{
|
{
|
||||||
TEB *teb;
|
TEB *teb;
|
||||||
|
|
||||||
if ((teb = THREAD_InitStack( NULL, pdb, stack_size, alloc_stack16 )))
|
if ((teb = THREAD_InitStack( NULL, pdb, stack_size, alloc_stack16 )))
|
||||||
{
|
{
|
||||||
teb->pid = pid;
|
|
||||||
teb->tid = tid;
|
|
||||||
teb->socket = fd;
|
teb->socket = fd;
|
||||||
fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
|
fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
|
||||||
TRACE("(%p) succeeded\n", teb);
|
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();
|
struct new_thread_request *req = get_req_buffer();
|
||||||
int socket, handle = -1;
|
int socket, handle = -1;
|
||||||
TEB *teb;
|
TEB *teb;
|
||||||
|
void *tid;
|
||||||
|
|
||||||
req->suspend = ((flags & CREATE_SUSPENDED) != 0);
|
req->suspend = ((flags & CREATE_SUSPENDED) != 0);
|
||||||
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
|
||||||
if (server_call_fd( REQ_NEW_THREAD, -1, &socket )) return 0;
|
if (server_call_fd( REQ_NEW_THREAD, -1, &socket )) return 0;
|
||||||
handle = req->handle;
|
handle = req->handle;
|
||||||
|
tid = req->tid;
|
||||||
|
|
||||||
if (!(teb = THREAD_Create( PROCESS_Current(), (void *)GetCurrentProcessId(),
|
if (!(teb = THREAD_Create( PROCESS_Current(), socket, stack, TRUE )))
|
||||||
req->tid, socket, stack, TRUE )))
|
|
||||||
{
|
{
|
||||||
close( socket );
|
close( socket );
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -282,7 +279,7 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
|
||||||
teb->entry_point = start;
|
teb->entry_point = start;
|
||||||
teb->entry_arg = param;
|
teb->entry_arg = param;
|
||||||
teb->startup = THREAD_Start;
|
teb->startup = THREAD_Start;
|
||||||
if (id) *id = (DWORD)teb->tid;
|
if (id) *id = (DWORD)tid;
|
||||||
if (SYSDEPS_SpawnThread( teb ) == -1)
|
if (SYSDEPS_SpawnThread( teb ) == -1)
|
||||||
{
|
{
|
||||||
CloseHandle( handle );
|
CloseHandle( handle );
|
||||||
|
|
387
server/process.c
387
server/process.c
|
@ -55,47 +55,54 @@ static const struct object_ops process_ops =
|
||||||
process_destroy /* destroy */
|
process_destroy /* destroy */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* set the process creation info */
|
/* process startup info */
|
||||||
static int set_creation_info( struct process *process, struct new_process_request *req,
|
|
||||||
const char *cmd_line, size_t len )
|
struct startup_info
|
||||||
{
|
{
|
||||||
if (!(process->info = mem_alloc( sizeof(*process->info) + len ))) return 0;
|
struct object obj; /* object header */
|
||||||
if (req)
|
int inherit_all; /* inherit all handles from parent */
|
||||||
{
|
int create_flags; /* creation flags */
|
||||||
/* copy the request structure */
|
int start_flags; /* flags from startup info */
|
||||||
memcpy( process->info, req, sizeof(*req) );
|
int exe_file; /* file handle for main exe */
|
||||||
}
|
int hstdin; /* handle for stdin */
|
||||||
else /* no request, use defaults */
|
int hstdout; /* handle for stdout */
|
||||||
{
|
int hstderr; /* handle for stderr */
|
||||||
req = process->info;
|
int cmd_show; /* main window show mode */
|
||||||
req->pinherit = 0;
|
struct process *process; /* created process */
|
||||||
req->tinherit = 0;
|
struct thread *thread; /* created thread */
|
||||||
req->inherit_all = 0;
|
};
|
||||||
req->create_flags = CREATE_NEW_CONSOLE;
|
|
||||||
req->start_flags = STARTF_USESTDHANDLES;
|
static void startup_info_dump( struct object *obj, int verbose );
|
||||||
req->exe_file = -1;
|
static int startup_info_signaled( struct object *obj, struct thread *thread );
|
||||||
req->hstdin = -1;
|
static void startup_info_destroy( struct object *obj );
|
||||||
req->hstdout = -1;
|
|
||||||
req->hstderr = -1;
|
static const struct object_ops startup_info_ops =
|
||||||
req->cmd_show = 0;
|
{
|
||||||
req->env_ptr = NULL;
|
sizeof(struct startup_info), /* size */
|
||||||
}
|
startup_info_dump, /* dump */
|
||||||
memcpy( process->info->cmdline, cmd_line, len );
|
add_queue, /* add_queue */
|
||||||
process->info->cmdline[len] = 0;
|
remove_queue, /* remove_queue */
|
||||||
process->create_flags = process->info->create_flags;
|
startup_info_signaled, /* signaled */
|
||||||
return 1;
|
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 */
|
/* 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 (process->create_flags & CREATE_NEW_CONSOLE)
|
||||||
{
|
{
|
||||||
if (!alloc_console( process )) return 0;
|
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_in) process->console_in = grab_object( parent->console_in );
|
||||||
if (parent->console_out) process->console_out = grab_object( parent->console_out );
|
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))
|
if (!info->inherit_all && !(info->start_flags & STARTF_USESTDHANDLES))
|
||||||
{
|
{
|
||||||
/* duplicate the handle from the parent into this process */
|
/* duplicate the handle from the parent into this process */
|
||||||
info->hstdin = duplicate_handle( parent, info->hstdin, process,
|
req->hstdin = duplicate_handle( parent, info->hstdin, process,
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS );
|
0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||||
info->hstdout = duplicate_handle( parent, info->hstdout, process,
|
req->hstdout = duplicate_handle( parent, info->hstdout, process,
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS );
|
0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||||
info->hstderr = duplicate_handle( parent, info->hstderr, process,
|
req->hstderr = duplicate_handle( parent, info->hstderr, process,
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS );
|
0, TRUE, DUPLICATE_SAME_ACCESS );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
req->hstdin = info->hstdin;
|
||||||
|
req->hstdout = info->hstdout;
|
||||||
|
req->hstderr = info->hstderr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* no parent, use handles to the console for stdio */
|
/* no parent, use handles to the console for stdio */
|
||||||
info->hstdin = alloc_handle( process, process->console_in,
|
req->hstdin = alloc_handle( process, process->console_in,
|
||||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
||||||
info->hstdout = alloc_handle( process, process->console_out,
|
req->hstdout = alloc_handle( process, process->console_out,
|
||||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
||||||
info->hstderr = alloc_handle( process, process->console_out,
|
req->hstderr = alloc_handle( process, process->console_out,
|
||||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create a new process and its main thread */
|
/* create a new process and its main thread */
|
||||||
struct thread *create_process( int fd, struct process *parent,
|
struct thread *create_process( int fd )
|
||||||
struct new_process_request *req,
|
|
||||||
const char *cmd_line, size_t len )
|
|
||||||
{
|
{
|
||||||
struct process *process;
|
struct process *process;
|
||||||
struct thread *thread = NULL;
|
struct thread *thread = NULL;
|
||||||
|
@ -153,7 +164,6 @@ struct thread *create_process( int fd, struct process *parent,
|
||||||
process->console_in = NULL;
|
process->console_in = NULL;
|
||||||
process->console_out = NULL;
|
process->console_out = NULL;
|
||||||
process->init_event = NULL;
|
process->init_event = NULL;
|
||||||
process->info = NULL;
|
|
||||||
process->ldt_copy = NULL;
|
process->ldt_copy = NULL;
|
||||||
process->ldt_flags = NULL;
|
process->ldt_flags = NULL;
|
||||||
process->exe.next = NULL;
|
process->exe.next = NULL;
|
||||||
|
@ -165,54 +175,99 @@ struct thread *create_process( int fd, struct process *parent,
|
||||||
if ((process->next = first_process) != NULL) process->next->prev = process;
|
if ((process->next = first_process) != NULL) process->next->prev = process;
|
||||||
first_process = process;
|
first_process = process;
|
||||||
|
|
||||||
/* copy the request structure */
|
|
||||||
if (!set_creation_info( process, req, cmd_line, len )) goto error;
|
|
||||||
|
|
||||||
if (process->info->inherit_all == 2) /* HACK! */
|
|
||||||
process->handles = grab_object( parent->handles );
|
|
||||||
else if (process->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)
|
|
||||||
{
|
|
||||||
if (!(process->exe.file = get_file_obj( parent, process->info->exe_file,
|
|
||||||
GENERIC_READ ))) goto error;
|
|
||||||
process->info->exe_file = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create the main thread */
|
/* create the main thread */
|
||||||
if (!(thread = create_thread( fd, process, (process->create_flags & CREATE_SUSPENDED) != 0)))
|
if (!(thread = create_thread( fd, process ))) goto error;
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* create the init done event */
|
/* create the init done event */
|
||||||
if (!(process->init_event = create_event( NULL, 0, 1, 0 ))) goto error;
|
if (!(process->init_event = create_event( NULL, 0, 1, 0 ))) goto error;
|
||||||
|
|
||||||
/* set the process console */
|
|
||||||
if (!set_process_console( process, parent )) 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 );
|
|
||||||
|
|
||||||
add_process_thread( process, thread );
|
add_process_thread( process, thread );
|
||||||
release_object( process );
|
release_object( process );
|
||||||
return thread;
|
return thread;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
close( fd );
|
|
||||||
free_console( process );
|
|
||||||
if (process->handles) release_object( process->handles );
|
|
||||||
if (thread) release_object( thread );
|
if (thread) release_object( thread );
|
||||||
release_object( process );
|
release_object( process );
|
||||||
return NULL;
|
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 (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 (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 */
|
||||||
|
req->exe_file = -1;
|
||||||
|
if (parent && 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the process console */
|
||||||
|
if (!set_process_console( process, parent, info, req )) goto error;
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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:
|
||||||
|
}
|
||||||
|
|
||||||
/* destroy a process when its refcount is 0 */
|
/* destroy a process when its refcount is 0 */
|
||||||
static void process_destroy( struct object *obj )
|
static void process_destroy( struct object *obj )
|
||||||
{
|
{
|
||||||
|
@ -224,7 +279,6 @@ static void process_destroy( struct object *obj )
|
||||||
if (process->next) process->next->prev = process->prev;
|
if (process->next) process->next->prev = process->prev;
|
||||||
if (process->prev) process->prev->next = process->next;
|
if (process->prev) process->prev->next = process->next;
|
||||||
else first_process = process->next;
|
else first_process = process->next;
|
||||||
if (process->info) free( process->info );
|
|
||||||
if (process->init_event) release_object( process->init_event );
|
if (process->init_event) release_object( process->init_event );
|
||||||
if (process->exe.file) release_object( process->exe.file );
|
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) */
|
/* get a process from an id (and increment the refcount) */
|
||||||
struct process *get_process_from_id( void *id )
|
struct process *get_process_from_id( void *id )
|
||||||
{
|
{
|
||||||
|
@ -314,7 +419,7 @@ static void process_killed( struct process *process )
|
||||||
{
|
{
|
||||||
assert( !process->thread_list );
|
assert( !process->thread_list );
|
||||||
gettimeofday( &process->end_time, NULL );
|
gettimeofday( &process->end_time, NULL );
|
||||||
release_object( process->handles );
|
if (process->handles) release_object( process->handles );
|
||||||
process->handles = NULL;
|
process->handles = NULL;
|
||||||
free_console( process );
|
free_console( process );
|
||||||
while (process->exe.next)
|
while (process->exe.next)
|
||||||
|
@ -594,83 +699,83 @@ struct module_snapshot *module_snap( struct process *process, int *count )
|
||||||
/* create a new process */
|
/* create a new process */
|
||||||
DECL_HANDLER(new_process)
|
DECL_HANDLER(new_process)
|
||||||
{
|
{
|
||||||
size_t len = get_req_strlen( req, req->cmdline );
|
struct startup_info *info;
|
||||||
struct thread *thread;
|
|
||||||
int sock[2];
|
int sock[2];
|
||||||
int event = -1, phandle = -1;
|
|
||||||
|
|
||||||
req->phandle = -1;
|
if (current->info)
|
||||||
req->thandle = -1;
|
|
||||||
req->event = -1;
|
|
||||||
req->pid = NULL;
|
|
||||||
req->tid = NULL;
|
|
||||||
|
|
||||||
if (socketpair( AF_UNIX, SOCK_STREAM, 0, sock ) == -1)
|
|
||||||
{
|
{
|
||||||
file_set_error();
|
fatal_protocol_error( current, "new_process: another process is being created\n" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(thread = create_process( sock[0], current->process, req, req->cmdline, len )))
|
/* build the startup info for a new process */
|
||||||
goto error;
|
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,
|
if (req->alloc_fd)
|
||||||
EVENT_ALL_ACCESS, 0 )) == -1)
|
{
|
||||||
goto error;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if ((phandle = alloc_handle( current->process, thread->process,
|
/* Wait for the new process to start */
|
||||||
PROCESS_ALL_ACCESS, req->pinherit )) == -1)
|
DECL_HANDLER(wait_process)
|
||||||
goto error;
|
{
|
||||||
|
if (!current->info)
|
||||||
if ((req->thandle = alloc_handle( current->process, thread,
|
{
|
||||||
THREAD_ALL_ACCESS, req->tinherit )) == -1)
|
fatal_protocol_error( current, "wait_process: no process is being created\n" );
|
||||||
goto error;
|
return;
|
||||||
|
}
|
||||||
/* thread object will be released when the thread gets killed */
|
req->pid = 0;
|
||||||
set_reply_fd( current, sock[1] );
|
req->tid = 0;
|
||||||
req->pid = get_process_id( thread->process );
|
req->phandle = -1;
|
||||||
req->tid = get_thread_id( thread );
|
req->thandle = -1;
|
||||||
req->phandle = phandle;
|
if (req->cancel)
|
||||||
req->event = event;
|
{
|
||||||
return;
|
release_object( current->info );
|
||||||
|
current->info = NULL;
|
||||||
error:
|
}
|
||||||
if (phandle != -1) close_handle( current->process, phandle );
|
else
|
||||||
if (event != -1) close_handle( current->process, event );
|
{
|
||||||
if (thread) release_object( thread );
|
struct object *obj = ¤t->info->obj;
|
||||||
close( sock[1] );
|
sleep_on( 1, &obj, SELECT_TIMEOUT, req->timeout, build_wait_process_reply );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize a new process */
|
/* initialize a new process */
|
||||||
DECL_HANDLER(init_process)
|
DECL_HANDLER(init_process)
|
||||||
{
|
{
|
||||||
struct new_process_request *info;
|
|
||||||
|
|
||||||
if (!current->unix_pid)
|
if (!current->unix_pid)
|
||||||
{
|
{
|
||||||
fatal_protocol_error( current, "init_process: init_thread not called yet\n" );
|
fatal_protocol_error( current, "init_process: init_thread not called yet\n" );
|
||||||
return;
|
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_copy = req->ldt_copy;
|
||||||
current->process->ldt_flags = req->ldt_flags;
|
current->process->ldt_flags = req->ldt_flags;
|
||||||
current->process->info = NULL;
|
init_process( req->ppid, req );
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* signal the end of the process initialization */
|
/* signal the end of the process initialization */
|
||||||
|
|
|
@ -48,7 +48,6 @@ struct process
|
||||||
struct process_dll exe; /* main exe file */
|
struct process_dll exe; /* main exe file */
|
||||||
void *ldt_copy; /* pointer to LDT copy in client addr space */
|
void *ldt_copy; /* pointer to LDT copy in client addr space */
|
||||||
void *ldt_flags; /* pointer to LDT flags 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
|
struct process_snapshot
|
||||||
|
@ -67,9 +66,7 @@ struct module_snapshot
|
||||||
|
|
||||||
/* process functions */
|
/* process functions */
|
||||||
|
|
||||||
extern struct thread *create_process( int fd, struct process *parent,
|
extern struct thread *create_process( int fd );
|
||||||
struct new_process_request *req,
|
|
||||||
const char *cmd_line, size_t len );
|
|
||||||
extern struct process *get_process_from_id( void *id );
|
extern struct process *get_process_from_id( void *id );
|
||||||
extern struct process *get_process_from_handle( int handle, unsigned int access );
|
extern struct process *get_process_from_handle( int handle, unsigned int access );
|
||||||
extern int process_set_debugger( struct process *process, struct thread *thread );
|
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;
|
struct sockaddr_un dummy;
|
||||||
int len = sizeof(dummy);
|
int len = sizeof(dummy);
|
||||||
int client = accept( master_socket->obj.fd, (struct sockaddr *) &dummy, &len );
|
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 ### */
|
/* ### make_requests begin ### */
|
||||||
|
|
||||||
DECL_HANDLER(new_process);
|
DECL_HANDLER(new_process);
|
||||||
|
DECL_HANDLER(wait_process);
|
||||||
DECL_HANDLER(new_thread);
|
DECL_HANDLER(new_thread);
|
||||||
DECL_HANDLER(boot_done);
|
DECL_HANDLER(boot_done);
|
||||||
DECL_HANDLER(init_process);
|
DECL_HANDLER(init_process);
|
||||||
|
@ -179,6 +180,7 @@ typedef void (*req_handler)( void *req );
|
||||||
static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
||||||
{
|
{
|
||||||
(req_handler)req_new_process,
|
(req_handler)req_new_process,
|
||||||
|
(req_handler)req_wait_process,
|
||||||
(req_handler)req_new_thread,
|
(req_handler)req_new_thread,
|
||||||
(req_handler)req_boot_done,
|
(req_handler)req_boot_done,
|
||||||
(req_handler)req_init_process,
|
(req_handler)req_init_process,
|
||||||
|
|
|
@ -116,7 +116,7 @@ static int alloc_client_buffer( struct thread *thread )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create a new 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;
|
struct thread *thread;
|
||||||
|
|
||||||
|
@ -131,6 +131,7 @@ struct thread *create_thread( int fd, struct process *process, int suspend )
|
||||||
thread->mutex = NULL;
|
thread->mutex = NULL;
|
||||||
thread->debug_ctx = NULL;
|
thread->debug_ctx = NULL;
|
||||||
thread->debug_event = NULL;
|
thread->debug_event = NULL;
|
||||||
|
thread->info = NULL;
|
||||||
thread->wait = NULL;
|
thread->wait = NULL;
|
||||||
thread->apc = NULL;
|
thread->apc = NULL;
|
||||||
thread->apc_count = 0;
|
thread->apc_count = 0;
|
||||||
|
@ -143,7 +144,7 @@ struct thread *create_thread( int fd, struct process *process, int suspend )
|
||||||
thread->prev = NULL;
|
thread->prev = NULL;
|
||||||
thread->priority = THREAD_PRIORITY_NORMAL;
|
thread->priority = THREAD_PRIORITY_NORMAL;
|
||||||
thread->affinity = 1;
|
thread->affinity = 1;
|
||||||
thread->suspend = (suspend != 0);
|
thread->suspend = 0;
|
||||||
thread->buffer = (void *)-1;
|
thread->buffer = (void *)-1;
|
||||||
thread->last_req = REQ_GET_THREAD_BUFFER;
|
thread->last_req = REQ_GET_THREAD_BUFFER;
|
||||||
thread->process = (struct process *)grab_object( process );
|
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;
|
if (thread->prev) thread->prev->next = thread->next;
|
||||||
else first_thread = thread->next;
|
else first_thread = thread->next;
|
||||||
if (thread->apc) free( thread->apc );
|
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->buffer != (void *)-1) munmap( thread->buffer, MAX_REQUEST_LENGTH );
|
||||||
if (thread->pass_fd != -1) close( thread->pass_fd );
|
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 (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;
|
req->tid = thread;
|
||||||
if ((req->handle = alloc_handle( current->process, thread,
|
if ((req->handle = alloc_handle( current->process, thread,
|
||||||
THREAD_ALL_ACCESS, req->inherit )) != -1)
|
THREAD_ALL_ACCESS, req->inherit )) != -1)
|
||||||
|
|
|
@ -21,6 +21,7 @@ struct thread_apc;
|
||||||
struct mutex;
|
struct mutex;
|
||||||
struct debug_ctx;
|
struct debug_ctx;
|
||||||
struct debug_event;
|
struct debug_event;
|
||||||
|
struct startup_info;
|
||||||
|
|
||||||
enum run_state
|
enum run_state
|
||||||
{
|
{
|
||||||
|
@ -40,6 +41,7 @@ struct thread
|
||||||
struct mutex *mutex; /* list of currently owned mutexes */
|
struct mutex *mutex; /* list of currently owned mutexes */
|
||||||
struct debug_ctx *debug_ctx; /* debugger context if this thread is a debugger */
|
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 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_wait *wait; /* current wait condition if sleeping */
|
||||||
struct thread_apc *apc; /* list of async procedure calls */
|
struct thread_apc *apc; /* list of async procedure calls */
|
||||||
int apc_count; /* number of outstanding APCs */
|
int apc_count; /* number of outstanding APCs */
|
||||||
|
@ -72,7 +74,7 @@ extern struct thread *current;
|
||||||
|
|
||||||
/* thread functions */
|
/* 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_id( void *id );
|
||||||
extern struct thread *get_thread_from_handle( int handle, unsigned int access );
|
extern struct thread *get_thread_from_handle( int handle, unsigned int access );
|
||||||
extern struct thread *get_thread_from_pid( int pid );
|
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 )
|
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, " inherit_all=%d,", req->inherit_all );
|
||||||
fprintf( stderr, " create_flags=%d,", req->create_flags );
|
fprintf( stderr, " create_flags=%d,", req->create_flags );
|
||||||
fprintf( stderr, " start_flags=%d,", req->start_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, " hstdout=%d,", req->hstdout );
|
||||||
fprintf( stderr, " hstderr=%d,", req->hstderr );
|
fprintf( stderr, " hstderr=%d,", req->hstderr );
|
||||||
fprintf( stderr, " cmd_show=%d,", req->cmd_show );
|
fprintf( stderr, " cmd_show=%d,", req->cmd_show );
|
||||||
fprintf( stderr, " env_ptr=%p,", req->env_ptr );
|
fprintf( stderr, " alloc_fd=%d", req->alloc_fd );
|
||||||
fprintf( stderr, " cmdline=" );
|
|
||||||
dump_string( req, req->cmdline );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_new_process_reply( const struct new_process_request *req )
|
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_wait_process_reply( const struct wait_process_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " pid=%p,", req->pid );
|
fprintf( stderr, " pid=%p,", req->pid );
|
||||||
fprintf( stderr, " phandle=%d,", req->phandle );
|
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 )
|
static void dump_init_process_request( const struct init_process_request *req )
|
||||||
{
|
{
|
||||||
fprintf( stderr, " ldt_copy=%p,", req->ldt_copy );
|
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 )
|
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, " hstdin=%d,", req->hstdin );
|
||||||
fprintf( stderr, " hstdout=%d,", req->hstdout );
|
fprintf( stderr, " hstdout=%d,", req->hstdout );
|
||||||
fprintf( stderr, " hstderr=%d,", req->hstderr );
|
fprintf( stderr, " hstderr=%d,", req->hstderr );
|
||||||
fprintf( stderr, " cmd_show=%d,", req->cmd_show );
|
fprintf( stderr, " cmd_show=%d", req->cmd_show );
|
||||||
fprintf( stderr, " env_ptr=%p,", req->env_ptr );
|
|
||||||
fprintf( stderr, " cmdline=" );
|
|
||||||
dump_string( req, req->cmdline );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_init_process_done_request( const struct init_process_done_request *req )
|
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] = {
|
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_new_process_request,
|
(dump_func)dump_new_process_request,
|
||||||
|
(dump_func)dump_wait_process_request,
|
||||||
(dump_func)dump_new_thread_request,
|
(dump_func)dump_new_thread_request,
|
||||||
(dump_func)dump_boot_done_request,
|
(dump_func)dump_boot_done_request,
|
||||||
(dump_func)dump_init_process_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] = {
|
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)dump_new_thread_reply,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
(dump_func)dump_init_process_reply,
|
(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] = {
|
static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
"new_process",
|
"new_process",
|
||||||
|
"wait_process",
|
||||||
"new_thread",
|
"new_thread",
|
||||||
"boot_done",
|
"boot_done",
|
||||||
"init_process",
|
"init_process",
|
||||||
|
|
|
@ -1533,7 +1533,7 @@ DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
|
||||||
return 0;
|
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 */
|
/* check whether we are waiting for a win32 process or the win16 subsystem */
|
||||||
if ( pdb->flags & PDB32_WIN16_PROC ) {
|
if ( pdb->flags & PDB32_WIN16_PROC ) {
|
||||||
|
|
Loading…
Reference in New Issue