Exec a separate wine binary for every win32 process so that they run
in separate address spaces. Run 16-bit tasks as Win32 threads, not processes.
This commit is contained in:
parent
8f65001f78
commit
c192ba2468
|
@ -392,13 +392,11 @@ HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation,
|
|||
strcpy(cmd,lpFile);
|
||||
strcat(cmd,lpParameters ? lpParameters : "");
|
||||
|
||||
SYSLEVEL_ReleaseWin16Lock();
|
||||
retval = WinExec( cmd, iShowCmd );
|
||||
SYSLEVEL_RestoreWin16Lock();
|
||||
retval = WinExec16( cmd, iShowCmd );
|
||||
|
||||
/* Unable to execute lpFile directly
|
||||
Check if we can match an application to lpFile */
|
||||
if(retval < 31)
|
||||
if(retval < 32)
|
||||
{
|
||||
cmd[0] = '\0';
|
||||
retval = SHELL_FindExecutable( lpFile, lpOperation, cmd );
|
||||
|
@ -410,9 +408,7 @@ HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation,
|
|||
strcat(cmd," ");
|
||||
strcat(cmd,lpParameters);
|
||||
}
|
||||
SYSLEVEL_ReleaseWin16Lock();
|
||||
retval = WinExec( cmd, iShowCmd );
|
||||
SYSLEVEL_RestoreWin16Lock();
|
||||
retval = WinExec16( cmd, iShowCmd );
|
||||
}
|
||||
else if(PathIsURLA((LPSTR)lpFile)) /* File not found, check for URL */
|
||||
{
|
||||
|
@ -477,9 +473,7 @@ HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation,
|
|||
}
|
||||
}
|
||||
|
||||
SYSLEVEL_ReleaseWin16Lock();
|
||||
retval = WinExec( cmd, iShowCmd );
|
||||
SYSLEVEL_RestoreWin16Lock();
|
||||
retval = WinExec16( cmd, iShowCmd );
|
||||
}
|
||||
}
|
||||
/* Check if file specified is in the form www.??????.*** */
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
#include "windef.h"
|
||||
|
||||
extern BOOL MAIN_MainInit( int argc, char *argv[], BOOL win32 );
|
||||
extern BOOL MAIN_WineInit( int argc, char *argv[] );
|
||||
extern BOOL MAIN_MainInit( char *argv[] );
|
||||
extern void MAIN_WineInit(void);
|
||||
extern int MAIN_GetLanguageID(char*lang, char*country, char*charset, char*dialect);
|
||||
extern void MAIN_ParseDebugOptions(const char *options);
|
||||
extern void MAIN_ParseLanguageOption( const char *arg );
|
||||
|
|
|
@ -183,6 +183,7 @@ extern void MODULE_DllThreadDetach( LPVOID lpReserved );
|
|||
extern WINE_MODREF *MODULE_LoadLibraryExA( LPCSTR libname, HFILE hfile, DWORD flags );
|
||||
extern BOOL MODULE_FreeLibrary( WINE_MODREF *wm );
|
||||
extern WINE_MODREF *MODULE_FindModule( LPCSTR path );
|
||||
extern BOOL MODULE_GetBinaryType( HANDLE hfile, LPCSTR filename, LPDWORD lpBinaryType );
|
||||
extern HMODULE MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
|
||||
extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name );
|
||||
extern SEGPTR WINAPI HasGPHandler16( SEGPTR address );
|
||||
|
@ -201,12 +202,6 @@ extern FARPROC16 WINAPI NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal );
|
|||
extern FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop );
|
||||
extern BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset );
|
||||
extern HANDLE NE_OpenFile( NE_MODULE *pModule );
|
||||
extern BOOL NE_CreateProcess( HANDLE hFile, LPCSTR filename, LPCSTR cmd_line, LPCSTR env,
|
||||
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
||||
BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
|
||||
LPPROCESS_INFORMATION info );
|
||||
extern BOOL NE_InitProcess( NE_MODULE *pModule );
|
||||
|
||||
|
||||
/* loader/ne/resource.c */
|
||||
extern HGLOBAL16 WINAPI NE_DefResourceHandler(HGLOBAL16,HMODULE16,HRSRC16);
|
||||
|
|
|
@ -70,7 +70,7 @@ extern struct options Options;
|
|||
extern const char *argv0;
|
||||
|
||||
extern void OPTIONS_Usage(void) WINE_NORETURN;
|
||||
extern void OPTIONS_ParseOptions( int argc, char *argv[] );
|
||||
extern void OPTIONS_ParseOptions( char *argv[] );
|
||||
|
||||
/* Profile functions */
|
||||
|
||||
|
|
|
@ -41,11 +41,6 @@ extern HGLOBAL PE_LoadResource(struct _wine_modref *wm,HRSRC);
|
|||
extern HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename );
|
||||
extern struct _wine_modref *PE_CreateModule( HMODULE hModule, LPCSTR filename,
|
||||
DWORD flags, BOOL builtin );
|
||||
extern BOOL PE_CreateProcess( HANDLE hFile, LPCSTR filename, LPCSTR cmd_line, LPCSTR env,
|
||||
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
||||
BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
|
||||
LPPROCESS_INFORMATION info );
|
||||
|
||||
extern void PE_InitTls(void);
|
||||
extern BOOL PE_InitDLL(struct _wine_modref *wm, DWORD type, LPVOID lpReserved);
|
||||
|
||||
|
|
|
@ -88,9 +88,7 @@ typedef struct _PDB
|
|||
DWORD unknown8; /* c0 Unknown (NT) */
|
||||
LCID locale; /* c4 Locale to be queried by GetThreadLocale (NT) */
|
||||
/* The following are Wine-specific fields */
|
||||
void *server_pid; /* Server id for this process */
|
||||
HANDLE *dos_handles; /* Handles mapping DOS -> Win32 */
|
||||
struct _PDB *next; /* List reference - list of PDB's */
|
||||
WORD winver; /* Windows version figured out by VERSION_GetVersion */
|
||||
struct _SERVICETABLE *service_table; /* Service table for service thread */
|
||||
HANDLE idle_event; /* event to signal, when the process is idle */
|
||||
|
@ -149,22 +147,17 @@ extern DWORD WINAPI MapProcessHandle( HANDLE handle );
|
|||
|
||||
/* 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 */
|
||||
extern BOOL PROCESS_Init( BOOL win32 );
|
||||
extern BOOL PROCESS_Init(void);
|
||||
extern void PROCESS_InitWine( int argc, char *argv[] ) WINE_NORETURN;
|
||||
extern void PROCESS_InitWinelib( int argc, char *argv[] ) WINE_NORETURN;
|
||||
extern PDB *PROCESS_IdToPDB( DWORD id );
|
||||
extern void PROCESS_CallUserSignalProc( UINT uCode, HMODULE hModule );
|
||||
extern PDB *PROCESS_Create( struct _NE_MODULE *pModule, HFILE hFile,
|
||||
LPCSTR cmd_line, LPCSTR env,
|
||||
extern BOOL PROCESS_Create( HFILE hFile, LPCSTR filename, LPCSTR cmd_line, LPCSTR env,
|
||||
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 );
|
||||
|
||||
static inline PDB * WINE_UNUSED PROCESS_Current(void)
|
||||
{
|
||||
|
|
|
@ -144,7 +144,8 @@ typedef struct _THHOOK
|
|||
|
||||
extern THHOOK *pThhook;
|
||||
|
||||
extern BOOL TASK_Create( struct _NE_MODULE *pModule, UINT16 cmdShow );
|
||||
extern BOOL TASK_Create( struct _NE_MODULE *pModule, UINT16 cmdShow,
|
||||
struct _TEB *teb, LPCSTR cmdline, BYTE len );
|
||||
extern void TASK_KillTask( HTASK16 hTask );
|
||||
extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
|
||||
extern void TASK_Reschedule(void);
|
||||
|
|
|
@ -120,7 +120,7 @@ typedef struct _TEB
|
|||
|
||||
/* scheduler/thread.c */
|
||||
extern void THREAD_Init(void);
|
||||
extern TEB *THREAD_Create( struct _PDB *pdb, int fd, DWORD stack_size, BOOL alloc_stack16 );
|
||||
extern TEB *THREAD_Create( int fd, DWORD stack_size, BOOL alloc_stack16 );
|
||||
extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size, BOOL alloc_stack16 );
|
||||
extern BOOL THREAD_IsWin16( TEB *thdb );
|
||||
extern TEB *THREAD_IdToTEB( DWORD id );
|
||||
|
|
|
@ -452,6 +452,7 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
BOOL MZ_CreateProcess( HANDLE hFile, LPCSTR filename, LPCSTR cmdline, LPCSTR env,
|
||||
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
||||
BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
|
||||
|
@ -508,6 +509,7 @@ BOOL MZ_CreateProcess( HANDLE hFile, LPCSTR filename, LPCSTR cmdline, LPCSTR env
|
|||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
void MZ_KillModule( LPDOSTASK lpDosTask )
|
||||
{
|
||||
|
|
|
@ -60,19 +60,17 @@ DEFAULT_DEBUG_CHANNEL(server);
|
|||
/***********************************************************************
|
||||
* Main initialisation routine
|
||||
*/
|
||||
BOOL MAIN_MainInit( int argc, char *argv[], BOOL win32 )
|
||||
BOOL MAIN_MainInit( char *argv[] )
|
||||
{
|
||||
/* store the program name */
|
||||
argv0 = argv[0];
|
||||
|
||||
/* Create the initial process */
|
||||
if (!PROCESS_Init( win32 )) return 0;
|
||||
|
||||
/* Initialize syslevel handling */
|
||||
SYSLEVEL_Init();
|
||||
if (!PROCESS_Init()) return FALSE;
|
||||
|
||||
/* Parse command line arguments */
|
||||
MAIN_WineInit( argc, argv );
|
||||
OPTIONS_ParseOptions( argv );
|
||||
MAIN_WineInit();
|
||||
|
||||
/* Load the configuration file */
|
||||
if (!PROFILE_LoadWineIni()) return FALSE;
|
||||
|
|
138
loader/module.c
138
loader/module.c
|
@ -39,35 +39,6 @@
|
|||
DEFAULT_DEBUG_CHANNEL(module);
|
||||
DECLARE_DEBUG_CHANNEL(win32);
|
||||
|
||||
/*************************************************************************
|
||||
* MODULE_WalkModref
|
||||
* Walk MODREFs for input process ID
|
||||
*/
|
||||
void MODULE_WalkModref( DWORD id )
|
||||
{
|
||||
int i;
|
||||
WINE_MODREF *zwm, *prev = NULL;
|
||||
PDB *pdb = PROCESS_IdToPDB( id );
|
||||
|
||||
if (!pdb) {
|
||||
MESSAGE("Invalid process id (pid)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
MESSAGE("Modref list for process pdb=%p\n", pdb);
|
||||
MESSAGE("Modref next prev handle deps flags name\n");
|
||||
for ( zwm = pdb->modref_list; zwm; zwm = zwm->next) {
|
||||
MESSAGE("%p %p %p %04x %5d %04x %s\n", zwm, zwm->next, zwm->prev,
|
||||
zwm->module, zwm->nDeps, zwm->flags, zwm->modname);
|
||||
for ( i = 0; i < zwm->nDeps; i++ ) {
|
||||
if ( zwm->deps[i] )
|
||||
MESSAGE(" %d %p %s\n", i, zwm->deps[i], zwm->deps[i]->modname);
|
||||
}
|
||||
if (prev != zwm->prev)
|
||||
MESSAGE(" --> modref corrupt, previous pointer wrong!!\n");
|
||||
prev = zwm;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* MODULE32_LookupHMODULE
|
||||
|
@ -502,8 +473,7 @@ WINE_MODREF *MODULE_FindModule(
|
|||
* Note that .COM and .PIF files are only recognized by their
|
||||
* file name extension; but Windows does it the same way ...
|
||||
*/
|
||||
static BOOL MODULE_GetBinaryType( HANDLE hfile, LPCSTR filename,
|
||||
LPDWORD lpBinaryType )
|
||||
BOOL MODULE_GetBinaryType( HANDLE hfile, LPCSTR filename, LPDWORD lpBinaryType )
|
||||
{
|
||||
IMAGE_DOS_HEADER mz_header;
|
||||
char magic[4], *ptr;
|
||||
|
@ -690,13 +660,59 @@ BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
|
|||
*/
|
||||
HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
|
||||
{
|
||||
HINSTANCE16 hInst;
|
||||
LPCSTR p;
|
||||
LPSTR name, cmdline;
|
||||
int len;
|
||||
HINSTANCE16 ret;
|
||||
char buffer[MAX_PATH];
|
||||
|
||||
SYSLEVEL_ReleaseWin16Lock();
|
||||
hInst = WinExec( lpCmdLine, nCmdShow );
|
||||
SYSLEVEL_RestoreWin16Lock();
|
||||
if ((p = strchr( lpCmdLine, ' ' )))
|
||||
{
|
||||
if (!(name = HeapAlloc( GetProcessHeap(), 0, p - lpCmdLine + 1 )))
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
memcpy( name, lpCmdLine, p - lpCmdLine );
|
||||
name[p - lpCmdLine] = 0;
|
||||
p++;
|
||||
len = strlen(p);
|
||||
cmdline = SEGPTR_ALLOC( len + 2 );
|
||||
cmdline[0] = (BYTE)len;
|
||||
strcpy( cmdline + 1, p );
|
||||
}
|
||||
else
|
||||
{
|
||||
name = (LPSTR)lpCmdLine;
|
||||
cmdline = SEGPTR_ALLOC(2);
|
||||
cmdline[0] = cmdline[1] = 0;
|
||||
}
|
||||
|
||||
return hInst;
|
||||
if (SearchPathA( NULL, name, ".exe", sizeof(buffer), buffer, NULL ))
|
||||
{
|
||||
LOADPARAMS16 params;
|
||||
WORD *showCmd = SEGPTR_ALLOC( 2*sizeof(WORD) );
|
||||
showCmd[0] = 2;
|
||||
showCmd[1] = nCmdShow;
|
||||
|
||||
params.hEnvironment = 0;
|
||||
params.cmdLine = SEGPTR_GET(cmdline);
|
||||
params.showCmd = SEGPTR_GET(showCmd);
|
||||
params.reserved = 0;
|
||||
|
||||
ret = LoadModule16( buffer, ¶ms );
|
||||
|
||||
SEGPTR_FREE( showCmd );
|
||||
SEGPTR_FREE( cmdline );
|
||||
}
|
||||
else ret = GetLastError();
|
||||
|
||||
if (name != lpCmdLine) HeapFree( GetProcessHeap(), 0, name );
|
||||
|
||||
if (ret == 21) /* 32-bit module */
|
||||
{
|
||||
SYSLEVEL_ReleaseWin16Lock();
|
||||
ret = WinExec( lpCmdLine, nCmdShow );
|
||||
SYSLEVEL_RestoreWin16Lock();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -719,14 +735,7 @@ HINSTANCE WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
|
|||
/* Give 30 seconds to the app to come up */
|
||||
if (Callout.WaitForInputIdle ( info.hProcess, 30000 ) == 0xFFFFFFFF)
|
||||
WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
|
||||
|
||||
/* Get 16-bit hInstance/hTask from process */
|
||||
hInstance = GetProcessDword( info.dwProcessId, GPD_HINSTANCE16 );
|
||||
/* If there is no hInstance (32-bit process) return a dummy value
|
||||
* that must be > 31
|
||||
* FIXME: should do this in all cases and fix Win16 callers */
|
||||
if (!hInstance) hInstance = 33;
|
||||
|
||||
hInstance = 33;
|
||||
/* Close off the handles */
|
||||
CloseHandle( info.hThread );
|
||||
CloseHandle( info.hProcess );
|
||||
|
@ -783,13 +792,7 @@ HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
|
|||
/* Give 30 seconds to the app to come up */
|
||||
if ( Callout.WaitForInputIdle ( info.hProcess, 30000 ) == 0xFFFFFFFF )
|
||||
WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
|
||||
|
||||
/* Get 16-bit hInstance/hTask from process */
|
||||
hInstance = GetProcessDword( info.dwProcessId, GPD_HINSTANCE16 );
|
||||
/* If there is no hInstance (32-bit process) return a dummy value
|
||||
* that must be > 31
|
||||
* FIXME: should do this in all cases and fix Win16 callers */
|
||||
if (!hInstance) hInstance = 33;
|
||||
hInstance = 33;
|
||||
/* Close off the handles */
|
||||
CloseHandle( info.hThread );
|
||||
CloseHandle( info.hProcess );
|
||||
|
@ -905,6 +908,8 @@ BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
|
|||
|
||||
/* Process the AppName and/or CmdLine to get module name and path */
|
||||
|
||||
TRACE("app '%s' cmdline '%s'\n", lpApplicationName, lpCommandLine );
|
||||
|
||||
if (!(tidy_cmdline = get_file_name( lpApplicationName, lpCommandLine, name, sizeof(name) )))
|
||||
return FALSE;
|
||||
|
||||
|
@ -972,11 +977,10 @@ BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
|
|||
if ( !MODULE_GetBinaryType( hFile, name, &type ) )
|
||||
{
|
||||
CloseHandle( hFile );
|
||||
/* FIXME: Try Unix executable only when appropriate! */
|
||||
retv = PROCESS_CreateUnixProcess( name, tidy_cmdline, lpEnvironment,
|
||||
lpProcessAttributes, lpThreadAttributes,
|
||||
bInheritHandles, dwCreationFlags,
|
||||
lpStartupInfo, lpProcessInfo );
|
||||
retv = PROCESS_Create( -1, name, tidy_cmdline, lpEnvironment,
|
||||
lpProcessAttributes, lpThreadAttributes,
|
||||
bInheritHandles, dwCreationFlags,
|
||||
lpStartupInfo, lpProcessInfo );
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -985,24 +989,12 @@ BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
|
|||
switch ( type )
|
||||
{
|
||||
case SCS_32BIT_BINARY:
|
||||
retv = PE_CreateProcess( hFile, name, tidy_cmdline, lpEnvironment,
|
||||
lpProcessAttributes, lpThreadAttributes,
|
||||
bInheritHandles, dwCreationFlags,
|
||||
lpStartupInfo, lpProcessInfo );
|
||||
break;
|
||||
|
||||
case SCS_DOS_BINARY:
|
||||
retv = MZ_CreateProcess( hFile, name, tidy_cmdline, lpEnvironment,
|
||||
lpProcessAttributes, lpThreadAttributes,
|
||||
bInheritHandles, dwCreationFlags,
|
||||
lpStartupInfo, lpProcessInfo );
|
||||
break;
|
||||
|
||||
case SCS_WOW_BINARY:
|
||||
retv = NE_CreateProcess( hFile, name, tidy_cmdline, lpEnvironment,
|
||||
lpProcessAttributes, lpThreadAttributes,
|
||||
bInheritHandles, dwCreationFlags,
|
||||
lpStartupInfo, lpProcessInfo );
|
||||
case SCS_DOS_BINARY:
|
||||
retv = PROCESS_Create( hFile, name, tidy_cmdline, lpEnvironment,
|
||||
lpProcessAttributes, lpThreadAttributes,
|
||||
bInheritHandles, dwCreationFlags,
|
||||
lpStartupInfo, lpProcessInfo );
|
||||
break;
|
||||
|
||||
case SCS_PIF_BINARY:
|
||||
|
|
|
@ -29,8 +29,9 @@
|
|||
#include "debugtools.h"
|
||||
#include "loadorder.h"
|
||||
#include "elfdll.h"
|
||||
#include "server.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(module)
|
||||
DEFAULT_DEBUG_CHANNEL(module);
|
||||
|
||||
#define hFirstModule (pThhook->hExeHead)
|
||||
|
||||
|
@ -38,6 +39,7 @@ static NE_MODULE *pCachedModule = 0; /* Module cached by NE_OpenFile */
|
|||
|
||||
static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only );
|
||||
static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep );
|
||||
static HINSTANCE16 NE_InitProcess( NE_MODULE *pModule, HTASK hTask );
|
||||
|
||||
static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_only );
|
||||
|
||||
|
@ -991,15 +993,16 @@ static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_
|
|||
*/
|
||||
HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
|
||||
{
|
||||
struct new_thread_request *req = get_req_buffer();
|
||||
TEB *teb = NULL;
|
||||
BOOL lib_only = !paramBlock || (paramBlock == (LPVOID)-1);
|
||||
LOADPARAMS16 *params;
|
||||
LPSTR cmd_line, new_cmd_line;
|
||||
LPCVOID env = NULL;
|
||||
STARTUPINFOA startup;
|
||||
PROCESS_INFORMATION info;
|
||||
HINSTANCE16 instance;
|
||||
HMODULE16 hModule;
|
||||
NE_MODULE *pModule;
|
||||
PDB *pdb;
|
||||
LPSTR cmdline;
|
||||
WORD cmdShow;
|
||||
int socket;
|
||||
|
||||
/* Load module */
|
||||
|
||||
|
@ -1037,128 +1040,52 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
|
|||
* has already been incremented (to avoid having the module vanish
|
||||
* in the meantime), or else to a stub module which contains only header
|
||||
* information.
|
||||
*
|
||||
* All remaining initialization (really loading the module in the second
|
||||
* case, and creating the new instance in both cases) are to be done in
|
||||
* the context of the new process. This happens in the NE_InitProcess
|
||||
* routine, which will be called from the 32-bit process initialization.
|
||||
*/
|
||||
|
||||
/* Create the main thread */
|
||||
|
||||
req->suspend = 0;
|
||||
req->inherit = 0;
|
||||
if (server_call_fd( REQ_NEW_THREAD, -1, &socket )) return 0;
|
||||
CloseHandle( req->handle );
|
||||
|
||||
if (!(teb = THREAD_Create( socket, 0, FALSE ))) goto error;
|
||||
teb->startup = TASK_CallToStart;
|
||||
|
||||
/* Create a task for this process */
|
||||
|
||||
params = (LOADPARAMS16 *)paramBlock;
|
||||
cmd_line = (LPSTR)PTR_SEG_TO_LIN( params->cmdLine );
|
||||
if (!cmd_line) cmd_line = "";
|
||||
else if (*cmd_line) cmd_line++; /* skip the length byte */
|
||||
cmdShow = ((WORD *)PTR_SEG_TO_LIN(params->showCmd))[1];
|
||||
cmdline = PTR_SEG_TO_LIN( params->cmdLine );
|
||||
if (!TASK_Create( pModule, cmdShow, teb, cmdline + 1, *cmdline )) goto error;
|
||||
|
||||
if (!(new_cmd_line = HeapAlloc( GetProcessHeap(), 0,
|
||||
strlen(cmd_line)+strlen(name)+2 )))
|
||||
return 0;
|
||||
strcpy( new_cmd_line, name );
|
||||
strcat( new_cmd_line, " " );
|
||||
strcat( new_cmd_line, cmd_line );
|
||||
if ((instance = NE_InitProcess( pModule, teb->htask16 )) < 32) goto error;
|
||||
|
||||
if (params->hEnvironment) env = GlobalLock16( params->hEnvironment );
|
||||
if (SYSDEPS_SpawnThread( teb ) == -1) goto error;
|
||||
|
||||
memset( &info, '\0', sizeof(info) );
|
||||
memset( &startup, '\0', sizeof(startup) );
|
||||
startup.cb = sizeof(startup);
|
||||
if (params->showCmd)
|
||||
{
|
||||
startup.dwFlags = STARTF_USESHOWWINDOW;
|
||||
startup.wShowWindow = ((UINT16 *)PTR_SEG_TO_LIN(params->showCmd))[1];
|
||||
}
|
||||
/* Post event to start the task */
|
||||
PostEvent16( teb->htask16 );
|
||||
OldYield16();
|
||||
|
||||
SYSLEVEL_ReleaseWin16Lock();
|
||||
pdb = PROCESS_Create( pModule, -1, new_cmd_line, env,
|
||||
NULL, NULL, TRUE, 0, &startup, &info );
|
||||
SYSLEVEL_RestoreWin16Lock();
|
||||
|
||||
CloseHandle( info.hThread );
|
||||
CloseHandle( info.hProcess );
|
||||
|
||||
if (params->hEnvironment) GlobalUnlock16( params->hEnvironment );
|
||||
HeapFree( GetProcessHeap(), 0, new_cmd_line );
|
||||
|
||||
return GetProcessDword( info.dwProcessId, GPD_HINSTANCE16 );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* NE_CreateProcess
|
||||
*/
|
||||
BOOL NE_CreateProcess( HANDLE hFile, LPCSTR filename, LPCSTR cmd_line, LPCSTR env,
|
||||
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
||||
BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
|
||||
LPPROCESS_INFORMATION info )
|
||||
{
|
||||
HMODULE16 hModule;
|
||||
NE_MODULE *pModule;
|
||||
|
||||
SYSLEVEL_EnterWin16Lock();
|
||||
|
||||
/* Special case: second instance of an already loaded NE module
|
||||
* FIXME: maybe we should mark the module in a special way during
|
||||
* "second instance" loading stage ?
|
||||
* NE_CreateSegment and NE_LoadSegment might get confused without it,
|
||||
* especially when it comes to self-loaders */
|
||||
|
||||
if ( ( hModule = NE_GetModuleByFilename( filename ) ) != 0 )
|
||||
{
|
||||
if ( !( pModule = NE_GetPtr( hModule) )
|
||||
|| ( pModule->flags & NE_FFLAGS_LIBMODULE )
|
||||
|| pModule->module32 )
|
||||
{
|
||||
SetLastError( ERROR_BAD_FORMAT );
|
||||
goto error;
|
||||
}
|
||||
|
||||
pModule->count++;
|
||||
}
|
||||
|
||||
/* Main case: load first instance of NE module */
|
||||
else
|
||||
{
|
||||
/* Load module */
|
||||
|
||||
hModule = NE_LoadExeHeader( filename );
|
||||
if ( hModule < 32 )
|
||||
{
|
||||
SetLastError( hModule );
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ( !( pModule = NE_GetPtr( hModule ) )
|
||||
|| ( pModule->flags & NE_FFLAGS_LIBMODULE) )
|
||||
{
|
||||
GlobalFreeAll16( hModule );
|
||||
SetLastError( ERROR_BAD_FORMAT );
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
SYSLEVEL_LeaveWin16Lock();
|
||||
|
||||
if ( !PROCESS_Create( pModule, hFile, cmd_line, env,
|
||||
psa, tsa, inherit, flags, startup, info ) )
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
return instance;
|
||||
|
||||
error:
|
||||
SYSLEVEL_LeaveWin16Lock();
|
||||
return FALSE;
|
||||
/* FIXME: free TEB and task */
|
||||
close( socket );
|
||||
return 0; /* FIXME */
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NE_InitProcess
|
||||
*/
|
||||
BOOL NE_InitProcess( NE_MODULE *pModule )
|
||||
static HINSTANCE16 NE_InitProcess( NE_MODULE *pModule, HTASK hTask )
|
||||
{
|
||||
HINSTANCE16 hInstance, hPrevInstance;
|
||||
BOOL retv = TRUE;
|
||||
TDB *pTask;
|
||||
|
||||
SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
|
||||
WORD sp;
|
||||
TDB *pTask;
|
||||
|
||||
SYSLEVEL_EnterWin16Lock();
|
||||
|
||||
|
@ -1187,30 +1114,25 @@ BOOL NE_InitProcess( NE_MODULE *pModule )
|
|||
hPrevInstance = 0;
|
||||
}
|
||||
|
||||
if ( hInstance < 32 )
|
||||
if ( hInstance >= 32 )
|
||||
{
|
||||
SYSLEVEL_LeaveWin16Lock();
|
||||
/* Enter instance handles into task struct */
|
||||
|
||||
SetLastError( hInstance );
|
||||
return FALSE;
|
||||
pTask = (TDB *)GlobalLock16( hTask );
|
||||
pTask->hInstance = hInstance;
|
||||
pTask->hPrevInstance = hPrevInstance;
|
||||
|
||||
/* Use DGROUP for 16-bit stack */
|
||||
|
||||
if (!(sp = pModule->sp))
|
||||
sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
|
||||
sp &= ~1;
|
||||
sp -= sizeof(STACK16FRAME);
|
||||
pTask->teb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( GlobalHandleToSel16(hInstance), sp );
|
||||
}
|
||||
|
||||
/* Enter instance handles into task struct */
|
||||
|
||||
pTask = (TDB *)GlobalLock16( GetCurrentTask() );
|
||||
pTask->hInstance = hInstance;
|
||||
pTask->hPrevInstance = hPrevInstance;
|
||||
|
||||
/* Use DGROUP for 16-bit stack */
|
||||
|
||||
if (!(sp = pModule->sp))
|
||||
sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
|
||||
sp &= ~1; sp -= sizeof(STACK16FRAME);
|
||||
pTask->teb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( GlobalHandleToSel16(hInstance), sp );
|
||||
|
||||
SYSLEVEL_LeaveWin16Lock();
|
||||
|
||||
return retv;
|
||||
return hInstance;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -572,6 +572,7 @@ HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename )
|
|||
filename, aoep, lowest_va );
|
||||
|
||||
|
||||
#if 0
|
||||
/* FIXME: Hack! While we don't really support shared sections yet,
|
||||
* this checks for those special cases where the whole DLL
|
||||
* consists only of shared sections and is mapped into the
|
||||
|
@ -599,7 +600,7 @@ HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename )
|
|||
return sharedMod;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Allocate memory for module */
|
||||
load_addr = nt->OptionalHeader.ImageBase;
|
||||
|
@ -983,53 +984,6 @@ void PE_UnloadLibrary(WINE_MODREF *wm)
|
|||
HeapFree( GetProcessHeap(), 0, wm );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Load the PE main .EXE. All other loading is done by PE_LoadLibraryExA
|
||||
* FIXME: this function should use PE_LoadLibraryExA, but currently can't
|
||||
* due to the PROCESS_Create stuff.
|
||||
*/
|
||||
BOOL PE_CreateProcess( HANDLE hFile, LPCSTR filename, LPCSTR cmd_line, LPCSTR env,
|
||||
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
||||
BOOL inherit, DWORD flags, LPSTARTUPINFOA startup,
|
||||
LPPROCESS_INFORMATION info )
|
||||
{
|
||||
HMODULE16 hModule16;
|
||||
HMODULE hModule32;
|
||||
NE_MODULE *pModule;
|
||||
|
||||
/* Load file */
|
||||
if ( (hModule32 = PE_LoadImage( hFile, filename )) < 32 )
|
||||
{
|
||||
SetLastError( hModule32 );
|
||||
return FALSE;
|
||||
}
|
||||
#if 0
|
||||
if (PE_HEADER(hModule32)->FileHeader.Characteristics & IMAGE_FILE_DLL)
|
||||
{
|
||||
SetLastError( 20 ); /* FIXME: not the right error code */
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create 16-bit dummy module */
|
||||
if ( (hModule16 = MODULE_CreateDummyModule( filename, hModule32 )) < 32 )
|
||||
{
|
||||
SetLastError( hModule16 );
|
||||
return FALSE;
|
||||
}
|
||||
pModule = (NE_MODULE *)GlobalLock16( hModule16 );
|
||||
|
||||
/* Create new process */
|
||||
if ( !PROCESS_Create( pModule, hFile, cmd_line, env,
|
||||
psa, tsa, inherit, flags, startup, info ) )
|
||||
return FALSE;
|
||||
|
||||
/* Note: PE_CreateModule and the remaining process initialization will
|
||||
be done in the context of the new process, in TASK_CallToStart */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Called if the library is loaded or freed.
|
||||
* NOTE: if a thread attaches a DLL, the current thread will only do
|
||||
|
|
|
@ -274,11 +274,10 @@ void TASK_CallToStart(void)
|
|||
* by entering the Win16Lock while linking the task into the
|
||||
* global task list.
|
||||
*/
|
||||
BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow)
|
||||
BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cmdline, BYTE len )
|
||||
{
|
||||
HTASK16 hTask;
|
||||
TDB *pTask;
|
||||
LPSTR cmd_line;
|
||||
char name[10];
|
||||
PDB *pdb32 = PROCESS_Current();
|
||||
|
||||
|
@ -310,7 +309,7 @@ BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow)
|
|||
pTask->hParent = GetCurrentTask();
|
||||
pTask->magic = TDB_MAGIC;
|
||||
pTask->nCmdShow = cmdShow;
|
||||
pTask->teb = NtCurrentTeb();
|
||||
pTask->teb = teb;
|
||||
pTask->curdrive = DRIVE_GetCurrentDrive() | 0x80;
|
||||
strcpy( pTask->curdir, "\\" );
|
||||
lstrcpynA( pTask->curdir + 1, DRIVE_GetDosCwd( DRIVE_GetCurrentDrive() ),
|
||||
|
@ -349,11 +348,17 @@ BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow)
|
|||
|
||||
/* Fill the command line */
|
||||
|
||||
cmd_line = pdb32->env_db->cmd_line;
|
||||
while (*cmd_line && (*cmd_line != ' ') && (*cmd_line != '\t')) cmd_line++;
|
||||
while ((*cmd_line == ' ') || (*cmd_line == '\t')) cmd_line++;
|
||||
lstrcpynA( pTask->pdb.cmdLine+1, cmd_line, sizeof(pTask->pdb.cmdLine)-1);
|
||||
pTask->pdb.cmdLine[0] = strlen( pTask->pdb.cmdLine + 1 );
|
||||
if (!cmdline)
|
||||
{
|
||||
cmdline = pdb32->env_db->cmd_line;
|
||||
while (*cmdline && (*cmdline != ' ') && (*cmdline != '\t')) cmdline++;
|
||||
while ((*cmdline == ' ') || (*cmdline == '\t')) cmdline++;
|
||||
len = strlen(cmdline);
|
||||
}
|
||||
if (len >= sizeof(pTask->pdb.cmdLine)) len = sizeof(pTask->pdb.cmdLine)-1;
|
||||
pTask->pdb.cmdLine[0] = len;
|
||||
memcpy( pTask->pdb.cmdLine + 1, cmdline, len );
|
||||
/* pTask->pdb.cmdLine[len+1] = 0; */
|
||||
|
||||
/* Get the compatibility flags */
|
||||
|
||||
|
@ -384,10 +389,10 @@ BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow)
|
|||
|
||||
/* Enter task handle into thread and process */
|
||||
|
||||
pTask->teb->htask16 = pTask->teb->process->task = hTask;
|
||||
teb->htask16 = hTask;
|
||||
if (!initial_task) initial_task = hTask;
|
||||
|
||||
TRACE("module='%s' cmdline='%s' task=%04x\n", name, cmd_line, hTask );
|
||||
TRACE("module='%s' cmdline='%.*s' task=%04x\n", name, *cmdline, cmdline+1, hTask );
|
||||
|
||||
/* Add the task to the linked list */
|
||||
|
||||
|
@ -932,7 +937,7 @@ FARPROC16 WINAPI MakeProcInstance16( FARPROC16 func, HANDLE16 hInstance )
|
|||
|
||||
hInstanceSelector = GlobalHandleToSel16(hInstance);
|
||||
|
||||
TRACE("(%08lx, %04x);", (DWORD)func, hInstance);
|
||||
TRACE("(%08lx, %04x);\n", (DWORD)func, hInstance);
|
||||
|
||||
if (!HIWORD(func)) {
|
||||
/* Win95 actually protects via SEH, but this is better for debugging */
|
||||
|
@ -1168,8 +1173,8 @@ HQUEUE16 WINAPI SetThreadQueue16( DWORD thread, HQUEUE16 hQueue )
|
|||
{
|
||||
teb->queue = hQueue;
|
||||
|
||||
if ( GetTaskQueue16( teb->process->task ) == oldQueue )
|
||||
SetTaskQueue16( teb->process->task, hQueue );
|
||||
if ( GetTaskQueue16( teb->htask16 ) == oldQueue )
|
||||
SetTaskQueue16( teb->htask16, hQueue );
|
||||
}
|
||||
|
||||
return oldQueue;
|
||||
|
@ -1334,7 +1339,7 @@ void WINAPI GetTaskQueueES16(void)
|
|||
*/
|
||||
HTASK16 WINAPI GetCurrentTask(void)
|
||||
{
|
||||
return PROCESS_Current()->task;
|
||||
return NtCurrentTeb()->htask16;
|
||||
}
|
||||
|
||||
DWORD WINAPI WIN16_GetCurrentTask(void)
|
||||
|
|
|
@ -82,6 +82,8 @@ BOOL ENV_BuildEnvironment(void)
|
|||
|
||||
if (!(p = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
|
||||
PROCESS_Current()->env_db->environ = p;
|
||||
PROCESS_Current()->env_db->env_sel = SELECTOR_AllocBlock( p, 0x10000, SEGMENT_DATA,
|
||||
FALSE, FALSE );
|
||||
|
||||
/* And fill it with the Unix environment */
|
||||
|
||||
|
@ -98,68 +100,6 @@ BOOL ENV_BuildEnvironment(void)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ENV_InheritEnvironment
|
||||
*
|
||||
* Make a process inherit the environment from its parent or from an
|
||||
* explicit environment.
|
||||
*/
|
||||
BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env )
|
||||
{
|
||||
DWORD size;
|
||||
LPCSTR src;
|
||||
LPSTR dst;
|
||||
|
||||
/* Compute the environment size */
|
||||
|
||||
src = env;
|
||||
size = EXTRA_ENV_SIZE;
|
||||
while (*src)
|
||||
{
|
||||
int len = strlen(src) + 1;
|
||||
src += len;
|
||||
if ((len > MAX_WIN16_LEN) && (pdb->flags & PDB32_WIN16_PROC))
|
||||
len = MAX_WIN16_LEN;
|
||||
size += len;
|
||||
}
|
||||
|
||||
/* Copy the environment */
|
||||
|
||||
if (!(pdb->env_db->environ = HeapAlloc( GetProcessHeap(), 0, size )))
|
||||
return FALSE;
|
||||
pdb->env_db->env_sel = SELECTOR_AllocBlock( pdb->env_db->environ,
|
||||
0x10000, SEGMENT_DATA,
|
||||
FALSE, FALSE );
|
||||
src = env;
|
||||
dst = pdb->env_db->environ;
|
||||
while (*src)
|
||||
{
|
||||
if (pdb->flags & PDB32_WIN16_PROC)
|
||||
lstrcpynA( dst, src, MAX_WIN16_LEN );
|
||||
else
|
||||
strcpy( dst, src );
|
||||
src += strlen(src) + 1;
|
||||
dst += strlen(dst) + 1;
|
||||
}
|
||||
FILL_EXTRA_ENV( dst );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ENV_FreeEnvironment
|
||||
*
|
||||
* Free a process environment.
|
||||
*/
|
||||
void ENV_FreeEnvironment( PDB *pdb )
|
||||
{
|
||||
if (!pdb->env_db) return;
|
||||
if (pdb->env_db->env_sel) SELECTOR_FreeBlock( pdb->env_db->env_sel, 1 );
|
||||
DeleteCriticalSection( &pdb->env_db->section );
|
||||
/* the storage will be deleted when the process heap is destroyed */
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* GetCommandLineA (KERNEL32.289)
|
||||
*/
|
||||
|
|
20
misc/main.c
20
misc/main.c
|
@ -80,21 +80,6 @@ const WINE_LANGUAGE_DEF Languages[] =
|
|||
|
||||
WORD WINE_LanguageId = 0x409; /* english as default */
|
||||
|
||||
struct options Options =
|
||||
{ /* default options */
|
||||
0, /* argc */
|
||||
NULL, /* argv */
|
||||
NULL, /* desktopGeometry */
|
||||
NULL, /* display */
|
||||
NULL, /* dllFlags */
|
||||
FALSE, /* synchronous */
|
||||
0, /* language */
|
||||
FALSE, /* Managed windows */
|
||||
NULL /* Alternate config file name */
|
||||
};
|
||||
|
||||
const char *argv0;
|
||||
|
||||
/***********************************************************************
|
||||
* MAIN_ParseDebugOptions
|
||||
*
|
||||
|
@ -636,7 +621,7 @@ static void called_at_exit(void)
|
|||
*
|
||||
* Wine initialisation and command-line parsing
|
||||
*/
|
||||
BOOL MAIN_WineInit( int argc, char *argv[] )
|
||||
void MAIN_WineInit(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
|
@ -662,10 +647,7 @@ BOOL MAIN_WineInit( int argc, char *argv[] )
|
|||
gettimeofday( &tv, NULL);
|
||||
MSG_WineStartTicks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
|
||||
|
||||
OPTIONS_ParseOptions( argc, argv );
|
||||
|
||||
atexit(called_at_exit);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -27,6 +27,20 @@ struct option
|
|||
int _ARGC;
|
||||
char **_ARGV;
|
||||
|
||||
/* default options */
|
||||
struct options Options =
|
||||
{
|
||||
NULL, /* desktopGeometry */
|
||||
NULL, /* display */
|
||||
NULL, /* dllFlags */
|
||||
FALSE, /* synchronous */
|
||||
0, /* language */
|
||||
FALSE, /* Managed windows */
|
||||
NULL /* Alternate config file name */
|
||||
};
|
||||
|
||||
const char *argv0;
|
||||
|
||||
static void do_config( const char *arg );
|
||||
static void do_desktop( const char *arg );
|
||||
static void do_display( const char *arg );
|
||||
|
@ -116,10 +130,9 @@ static void do_config( const char *arg )
|
|||
Options.configFileName = strdup( arg );
|
||||
}
|
||||
|
||||
static inline void remove_options( int *argc, char *argv[], int pos, int count )
|
||||
static inline void remove_options( char *argv[], int pos, int count )
|
||||
{
|
||||
while ((argv[pos] = argv[pos+count])) pos++;
|
||||
*argc -= count;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -128,7 +141,7 @@ static inline void remove_options( int *argc, char *argv[], int pos, int count )
|
|||
void OPTIONS_Usage(void)
|
||||
{
|
||||
const struct option *opt;
|
||||
MESSAGE( "Usage: %s [options] \"program_name [arguments]\"\n\n", argv0 );
|
||||
MESSAGE( "Usage: %s [options] program_name [arguments]\n\n", argv0 );
|
||||
MESSAGE( "Options:\n" );
|
||||
for (opt = option_table; opt->longname; opt++) MESSAGE( " %s\n", opt->usage );
|
||||
ExitProcess(0);
|
||||
|
@ -137,7 +150,7 @@ void OPTIONS_Usage(void)
|
|||
/***********************************************************************
|
||||
* OPTIONS_ParseOptions
|
||||
*/
|
||||
void OPTIONS_ParseOptions( int argc, char *argv[] )
|
||||
void OPTIONS_ParseOptions( char *argv[] )
|
||||
{
|
||||
const struct option *opt;
|
||||
int i;
|
||||
|
@ -163,12 +176,12 @@ void OPTIONS_ParseOptions( int argc, char *argv[] )
|
|||
if (opt->has_arg && argv[i+1])
|
||||
{
|
||||
opt->func( argv[i+1] );
|
||||
remove_options( &argc, argv, i, 2 );
|
||||
remove_options( argv, i, 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
opt->func( "" );
|
||||
remove_options( &argc, argv, i, 1 );
|
||||
remove_options( argv, i, 1 );
|
||||
}
|
||||
i--;
|
||||
}
|
||||
|
@ -178,7 +191,7 @@ void OPTIONS_ParseOptions( int argc, char *argv[] )
|
|||
{
|
||||
if (!strcmp( argv[i], "--" ))
|
||||
{
|
||||
remove_options( &argc, argv, i, 1 );
|
||||
remove_options( argv, i, 1 );
|
||||
break;
|
||||
}
|
||||
if (argv[i][0] == '-')
|
||||
|
@ -187,8 +200,9 @@ void OPTIONS_ParseOptions( int argc, char *argv[] )
|
|||
OPTIONS_Usage();
|
||||
}
|
||||
}
|
||||
Options.argc = argc;
|
||||
Options.argv = argv;
|
||||
_ARGC = argc;
|
||||
|
||||
/* count the resulting arguments */
|
||||
_ARGV = argv;
|
||||
_ARGC = 0;
|
||||
while (argv[_ARGC]) _ARGC++;
|
||||
}
|
||||
|
|
114
miscemu/main.c
114
miscemu/main.c
|
@ -3,89 +3,40 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "winbase.h"
|
||||
#include "wine/winbase16.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
|
||||
#include "builtin32.h"
|
||||
#include "callback.h"
|
||||
#include "main.h"
|
||||
#include "miscemu.h"
|
||||
#include "module.h"
|
||||
#include "options.h"
|
||||
#include "process.h"
|
||||
#include "thread.h"
|
||||
#include "task.h"
|
||||
#include "stackframe.h"
|
||||
#include "wine/exception.h"
|
||||
#include "debugtools.h"
|
||||
|
||||
static BOOL exec_program( LPCSTR cmdline )
|
||||
{
|
||||
HINSTANCE handle = WinExec( cmdline, SW_SHOWNORMAL );
|
||||
if (handle < 32)
|
||||
{
|
||||
MESSAGE( "%s: can't exec '%s': ", argv0, cmdline );
|
||||
switch (handle)
|
||||
{
|
||||
case 2: MESSAGE("file not found\n" ); break;
|
||||
case 11: MESSAGE("invalid exe file\n" ); break;
|
||||
default: MESSAGE("error=%d\n", handle ); break;
|
||||
}
|
||||
}
|
||||
return (handle >= 32);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Main loop of initial task
|
||||
*/
|
||||
void MAIN_EmulatorRun( void )
|
||||
static void initial_task(void)
|
||||
{
|
||||
char startProg[256], defProg[256];
|
||||
int i, tasks = 0;
|
||||
MSG msg;
|
||||
char szGraphicsDriver[MAX_PATH];
|
||||
HINSTANCE16 instance;
|
||||
STARTUPINFOA info;
|
||||
|
||||
if (PROFILE_GetWineIniString( "Wine", "GraphicsDriver",
|
||||
"x11drv", szGraphicsDriver, sizeof(szGraphicsDriver)))
|
||||
GetStartupInfoA( &info );
|
||||
if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = SW_SHOWNORMAL;
|
||||
|
||||
if ((instance = WinExec16( GetCommandLineA(), info.wShowWindow )) < 32)
|
||||
{
|
||||
if (!LoadLibraryA( szGraphicsDriver )) ExitProcess(1);
|
||||
}
|
||||
|
||||
/* Load system DLLs into the initial process (and initialize them) */
|
||||
if ( !LoadLibrary16("GDI.EXE" ) || !LoadLibraryA("GDI32.DLL" )
|
||||
|| !LoadLibrary16("USER.EXE") || !LoadLibraryA("USER32.DLL"))
|
||||
ExitProcess( 1 );
|
||||
|
||||
/* Get pointers to USER routines called by KERNEL */
|
||||
THUNK_InitCallout();
|
||||
|
||||
/* Call FinalUserInit routine */
|
||||
Callout.FinalUserInit16();
|
||||
|
||||
/* Call InitApp for initial task */
|
||||
Callout.InitApp16( MapHModuleLS( 0 ) );
|
||||
|
||||
/* Add the Startup Program to the run list */
|
||||
PROFILE_GetWineIniString( "programs", "Startup", "",
|
||||
startProg, sizeof(startProg) );
|
||||
if (startProg[0]) tasks += exec_program( startProg );
|
||||
|
||||
/* Add the Default Program if no program on the command line */
|
||||
if (!Options.argv[1])
|
||||
{
|
||||
PROFILE_GetWineIniString( "programs", "Default", "",
|
||||
defProg, sizeof(defProg) );
|
||||
if (defProg[0]) tasks += exec_program( defProg );
|
||||
else if (!tasks && !startProg[0]) OPTIONS_Usage();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Load and run executables given on command line */
|
||||
for (i = 1; Options.argv[i]; i++)
|
||||
MESSAGE( "%s: can't exec '%s': ", argv0, GetCommandLineA() );
|
||||
switch (instance)
|
||||
{
|
||||
tasks += exec_program( Options.argv[i] );
|
||||
case 2: MESSAGE("file not found\n" ); break;
|
||||
case 11: MESSAGE("invalid exe file\n" ); break;
|
||||
default: MESSAGE("error=%d\n", instance ); break;
|
||||
}
|
||||
ExitProcess(instance);
|
||||
}
|
||||
if (!tasks) ExitProcess( 0 );
|
||||
|
||||
/* Start message loop for desktop window */
|
||||
|
||||
|
@ -104,28 +55,13 @@ void MAIN_EmulatorRun( void )
|
|||
*/
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
NE_MODULE *pModule;
|
||||
BUILTIN32_DESCRIPTOR descriptor;
|
||||
|
||||
/* Initialize everything */
|
||||
if (!MAIN_MainInit( argc, argv, FALSE )) return 1;
|
||||
memset( &descriptor, 0, sizeof(descriptor) );
|
||||
descriptor.filename = argv[0];
|
||||
descriptor.dllentrypoint = initial_task;
|
||||
BUILTIN32_RegisterDLL( &descriptor );
|
||||
|
||||
if (!THREAD_InitStack( NtCurrentTeb(), 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;
|
||||
|
||||
/* Switch to initial task */
|
||||
PostEvent16( PROCESS_Current()->task );
|
||||
TASK_Reschedule();
|
||||
|
||||
/* Switch stacks and jump to MAIN_EmulatorRun */
|
||||
CALL32_Init( &IF1632_CallLargeStack, MAIN_EmulatorRun, NtCurrentTeb()->stack_top );
|
||||
|
||||
MESSAGE( "main: Should never happen: returned from CALL32_Init()\n" );
|
||||
return 0;
|
||||
PROCESS_InitWine( argc, argv );
|
||||
return 1; /* not reached */
|
||||
}
|
||||
|
|
|
@ -16,5 +16,5 @@
|
|||
*/
|
||||
void WINAPI INT_Int20Handler( CONTEXT86 *context )
|
||||
{
|
||||
ExitProcess( 0 );
|
||||
ExitThread( 0 );
|
||||
}
|
||||
|
|
|
@ -1146,7 +1146,7 @@ void WINAPI DOS3Call( CONTEXT86 *context )
|
|||
|
||||
case 0x00: /* TERMINATE PROGRAM */
|
||||
TRACE("TERMINATE PROGRAM\n");
|
||||
ExitProcess( 0 );
|
||||
ExitThread( 0 );
|
||||
break;
|
||||
|
||||
case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
|
||||
|
@ -1841,7 +1841,7 @@ void WINAPI DOS3Call( CONTEXT86 *context )
|
|||
|
||||
case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
|
||||
TRACE("EXIT with return code %d\n",AL_reg(context));
|
||||
ExitProcess( AL_reg(context) );
|
||||
ExitThread( AL_reg(context) );
|
||||
break;
|
||||
|
||||
case 0x4d: /* GET RETURN CODE */
|
||||
|
|
|
@ -504,7 +504,6 @@ int CLIENT_InitThread(void)
|
|||
close( fd );
|
||||
if (teb->buffer == (void*)-1) server_perror( "mmap" );
|
||||
first_req = teb->buffer;
|
||||
teb->process->server_pid = first_req->pid;
|
||||
teb->pid = first_req->pid;
|
||||
teb->tid = first_req->tid;
|
||||
if (first_req->version != SERVER_PROTOCOL_VERSION)
|
||||
|
|
|
@ -39,10 +39,10 @@ DECLARE_DEBUG_CHANNEL(win32);
|
|||
|
||||
static ENVDB initial_envdb;
|
||||
static STARTUPINFOA initial_startup;
|
||||
static char **main_exe_argv;
|
||||
static char *main_exe_name;
|
||||
static HFILE main_exe_file = -1;
|
||||
|
||||
static PDB *PROCESS_First;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_IdToPDB
|
||||
|
@ -51,16 +51,7 @@ static PDB *PROCESS_First;
|
|||
*/
|
||||
PDB *PROCESS_IdToPDB( DWORD pid )
|
||||
{
|
||||
PDB *pdb;
|
||||
|
||||
if (!pid) return PROCESS_Current();
|
||||
pdb = PROCESS_First;
|
||||
while (pdb)
|
||||
{
|
||||
if ((DWORD)pdb->server_pid == pid) return pdb;
|
||||
pdb = pdb->next;
|
||||
}
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
if (!pid || pid == GetCurrentProcessId()) return PROCESS_Current();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -178,87 +169,11 @@ void PROCESS_CallUserSignalProc( UINT uCode, HMODULE hModule )
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_CreateEnvDB
|
||||
*
|
||||
* Create the env DB for a newly started process.
|
||||
*/
|
||||
static BOOL PROCESS_CreateEnvDB(void)
|
||||
{
|
||||
struct init_process_request *req = get_req_buffer();
|
||||
PDB *pdb = PROCESS_Current();
|
||||
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;
|
||||
startup->dwFlags = req->start_flags;
|
||||
startup->wShowWindow = req->cmd_show;
|
||||
env_db->hStdin = startup->hStdInput = req->hstdin;
|
||||
env_db->hStdout = startup->hStdOutput = req->hstdout;
|
||||
env_db->hStderr = startup->hStdError = req->hstderr;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_FreePDB
|
||||
*
|
||||
* Free a PDB and all associated storage.
|
||||
*/
|
||||
static void PROCESS_FreePDB( PDB *pdb )
|
||||
{
|
||||
PDB **pptr = &PROCESS_First;
|
||||
|
||||
ENV_FreeEnvironment( pdb );
|
||||
while (*pptr && (*pptr != pdb)) pptr = &(*pptr)->next;
|
||||
if (*pptr) *pptr = pdb->next;
|
||||
HeapFree( GetProcessHeap(), 0, pdb );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_CreatePDB
|
||||
*
|
||||
* Allocate and fill a PDB structure.
|
||||
* Runs in the context of the parent process.
|
||||
*/
|
||||
static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
|
||||
{
|
||||
PDB *pdb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof(PDB) + sizeof(ENVDB) + sizeof(STARTUPINFOA) );
|
||||
|
||||
if (!pdb) return NULL;
|
||||
pdb->exit_code = STILL_ACTIVE;
|
||||
pdb->heap = GetProcessHeap();
|
||||
pdb->threads = 1;
|
||||
pdb->running_threads = 1;
|
||||
pdb->ring0_threads = 1;
|
||||
pdb->parent = parent;
|
||||
pdb->group = pdb;
|
||||
pdb->priority = 8; /* Normal */
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_Init
|
||||
*/
|
||||
BOOL PROCESS_Init( BOOL win32 )
|
||||
BOOL PROCESS_Init(void)
|
||||
{
|
||||
struct init_process_request *req;
|
||||
PDB *pdb = PROCESS_Current();
|
||||
|
@ -274,13 +189,6 @@ BOOL PROCESS_Init( BOOL win32 )
|
|||
pdb->winver = 0xffff; /* to be determined */
|
||||
pdb->main_queue = INVALID_HANDLE_VALUE16;
|
||||
initial_envdb.startup_info = &initial_startup;
|
||||
PROCESS_First = pdb;
|
||||
|
||||
if (!win32)
|
||||
{
|
||||
pdb->flags = PDB32_WIN16_PROC;
|
||||
NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
|
||||
}
|
||||
|
||||
/* Setup the server connection */
|
||||
NtCurrentTeb()->socket = CLIENT_InitServer();
|
||||
|
@ -293,12 +201,12 @@ BOOL PROCESS_Init( BOOL win32 )
|
|||
req->ppid = getppid();
|
||||
if (server_call( REQ_INIT_PROCESS )) return FALSE;
|
||||
main_exe_file = req->exe_file;
|
||||
if (req->filename[0]) main_exe_name = strdup( req->filename );
|
||||
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;
|
||||
|
@ -328,6 +236,9 @@ BOOL PROCESS_Init( BOOL win32 )
|
|||
InitializeCriticalSection( &pdb->crit_section );
|
||||
InitializeCriticalSection( &initial_envdb.section );
|
||||
|
||||
/* Initialize syslevel handling */
|
||||
SYSLEVEL_Init();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -337,7 +248,7 @@ BOOL PROCESS_Init( BOOL win32 )
|
|||
*
|
||||
* Load system DLLs into the initial process (and initialize them)
|
||||
*/
|
||||
static inline int load_system_dlls(void)
|
||||
static int load_system_dlls(void)
|
||||
{
|
||||
char driver[MAX_PATH];
|
||||
|
||||
|
@ -350,55 +261,8 @@ static inline int load_system_dlls(void)
|
|||
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.
|
||||
*/
|
||||
static void start_process(void)
|
||||
{
|
||||
struct init_process_done_request *req = get_req_buffer();
|
||||
int debugged;
|
||||
HMODULE16 hModule16;
|
||||
UINT cmdShow = SW_SHOWNORMAL;
|
||||
LPTHREAD_START_ROUTINE entry;
|
||||
PDB *pdb = PROCESS_Current();
|
||||
HMODULE main_module = pdb->exe_modref->module;
|
||||
|
||||
/* Increment EXE refcount */
|
||||
pdb->exe_modref->refCount++;
|
||||
|
||||
/* Retrieve entry point address */
|
||||
entry = (LPTHREAD_START_ROUTINE)RVA_PTR( main_module, OptionalHeader.AddressOfEntryPoint );
|
||||
|
||||
/* Create 16-bit dummy module */
|
||||
if ((hModule16 = MODULE_CreateDummyModule( pdb->exe_modref->filename, main_module )) < 32)
|
||||
ExitProcess( hModule16 );
|
||||
|
||||
if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
|
||||
cmdShow = pdb->env_db->startup_info->wShowWindow;
|
||||
if (!TASK_Create( (NE_MODULE *)GlobalLock16( hModule16 ), cmdShow )) goto error;
|
||||
|
||||
/* Signal the parent process to continue */
|
||||
req->module = (void *)main_module;
|
||||
req->entry = entry;
|
||||
server_call( REQ_INIT_PROCESS_DONE );
|
||||
debugged = req->debugged;
|
||||
|
||||
if (pdb->flags & PDB32_CONSOLE_PROC) AllocConsole();
|
||||
|
||||
/* Load the system dlls */
|
||||
if (!load_system_dlls()) goto error;
|
||||
|
||||
/* Get pointers to USER routines called by KERNEL */
|
||||
THUNK_InitCallout();
|
||||
|
||||
|
@ -413,67 +277,238 @@ static void start_process(void)
|
|||
* 16-bit stack must be set up, which it is only after TASK_Create
|
||||
* in the case of a 16-bit process. Thus, we send the signal here.
|
||||
*/
|
||||
|
||||
PROCESS_CallUserSignalProc( USIG_PROCESS_CREATE, 0 );
|
||||
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 );
|
||||
PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0 );
|
||||
PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0 );
|
||||
|
||||
EnterCriticalSection( &pdb->crit_section );
|
||||
PE_InitTls();
|
||||
MODULE_DllProcessAttach( pdb->exe_modref, (LPVOID)1 );
|
||||
LeaveCriticalSection( &pdb->crit_section );
|
||||
|
||||
/* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */
|
||||
if (pdb->flags & PDB32_CONSOLE_PROC)
|
||||
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 );
|
||||
|
||||
TRACE_(relay)( "Starting Win32 process (entryproc=%p)\n", entry );
|
||||
if (debugged) DbgBreakPoint();
|
||||
/* FIXME: should use _PEB as parameter for NT 3.5 programs !
|
||||
* Dunno about other OSs */
|
||||
ExitProcess( entry(NULL) );
|
||||
|
||||
error:
|
||||
ExitProcess( GetLastError() );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_Init32
|
||||
* build_command_line
|
||||
*
|
||||
* Initialisation of a new Win32 process.
|
||||
* Build the command-line of a process from the argv array.
|
||||
*/
|
||||
void PROCESS_Init32( HFILE hFile, LPCSTR filename, LPCSTR cmd_line )
|
||||
static inline char *build_command_line( char **argv )
|
||||
{
|
||||
HMODULE main_module;
|
||||
PDB *pdb = PROCESS_Current();
|
||||
int len, quote;
|
||||
char *cmdline, *p, **arg;
|
||||
|
||||
pdb->env_db->cmd_line = HEAP_strdupA( GetProcessHeap(), 0, cmd_line );
|
||||
|
||||
/* load main module */
|
||||
if ((main_module = PE_LoadImage( hFile, filename )) < 32)
|
||||
ExitProcess( main_module );
|
||||
#if 0
|
||||
if (PE_HEADER(main_module)->FileHeader.Characteristics & IMAGE_FILE_DLL)
|
||||
for (arg = argv, len = 0; *arg; arg++) len += strlen(*arg) + 1;
|
||||
if ((quote = (strchr( argv[0], ' ' ) != NULL))) len += 2;
|
||||
if (!(p = cmdline = HeapAlloc( GetProcessHeap(), 0, len ))) return NULL;
|
||||
arg = argv;
|
||||
if (quote)
|
||||
{
|
||||
SetLastError( 20 ); /* FIXME: not the right error code */
|
||||
goto error;
|
||||
*p++ = '\"';
|
||||
strcpy( p, *arg );
|
||||
p += strlen(p);
|
||||
*p++ = '\"';
|
||||
*p++ = ' ';
|
||||
arg++;
|
||||
}
|
||||
#endif
|
||||
while (*arg)
|
||||
{
|
||||
strcpy( p, *arg );
|
||||
p += strlen(p);
|
||||
*p++ = ' ';
|
||||
arg++;
|
||||
}
|
||||
if (p > cmdline) p--; /* remove last space */
|
||||
*p = 0;
|
||||
return cmdline;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* start_process
|
||||
*
|
||||
* Startup routine of a new process. Runs on the new process stack.
|
||||
*/
|
||||
static void start_process(void)
|
||||
{
|
||||
__TRY
|
||||
{
|
||||
struct init_process_done_request *req = get_req_buffer();
|
||||
int debugged;
|
||||
HMODULE16 hModule16;
|
||||
UINT cmdShow = SW_SHOWNORMAL;
|
||||
LPTHREAD_START_ROUTINE entry;
|
||||
PDB *pdb = PROCESS_Current();
|
||||
HMODULE module = pdb->exe_modref->module;
|
||||
|
||||
/* Increment EXE refcount */
|
||||
pdb->exe_modref->refCount++;
|
||||
|
||||
/* build command line */
|
||||
if (!(pdb->env_db->cmd_line = build_command_line( main_exe_argv ))) goto error;
|
||||
|
||||
/* Retrieve entry point address */
|
||||
entry = (LPTHREAD_START_ROUTINE)RVA_PTR( module, OptionalHeader.AddressOfEntryPoint );
|
||||
|
||||
/* Create 16-bit dummy module */
|
||||
if ((hModule16 = MODULE_CreateDummyModule( pdb->exe_modref->filename, module )) < 32)
|
||||
ExitProcess( hModule16 );
|
||||
|
||||
if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
|
||||
cmdShow = pdb->env_db->startup_info->wShowWindow;
|
||||
if (!TASK_Create( (NE_MODULE *)GlobalLock16( hModule16 ), cmdShow,
|
||||
NtCurrentTeb(), NULL, 0 ))
|
||||
goto error;
|
||||
|
||||
if (PE_HEADER(module)->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
|
||||
pdb->flags |= PDB32_CONSOLE_PROC;
|
||||
|
||||
/* Signal the parent process to continue */
|
||||
req->module = (void *)module;
|
||||
req->entry = entry;
|
||||
server_call( REQ_INIT_PROCESS_DONE );
|
||||
debugged = req->debugged;
|
||||
|
||||
/* Load the system dlls */
|
||||
if (!load_system_dlls()) goto error;
|
||||
|
||||
EnterCriticalSection( &pdb->crit_section );
|
||||
PE_InitTls();
|
||||
MODULE_DllProcessAttach( pdb->exe_modref, (LPVOID)1 );
|
||||
LeaveCriticalSection( &pdb->crit_section );
|
||||
|
||||
/* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */
|
||||
if (pdb->flags & PDB32_CONSOLE_PROC)
|
||||
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 );
|
||||
|
||||
TRACE_(relay)( "Starting Win32 process (entryproc=%p)\n", entry );
|
||||
if (debugged) DbgBreakPoint();
|
||||
/* FIXME: should use _PEB as parameter for NT 3.5 programs !
|
||||
* Dunno about other OSs */
|
||||
ExitThread( entry(NULL) );
|
||||
|
||||
error:
|
||||
ExitProcess( GetLastError() );
|
||||
|
||||
}
|
||||
__EXCEPT(UnhandledExceptionFilter)
|
||||
{
|
||||
TerminateThread( GetCurrentThread(), GetExceptionCode() );
|
||||
}
|
||||
__ENDTRY
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_Start
|
||||
*
|
||||
* Startup routine of a new Win32 process once the main module has been loaded.
|
||||
*/
|
||||
static void PROCESS_Start( HMODULE main_module, LPCSTR filename ) WINE_NORETURN;
|
||||
static void PROCESS_Start( HMODULE main_module, LPCSTR filename )
|
||||
{
|
||||
/* load main module */
|
||||
if (PE_HEADER(main_module)->FileHeader.Characteristics & IMAGE_FILE_DLL)
|
||||
ExitProcess( ERROR_BAD_EXE_FORMAT );
|
||||
|
||||
/* Create 32-bit MODREF */
|
||||
if (!PE_CreateModule( main_module, filename, 0, FALSE )) goto error;
|
||||
if (!PE_CreateModule( main_module, filename, 0, FALSE ))
|
||||
ExitProcess( GetLastError() );
|
||||
|
||||
/* allocate main thread stack */
|
||||
if (!THREAD_InitStack( NtCurrentTeb(),
|
||||
PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
|
||||
goto error;
|
||||
ExitProcess( GetLastError() );
|
||||
|
||||
SIGNAL_Init(); /* reinitialize signal stack */
|
||||
|
||||
/* switch to the new stack */
|
||||
CALL32_Init( &IF1632_CallLargeStack, start_process, NtCurrentTeb()->stack_top );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_InitWine
|
||||
*
|
||||
* Wine initialisation: load and start the main exe file.
|
||||
*/
|
||||
void PROCESS_InitWine( int argc, char *argv[] )
|
||||
{
|
||||
DWORD type;
|
||||
|
||||
/* Initialize everything */
|
||||
if (!MAIN_MainInit( argv )) exit(1);
|
||||
|
||||
main_exe_argv = ++argv; /* remove argv[0] (wine itself) */
|
||||
|
||||
if (!main_exe_name)
|
||||
{
|
||||
char buffer[MAX_PATH];
|
||||
if (!argv[0]) OPTIONS_Usage();
|
||||
|
||||
/* open the exe file */
|
||||
if (!SearchPathA( NULL, argv[0], ".exe", sizeof(buffer), buffer, NULL ) &&
|
||||
!SearchPathA( NULL, argv[0], NULL, sizeof(buffer), buffer, NULL ))
|
||||
{
|
||||
MESSAGE( "%s: cannot find '%s'\n", argv0, argv[0] );
|
||||
goto error;
|
||||
}
|
||||
if (!(main_exe_name = strdup(buffer)))
|
||||
{
|
||||
MESSAGE( "%s: out of memory\n", argv0 );
|
||||
ExitProcess(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (main_exe_file == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if ((main_exe_file = CreateFileA( main_exe_name, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, 0, -1 )) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
MESSAGE( "%s: cannot open '%s'\n", argv0, main_exe_name );
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (!MODULE_GetBinaryType( main_exe_file, main_exe_name, &type ))
|
||||
{
|
||||
MESSAGE( "%s: unrecognized executable '%s'\n", argv0, main_exe_name );
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case SCS_32BIT_BINARY:
|
||||
{
|
||||
HMODULE main_module = PE_LoadImage( main_exe_file, main_exe_name );
|
||||
if (main_module) PROCESS_Start( main_module, main_exe_name );
|
||||
}
|
||||
break;
|
||||
|
||||
case SCS_WOW_BINARY:
|
||||
{
|
||||
HMODULE main_module;
|
||||
LPCSTR filename;
|
||||
/* create 32-bit module for main exe */
|
||||
if (!(main_module = BUILTIN32_LoadExeModule( &filename ))) goto error;
|
||||
NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
|
||||
PROCESS_Current()->flags |= PDB32_WIN16_PROC;
|
||||
SYSLEVEL_EnterWin16Lock();
|
||||
PROCESS_Start( main_module, filename );
|
||||
}
|
||||
break;
|
||||
|
||||
case SCS_DOS_BINARY:
|
||||
FIXME( "DOS binaries support is broken at the moment; feel free to fix it...\n" );
|
||||
SetLastError( ERROR_BAD_FORMAT );
|
||||
break;
|
||||
|
||||
case SCS_PIF_BINARY:
|
||||
case SCS_POSIX_BINARY:
|
||||
case SCS_OS216_BINARY:
|
||||
default:
|
||||
MESSAGE( "%s: unrecognized executable '%s'\n", argv0, main_exe_name );
|
||||
SetLastError( ERROR_BAD_FORMAT );
|
||||
break;
|
||||
}
|
||||
error:
|
||||
ExitProcess( GetLastError() );
|
||||
}
|
||||
|
@ -486,45 +521,17 @@ void PROCESS_Init32( HFILE hFile, LPCSTR filename, LPCSTR cmd_line )
|
|||
*/
|
||||
void PROCESS_InitWinelib( int argc, char *argv[] )
|
||||
{
|
||||
PDB *pdb;
|
||||
HMODULE main_module;
|
||||
LPCSTR filename;
|
||||
LPSTR cmdline, p;
|
||||
int i, len = 0;
|
||||
|
||||
if (!MAIN_MainInit( argc, argv, TRUE )) exit(1);
|
||||
pdb = PROCESS_Current();
|
||||
if (!MAIN_MainInit( argv )) exit(1);
|
||||
|
||||
/* build command-line */
|
||||
for (i = 0; Options.argv[i]; i++) len += strlen(Options.argv[i]) + 1;
|
||||
if (!(cmdline = HeapAlloc( GetProcessHeap(), 0, len ))) goto error;
|
||||
for (p = cmdline, i = 0; Options.argv[i]; i++)
|
||||
{
|
||||
strcpy( p, Options.argv[i] );
|
||||
p += strlen(p);
|
||||
*p++ = ' ';
|
||||
}
|
||||
if (p > cmdline) p--;
|
||||
*p = 0;
|
||||
pdb->env_db->cmd_line = cmdline;
|
||||
main_exe_argv = argv;
|
||||
|
||||
/* create 32-bit module for main exe */
|
||||
if ((main_module = BUILTIN32_LoadExeModule( &filename )) < 32 ) goto error;
|
||||
if (!(main_module = BUILTIN32_LoadExeModule( &filename ))) ExitProcess( GetLastError() );
|
||||
|
||||
/* Create 32-bit MODREF */
|
||||
if (!PE_CreateModule( main_module, filename, 0, FALSE )) goto error;
|
||||
|
||||
/* allocate main thread stack */
|
||||
if (!THREAD_InitStack( NtCurrentTeb(),
|
||||
PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
|
||||
goto error;
|
||||
|
||||
SIGNAL_Init(); /* reinitialize signal stack */
|
||||
|
||||
/* switch to the new stack */
|
||||
CALL32_Init( &IF1632_CallLargeStack, start_process, NtCurrentTeb()->stack_top );
|
||||
error:
|
||||
ExitProcess( GetLastError() );
|
||||
PROCESS_Start( main_module, filename );
|
||||
}
|
||||
|
||||
|
||||
|
@ -533,13 +540,24 @@ void PROCESS_InitWinelib( int argc, char *argv[] )
|
|||
*
|
||||
* Build an argv array from a command-line.
|
||||
* The command-line is modified to insert nulls.
|
||||
* 'reserved' is the number of args to reserve before the first one.
|
||||
*/
|
||||
static char **build_argv( char *cmdline, char *argv0 )
|
||||
static char **build_argv( char *cmdline, int reserved )
|
||||
{
|
||||
char **argv;
|
||||
int count = 1;
|
||||
int count = reserved + 1;
|
||||
char *p = cmdline;
|
||||
|
||||
/* if first word is quoted store it as a single arg */
|
||||
if (*cmdline == '\"')
|
||||
{
|
||||
if ((p = strchr( cmdline + 1, '\"' )))
|
||||
{
|
||||
p++;
|
||||
count++;
|
||||
}
|
||||
else p = cmdline;
|
||||
}
|
||||
while (*p)
|
||||
{
|
||||
while (*p && isspace(*p)) p++;
|
||||
|
@ -547,12 +565,20 @@ static char **build_argv( char *cmdline, char *argv0 )
|
|||
count++;
|
||||
while (*p && !isspace(*p)) p++;
|
||||
}
|
||||
if (argv0) count++;
|
||||
|
||||
if ((argv = malloc( count * sizeof(*argv) )))
|
||||
{
|
||||
char **argvptr = argv;
|
||||
if (argv0) *argvptr++ = argv0;
|
||||
char **argvptr = argv + reserved;
|
||||
p = cmdline;
|
||||
if (*cmdline == '\"')
|
||||
{
|
||||
if ((p = strchr( cmdline + 1, '\"' )))
|
||||
{
|
||||
*argvptr++ = cmdline + 1;
|
||||
*p++ = 0;
|
||||
}
|
||||
else p = cmdline;
|
||||
}
|
||||
while (*p)
|
||||
{
|
||||
while (*p && isspace(*p)) *p++ = 0;
|
||||
|
@ -654,7 +680,8 @@ static void exec_wine_binary( char **argv, char **envp )
|
|||
*
|
||||
* Fork and exec a new Unix process, checking for errors.
|
||||
*/
|
||||
static int fork_and_exec( const char *filename, const char *cmdline, const char *env )
|
||||
static int fork_and_exec( const char *filename, const char *cmdline,
|
||||
const char *env, int use_wine )
|
||||
{
|
||||
int fd[2];
|
||||
int pid, err;
|
||||
|
@ -667,10 +694,18 @@ static int fork_and_exec( const char *filename, const char *cmdline, const char
|
|||
fcntl( fd[1], F_SETFD, 1 ); /* set close on exec */
|
||||
if (!(pid = fork())) /* child */
|
||||
{
|
||||
char **argv = build_argv( (char *)cmdline, NULL );
|
||||
char **argv = build_argv( (char *)cmdline, use_wine ? 2 : 0 );
|
||||
char **envp = build_envp( env );
|
||||
close( fd[0] );
|
||||
if (argv && envp) execve( filename, argv, envp );
|
||||
if (argv && envp)
|
||||
{
|
||||
if (use_wine)
|
||||
{
|
||||
argv[1] = "--";
|
||||
exec_wine_binary( argv, envp );
|
||||
}
|
||||
else execve( filename, argv, envp );
|
||||
}
|
||||
err = errno;
|
||||
write( fd[1], &err, sizeof(err) );
|
||||
_exit(1);
|
||||
|
@ -688,12 +723,16 @@ static int fork_and_exec( const char *filename, const char *cmdline, const char
|
|||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_CreateUnixProcess
|
||||
* PROCESS_Create
|
||||
*
|
||||
* Create a new process. If hFile is a valid handle we have an exe
|
||||
* file, and we exec a new copy of wine to load it; otherwise we
|
||||
* simply exec the specified filename as a Unix process.
|
||||
*/
|
||||
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 )
|
||||
BOOL PROCESS_Create( HFILE hFile, 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;
|
||||
|
@ -711,7 +750,7 @@ BOOL PROCESS_CreateUnixProcess( LPCSTR filename, LPCSTR cmd_line, LPCSTR env,
|
|||
req->inherit_all = inherit;
|
||||
req->create_flags = flags;
|
||||
req->start_flags = startup->dwFlags;
|
||||
req->exe_file = -1;
|
||||
req->exe_file = hFile;
|
||||
if (startup->dwFlags & STARTF_USESTDHANDLES)
|
||||
{
|
||||
req->hstdin = startup->hStdInput;
|
||||
|
@ -731,7 +770,8 @@ BOOL PROCESS_CreateUnixProcess( LPCSTR filename, LPCSTR cmd_line, LPCSTR env,
|
|||
|
||||
/* fork and execute */
|
||||
|
||||
pid = fork_and_exec( unixfilename, cmd_line, env ? env : GetEnvironmentStringsA() );
|
||||
pid = fork_and_exec( unixfilename, cmd_line,
|
||||
env ? env : GetEnvironmentStringsA(), (hFile != -1) );
|
||||
|
||||
wait_req->cancel = (pid == -1);
|
||||
wait_req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle);
|
||||
|
@ -773,271 +813,6 @@ error:
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_Start
|
||||
*
|
||||
* Startup routine of a new process. Called in the context of the new process.
|
||||
*/
|
||||
void PROCESS_Start(void)
|
||||
{
|
||||
struct init_process_done_request *req = get_req_buffer();
|
||||
int debugged;
|
||||
UINT cmdShow = SW_SHOWNORMAL;
|
||||
LPTHREAD_START_ROUTINE entry = NULL;
|
||||
PDB *pdb = PROCESS_Current();
|
||||
NE_MODULE *pModule = NE_GetPtr( pdb->module );
|
||||
LPCSTR filename = ((OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo))->szPathName;
|
||||
|
||||
/* Get process type */
|
||||
enum { PROC_DOS, PROC_WIN16, PROC_WIN32 } type;
|
||||
if ( pdb->flags & PDB32_DOS_PROC )
|
||||
type = PROC_DOS;
|
||||
else if ( pdb->flags & PDB32_WIN16_PROC )
|
||||
type = PROC_WIN16;
|
||||
else
|
||||
type = PROC_WIN32;
|
||||
|
||||
/* Initialize the critical section */
|
||||
InitializeCriticalSection( &pdb->crit_section );
|
||||
|
||||
/* Create the environment db */
|
||||
if (!PROCESS_CreateEnvDB()) goto error;
|
||||
|
||||
/* Create a task for this process */
|
||||
if (pdb->env_db->startup_info->dwFlags & STARTF_USESHOWWINDOW)
|
||||
cmdShow = pdb->env_db->startup_info->wShowWindow;
|
||||
if (!TASK_Create( pModule, cmdShow ))
|
||||
goto error;
|
||||
|
||||
/* Load all process modules */
|
||||
switch ( type )
|
||||
{
|
||||
case PROC_WIN16:
|
||||
if ( !NE_InitProcess( pModule ) )
|
||||
goto error;
|
||||
break;
|
||||
|
||||
case PROC_WIN32:
|
||||
/* Create 32-bit MODREF */
|
||||
if ( !PE_CreateModule( pModule->module32, filename, 0, FALSE ) )
|
||||
goto error;
|
||||
|
||||
/* Increment EXE refcount */
|
||||
assert( pdb->exe_modref );
|
||||
pdb->exe_modref->refCount++;
|
||||
|
||||
/* Retrieve entry point address */
|
||||
entry = (LPTHREAD_START_ROUTINE)RVA_PTR(pModule->module32,
|
||||
OptionalHeader.AddressOfEntryPoint);
|
||||
break;
|
||||
|
||||
case PROC_DOS:
|
||||
/* FIXME: move DOS startup code here */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Note: The USIG_PROCESS_CREATE signal is supposed to be sent in the
|
||||
* context of the parent process. Actually, the USER signal proc
|
||||
* doesn't really care about that, but it *does* require that the
|
||||
* startup parameters are correctly set up, so that GetProcessDword
|
||||
* works. Furthermore, before calling the USER signal proc the
|
||||
* 16-bit stack must be set up, which it is only after TASK_Create
|
||||
* in the case of a 16-bit process. Thus, we send the signal here.
|
||||
*/
|
||||
|
||||
PROCESS_CallUserSignalProc( USIG_PROCESS_CREATE, 0 );
|
||||
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 );
|
||||
PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0 );
|
||||
PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0 );
|
||||
|
||||
/* Signal the parent process to continue */
|
||||
req->module = (void *)pModule->module32;
|
||||
req->entry = entry;
|
||||
server_call( REQ_INIT_PROCESS_DONE );
|
||||
debugged = req->debugged;
|
||||
|
||||
if ( (pdb->flags & PDB32_CONSOLE_PROC) || (pdb->flags & PDB32_DOS_PROC) )
|
||||
AllocConsole();
|
||||
|
||||
/* Perform Win32 specific process initialization */
|
||||
if ( type == PROC_WIN32 )
|
||||
{
|
||||
EnterCriticalSection( &pdb->crit_section );
|
||||
|
||||
PE_InitTls();
|
||||
MODULE_DllProcessAttach( pdb->exe_modref, (LPVOID)1 );
|
||||
|
||||
LeaveCriticalSection( &pdb->crit_section );
|
||||
}
|
||||
|
||||
/* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */
|
||||
if ( type != PROC_WIN16 && (pdb->flags & PDB32_CONSOLE_PROC))
|
||||
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 );
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case PROC_DOS:
|
||||
TRACE_(relay)( "Starting DOS process\n" );
|
||||
DOSVM_Enter( NULL );
|
||||
ERR_(relay)( "DOSVM_Enter returned; should not happen!\n" );
|
||||
ExitProcess( 0 );
|
||||
|
||||
case PROC_WIN16:
|
||||
TRACE_(relay)( "Starting Win16 process\n" );
|
||||
TASK_CallToStart();
|
||||
ERR_(relay)( "TASK_CallToStart returned; should not happen!\n" );
|
||||
ExitProcess( 0 );
|
||||
|
||||
case PROC_WIN32:
|
||||
TRACE_(relay)( "Starting Win32 process (entryproc=%p)\n", entry );
|
||||
if (debugged) DbgBreakPoint();
|
||||
/* FIXME: should use _PEB as parameter for NT 3.5 programs !
|
||||
* Dunno about other OSs */
|
||||
ExitProcess( entry(NULL) );
|
||||
}
|
||||
|
||||
error:
|
||||
ExitProcess( GetLastError() );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* PROCESS_Create
|
||||
*
|
||||
* Create a new process database and associated info.
|
||||
*/
|
||||
PDB *PROCESS_Create( NE_MODULE *pModule, HFILE hFile, LPCSTR cmd_line, LPCSTR env,
|
||||
LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa,
|
||||
BOOL inherit, DWORD flags, STARTUPINFOA *startup,
|
||||
PROCESS_INFORMATION *info )
|
||||
{
|
||||
HANDLE handles[2], load_done_evt = -1;
|
||||
DWORD exitcode, size;
|
||||
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 );
|
||||
|
||||
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->inherit_all = 2 /*inherit*/; /* HACK! */
|
||||
req->create_flags = flags;
|
||||
req->start_flags = startup->dwFlags;
|
||||
req->exe_file = hFile;
|
||||
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 = 1;
|
||||
req->filename[0] = 0;
|
||||
if (server_call_fd( REQ_NEW_PROCESS, -1, &fd )) goto error;
|
||||
|
||||
if (pModule->module32) /* Win32 process */
|
||||
{
|
||||
IMAGE_OPTIONAL_HEADER *header = &PE_HEADER(pModule->module32)->OptionalHeader;
|
||||
size = header->SizeOfStackReserve;
|
||||
if (header->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
|
||||
pdb->flags |= PDB32_CONSOLE_PROC;
|
||||
alloc_stack16 = TRUE;
|
||||
}
|
||||
else if (!pModule->dos_image) /* Win16 process */
|
||||
{
|
||||
alloc_stack16 = FALSE;
|
||||
size = 0;
|
||||
pdb->flags |= PDB32_WIN16_PROC;
|
||||
}
|
||||
else /* DOS process */
|
||||
{
|
||||
alloc_stack16 = FALSE;
|
||||
size = 0;
|
||||
pdb->flags |= PDB32_DOS_PROC;
|
||||
}
|
||||
|
||||
/* Create the main thread */
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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;
|
||||
handles[1] = load_done_evt;
|
||||
|
||||
switch ( WaitForMultipleObjects( 2, handles, FALSE, INFINITE ) )
|
||||
{
|
||||
default:
|
||||
ERR( "WaitForMultipleObjects failed\n" );
|
||||
break;
|
||||
|
||||
case 0:
|
||||
/* Child initialization code returns error condition as exitcode */
|
||||
if ( GetExitCodeProcess( info->hProcess, &exitcode ) )
|
||||
SetLastError( exitcode );
|
||||
goto error;
|
||||
|
||||
case 1:
|
||||
/* Get 16-bit task up and running */
|
||||
if ( pdb->flags & PDB32_WIN16_PROC )
|
||||
{
|
||||
/* Post event to start the task */
|
||||
PostEvent16( pdb->task );
|
||||
|
||||
/* If we ourselves are a 16-bit task, we Yield() directly. */
|
||||
if ( parent->flags & PDB32_WIN16_PROC )
|
||||
OldYield16();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
CloseHandle( load_done_evt );
|
||||
return pdb;
|
||||
|
||||
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 );
|
||||
PROCESS_FreePDB( pdb );
|
||||
if (fd != -1) close( fd );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ExitProcess (KERNEL32.100)
|
||||
*/
|
||||
|
@ -1046,15 +821,11 @@ void WINAPI ExitProcess( DWORD status )
|
|||
struct terminate_process_request *req = get_req_buffer();
|
||||
|
||||
MODULE_DllProcessDetach( TRUE, (LPVOID)1 );
|
||||
TASK_KillTask( 0 );
|
||||
|
||||
/* send the exit code to the server */
|
||||
req->handle = GetCurrentProcess();
|
||||
req->exit_code = status;
|
||||
server_call( REQ_TERMINATE_PROCESS );
|
||||
/* FIXME: need separate address spaces for that */
|
||||
/* exit( status ); */
|
||||
SYSDEPS_ExitThread( status );
|
||||
exit( status );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1091,23 +862,27 @@ DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset )
|
|||
DWORD x, y;
|
||||
|
||||
TRACE_(win32)("(%ld, %d)\n", dwProcessID, offset );
|
||||
if ( !process ) return 0;
|
||||
if ( !process )
|
||||
{
|
||||
ERR("%d: process %lx not accessible\n", offset, dwProcessID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch ( offset )
|
||||
{
|
||||
case GPD_APP_COMPAT_FLAGS:
|
||||
pTask = (TDB *)GlobalLock16( process->task );
|
||||
pTask = (TDB *)GlobalLock16( GetCurrentTask() );
|
||||
return pTask? pTask->compat_flags : 0;
|
||||
|
||||
case GPD_LOAD_DONE_EVENT:
|
||||
return process->load_done_evt;
|
||||
|
||||
case GPD_HINSTANCE16:
|
||||
pTask = (TDB *)GlobalLock16( process->task );
|
||||
pTask = (TDB *)GlobalLock16( GetCurrentTask() );
|
||||
return pTask? pTask->hInstance : 0;
|
||||
|
||||
case GPD_WINDOWS_VERSION:
|
||||
pTask = (TDB *)GlobalLock16( process->task );
|
||||
pTask = (TDB *)GlobalLock16( GetCurrentTask() );
|
||||
return pTask? pTask->version : 0;
|
||||
|
||||
case GPD_THDB:
|
||||
|
@ -1144,7 +919,7 @@ DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset )
|
|||
return process->env_db->startup_info->dwFlags;
|
||||
|
||||
case GPD_PARENT:
|
||||
return process->parent? (DWORD)process->parent->server_pid : 0;
|
||||
return 0;
|
||||
|
||||
case GPD_FLAGS:
|
||||
return process->flags;
|
||||
|
@ -1167,7 +942,11 @@ void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value )
|
|||
PDB *process = PROCESS_IdToPDB( dwProcessID );
|
||||
|
||||
TRACE_(win32)("(%ld, %d)\n", dwProcessID, offset );
|
||||
if ( !process ) return;
|
||||
if ( !process )
|
||||
{
|
||||
ERR("%d: process %lx not accessible\n", offset, dwProcessID);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( offset )
|
||||
{
|
||||
|
|
|
@ -229,14 +229,14 @@ DECL_GLOBAL_CONSTRUCTOR(thread_init) { THREAD_Init(); }
|
|||
* THREAD_Create
|
||||
*
|
||||
*/
|
||||
TEB *THREAD_Create( PDB *pdb, int fd, DWORD stack_size, BOOL alloc_stack16 )
|
||||
TEB *THREAD_Create( int fd, DWORD stack_size, BOOL alloc_stack16 )
|
||||
{
|
||||
TEB *teb;
|
||||
|
||||
if ((teb = THREAD_InitStack( NULL, stack_size, alloc_stack16 )))
|
||||
{
|
||||
teb->tibflags = (pdb->flags & PDB32_WIN16_PROC) ? 0 : TEBF_WIN32;
|
||||
teb->process = pdb;
|
||||
teb->tibflags = (PROCESS_Current()->flags & PDB32_WIN16_PROC) ? 0 : TEBF_WIN32;
|
||||
teb->process = PROCESS_Current();
|
||||
teb->socket = fd;
|
||||
fcntl( fd, F_SETFD, 1 ); /* set close on exec flag */
|
||||
TRACE("(%p) succeeded\n", teb);
|
||||
|
@ -287,7 +287,7 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
|
|||
handle = req->handle;
|
||||
tid = req->tid;
|
||||
|
||||
if (!(teb = THREAD_Create( PROCESS_Current(), socket, stack, TRUE )))
|
||||
if (!(teb = THREAD_Create( socket, stack, TRUE )))
|
||||
{
|
||||
close( socket );
|
||||
return 0;
|
||||
|
@ -296,6 +296,7 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
|
|||
teb->entry_point = start;
|
||||
teb->entry_arg = param;
|
||||
teb->startup = THREAD_Start;
|
||||
teb->htask16 = GetCurrentTask();
|
||||
if (id) *id = (DWORD)tid;
|
||||
if (SYSDEPS_SpawnThread( teb ) == -1)
|
||||
{
|
||||
|
@ -347,13 +348,12 @@ void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */
|
|||
if (req->last)
|
||||
{
|
||||
MODULE_DllProcessDetach( TRUE, (LPVOID)1 );
|
||||
TASK_KillTask( 0 );
|
||||
exit( code );
|
||||
}
|
||||
else
|
||||
{
|
||||
MODULE_DllThreadDetach( NULL );
|
||||
PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 );
|
||||
if (!(NtCurrentTeb()->tibflags & TEBF_WIN32)) TASK_KillTask( 0 );
|
||||
SYSDEPS_ExitThread( code );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ DWORD WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers)
|
|||
|
||||
TRACE("Starting debugger (fmt=%s)\n", format);
|
||||
hEvent = ConvertToGlobalHandle(CreateEventA(NULL, FALSE, FALSE, NULL));
|
||||
sprintf(buffer, format, (unsigned long)pdb->server_pid, hEvent);
|
||||
sprintf(buffer, format, GetCurrentProcessId(), hEvent);
|
||||
memset(&startup, 0, sizeof(startup));
|
||||
startup.cb = sizeof(startup);
|
||||
startup.dwFlags = STARTF_USESHOWWINDOW;
|
||||
|
|
|
@ -2225,6 +2225,13 @@ static void NC_DoSizeMove( HWND hwnd, WORD wParam )
|
|||
((msg.message == WM_KEYDOWN) &&
|
||||
((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
|
||||
|
||||
if (msg.message == WM_PAINT)
|
||||
{
|
||||
if(!iconic) NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
|
||||
UpdateWindow( msg.hwnd );
|
||||
if(!iconic) NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
|
||||
continue;
|
||||
}
|
||||
if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
|
||||
continue; /* We are not interested in other messages */
|
||||
|
||||
|
|
|
@ -404,10 +404,10 @@ void QUEUE_WalkQueues(void)
|
|||
WARN_(msg)("Bad queue handle %04x\n", hQueue );
|
||||
return;
|
||||
}
|
||||
if (!GetModuleName16( queue->teb->process->task, module, sizeof(module )))
|
||||
if (!GetModuleName16( queue->teb->htask16, module, sizeof(module )))
|
||||
strcpy( module, "???" );
|
||||
DPRINTF( "%04x %4d %p %04x %s\n", hQueue,queue->msgCount,
|
||||
queue->teb, queue->teb->process->task, module );
|
||||
queue->teb, queue->teb->htask16, module );
|
||||
hQueue = queue->next;
|
||||
QUEUE_Unlock( queue );
|
||||
}
|
||||
|
@ -640,7 +640,7 @@ void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
|
|||
if ( THREAD_IsWin16( queue->teb ) )
|
||||
{
|
||||
int iWndsLock = WIN_SuspendWndsLock();
|
||||
PostEvent16( queue->teb->process->task );
|
||||
PostEvent16( queue->teb->htask16 );
|
||||
WIN_RestoreWndsLock( iWndsLock );
|
||||
}
|
||||
else
|
||||
|
@ -1274,7 +1274,7 @@ HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue )
|
|||
|
||||
if (queue)
|
||||
{
|
||||
hTask = queue->teb->process->task;
|
||||
hTask = queue->teb->htask16;
|
||||
QUEUE_Unlock( queue );
|
||||
}
|
||||
|
||||
|
|
|
@ -271,7 +271,7 @@ WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
|
|||
break;
|
||||
|
||||
case USIG_PROCESS_DESTROY:
|
||||
hInst = GetProcessDword( dwThreadOrProcessID, GPD_HINSTANCE16 );
|
||||
hInst = ((TDB *)GlobalLock16( GetCurrentTask() ))->hInstance;
|
||||
USER_AppExit( hInst );
|
||||
|
||||
pdb = PROCESS_Current();
|
||||
|
|
Loading…
Reference in New Issue