Improved Winelib apps initialisation code. No longer need to link
winestub.o with Winelib apps.

diff --git a/Make.rules.in b/Make.rules.in
index 6dd52f1..3df7174 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -30,7 +30,7 @@
 X_LIBS    = @X_LIBS@
 XLIB      = @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@
 DLL_LINK  = @DLL_LINK@
-WINELIB   = $(WINESTUB) $(DLL_LINK)
+WINELIB   = $(DLL_LINK)
 LIBS      = @LIBS@
 YACC      = @YACC@
 LEX       = @LEX@
@@ -58,7 +58,6 @@
 MAKEDEP   = $(TOPOBJDIR)/tools/makedep@PROGEXT@
 WRC       = $(TOPOBJDIR)/tools/wrc/wrc@PROGEXT@
 WRCFLAGS  = -c
-WINESTUB  = $(TOPOBJDIR)/library/winestub.o
 DLLDIR    = $(TOPOBJDIR)/dlls
 @SET_MAKE@
 
@@ -205,11 +204,6 @@
 $(BUILD) checkbuild:
 	cd $(TOPOBJDIR)/tools && $(MAKE) build@PROGEXT@
 
-# Rule to rebuild winestub.o
-
-$(WINESTUB) check_winestub:
-	cd $(TOPOBJDIR)/library && $(MAKE) winestub.o
-
 # Rule for main module
 
 $(MODULE).o: $(OBJS) Makefile.in $(TOPSRCDIR)/Make.rules.in
diff --git a/debugger/Makefile.in b/debugger/Makefile.in
index 590b852..a6d15b9 100644
--- a/debugger/Makefile.in
+++ b/debugger/Makefile.in
@@ -44,7 +44,7 @@
 lex.yy.c: debug.l
 	$(LEX) -8 -I $(SRCDIR)/debug.l
 
-winedbg: $(OBJS) $(WINESTUB)
+winedbg: $(OBJS)
 	$(CC) -o $@ $(OBJS) $(LDOPTIONS) $(ALL_LIBS)
 
 ### Dependencies:
diff --git a/include/callback.h b/include/callback.h
index 389bacb..75603d3 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -22,6 +22,10 @@
 typedef void (*RELAY)();
 extern FARPROC THUNK_Alloc( FARPROC16 func, RELAY relay );
 extern void THUNK_Free( FARPROC thunk );
+extern BOOL THUNK_Init(void);
+extern void THUNK_InitCallout(void);
+
+extern void CALL32_Init( void *func, void *target, void *stack ) WINE_NORETURN;
 
 typedef struct
 {
diff --git a/include/main.h b/include/main.h
index 76b920b..9341f36 100644
--- a/include/main.h
+++ b/include/main.h
@@ -9,16 +9,11 @@
 
 extern BOOL MAIN_MainInit( int argc, char *argv[], BOOL win32 );
 extern BOOL MAIN_WineInit( int argc, char *argv[] );
-extern HINSTANCE MAIN_WinelibInit( int *argc, char *argv[] );
 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 );
 
 extern BOOL RELAY_Init(void);
-extern void THUNK_InitCallout(void);
 extern int RELAY_ShowDebugmsgRelay(const char *func);
-extern void CALL32_Init( void *func, void *target, void *stack );
-
-extern BOOL THUNK_Init(void);
 
 #endif  /* __WINE_MAIN_H */
diff --git a/include/module.h b/include/module.h
index 5a62dc4..a8d6a992 100644
--- a/include/module.h
+++ b/include/module.h
@@ -184,7 +184,7 @@
 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 HMODULE MODULE_CreateDummyModule( LPCSTR filename, WORD version );
+extern HMODULE MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 );
 extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name );
 extern SEGPTR WINAPI HasGPHandler16( SEGPTR address );
 extern void MODULE_WalkModref( DWORD id );
@@ -234,7 +234,7 @@
 
 /* relay32/builtin.c */
 extern WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR name, DWORD flags);
-extern HMODULE16 BUILTIN32_LoadExeModule(void);
+extern HMODULE BUILTIN32_LoadExeModule( LPCSTR *filename );
 extern void BUILTIN32_UnloadLibrary(WINE_MODREF *wm);
 
 #endif  /* __WINE_MODULE_H */
diff --git a/include/thread.h b/include/thread.h
index 8b96738..0c709c0 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -122,6 +122,7 @@
 extern TEB *THREAD_CreateInitialThread( struct _PDB *pdb, int server_fd );
 extern TEB *THREAD_Create( struct _PDB *pdb, void *pid, void *tid, int fd,
                            DWORD stack_size, BOOL alloc_stack16 );
+extern TEB *THREAD_InitStack( TEB *teb, struct _PDB *pdb, DWORD stack_size, BOOL alloc_stack16 );
 extern BOOL THREAD_IsWin16( TEB *thdb );
 extern TEB *THREAD_IdToTEB( DWORD id );
 
diff --git a/libtest/Makefile.in b/libtest/Makefile.in
index 8dc50b6..a04f247 100644
--- a/libtest/Makefile.in
+++ b/libtest/Makefile.in
@@ -22,7 +22,7 @@
 RC_SRCS = \
 	hello3res.rc
 
-all: check_wrc check_winestub $(PROGRAMS)
+all: check_wrc $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/loader/main.c b/loader/main.c
index 48dca56..4ad2956 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -55,7 +55,7 @@
 #include "server.h"
 #include "loadorder.h"
 
-DEFAULT_DEBUG_CHANNEL(server)
+DEFAULT_DEBUG_CHANNEL(server);
 
 /***********************************************************************
  *           Main initialisation routine
@@ -92,20 +92,7 @@
     /* Initialize module loadorder */
     if (!MODULE_InitLoadOrder()) return FALSE;
 
-    /* Initialize DOS memory */
-    if (!DOSMEM_Init(0)) return FALSE;
-
-    /* Initialize communications */
-    COMM_Init();
-
-    /* Initialize IO-port permissions */
-    IO_port_init();
-
-    /* Read DOS config.sys */
-    if (!DOSCONF_ReadConfig()) return FALSE;
-
     /* Initialize KERNEL */
-    if (!LoadLibrary16( "KRNL386.EXE" )) return FALSE;
     if (!LoadLibraryA( "KERNEL32" )) return FALSE;
 
     if (!LoadLibraryA( "x11drv" )) return FALSE;
@@ -127,6 +114,11 @@
     if ( initDone ) return TRUE;
     initDone = TRUE;
 
+    /* Initialize DOS memory */
+    if (!DOSMEM_Init(0)) return FALSE;
+
+    if (!LoadLibrary16( "KRNL386.EXE" )) return FALSE;
+
     /* Initialize special KERNEL entry points */
     hModule = GetModuleHandle16( "KERNEL" );
     if ( hModule )
@@ -164,55 +156,20 @@
     /* Initialize relay code */
     if (!RELAY_Init()) return FALSE;
 
+    /* Initialize communications */
+    COMM_Init();
+
+    /* Initialize IO-port permissions */
+    IO_port_init();
+
+    /* Read DOS config.sys */
+    if (!DOSCONF_ReadConfig()) return FALSE;
+
     return TRUE;
 }
 
 
 /***********************************************************************
- *           Winelib initialisation routine
- */
-HINSTANCE MAIN_WinelibInit( int *argc, char *argv[] )
-{
-    NE_MODULE *pModule;
-    HMODULE16 hModule;
-    PDB	      *curr;
-
-    /* Main initialization */
-    if (!MAIN_MainInit( *argc, argv, TRUE )) return 0;
-    *argc = Options.argc;
-
-    /* Load WineLib EXE module */
-    if ( (hModule = BUILTIN32_LoadExeModule()) < 32 ) return 0;
-    pModule = (NE_MODULE *)GlobalLock16( hModule );
-
-    /* Create initial task */
-    if (!TASK_Create( pModule, FALSE )) return 0;
-
-    /* Create 32-bit MODREF */
-    if ( !PE_CreateModule( pModule->module32, NE_MODULE_NAME(pModule), 0, FALSE ) )
-        return 0;
-
-    /* Increment EXE refcount */
-    curr = PROCESS_Current();
-    assert( curr->exe_modref );
-    curr->exe_modref->refCount++;
-
-    /* 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 );
-
-    /* attach the imported DLLs */
-    if ( !MODULE_DllProcessAttach( curr->exe_modref, NULL ) )
-       ExitProcess( 1 );
-
-    /* Get pointers to USER routines called by KERNEL */
-    THUNK_InitCallout();
-
-    return pModule->module32;
-}
-
-/***********************************************************************
  *           ExitKernel16 (KERNEL.2)
  *
  * Clean-up everything and exit the Wine process.
diff --git a/loader/module.c b/loader/module.c
index 7bb5667..10189e3 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -336,7 +336,7 @@
  *
  * Create a dummy NE module for Win32 or Winelib.
  */
-HMODULE MODULE_CreateDummyModule( LPCSTR filename, WORD version )
+HMODULE MODULE_CreateDummyModule( LPCSTR filename, HMODULE module32 )
 {
     HMODULE hModule;
     NE_MODULE *pModule;
@@ -388,8 +388,19 @@
     pModule->nrname_size      = 0;
     pModule->fileinfo         = sizeof(NE_MODULE);
     pModule->os_flags         = NE_OSFLAGS_WINDOWS;
-    pModule->expected_version = version;
     pModule->self             = hModule;
+    pModule->module32         = module32;
+
+    /* Set version and flags */
+    if (module32)
+    {
+        pModule->expected_version =
+            ((PE_HEADER(module32)->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 ) |
+             (PE_HEADER(module32)->OptionalHeader.MinorSubsystemVersion & 0xff);
+        pModule->flags |= NE_FFLAGS_WIN32;
+        if (PE_HEADER(module32)->FileHeader.Characteristics & IMAGE_FILE_DLL)
+            pModule->flags |= NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA;
+    }
 
     /* Set loaded file information */
     ofs = (OFSTRUCT *)(pModule + 1);
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 27c5e0d..2ce45c4 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -892,7 +892,6 @@
         struct load_dll_request *req = get_req_buffer();
 	HMODULE		hModule32;
 	HMODULE16	hModule16;
-	NE_MODULE	*pModule;
 	WINE_MODREF	*wm;
 	char        	filename[256];
 	HANDLE		hFile;
@@ -916,15 +915,12 @@
 	}
 
 	/* Create 16-bit dummy module */
-	if ((hModule16 = MODULE_CreateDummyModule( filename, version )) < 32)
+	if ((hModule16 = MODULE_CreateDummyModule( filename, hModule32 )) < 32)
 	{
                 CloseHandle( hFile );
 		SetLastError( (DWORD)hModule16 );	/* This should give the correct error */
 		return NULL;
 	}
-	pModule = (NE_MODULE *)GlobalLock16( hModule16 );
-	pModule->flags    = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA | NE_FFLAGS_WIN32;
-	pModule->module32 = hModule32;
 
 	/* Create 32-bit MODREF */
 	if ( !(wm = PE_CreateModule( hModule32, filename, flags, FALSE )) )
@@ -994,14 +990,12 @@
 #endif
 
     /* Create 16-bit dummy module */
-    if ( (hModule16 = MODULE_CreateDummyModule( filename, version )) < 32 ) 
+    if ( (hModule16 = MODULE_CreateDummyModule( filename, hModule32 )) < 32 ) 
     {
         SetLastError( hModule16 );
         return FALSE;
     }
     pModule = (NE_MODULE *)GlobalLock16( hModule16 );
-    pModule->flags    = NE_FFLAGS_WIN32;
-    pModule->module32 = hModule32;
 
     /* Create new process */
     if ( !PROCESS_Create( pModule, hFile, cmd_line, env,
diff --git a/misc/options.c b/misc/options.c
index aee4caa..ff47176 100644
--- a/misc/options.c
+++ b/misc/options.c
@@ -22,6 +22,11 @@
     const char *usage;
 };
 
+/* Most Windows C/C++ compilers use something like this to */
+/* access argc and argv globally: */
+int _ARGC;
+char **_ARGV;
+
 static void do_config( const char *arg );
 static void do_desktop( const char *arg );
 static void do_display( const char *arg );
@@ -184,4 +189,6 @@
     }
     Options.argc = argc;
     Options.argv = argv;
+    _ARGC = argc;
+    _ARGV = argv;
 }
diff --git a/programs/avitools/Makefile.in b/programs/avitools/Makefile.in
index 94199d7..09f90ae 100644
--- a/programs/avitools/Makefile.in
+++ b/programs/avitools/Makefile.in
@@ -13,7 +13,7 @@
 	aviinfo.spec \
 	aviplay.spec
 
-all: check_wrc check_winestub $(PROGRAMS)
+all: check_wrc $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/programs/clock/Makefile.in b/programs/clock/Makefile.in
index 36498df..4419c11 100644
--- a/programs/clock/Makefile.in
+++ b/programs/clock/Makefile.in
@@ -21,7 +21,7 @@
 
 RC_SRCS = rsrc.rc
 
-all: check_wrc check_winestub $(PROGRAMS)
+all: check_wrc $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/programs/cmdlgtst/Makefile.in b/programs/cmdlgtst/Makefile.in
index 52fbec1..07b4978 100644
--- a/programs/cmdlgtst/Makefile.in
+++ b/programs/cmdlgtst/Makefile.in
@@ -17,7 +17,7 @@
 RC_SRCS = \
 	cmdlgr.rc
 
-all: check_wrc check_winestub $(PROGRAMS)
+all: check_wrc $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/programs/control/Makefile.in b/programs/control/Makefile.in
index 603c269..70e98d0 100644
--- a/programs/control/Makefile.in
+++ b/programs/control/Makefile.in
@@ -11,7 +11,7 @@
 
 SPEC_SRCS = control.spec
 
-all: check_winestub $(PROGRAMS)
+all: $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/programs/notepad/Makefile.in b/programs/notepad/Makefile.in
index 78de8db..a83922b 100644
--- a/programs/notepad/Makefile.in
+++ b/programs/notepad/Makefile.in
@@ -22,7 +22,7 @@
 
 RC_SRCS = rsrc.rc
 
-all: check_wrc check_winestub $(PROGRAMS)
+all: check_wrc $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/programs/osversioncheck/Makefile.in b/programs/osversioncheck/Makefile.in
index 29f28cc..bf361c7 100644
--- a/programs/osversioncheck/Makefile.in
+++ b/programs/osversioncheck/Makefile.in
@@ -15,9 +15,6 @@
 
 @MAKE_RULES@
 
-#this line is needed to prevent winestub.o being linked
-WINESTUB = 
-
 osversioncheck: $(OBJS)
 	$(CC) -o osversioncheck $(OBJS) $(LDOPTIONS) $(ALL_LIBS)
 
diff --git a/programs/osversioncheck/osversioncheck.c b/programs/osversioncheck/osversioncheck.c
index fd8510f..f7c1ddd 100644
--- a/programs/osversioncheck/osversioncheck.c
+++ b/programs/osversioncheck/osversioncheck.c
@@ -11,13 +11,6 @@
 #include <winbase.h>
 #include <stdio.h>
 
-#ifdef WINELIB
-/* External declaration here because we don't want to depend on Wine's
-   internal headers. */
-extern HINSTANCE MAIN_WinelibInit( int *argc, char *argv[] );
-#endif /* WINELIB */
-
-
 void
 show_last_error(void)
 {
@@ -47,15 +40,10 @@
 }
 
 int
-main(int argc, char ** argv)
+wine_main(int argc, char ** argv)
 {
   BOOL result;
   OSVERSIONINFO oiv;
-  HINSTANCE hinst;
-
-#ifdef WINELIB
-  if (!(hinst = MAIN_WinelibInit(&argc, argv))) return 0;
-#endif /* WINELIB */
 
   /* FIXME: GetVersionEx() is a Win32 API call, so there should be a
      preliminary check to see if we're running bare-bones Windows3.xx
diff --git a/programs/osversioncheck/osversioncheck.spec b/programs/osversioncheck/osversioncheck.spec
index da3eac9..585ef75 100644
--- a/programs/osversioncheck/osversioncheck.spec
+++ b/programs/osversioncheck/osversioncheck.spec
@@ -1,4 +1,4 @@
 name	osversioncheck
 mode    cuiexe
 type	win32
-init	main
+init	wine_main
diff --git a/programs/progman/Makefile.in b/programs/progman/Makefile.in
index ce6378d..f69ce7c 100644
--- a/programs/progman/Makefile.in
+++ b/programs/progman/Makefile.in
@@ -24,7 +24,7 @@
 
 RC_SRCS = rsrc.rc
 
-all: check_wrc check_winestub $(PROGRAMS)
+all: check_wrc $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/programs/regapi/Makefile.in b/programs/regapi/Makefile.in
index 55d2461..d3d8127 100644
--- a/programs/regapi/Makefile.in
+++ b/programs/regapi/Makefile.in
@@ -13,7 +13,7 @@
 SPEC_SRCS = \
 	regapi.spec
 
-all: check_winestub $(PROGRAMS)
+all: $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/programs/regtest/Makefile.in b/programs/regtest/Makefile.in
index 3078d7b..1cc86f1 100644
--- a/programs/regtest/Makefile.in
+++ b/programs/regtest/Makefile.in
@@ -11,7 +11,7 @@
 
 SPEC_SRCS = regtest.spec
 
-all: check_winestub $(PROGRAMS)
+all: $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/programs/view/Makefile.in b/programs/view/Makefile.in
index 94e0b83..f34739e 100644
--- a/programs/view/Makefile.in
+++ b/programs/view/Makefile.in
@@ -19,7 +19,7 @@
 RC_SRCS = \
 	viewrc.rc
 
-all: check_wrc check_winestub $(PROGRAMS)
+all: check_wrc $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/programs/wcmd/Makefile.in b/programs/wcmd/Makefile.in
index 60df63e..2da5eb1 100644
--- a/programs/wcmd/Makefile.in
+++ b/programs/wcmd/Makefile.in
@@ -24,9 +24,6 @@
 
 @MAKE_RULES@
 
-#this line is needed to prevent winestub.o being linked
-WINESTUB = 
-
 wcmd: $(OBJS)
 	$(CC) -o wcmd $(OBJS) $(LDOPTIONS) $(ALL_LIBS)
 
diff --git a/programs/wcmd/wcmd.spec b/programs/wcmd/wcmd.spec
index a78c34d..4c881b5 100644
--- a/programs/wcmd/wcmd.spec
+++ b/programs/wcmd/wcmd.spec
@@ -1,4 +1,4 @@
 name	wcmd
 mode    cuiexe
 type	win32
-init	main
+init	wine_main
diff --git a/programs/wcmd/wcmdmain.c b/programs/wcmd/wcmdmain.c
index 281c7b2..23f4aa9 100644
--- a/programs/wcmd/wcmdmain.c
+++ b/programs/wcmd/wcmdmain.c
@@ -14,22 +14,12 @@
 
 #include "wcmd.h"
 
-#ifdef WINELIB
-/* external declaration here because we don't want to depend on Wine headers */
-#ifdef __cplusplus
-extern "C" HINSTANCE MAIN_WinelibInit( int *argc, char *argv[] );
-#else
-extern HINSTANCE MAIN_WinelibInit( int *argc, char *argv[] );
-#endif
-#endif /* WINELIB */
-
 char *inbuilt[] = {"ATTRIB", "CALL", "CD", "CHDIR", "CLS", "COPY", "CTTY",
 		"DATE", "DEL", "DIR", "ECHO", "ERASE", "FOR", "GOTO",
 		"HELP", "IF", "LABEL", "MD", "MKDIR", "MOVE", "PATH", "PAUSE",
 		"PROMPT", "REM", "REN", "RENAME", "RD", "RMDIR", "SET", "SHIFT",
 		"TIME", "TYPE", "VERIFY", "VER", "VOL", "EXIT"};
 
-HINSTANCE hinst;
 int echo_mode = 1, verify_mode = 0;
 char nyi[] = "Not Yet Implemented\n\n";
 char newline[] = "\n";
@@ -44,19 +34,13 @@
  */
 
 
-int main (int argc, char *argv[]) {
+int wine_main (int argc, char *argv[]) {
 
 char string[1024], args[MAX_PATH], param[MAX_PATH];
 int status, i;
 DWORD count;
 HANDLE h;
 
-#ifdef WINELIB
-  if (!(hinst = MAIN_WinelibInit( &argc, argv ))) return 0;
-#else
-  hinst = 0;
-#endif
-
   args[0] = param[0] = '\0';
   if (argc > 1) {
     for (i=1; i<argc; i++) {
diff --git a/programs/winemine/Makefile.in b/programs/winemine/Makefile.in
index 2afd0e0..ddd4d01 100644
--- a/programs/winemine/Makefile.in
+++ b/programs/winemine/Makefile.in
@@ -19,7 +19,7 @@
 
 RC_SRCS = rsrc.rc
 
-all: check_wrc check_winestub $(PROGRAMS)
+all: check_wrc $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/programs/winhelp/Makefile.in b/programs/winhelp/Makefile.in
index 67a0f5b..9d0d9c7 100644
--- a/programs/winhelp/Makefile.in
+++ b/programs/winhelp/Makefile.in
@@ -21,7 +21,7 @@
 
 RC_SRCS = rsrc.rc
 
-all: check_wrc check_winestub $(PROGRAMS)
+all: check_wrc $(PROGRAMS)
 
 depend: y.tab.h
 
diff --git a/programs/winver/Makefile.in b/programs/winver/Makefile.in
index 343ac65..b8b3446 100644
--- a/programs/winver/Makefile.in
+++ b/programs/winver/Makefile.in
@@ -11,7 +11,7 @@
 
 SPEC_SRCS = winver.spec
 
-all: check_winestub $(PROGRAMS)
+all: $(PROGRAMS)
 
 @MAKE_RULES@
 
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
index 5a91237..6930f42 100644
--- a/relay32/builtin32.c
+++ b/relay32/builtin32.c
@@ -385,15 +385,13 @@
     else BUILTIN32_WarnSecondInstance( builtin_dlls[i]->name );
 
     /* Create 16-bit dummy module */
-    if ((hModule16 = MODULE_CreateDummyModule( dllname, 0 )) < 32)
+    if ((hModule16 = MODULE_CreateDummyModule( dllname, dll_modules[i] )) < 32)
     {
         SetLastError( (DWORD)hModule16 );
         return NULL;	/* FIXME: Should unload the builtin module */
     }
-
     pModule = (NE_MODULE *)GlobalLock16( hModule16 );
     pModule->flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_SINGLEDATA | NE_FFLAGS_WIN32 | NE_FFLAGS_BUILTIN;
-    pModule->module32 = dll_modules[i];
 
     /* Create 32-bit MODREF */
     if ( !(wm = PE_CreateModule( pModule->module32, dllname, flags, TRUE )) )
@@ -419,7 +417,7 @@
 /***********************************************************************
  *           BUILTIN32_LoadExeModule
  */
-HMODULE16 BUILTIN32_LoadExeModule( void )
+HMODULE BUILTIN32_LoadExeModule( LPCSTR *filename )
 {
     HMODULE16 hModule16;
     NE_MODULE *pModule;
@@ -449,14 +447,8 @@
         if ( !(dll_modules[exe] = BUILTIN32_DoLoadImage( builtin_dlls[exe] )) )
             return 0;
 
-    /* Create 16-bit dummy module */
-    hModule16 = MODULE_CreateDummyModule( builtin_dlls[exe]->filename, 0 );
-    if ( hModule16 < 32 ) return 0;
-    pModule = (NE_MODULE *)GlobalLock16( hModule16 );
-    pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_WIN32 | NE_FFLAGS_BUILTIN;
-    pModule->module32 = dll_modules[exe];
-
-    return hModule16;
+    *filename = builtin_dlls[exe]->filename;
+    return dll_modules[exe];
 }
 
 
diff --git a/scheduler/process.c b/scheduler/process.c
index ba2ed7b..b7cd744 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -7,11 +7,13 @@
 #include <assert.h>
 #include <fcntl.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include "wine/winbase16.h"
 #include "wine/exception.h"
 #include "process.h"
+#include "main.h"
 #include "module.h"
 #include "neexe.h"
 #include "file.h"
@@ -28,13 +30,15 @@
 #include "callback.h"
 #include "debugtools.h"
 
-DEFAULT_DEBUG_CHANNEL(process)
-DECLARE_DEBUG_CHANNEL(relay)
-DECLARE_DEBUG_CHANNEL(win32)
+DEFAULT_DEBUG_CHANNEL(process);
+DECLARE_DEBUG_CHANNEL(relay);
+DECLARE_DEBUG_CHANNEL(win32);
 
 
 /* The initial process PDB */
 static PDB initial_pdb;
+static ENVDB initial_envdb;
+static STARTUPINFOA initial_startup;
 
 static PDB *PROCESS_First = &initial_pdb;
 
@@ -297,6 +301,7 @@
  */
 BOOL PROCESS_Init( BOOL win32 )
 {
+    struct init_process_request *req;
     TEB *teb;
     int server_fd;
 
@@ -308,11 +313,13 @@
     initial_pdb.threads         = 1;
     initial_pdb.running_threads = 1;
     initial_pdb.ring0_threads   = 1;
+    initial_pdb.env_db          = &initial_envdb;
     initial_pdb.group           = &initial_pdb;
     initial_pdb.priority        = 8;  /* Normal */
     initial_pdb.flags           = win32? 0 : PDB32_WIN16_PROC;
     initial_pdb.winver          = 0xffff; /* to be determined */
     initial_pdb.main_queue      = INVALID_HANDLE_VALUE16;
+    initial_envdb.startup_info  = &initial_startup;
 
     /* Initialize virtual memory management */
     if (!VIRTUAL_Init()) return FALSE;
@@ -338,20 +345,209 @@
     /* Initialize signal handling */
     if (!SIGNAL_Init()) return FALSE;
 
-    /* Create the environment DB of the first process */
-    if (!PROCESS_CreateEnvDB()) return FALSE;
+    /* Retrieve startup info from the server */
+    req = get_req_buffer();
+    req->ldt_copy  = ldt_copy;
+    req->ldt_flags = ldt_flags_copy;
+    if (server_call( REQ_INIT_PROCESS )) return FALSE;
+    initial_pdb.exe_file        = req->exe_file;
+    initial_startup.dwFlags     = req->start_flags;
+    initial_startup.wShowWindow = req->cmd_show;
+    initial_envdb.hStdin   = initial_startup.hStdInput  = req->hstdin;
+    initial_envdb.hStdout  = initial_startup.hStdOutput = req->hstdout;
+    initial_envdb.hStderr  = initial_startup.hStdError  = req->hstderr;
+    initial_envdb.cmd_line = "";
+
+    /* Copy the parent environment */
+    if (!ENV_InheritEnvironment( NULL )) return FALSE;
 
     /* Create the SEGPTR heap */
     if (!(SegptrHeap = HeapCreate( HEAP_WINE_SEGPTR, 0, 0 ))) return FALSE;
 
-    /* Initialize the first process critical section */
+    /* Initialize the critical sections */
     InitializeCriticalSection( &initial_pdb.crit_section );
+    InitializeCriticalSection( &initial_envdb.section );
 
     return TRUE;
 }
 
 
 /***********************************************************************
+ *           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 system DLLs into the initial process (and initialize them) */
+    if (!LoadLibraryA( "KERNEL32" )) goto error;
+    if (!LoadLibraryA( "x11drv" )) goto error;
+
+    if (   !LoadLibrary16("GDI.EXE" ) || !LoadLibraryA("GDI32.DLL" )
+        || !LoadLibrary16("USER.EXE") || !LoadLibraryA("USER32.DLL"))
+        goto error;
+
+    /* Get pointers to USER routines called by KERNEL */
+    THUNK_InitCallout();
+
+    /* Call FinalUserInit routine */
+    Callout.FinalUserInit16();
+
+    /* 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 );
+
+    EnterCriticalSection( &pdb->crit_section );
+    PE_InitTls();
+    MODULE_DllProcessAttach( pdb->exe_modref, (LPVOID)1 );
+    LeaveCriticalSection( &pdb->crit_section );
+
+    /* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */
+    if (pdb->flags & PDB32_CONSOLE_PROC)
+        PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 );
+
+    TRACE_(relay)( "Starting Win32 process (entryproc=%p)\n", entry );
+    if (debugged) DbgBreakPoint();
+    /* FIXME: should use _PEB as parameter for NT 3.5 programs !
+     * Dunno about other OSs */
+    ExitProcess( entry(NULL) );
+
+ error:
+    ExitProcess( GetLastError() );
+}
+
+
+/***********************************************************************
+ *           PROCESS_Init32
+ *
+ * Initialisation of a new Win32 process.
+ */
+void PROCESS_Init32( HFILE hFile, LPCSTR filename, LPCSTR cmd_line )
+{
+    WORD version;
+    HMODULE main_module;
+    PDB *pdb = PROCESS_Current();
+
+    pdb->env_db->cmd_line = HEAP_strdupA( GetProcessHeap(), 0, cmd_line );
+
+    /* load main module */
+    if ((main_module = PE_LoadImage( hFile, filename, &version )) < 32)
+        ExitProcess( main_module );
+#if 0
+    if (PE_HEADER(main_module)->FileHeader.Characteristics & IMAGE_FILE_DLL)
+    {
+        SetLastError( 20 );  /* FIXME: not the right error code */
+        goto error;
+    }
+#endif
+
+    /* Create 32-bit MODREF */
+    if (!PE_CreateModule( main_module, filename, 0, FALSE )) goto error;
+
+    /* allocate main thread stack */
+    if (!THREAD_InitStack( NtCurrentTeb(), pdb,
+                           PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
+        goto error;
+
+    SIGNAL_Init();  /* reinitialize signal stack */
+
+    /* switch to the new stack */
+    CALL32_Init( &IF1632_CallLargeStack, start_process, NtCurrentTeb()->stack_top );
+ error:
+    ExitProcess( GetLastError() );
+}
+
+
+/***********************************************************************
+ *           PROCESS_InitWinelib
+ *
+ * Initialisation of a new Winelib process.
+ */
+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();
+
+    /* 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;
+
+    /* 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(), pdb,
+                           PE_HEADER(main_module)->OptionalHeader.SizeOfStackReserve, TRUE ))
+        goto error;
+
+    SIGNAL_Init();  /* reinitialize signal stack */
+
+    /* switch to the new stack */
+    CALL32_Init( &IF1632_CallLargeStack, start_process, NtCurrentTeb()->stack_top );
+ error:
+    ExitProcess( GetLastError() );
+}
+
+
+/***********************************************************************
  *           PROCESS_Start
  *
  * Startup routine of a new process. Called in the context of the new process.
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 16ede62..046ae04 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -119,7 +119,7 @@
  *
  * Allocate the stack of a thread.
  */
-static TEB *THREAD_InitStack( TEB *teb, PDB *pdb, DWORD stack_size, BOOL alloc_stack16 )
+TEB *THREAD_InitStack( TEB *teb, PDB *pdb, DWORD stack_size, BOOL alloc_stack16 )
 {
     DWORD old_prot, total_size;
     DWORD page_size = VIRTUAL_GetPageSize();
diff --git a/tools/build.c b/tools/build.c
index 838a1a7..4bd1cd8 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -733,6 +733,8 @@
                 fatal_error( "init cannot be used for Win16 spec files\n" );
             if (!DLLInitFunc[0])
                 fatal_error( "Expected function name after init\n" );
+            if (!strcmp(DLLInitFunc, "main"))
+                fatal_error( "The init function cannot be named 'main'\n" );
         }
         else if (strcmp(token, "import") == 0)
         {
@@ -1033,6 +1035,7 @@
     ORDDEF *odp;
     int i, fwd_size = 0, have_regs = FALSE;
     int nr_exports;
+    const char *init_func;
 
     AssignOrdinals();
     nr_exports = Base <= Limit ? Limit - Base + 1 : 0;
@@ -1040,8 +1043,7 @@
     fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
              input_file_name );
     fprintf( outfile, "#include \"builtin32.h\"\n\n" );
-    fprintf( outfile, "extern const BUILTIN32_DESCRIPTOR %s_Descriptor;\n",
-             DLLName );
+    fprintf( outfile, "static const BUILTIN32_DESCRIPTOR descriptor;\n" );
 
     /* Output the DLL functions prototypes */
 
@@ -1065,8 +1067,8 @@
             have_regs = TRUE;
             break;
         case TYPE_STUB:
-            fprintf( outfile, "static void __stub_%d() { BUILTIN32_Unimplemented(&%s_Descriptor,%d); }\n",
-                     odp->ordinal, DLLName, odp->ordinal );
+            fprintf( outfile, "static void __stub_%d() { BUILTIN32_Unimplemented(&descriptor,%d); }\n",
+                     odp->ordinal, odp->ordinal );
             break;
         default:
             fprintf(stderr,"build: function type %d not available for Win32\n",
@@ -1075,10 +1077,6 @@
         }
     }
 
-    /* Output LibMain function */
-    if (DLLInitFunc[0]) fprintf( outfile, "extern void %s();\n", DLLInitFunc );
-
-
     /* Output code for all register functions */
 
     if ( have_regs )
@@ -1230,12 +1228,65 @@
         fprintf( outfile, "\n};\n\n" );
     }
 
+    /* Output LibMain function */
+
+    init_func = DLLInitFunc[0] ? DLLInitFunc : NULL;
+    switch(SpecMode)
+    {
+    case SPEC_MODE_DLL:
+        if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
+        break;
+    case SPEC_MODE_GUIEXE:
+        if (!init_func) init_func = "WinMain";
+        fprintf( outfile,
+                 "\n#include <winbase.h>\n"
+                 "static void exe_main(void)\n"
+                 "{\n"
+                 "    extern int PASCAL %s(HINSTANCE,HINSTANCE,LPCSTR,INT);\n"
+                 "    STARTUPINFOA info;\n"
+                 "    const char *cmdline = GetCommandLineA();\n"
+                 "    while (*cmdline && *cmdline != ' ') cmdline++;\n"
+                 "    if (*cmdline) cmdline++;\n"
+                 "    GetStartupInfoA( &info );\n"
+                 "    if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = 1;\n"
+                 "    ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
+                 "}\n\n", init_func, init_func );
+        fprintf( outfile,
+                 "int main( int argc, char *argv[] )\n"
+                 "{\n"
+                 "    extern void PROCESS_InitWinelib( int, char ** );\n"
+                 "    PROCESS_InitWinelib( argc, argv );\n"
+                 "    return 1;\n"
+                 "}\n\n" );
+        init_func = "exe_main";
+        break;
+    case SPEC_MODE_CUIEXE:
+        if (!init_func) init_func = "wine_main";
+        fprintf( outfile,
+                 "\n#include <winbase.h>\n"
+                 "static void exe_main(void)\n"
+                 "{\n"
+                 "    extern int %s( int argc, char *argv[] );\n"
+                 "    extern int _ARGC;\n"
+                 "    extern char *_ARGV[];\n"
+                 "    ExitProcess( %s( _ARGC, _ARGV ) );\n"
+                 "}\n\n", init_func, init_func );
+        fprintf( outfile,
+                 "int main( int argc, char *argv[] )\n"
+                 "{\n"
+                 "    extern void PROCESS_InitWinelib( int, char ** );\n"
+                 "    PROCESS_InitWinelib( argc, argv );\n"
+                 "    return 1;\n"
+                 "}\n\n" );
+        init_func = "exe_main";
+        break;
+    }
+
     /* Output the DLL descriptor */
 
     if (rsrc_name[0]) fprintf( outfile, "extern const char %s[];\n\n", rsrc_name );
 
-    fprintf( outfile, "const BUILTIN32_DESCRIPTOR %s_Descriptor =\n{\n",
-             DLLName );
+    fprintf( outfile, "static const BUILTIN32_DESCRIPTOR descriptor =\n{\n" );
     fprintf( outfile, "    \"%s\",\n", DLLName );
     fprintf( outfile, "    \"%s\",\n", DLLFileName );
     fprintf( outfile, "    %d,\n", nr_exports? Base : 0 );
@@ -1249,7 +1300,7 @@
     fprintf( outfile, "    %s,\n", nr_exports ? "FuncArgs" : "0" );
     fprintf( outfile, "    %s,\n", nr_exports ? "ArgTypes" : "0" );
     fprintf( outfile, "    %s,\n", nb_imports ? "Imports" : "0" );
-    fprintf( outfile, "    %s,\n", DLLInitFunc[0] ? DLLInitFunc : "0" );
+    fprintf( outfile, "    %s,\n", init_func ? init_func : "0" );
     fprintf( outfile, "    %d,\n", SpecMode == SPEC_MODE_DLL ? IMAGE_FILE_DLL : 0 );
     fprintf( outfile, "    %s\n", rsrc_name[0] ? rsrc_name : "0" );
     fprintf( outfile, "};\n" );
@@ -1265,8 +1316,8 @@
     fprintf( outfile, "    \"\\t.previous\\n\");\n" );
     fprintf( outfile, "}\n" );
     fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
-    fprintf( outfile, "static void %s_init(void) { BUILTIN32_RegisterDLL( &%s_Descriptor ); }\n",
-             DLLName, DLLName );
+    fprintf( outfile, "static void %s_init(void) { BUILTIN32_RegisterDLL( &descriptor ); }\n",
+             DLLName );
 
     return 0;
 }
@@ -1508,7 +1559,7 @@
 
     if (rsrc_name[0]) fprintf( outfile, "extern const char %s[];\n\n", rsrc_name );
 
-    fprintf( outfile, "\nconst BUILTIN16_DESCRIPTOR %s_Descriptor = \n{\n", DLLName );
+    fprintf( outfile, "\nstatic const BUILTIN16_DESCRIPTOR descriptor = \n{\n" );
     fprintf( outfile, "    \"%s\",\n", DLLName );
     fprintf( outfile, "    Module,\n" );
     fprintf( outfile, "    sizeof(Module),\n" );
@@ -1528,8 +1579,8 @@
     fprintf( outfile, "    \"\\t.previous\\n\");\n" );
     fprintf( outfile, "}\n" );
     fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
-    fprintf( outfile, "static void %s_init(void) { BUILTIN_RegisterDLL( &%s_Descriptor ); }\n",
-             DLLName, DLLName );
+    fprintf( outfile, "static void %s_init(void) { BUILTIN_RegisterDLL( &descriptor ); }\n",
+             DLLName );
 
     return 0;
 }