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:
Alexandre Julliard 2000-05-29 21:25:10 +00:00
parent 8f65001f78
commit c192ba2468
27 changed files with 512 additions and 1004 deletions

View File

@ -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.??????.*** */

View File

@ -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 );

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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 );

View File

@ -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 )
{

View File

@ -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;

View File

@ -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, &params );
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:

View File

@ -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;
}
/***********************************************************************

View File

@ -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

View File

@ -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)

View File

@ -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)
*/

View File

@ -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;
}
/***********************************************************************

View File

@ -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++;
}

View File

@ -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 */
}

View File

@ -16,5 +16,5 @@
*/
void WINAPI INT_Int20Handler( CONTEXT86 *context )
{
ExitProcess( 0 );
ExitThread( 0 );
}

View File

@ -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 */

View File

@ -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)

View File

@ -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 )
{

View File

@ -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 );
}
}

View File

@ -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;

View File

@ -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 */

View File

@ -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 );
}

View File

@ -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();