From c192ba24687d1016a4a990236b1f53ae463e58d3 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard <julliard@winehq.org> Date: Mon, 29 May 2000 21:25:10 +0000 Subject: [PATCH] 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. --- dlls/shell32/shell.c | 14 +- include/main.h | 4 +- include/module.h | 7 +- include/options.h | 2 +- include/pe_image.h | 5 - include/process.h | 15 +- include/task.h | 3 +- include/thread.h | 2 +- loader/dos/module.c | 2 + loader/main.c | 10 +- loader/module.c | 138 ++++---- loader/ne/module.c | 172 +++------- loader/pe_image.c | 50 +-- loader/task.c | 33 +- memory/environ.c | 64 +--- misc/main.c | 20 +- misc/options.c | 34 +- miscemu/main.c | 112 ++----- msdos/int20.c | 2 +- msdos/int21.c | 4 +- scheduler/client.c | 1 - scheduler/process.c | 779 ++++++++++++++++--------------------------- scheduler/thread.c | 12 +- win32/except.c | 2 +- windows/nonclient.c | 7 + windows/queue.c | 8 +- windows/user.c | 2 +- 27 files changed, 506 insertions(+), 998 deletions(-) diff --git a/dlls/shell32/shell.c b/dlls/shell32/shell.c index d3275421d5a..875d4a93cff 100644 --- a/dlls/shell32/shell.c +++ b/dlls/shell32/shell.c @@ -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.??????.*** */ diff --git a/include/main.h b/include/main.h index 9341f3688cd..b724c07652a 100644 --- a/include/main.h +++ b/include/main.h @@ -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 ); diff --git a/include/module.h b/include/module.h index 34bf2fee3b7..5844b0288af 100644 --- a/include/module.h +++ b/include/module.h @@ -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); diff --git a/include/options.h b/include/options.h index 7ba4f99dc1f..b202de4922b 100644 --- a/include/options.h +++ b/include/options.h @@ -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 */ diff --git a/include/pe_image.h b/include/pe_image.h index 809c289c3ec..4aaac264c9b 100644 --- a/include/pe_image.h +++ b/include/pe_image.h @@ -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); diff --git a/include/process.h b/include/process.h index 48a7c9ba074..f7bf4589f4a 100644 --- a/include/process.h +++ b/include/process.h @@ -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) { diff --git a/include/task.h b/include/task.h index d3e6a12ce7a..eeb69394c14 100644 --- a/include/task.h +++ b/include/task.h @@ -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); diff --git a/include/thread.h b/include/thread.h index 9939f322c83..e58b95d6cc7 100644 --- a/include/thread.h +++ b/include/thread.h @@ -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 ); diff --git a/loader/dos/module.c b/loader/dos/module.c index a2522c3156e..8acf083a707 100644 --- a/loader/dos/module.c +++ b/loader/dos/module.c @@ -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 ) { diff --git a/loader/main.c b/loader/main.c index a036a08e430..1652e5e58cc 100644 --- a/loader/main.c +++ b/loader/main.c @@ -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; diff --git a/loader/module.c b/loader/module.c index 65a9624ac96..0b324ba2a0e 100644 --- a/loader/module.c +++ b/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; + } + + 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(); - return hInst; + 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: diff --git a/loader/ne/module.c b/loader/ne/module.c index e1fec116475..45a879be9b2 100644 --- a/loader/ne/module.c +++ b/loader/ne/module.c @@ -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 */ - 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 */ - - 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 (params->hEnvironment) env = GlobalLock16( params->hEnvironment ); - - 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]; - } - - 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; - } + req->suspend = 0; + req->inherit = 0; + if (server_call_fd( REQ_NEW_THREAD, -1, &socket )) return 0; + CloseHandle( req->handle ); - pModule->count++; - } + if (!(teb = THREAD_Create( socket, 0, FALSE ))) goto error; + teb->startup = TASK_CallToStart; - /* Main case: load first instance of NE module */ - else - { - /* Load module */ + /* Create a task for this process */ - hModule = NE_LoadExeHeader( filename ); - if ( hModule < 32 ) - { - SetLastError( hModule ); - goto error; - } + params = (LOADPARAMS16 *)paramBlock; + 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 ( !( pModule = NE_GetPtr( hModule ) ) - || ( pModule->flags & NE_FFLAGS_LIBMODULE) ) - { - GlobalFreeAll16( hModule ); - SetLastError( ERROR_BAD_FORMAT ); - goto error; - } - } + if ((instance = NE_InitProcess( pModule, teb->htask16 )) < 32) goto error; - SYSLEVEL_LeaveWin16Lock(); + if (SYSDEPS_SpawnThread( teb ) == -1) goto error; - if ( !PROCESS_Create( pModule, hFile, cmd_line, env, - psa, tsa, inherit, flags, startup, info ) ) - return FALSE; + /* Post event to start the task */ + PostEvent16( teb->htask16 ); + OldYield16(); - 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(); - - SetLastError( hInstance ); - return FALSE; - } + /* Enter instance handles into task struct */ - /* Enter instance handles into task struct */ + pTask = (TDB *)GlobalLock16( hTask ); + pTask->hInstance = hInstance; + pTask->hPrevInstance = hPrevInstance; - 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 ); + /* Use DGROUP for 16-bit stack */ - SYSLEVEL_LeaveWin16Lock(); + 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 ); + } - return retv; + SYSLEVEL_LeaveWin16Lock(); + return hInstance; } /*********************************************************************** diff --git a/loader/pe_image.c b/loader/pe_image.c index f0df822adab..09570628feb 100644 --- a/loader/pe_image.c +++ b/loader/pe_image.c @@ -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 diff --git a/loader/task.c b/loader/task.c index cce67b5dd2b..7725545194c 100644 --- a/loader/task.c +++ b/loader/task.c @@ -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) diff --git a/memory/environ.c b/memory/environ.c index 2fa96b32065..d3eb41df926 100644 --- a/memory/environ.c +++ b/memory/environ.c @@ -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) */ diff --git a/misc/main.c b/misc/main.c index 9a919b84125..c661e0d517a 100644 --- a/misc/main.c +++ b/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; } /*********************************************************************** diff --git a/misc/options.c b/misc/options.c index ff471768538..37cc31c87cc 100644 --- a/misc/options.c +++ b/misc/options.c @@ -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++; } diff --git a/miscemu/main.c b/miscemu/main.c index f4550c44e09..b35d94db4a1 100644 --- a/miscemu/main.c +++ b/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]; - - if (PROFILE_GetWineIniString( "Wine", "GraphicsDriver", - "x11drv", szGraphicsDriver, sizeof(szGraphicsDriver))) - { - if (!LoadLibraryA( szGraphicsDriver )) ExitProcess(1); - } + HINSTANCE16 instance; + STARTUPINFOA info; - /* 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 ); + GetStartupInfoA( &info ); + if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = SW_SHOWNORMAL; - /* 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]) + if ((instance = WinExec16( GetCommandLineA(), info.wShowWindow )) < 32) { - 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; - - /* Initialize everything */ - if (!MAIN_MainInit( argc, argv, FALSE )) return 1; - - 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(); + BUILTIN32_DESCRIPTOR descriptor; - /* Switch stacks and jump to MAIN_EmulatorRun */ - CALL32_Init( &IF1632_CallLargeStack, MAIN_EmulatorRun, NtCurrentTeb()->stack_top ); + memset( &descriptor, 0, sizeof(descriptor) ); + descriptor.filename = argv[0]; + descriptor.dllentrypoint = initial_task; + BUILTIN32_RegisterDLL( &descriptor ); - MESSAGE( "main: Should never happen: returned from CALL32_Init()\n" ); - return 0; + PROCESS_InitWine( argc, argv ); + return 1; /* not reached */ } diff --git a/msdos/int20.c b/msdos/int20.c index a818acfb6d3..232ad65472e 100644 --- a/msdos/int20.c +++ b/msdos/int20.c @@ -16,5 +16,5 @@ */ void WINAPI INT_Int20Handler( CONTEXT86 *context ) { - ExitProcess( 0 ); + ExitThread( 0 ); } diff --git a/msdos/int21.c b/msdos/int21.c index 0910fa55dbe..8f1a94f0cd3 100644 --- a/msdos/int21.c +++ b/msdos/int21.c @@ -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 */ diff --git a/scheduler/client.c b/scheduler/client.c index 4aa2a638eaa..ffb33fcb645 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -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) diff --git a/scheduler/process.c b/scheduler/process.c index 14e08647308..dd55f7dcf12 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -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 ); + return 1; +} - 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() ); +/*********************************************************************** + * build_command_line + * + * Build the command-line of a process from the argv array. + */ +static inline char *build_command_line( char **argv ) +{ + int len, quote; + char *cmdline, *p, **arg; + + 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) + { + *p++ = '\"'; + strcpy( p, *arg ); + p += strlen(p); + *p++ = '\"'; + *p++ = ' '; + arg++; + } + while (*arg) + { + strcpy( p, *arg ); + p += strlen(p); + *p++ = ' '; + arg++; + } + if (p > cmdline) p--; /* remove last space */ + *p = 0; + return cmdline; } /*********************************************************************** - * PROCESS_Init32 + * start_process * - * Initialisation of a new Win32 process. + * Startup routine of a new process. Runs on the new process stack. */ -void PROCESS_Init32( HFILE hFile, LPCSTR filename, LPCSTR cmd_line ) +static void start_process(void) { - HMODULE main_module; - PDB *pdb = PROCESS_Current(); + __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; - pdb->env_db->cmd_line = HEAP_strdupA( GetProcessHeap(), 0, cmd_line ); + /* Increment EXE refcount */ + pdb->exe_modref->refCount++; - /* 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) + /* 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) { - SetLastError( 20 ); /* FIXME: not the right error code */ - goto error; + TerminateThread( GetCurrentThread(), GetExceptionCode() ); } -#endif + __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; - - /* 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; + if (!(main_module = BUILTIN32_LoadExeModule( &filename ))) ExitProcess( GetLastError() ); - 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 ) { diff --git a/scheduler/thread.c b/scheduler/thread.c index f9d710572b3..40cf44c8338 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -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 ); } } diff --git a/win32/except.c b/win32/except.c index 31966b3986a..d83521e48de 100644 --- a/win32/except.c +++ b/win32/except.c @@ -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; diff --git a/windows/nonclient.c b/windows/nonclient.c index a2bf12d4250..8a7b6c53001 100644 --- a/windows/nonclient.c +++ b/windows/nonclient.c @@ -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 */ diff --git a/windows/queue.c b/windows/queue.c index 34249e1c5c5..67fabc5d192 100644 --- a/windows/queue.c +++ b/windows/queue.c @@ -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 ); } diff --git a/windows/user.c b/windows/user.c index 697ee080172..c427c178ef1 100644 --- a/windows/user.c +++ b/windows/user.c @@ -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(); -- GitLab