From fedc4117439af16544f0ac24a3542fb02c345d73 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 27 Apr 2003 00:47:58 +0000 Subject: [PATCH] Moved the functionality of starting Win16 and DOS programs from the common process startup into a separate winevdm application. --- configure | 3 +- configure.ac | 1 + dlls/winedos/module.c | 18 +-- dlls/winedos/winedos.spec | 3 +- include/callback.h | 1 - libs/wine/loader.c | 15 +++ loader/ne/module.c | 38 ------ loader/task.c | 8 +- miscemu/.cvsignore | 1 - miscemu/Makefile.in | 10 +- miscemu/main.c | 83 ++----------- msdos/dpmi.c | 1 - programs/Makefile.in | 6 + programs/winevdm/.cvsignore | 3 + programs/winevdm/Makefile.in | 14 +++ programs/winevdm/winevdm.c | 229 +++++++++++++++++++++++++++++++++++ scheduler/process.c | 59 ++++++--- 17 files changed, 337 insertions(+), 156 deletions(-) create mode 100644 programs/winevdm/.cvsignore create mode 100644 programs/winevdm/Makefile.in create mode 100644 programs/winevdm/winevdm.c diff --git a/configure b/configure index d486e98e585..ef4fdcd0c97 100755 --- a/configure +++ b/configure @@ -16073,7 +16073,7 @@ MAKE_TEST_RULES=dlls/Maketest.rules MAKE_PROG_RULES=programs/Makeprog.rules - ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3dim/Makefile dlls/d3dx8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrtd/Makefile dlls/msvideo/Makefile dlls/msvideo/msrle32/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/version/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winenas/Makefile dlls/winmm/winejack/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/uuid/Makefile libs/wine/Makefile miscemu/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/osversioncheck/Makefile programs/progman/Makefile programs/regapi/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/regtest/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/wmc/Makefile tools/wpp/Makefile tools/wrc/Makefile" + ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3dim/Makefile dlls/d3dx8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrtd/Makefile dlls/msvideo/Makefile dlls/msvideo/msrle32/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/version/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winenas/Makefile dlls/winmm/winejack/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/uuid/Makefile libs/wine/Makefile miscemu/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/osversioncheck/Makefile programs/progman/Makefile programs/regapi/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/regtest/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/wmc/Makefile tools/wpp/Makefile tools/wrc/Makefile" cat >confcache <<\_ACEOF @@ -16773,6 +16773,7 @@ do "programs/winefile/Makefile" ) CONFIG_FILES="$CONFIG_FILES programs/winefile/Makefile" ;; "programs/winemine/Makefile" ) CONFIG_FILES="$CONFIG_FILES programs/winemine/Makefile" ;; "programs/winepath/Makefile" ) CONFIG_FILES="$CONFIG_FILES programs/winepath/Makefile" ;; + "programs/winevdm/Makefile" ) CONFIG_FILES="$CONFIG_FILES programs/winevdm/Makefile" ;; "programs/winhelp/Makefile" ) CONFIG_FILES="$CONFIG_FILES programs/winhelp/Makefile" ;; "programs/winver/Makefile" ) CONFIG_FILES="$CONFIG_FILES programs/winver/Makefile" ;; "server/Makefile" ) CONFIG_FILES="$CONFIG_FILES server/Makefile" ;; diff --git a/configure.ac b/configure.ac index c2d0718b7bc..7cd3a37919e 100644 --- a/configure.ac +++ b/configure.ac @@ -1523,6 +1523,7 @@ programs/winedbg/Makefile programs/winefile/Makefile programs/winemine/Makefile programs/winepath/Makefile +programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile diff --git a/dlls/winedos/module.c b/dlls/winedos/module.c index 9fdf0d26c5d..fde7245bcac 100644 --- a/dlls/winedos/module.c +++ b/dlls/winedos/module.c @@ -105,7 +105,7 @@ static WORD init_cs,init_ip,init_ss,init_sp; static HANDLE dosvm_thread, loop_thread; static DWORD dosvm_tid, loop_tid; -static void MZ_Launch(void); +static void MZ_Launch( LPCSTR cmdline ); static BOOL MZ_InitTask(void); static void MZ_CreatePSP( LPVOID lpPSP, WORD env, WORD par ) @@ -124,7 +124,7 @@ static void MZ_CreatePSP( LPVOID lpPSP, WORD env, WORD par ) /* FIXME: more PSP stuff */ } -static void MZ_FillPSP( LPVOID lpPSP, LPBYTE cmdline, int length ) +static void MZ_FillPSP( LPVOID lpPSP, LPCSTR cmdline, int length ) { PDB16 *psp = lpPSP; @@ -346,15 +346,18 @@ load_error: } /*********************************************************************** - * LoadDosExe (WINEDOS.@) + * wine_load_dos_exe (WINEDOS.@) * - * Called from Wine loader when a new real-mode DOS process is started. + * Called from WineVDM when a new real-mode DOS process is started. * Loads DOS program into memory and executes the program. */ -void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile ) +void WINAPI wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline ) { + HANDLE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); + if (hFile == INVALID_HANDLE_VALUE) return; DOSVM_isdosexe = TRUE; - if (MZ_DoLoadImage( hFile, filename, NULL )) MZ_Launch(); + if (MZ_DoLoadImage( hFile, filename, NULL )) MZ_Launch( cmdline ); + } /*********************************************************************** @@ -557,11 +560,10 @@ static BOOL MZ_InitTask(void) return TRUE; } -static void MZ_Launch(void) +static void MZ_Launch( LPCSTR cmdline ) { TDB *pTask = GlobalLock16( GetCurrentTask() ); BYTE *psp_start = PTR_REAL_TO_LIN( DOSVM_psp, 0 ); - LPSTR cmdline = GetCommandLineA(); DWORD rv; SYSLEVEL *lock; diff --git a/dlls/winedos/winedos.spec b/dlls/winedos/winedos.spec index 4c2426b9978..74d7a65662d 100644 --- a/dlls/winedos/winedos.spec +++ b/dlls/winedos/winedos.spec @@ -1,4 +1,5 @@ -@ stdcall LoadDosExe(str long) MZ_LoadImage +@ stdcall wine_load_dos_exe(str str) + @ stdcall EmulateInterruptPM(ptr long) DOSVM_EmulateInterruptPM @ stdcall CallBuiltinHandler(ptr long) DOSVM_CallBuiltinHandler diff --git a/include/callback.h b/include/callback.h index 903c4020d4c..0d1168c5919 100644 --- a/include/callback.h +++ b/include/callback.h @@ -25,7 +25,6 @@ #include "winnt.h" typedef struct { - void (WINAPI *LoadDosExe)( LPCSTR filename, HANDLE hFile ); void (WINAPI *EmulateInterruptPM)( CONTEXT86 *context, BYTE intnum ); void (WINAPI *CallBuiltinHandler)( CONTEXT86 *context, BYTE intnum ); diff --git a/libs/wine/loader.c b/libs/wine/loader.c index 42c6e38efb4..dbac56bf8a7 100644 --- a/libs/wine/loader.c +++ b/libs/wine/loader.c @@ -414,6 +414,21 @@ void *wine_dll_load_main_exe( const char *name, char *error, int errorsize, int } +/*********************************************************************** + * wine_init + * + * Main Wine initialisation. + */ +void wine_init( int argc, char *argv[], char *error, int error_size ) +{ + void *ntdll; + void (*init_func)(int, char **); + + if (!(ntdll = dlopen_dll( "ntdll.dll", error, error_size, 0 ))) return; + if (!(init_func = wine_dlsym( ntdll, "__wine_process_init", error, error_size ))) return; + init_func( argc, argv ); +} + #if defined(__svr4__) || defined(__NetBSD__) /*********************************************************************** diff --git a/loader/ne/module.c b/loader/ne/module.c index 20f2c19024d..b549e9fbb63 100644 --- a/loader/ne/module.c +++ b/loader/ne/module.c @@ -1107,44 +1107,6 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock ) } -/********************************************************************** - * NE_StartMain - * - * Start the main NE task. - */ -HINSTANCE16 NE_StartMain( LPCSTR name, HANDLE file ) -{ - STARTUPINFOA info; - HMODULE16 hModule; - NE_MODULE *pModule; - INT len; - LPSTR pCmdLine, cmdline = GetCommandLineA(); - - if ((hModule = NE_LoadExeHeader( file, name )) < 32) return hModule; - - if (!(pModule = NE_GetPtr( hModule ))) return (HINSTANCE16)11; - if (pModule->flags & NE_FFLAGS_LIBMODULE) - { - MESSAGE( "%s is not a valid Win16 executable\n", name ); - ExitProcess( ERROR_BAD_EXE_FORMAT ); - } - - while (*cmdline && *cmdline != ' ') cmdline++; - if (*cmdline) cmdline++; - len = strlen(cmdline); - pCmdLine = HeapAlloc(GetProcessHeap(), 0, len+2); - if (pCmdLine) - { - strcpy(pCmdLine+1, cmdline); - *pCmdLine = len; - } - GetStartupInfoA( &info ); - if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = 1; - - return NE_CreateThread( pModule, info.wShowWindow, pCmdLine ); -} - - /********************************************************************** * NE_StartTask * diff --git a/loader/task.c b/loader/task.c index f7a23acc80d..992b5e131ae 100644 --- a/loader/task.c +++ b/loader/task.c @@ -720,15 +720,9 @@ void WINAPI DirectedYield16( HTASK16 hTask ) { TDB *pCurTask = TASK_GetCurrent(); - if (!pCurTask) OldYield16(); + if (!pCurTask || (pCurTask->flags & TDBF_WIN32)) OldYield16(); else { - if (pCurTask->flags & TDBF_WIN32) - { - FIXME("called for Win32 thread (%04x)!\n", NtCurrentTeb()->teb_sel); - return; - } - TRACE("%04x: DirectedYield(%04x)\n", pCurTask->hSelf, hTask ); pCurTask->hYieldTo = hTask; OldYield16(); diff --git a/miscemu/.cvsignore b/miscemu/.cvsignore index 1bf52a43217..dfe93696fde 100644 --- a/miscemu/.cvsignore +++ b/miscemu/.cvsignore @@ -1,3 +1,2 @@ Makefile wine -wine.spec.c diff --git a/miscemu/Makefile.in b/miscemu/Makefile.in index 04bb3a87a58..b8ac569089f 100644 --- a/miscemu/Makefile.in +++ b/miscemu/Makefile.in @@ -3,8 +3,6 @@ TOPOBJDIR = .. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = wine -IMPORTS = ntdll -LDIMPORTS = ntdll.dll C_SRCS = \ main.c @@ -13,14 +11,10 @@ all: $(MODULE) @MAKE_RULES@ -ALL_OBJS = $(MODULE).spec.o $(OBJS) LDEXECFLAGS = @LDEXECFLAGS@ -$(MODULE): $(ALL_OBJS) - $(CC) -o $@ $(LDEXECFLAGS) $(ALL_OBJS) -L$(DLLDIR) $(LDIMPORTS:%=-l%) $(LIBWINE) $(LIBUNICODE) $(LIBPORT) $(LIBS) $(LDFLAGS) - -$(MODULE).spec.c: $(WINEBUILD) - $(WINEBUILD) $(DEFS) -o $@ --exe $(MODULE) --exe-mode gui --entry wine_initial_task -L$(DLLDIR) $(IMPORTS:%=-l%) +$(MODULE): $(OBJS) + $(CC) -o $@ $(LDEXECFLAGS) $(OBJS) $(LIBWINE) $(LIBPORT) $(LDFLAGS) install:: $(MODULE) $(MKINSTALLDIRS) $(bindir) diff --git a/miscemu/main.c b/miscemu/main.c index 14f983bf0bd..6b06bc34d35 100644 --- a/miscemu/main.c +++ b/miscemu/main.c @@ -18,87 +18,18 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "winbase.h" -#include "wine/winbase16.h" -#include "wingdi.h" -#include "winuser.h" - -#include "miscemu.h" -#include "callback.h" -#include "options.h" -#include "wine/debug.h" - -static char main_exe_name[MAX_PATH]; -static HANDLE main_exe_file; - -static BOOL (WINAPI *pGetMessageA)(LPMSG,HWND,UINT,UINT); -static BOOL (WINAPI *pTranslateMessage)(const MSG*); -static LONG (WINAPI *pDispatchMessageA)(const MSG*); - -extern void DECLSPEC_NORETURN PROCESS_InitWine( - int argc, char *argv[], LPSTR win16_exe_name, - HANDLE *win16_exe_file ); -extern HINSTANCE16 NE_StartMain( LPCSTR name, HANDLE file ); - -/*********************************************************************** - * Main loop of initial task - */ -int WINAPI wine_initial_task( HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, INT show ) -{ - MSG msg; - HINSTANCE16 instance; - HMODULE user32; - - /* some programs assume mmsystem is always present */ - LoadLibrary16( "mmsystem.dll" ); - - if ((instance = NE_StartMain( main_exe_name, main_exe_file )) < 32) - { - if (instance == 11) /* try DOS format */ - { - if (DPMI_LoadDosSystem()) - Dosvm.LoadDosExe( main_exe_name, main_exe_file ); - /* if we get back here it failed */ - instance = GetLastError(); - } - - WINE_MESSAGE( "%s: can't exec '%s': ", argv0, GetCommandLineA() ); - switch (instance) - { - case 2: WINE_MESSAGE("file not found\n" ); break; - case 11: WINE_MESSAGE("invalid exe file\n" ); break; - default: WINE_MESSAGE("error=%d\n", instance ); break; - } - ExitProcess(instance); - } - CloseHandle( main_exe_file ); /* avoid file sharing problems */ - - /* Start message loop for desktop window */ - - if (!(user32 = LoadLibraryA( "user32.dll" ))) - { - WINE_MESSAGE( "Cannot load user32.dll\n" ); - ExitProcess( GetLastError() ); - } - pGetMessageA = (void *)GetProcAddress( user32, "GetMessageA" ); - pTranslateMessage = (void *)GetProcAddress( user32, "TranslateMessage" ); - pDispatchMessageA = (void *)GetProcAddress( user32, "DispatchMessageA" ); - - while ( GetNumTasks16() > 1 && pGetMessageA( &msg, 0, 0, 0 ) ) - { - pTranslateMessage( &msg ); - pDispatchMessageA( &msg ); - } - - ExitProcess( 0 ); -} +#include +extern void wine_init( int argc, char *argv[], char *error, int error_size ); /********************************************************************** * main */ int main( int argc, char *argv[] ) { - PROCESS_InitWine( argc, argv, main_exe_name, &main_exe_file ); - return 1; /* not reached */ + char error[1024]; + + wine_init( argc, argv, error, sizeof(error) ); + fprintf( stderr, "wine: failed to initialize: %s\n", error ); + exit(1); } diff --git a/msdos/dpmi.c b/msdos/dpmi.c index ca0cdf6db50..81c6726b6f7 100644 --- a/msdos/dpmi.c +++ b/msdos/dpmi.c @@ -45,7 +45,6 @@ BOOL DPMI_LoadDosSystem(void) } #define GET_ADDR(func) Dosvm.func = (void *)GetProcAddress(DosModule, #func); - GET_ADDR(LoadDosExe); GET_ADDR(SetTimer); GET_ADDR(GetTimer); GET_ADDR(inport); diff --git a/programs/Makefile.in b/programs/Makefile.in index f4909a04cb6..35494f54d3c 100644 --- a/programs/Makefile.in +++ b/programs/Makefile.in @@ -30,6 +30,7 @@ SUBDIRS = \ winefile \ winemine \ winepath \ + winevdm \ winhelp \ winver @@ -82,6 +83,7 @@ SYMLINKS = \ wcmd.exe \ wineconsole.exe \ winedbg.exe \ + winevdm.exe \ winhelp.exe @MAKE_RULES@ @@ -139,12 +141,16 @@ wineconsole.exe$(DLLEXT): wineconsole/wineconsole.exe$(DLLEXT) winedbg.exe$(DLLEXT): winedbg/winedbg.exe$(DLLEXT) $(RM) $@ && $(LN_S) winedbg/winedbg.exe$(DLLEXT) $@ +winevdm.exe$(DLLEXT): winevdm/winevdm.exe$(DLLEXT) + $(RM) $@ && $(LN_S) winevdm/winevdm.exe$(DLLEXT) $@ + winhelp.exe$(DLLEXT): winhelp/winhelp.exe$(DLLEXT) $(RM) $@ && $(LN_S) winhelp/winhelp.exe$(DLLEXT) $@ wcmd/wcmd.exe$(DLLEXT): wcmd wineconsole/wineconsole.exe$(DLLEXT): wineconsole winedbg/winedbg.exe$(DLLEXT): winedbg +winevdm/winevdm.exe$(DLLEXT): winevdm winhelp/winhelp.exe$(DLLEXT): winhelp ### Dependencies: diff --git a/programs/winevdm/.cvsignore b/programs/winevdm/.cvsignore new file mode 100644 index 00000000000..4621aa916cc --- /dev/null +++ b/programs/winevdm/.cvsignore @@ -0,0 +1,3 @@ +Makefile +winevdm.exe.dbg.c +winevdm.exe.spec.c diff --git a/programs/winevdm/Makefile.in b/programs/winevdm/Makefile.in new file mode 100644 index 00000000000..61b1db0c9f5 --- /dev/null +++ b/programs/winevdm/Makefile.in @@ -0,0 +1,14 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = winevdm.exe +APPMODE = cui +IMPORTS = winedos kernel32 + +C_SRCS = \ + winevdm.c + +@MAKE_PROG_RULES@ + +### Dependencies: diff --git a/programs/winevdm/winevdm.c b/programs/winevdm/winevdm.c new file mode 100644 index 00000000000..96366d2503d --- /dev/null +++ b/programs/winevdm/winevdm.c @@ -0,0 +1,229 @@ +/* + * Wine virtual DOS machine + * + * Copyright 2003 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "winbase.h" +#include "wine/winbase16.h" +#include "winuser.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(winevdm); + +extern void WINAPI wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline ); + + +/*********************************************************************** + * build_command_line + * + * Build the command line of a process from the argv array. + * Copied from ENV_BuildCommandLine. + */ +static char *build_command_line( char **argv ) +{ + int len; + char *p, **arg, *cmd_line; + + len = 0; + for (arg = argv; *arg; arg++) + { + int has_space,bcount; + char* a; + + has_space=0; + bcount=0; + a=*arg; + while (*a!='\0') { + if (*a=='\\') { + bcount++; + } else { + if (*a==' ' || *a=='\t') { + has_space=1; + } else if (*a=='"') { + /* doubling of '\' preceeding a '"', + * plus escaping of said '"' + */ + len+=2*bcount+1; + } + bcount=0; + } + a++; + } + len+=(a-*arg)+1 /* for the separating space */; + if (has_space) + len+=2; /* for the quotes */ + } + + if (!(cmd_line = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return NULL; + + p = cmd_line; + *p++ = len; + for (arg = argv; *arg; arg++) + { + int has_space,has_quote; + char* a; + + /* Check for quotes and spaces in this argument */ + has_space=has_quote=0; + a=*arg; + while (*a!='\0') { + if (*a==' ' || *a=='\t') { + has_space=1; + if (has_quote) + break; + } else if (*a=='"') { + has_quote=1; + if (has_space) + break; + } + a++; + } + + /* Now transfer it to the command line */ + if (has_space) + *p++='"'; + if (has_quote) { + int bcount; + char* a; + + bcount=0; + a=*arg; + while (*a!='\0') { + if (*a=='\\') { + *p++=*a; + bcount++; + } else { + if (*a=='"') { + int i; + + /* Double all the '\\' preceeding this '"', plus one */ + for (i=0;i<=bcount;i++) + *p++='\\'; + *p++='"'; + } else { + *p++=*a; + } + bcount=0; + } + a++; + } + } else { + strcpy(p,*arg); + p+=strlen(*arg); + } + if (has_space) + *p++='"'; + *p++=' '; + } + if (p > cmd_line) p--; /* remove last space */ + *p = '\0'; + return cmd_line; +} + + +/*********************************************************************** + * usage + */ +static void usage(void) +{ + WINE_MESSAGE( "Usage: winevdm.exe [--app-name app.exe] command line\n\n" ); + ExitProcess(1); +} + + +/*********************************************************************** + * main + */ +int main( int argc, char *argv[] ) +{ + DWORD count; + HINSTANCE16 instance; + LOADPARAMS16 params; + WORD showCmd[2]; + char buffer[MAX_PATH]; + STARTUPINFOA info; + char *cmdline, *appname, **first_arg; + + if (!argv[1]) usage(); + + if (!strcmp( argv[1], "--app-name" )) + { + if (!(appname = argv[2])) usage(); + first_arg = argv + 3; + } + else + { + if (!SearchPathA( NULL, argv[1], ".exe", sizeof(buffer), buffer, NULL )) + { + WINE_MESSAGE( "winevdm: can't exec '%s': file not found\n", argv[1] ); + ExitProcess(1); + } + appname = buffer; + first_arg = argv + 1; + } + + if (*first_arg) first_arg++; /* skip program name */ + cmdline = build_command_line( first_arg ); + + if (WINE_TRACE_ON(winevdm)) + { + int i; + WINE_TRACE( "GetCommandLine = '%s'\n", GetCommandLineA() ); + WINE_TRACE( "appname = '%s'\n", appname ); + WINE_TRACE( "cmdline = '%.*s'\n", cmdline[0], cmdline+1 ); + for (i = 0; argv[i]; i++) WINE_TRACE( "argv[%d]: '%s'\n", i, argv[i] ); + } + + GetStartupInfoA( &info ); + showCmd[0] = 2; + showCmd[1] = (info.dwFlags & STARTF_USESHOWWINDOW) ? info.wShowWindow : SW_SHOWNORMAL; + + params.hEnvironment = 0; + params.cmdLine = MapLS( cmdline ); + params.showCmd = MapLS( showCmd ); + params.reserved = 0; + + RestoreThunkLock(1); /* grab the Win16 lock */ + + /* some programs assume mmsystem is always present */ + LoadLibrary16( "mmsystem.dll" ); + + if ((instance = LoadModule16( appname, ¶ms )) < 32) + { + if (instance == 11) /* try DOS format */ + { + wine_load_dos_exe( appname, cmdline ); + /* if we get back here it failed */ + instance = GetLastError(); + } + + WINE_MESSAGE( "winevdm: can't exec '%s': ", appname ); + switch (instance) + { + case 2: WINE_MESSAGE("file not found\n" ); break; + case 11: WINE_MESSAGE("invalid exe file\n" ); break; + default: WINE_MESSAGE("error=%d\n", instance ); break; + } + ExitProcess(instance); + } + + /* wait forever; the process will be killed when the last task exits */ + ReleaseThunkLock( &count ); + Sleep( INFINITE ); + return 0; +} diff --git a/scheduler/process.c b/scheduler/process.c index 634e614e1d7..63769a781fc 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -572,11 +572,11 @@ static void start_process(void) /*********************************************************************** - * PROCESS_InitWine + * __wine_process_init * * Wine initialisation: load and start the main exe file. */ -void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win16_exe_file ) +void __wine_process_init( int argc, char *argv[] ) { char error[1024], *p; DWORD stack_size = 0; @@ -636,14 +636,15 @@ void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win case BINARY_WIN16: case BINARY_DOS: TRACE( "starting Win16/DOS binary %s\n", debugstr_a(main_exe_name) ); - NtCurrentTeb()->tibflags &= ~TEBF_WIN32; - current_process.flags |= PDB32_WIN16_PROC; - strcpy( win16_exe_name, main_exe_name ); - main_exe_name[0] = 0; - *win16_exe_file = main_exe_file; + CloseHandle( main_exe_file ); main_exe_file = 0; - _EnterWin16Lock(); - goto found; + argv--; + argv[0] = "winevdm.exe"; + if (open_builtin_exe_file( "winevdm.exe", error, sizeof(error), 0 )) + goto found; + MESSAGE( "%s: trying to run '%s', cannot open builtin library for 'winevdm.exe': %s\n", + argv0, main_exe_name, error ); + ExitProcess(1); case BINARY_OS216: MESSAGE( "%s: '%s' is an OS/2 binary, not supported\n", argv0, main_exe_name ); ExitProcess(1); @@ -1132,6 +1133,32 @@ static BOOL create_process( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCST } +/*********************************************************************** + * create_vdm_process + * + * Create a new VDM process for a 16-bit or DOS application. + */ +static BOOL create_vdm_process( LPCSTR filename, LPSTR cmd_line, LPCSTR env, + LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, + BOOL inherit, DWORD flags, LPSTARTUPINFOA startup, + LPPROCESS_INFORMATION info, LPCSTR unixdir ) +{ + BOOL ret; + LPSTR new_cmd_line = HeapAlloc( GetProcessHeap(), 0, strlen(filename) + strlen(cmd_line) + 30 ); + + if (!new_cmd_line) + { + SetLastError( ERROR_OUTOFMEMORY ); + return FALSE; + } + sprintf( new_cmd_line, "winevdm.exe --app-name \"%s\" %s", filename, cmd_line ); + ret = create_process( 0, "winevdm.exe", new_cmd_line, env, psa, tsa, inherit, + flags, startup, info, unixdir ); + HeapFree( GetProcessHeap(), 0, new_cmd_line ); + return ret; +} + + /************************************************************************* * get_file_name * @@ -1310,12 +1337,16 @@ BOOL WINAPI CreateProcessA( LPCSTR app_name, LPSTR cmd_line, LPSECURITY_ATTRIBUT switch( MODULE_GetBinaryType( hFile )) { case BINARY_PE_EXE: - case BINARY_WIN16: - case BINARY_DOS: - TRACE( "starting %s as Windows binary\n", debugstr_a(name) ); + TRACE( "starting %s as Win32 binary\n", debugstr_a(name) ); retv = create_process( hFile, name, tidy_cmdline, env, process_attr, thread_attr, inherit, flags, startup_info, info, unixdir ); break; + case BINARY_WIN16: + case BINARY_DOS: + TRACE( "starting %s as Win16/DOS binary\n", debugstr_a(name) ); + retv = create_vdm_process( name, tidy_cmdline, env, process_attr, thread_attr, + inherit, flags, startup_info, info, unixdir ); + break; case BINARY_OS216: FIXME( "%s is OS/2 binary, not supported\n", debugstr_a(name) ); SetLastError( ERROR_BAD_EXE_FORMAT ); @@ -1336,8 +1367,8 @@ BOOL WINAPI CreateProcessA( LPCSTR app_name, LPSTR cmd_line, LPSECURITY_ATTRIBUT if (!FILE_strcasecmp( p, ".com" )) { TRACE( "starting %s as DOS binary\n", debugstr_a(name) ); - retv = create_process( hFile, name, tidy_cmdline, env, process_attr, thread_attr, - inherit, flags, startup_info, info, unixdir ); + retv = create_vdm_process( name, tidy_cmdline, env, process_attr, thread_attr, + inherit, flags, startup_info, info, unixdir ); break; } if (!FILE_strcasecmp( p, ".bat" ))