From b44595283fac60b84339a1e7f655095fa9507338 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sat, 15 Apr 2000 21:00:55 +0000 Subject: [PATCH] Improved Winelib apps initialisation code. No longer need to link winestub.o with Winelib apps. --- Make.rules.in | 8 +- debugger/Makefile.in | 2 +- include/callback.h | 4 + include/main.h | 5 - include/module.h | 4 +- include/thread.h | 1 + libtest/Makefile.in | 2 +- loader/main.c | 71 ++-------- loader/module.c | 15 +- loader/pe_image.c | 10 +- misc/options.c | 7 + programs/avitools/Makefile.in | 2 +- programs/clock/Makefile.in | 2 +- programs/cmdlgtst/Makefile.in | 2 +- programs/control/Makefile.in | 2 +- programs/notepad/Makefile.in | 2 +- programs/osversioncheck/Makefile.in | 3 - programs/osversioncheck/osversioncheck.c | 14 +- programs/osversioncheck/osversioncheck.spec | 2 +- programs/progman/Makefile.in | 2 +- programs/regapi/Makefile.in | 2 +- programs/regtest/Makefile.in | 2 +- programs/view/Makefile.in | 2 +- programs/wcmd/Makefile.in | 3 - programs/wcmd/wcmd.spec | 2 +- programs/wcmd/wcmdmain.c | 18 +-- programs/winemine/Makefile.in | 2 +- programs/winhelp/Makefile.in | 2 +- programs/winver/Makefile.in | 2 +- relay32/builtin32.c | 16 +-- scheduler/process.c | 208 +++++++++++++++++++++++++++- scheduler/thread.c | 2 +- tools/build.c | 83 ++++++++--- 33 files changed, 336 insertions(+), 168 deletions(-) diff --git a/Make.rules.in b/Make.rules.in index 6dd52f181c9..3df71748706 100644 --- a/Make.rules.in +++ b/Make.rules.in @@ -30,7 +30,7 @@ X_CFLAGS = @X_CFLAGS@ 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 @@ BUILD = $(TOPOBJDIR)/tools/build@PROGEXT@ 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 @@ $(MAKEDEP) check_makedep: $(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 590b8523499..a6d15b98475 100644 --- a/debugger/Makefile.in +++ b/debugger/Makefile.in @@ -44,7 +44,7 @@ y.tab.c y.tab.h: dbg.y 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 389bacbe913..75603d3c93e 100644 --- a/include/callback.h +++ b/include/callback.h @@ -22,6 +22,10 @@ extern int (*IF1632_CallLargeStack)( int (*func)(void), void *arg ); 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 76b920b17e5..9341f3688cd 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 5a62dc47dbe..a8d6a992fdc 100644 --- a/include/module.h +++ b/include/module.h @@ -184,7 +184,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 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 @@ HGLOBAL16 NE_LoadPEResource( NE_MODULE *pModule, WORD type, LPVOID bits, DWORD s /* 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 8b96738b493..0c709c036f2 100644 --- a/include/thread.h +++ b/include/thread.h @@ -122,6 +122,7 @@ typedef struct _TEB 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 8dc50b6341b..a04f2472969 100644 --- a/libtest/Makefile.in +++ b/libtest/Makefile.in @@ -22,7 +22,7 @@ SPEC_SRCS = \ 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 48dca560e17..4ad29566625 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 @@ BOOL MAIN_MainInit( int argc, char *argv[], BOOL win32 ) /* 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 @@ BOOL WINAPI MAIN_KernelInit(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReser 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,54 +156,19 @@ BOOL WINAPI MAIN_KernelInit(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReser /* Initialize relay code */ if (!RELAY_Init()) 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 ); + /* Initialize communications */ + COMM_Init(); - /* attach the imported DLLs */ - if ( !MODULE_DllProcessAttach( curr->exe_modref, NULL ) ) - ExitProcess( 1 ); + /* Initialize IO-port permissions */ + IO_port_init(); - /* Get pointers to USER routines called by KERNEL */ - THUNK_InitCallout(); + /* Read DOS config.sys */ + if (!DOSCONF_ReadConfig()) return FALSE; - return pModule->module32; + return TRUE; } + /*********************************************************************** * ExitKernel16 (KERNEL.2) * diff --git a/loader/module.c b/loader/module.c index 7bb56675be3..10189e34f2d 100644 --- a/loader/module.c +++ b/loader/module.c @@ -336,7 +336,7 @@ BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule ) * * 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 @@ HMODULE MODULE_CreateDummyModule( LPCSTR filename, WORD version ) 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 27c5e0df897..2ce45c4c71d 100644 --- a/loader/pe_image.c +++ b/loader/pe_image.c @@ -892,7 +892,6 @@ WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags) 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 @@ WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags) } /* 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 @@ BOOL PE_CreateProcess( HANDLE hFile, LPCSTR filename, LPCSTR cmd_line, LPCSTR en #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 aee4caaae83..ff471768538 100644 --- a/misc/options.c +++ b/misc/options.c @@ -22,6 +22,11 @@ struct option 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 @@ void OPTIONS_ParseOptions( int argc, char *argv[] ) } Options.argc = argc; Options.argv = argv; + _ARGC = argc; + _ARGV = argv; } diff --git a/programs/avitools/Makefile.in b/programs/avitools/Makefile.in index 94199d79248..09f90aea926 100644 --- a/programs/avitools/Makefile.in +++ b/programs/avitools/Makefile.in @@ -13,7 +13,7 @@ SPEC_SRCS = \ 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 36498df4b0f..4419c11c436 100644 --- a/programs/clock/Makefile.in +++ b/programs/clock/Makefile.in @@ -21,7 +21,7 @@ SPEC_SRCS = clock.spec 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 52fbec18342..07b497866af 100644 --- a/programs/cmdlgtst/Makefile.in +++ b/programs/cmdlgtst/Makefile.in @@ -17,7 +17,7 @@ SPEC_SRCS = \ 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 603c269cdf4..70e98d0d381 100644 --- a/programs/control/Makefile.in +++ b/programs/control/Makefile.in @@ -11,7 +11,7 @@ C_SRCS = control.c 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 78de8dbb71e..a83922bfb4b 100644 --- a/programs/notepad/Makefile.in +++ b/programs/notepad/Makefile.in @@ -22,7 +22,7 @@ SPEC_SRCS = notepad.spec 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 29f28ccc5e0..bf361c713f3 100644 --- a/programs/osversioncheck/Makefile.in +++ b/programs/osversioncheck/Makefile.in @@ -15,9 +15,6 @@ all: $(PROGRAMS) @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 fd8510f190d..f7c1ddd6580 100644 --- a/programs/osversioncheck/osversioncheck.c +++ b/programs/osversioncheck/osversioncheck.c @@ -11,13 +11,6 @@ #include #include -#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 @@ show_last_error(void) } 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 da3eac9628a..585ef75f774 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 ce6378d795c..f69ce7c4fd6 100644 --- a/programs/progman/Makefile.in +++ b/programs/progman/Makefile.in @@ -24,7 +24,7 @@ SPEC_SRCS = progman.spec 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 55d24610d6e..d3d8127a8ea 100644 --- a/programs/regapi/Makefile.in +++ b/programs/regapi/Makefile.in @@ -13,7 +13,7 @@ C_SRCS = \ 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 3078d7b6771..1cc86f1641d 100644 --- a/programs/regtest/Makefile.in +++ b/programs/regtest/Makefile.in @@ -11,7 +11,7 @@ C_SRCS = regtest.c 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 94e0b83a064..f34739ed78a 100644 --- a/programs/view/Makefile.in +++ b/programs/view/Makefile.in @@ -19,7 +19,7 @@ SPEC_SRCS = \ 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 60df63ecc54..2da5eb1d29f 100644 --- a/programs/wcmd/Makefile.in +++ b/programs/wcmd/Makefile.in @@ -24,9 +24,6 @@ all: check_wrc $(PROGRAMS) @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 a78c34d3362..4c881b52f68 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 281c7b2d31f..23f4aa94f4c 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 @@ BATCH_CONTEXT *context = NULL; */ -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; iname ); /* 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 @@ WINE_MODREF *BUILTIN32_LoadLibraryExA(LPCSTR path, DWORD flags) /*********************************************************************** * BUILTIN32_LoadExeModule */ -HMODULE16 BUILTIN32_LoadExeModule( void ) +HMODULE BUILTIN32_LoadExeModule( LPCSTR *filename ) { HMODULE16 hModule16; NE_MODULE *pModule; @@ -449,14 +447,8 @@ HMODULE16 BUILTIN32_LoadExeModule( void ) 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 ba2ed7b4e38..b7cd744828c 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -7,11 +7,13 @@ #include #include #include +#include #include #include #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 @@ static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit ) */ BOOL PROCESS_Init( BOOL win32 ) { + struct init_process_request *req; TEB *teb; int server_fd; @@ -308,11 +313,13 @@ BOOL PROCESS_Init( BOOL win32 ) 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 @@ BOOL PROCESS_Init( BOOL win32 ) /* 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 16ede628fe3..046ae0438fd 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -119,7 +119,7 @@ static void CALLBACK THREAD_FreeTEB( TEB *teb ) * * 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 838a1a76a45..4bd1cd888e3 100644 --- a/tools/build.c +++ b/tools/build.c @@ -733,6 +733,8 @@ static void ParseTopLevel(void) 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 @@ static int BuildSpec32File( FILE *outfile ) 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 @@ static int BuildSpec32File( FILE *outfile ) 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 @@ static int BuildSpec32File( FILE *outfile ) 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 @@ static int BuildSpec32File( FILE *outfile ) } } - /* 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 @@ static int BuildSpec32File( FILE *outfile ) 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 \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 \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 @@ static int BuildSpec32File( FILE *outfile ) 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 @@ static int BuildSpec32File( FILE *outfile ) 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 @@ static int BuildSpec16File( FILE *outfile ) 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 @@ static int BuildSpec16File( FILE *outfile ) 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; } -- 2.11.4.GIT