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