Moved the functionality of starting Win16 and DOS programs from the
common process startup into a separate winevdm application.
This commit is contained in:
parent
8f6727c57d
commit
fedc411743
|
@ -1523,6 +1523,7 @@ programs/winedbg/Makefile
|
||||||
programs/winefile/Makefile
|
programs/winefile/Makefile
|
||||||
programs/winemine/Makefile
|
programs/winemine/Makefile
|
||||||
programs/winepath/Makefile
|
programs/winepath/Makefile
|
||||||
|
programs/winevdm/Makefile
|
||||||
programs/winhelp/Makefile
|
programs/winhelp/Makefile
|
||||||
programs/winver/Makefile
|
programs/winver/Makefile
|
||||||
server/Makefile
|
server/Makefile
|
||||||
|
|
|
@ -105,7 +105,7 @@ static WORD init_cs,init_ip,init_ss,init_sp;
|
||||||
static HANDLE dosvm_thread, loop_thread;
|
static HANDLE dosvm_thread, loop_thread;
|
||||||
static DWORD dosvm_tid, loop_tid;
|
static DWORD dosvm_tid, loop_tid;
|
||||||
|
|
||||||
static void MZ_Launch(void);
|
static void MZ_Launch( LPCSTR cmdline );
|
||||||
static BOOL MZ_InitTask(void);
|
static BOOL MZ_InitTask(void);
|
||||||
|
|
||||||
static void MZ_CreatePSP( LPVOID lpPSP, WORD env, WORD par )
|
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 */
|
/* 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;
|
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.
|
* 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;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MZ_Launch(void)
|
static void MZ_Launch( LPCSTR cmdline )
|
||||||
{
|
{
|
||||||
TDB *pTask = GlobalLock16( GetCurrentTask() );
|
TDB *pTask = GlobalLock16( GetCurrentTask() );
|
||||||
BYTE *psp_start = PTR_REAL_TO_LIN( DOSVM_psp, 0 );
|
BYTE *psp_start = PTR_REAL_TO_LIN( DOSVM_psp, 0 );
|
||||||
LPSTR cmdline = GetCommandLineA();
|
|
||||||
DWORD rv;
|
DWORD rv;
|
||||||
SYSLEVEL *lock;
|
SYSLEVEL *lock;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
@ stdcall LoadDosExe(str long) MZ_LoadImage
|
@ stdcall wine_load_dos_exe(str str)
|
||||||
|
|
||||||
@ stdcall EmulateInterruptPM(ptr long) DOSVM_EmulateInterruptPM
|
@ stdcall EmulateInterruptPM(ptr long) DOSVM_EmulateInterruptPM
|
||||||
@ stdcall CallBuiltinHandler(ptr long) DOSVM_CallBuiltinHandler
|
@ stdcall CallBuiltinHandler(ptr long) DOSVM_CallBuiltinHandler
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void (WINAPI *LoadDosExe)( LPCSTR filename, HANDLE hFile );
|
|
||||||
void (WINAPI *EmulateInterruptPM)( CONTEXT86 *context, BYTE intnum );
|
void (WINAPI *EmulateInterruptPM)( CONTEXT86 *context, BYTE intnum );
|
||||||
void (WINAPI *CallBuiltinHandler)( CONTEXT86 *context, BYTE intnum );
|
void (WINAPI *CallBuiltinHandler)( CONTEXT86 *context, BYTE intnum );
|
||||||
|
|
||||||
|
|
|
@ -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__)
|
#if defined(__svr4__) || defined(__NetBSD__)
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
|
@ -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
|
* NE_StartTask
|
||||||
*
|
*
|
||||||
|
|
|
@ -720,15 +720,9 @@ void WINAPI DirectedYield16( HTASK16 hTask )
|
||||||
{
|
{
|
||||||
TDB *pCurTask = TASK_GetCurrent();
|
TDB *pCurTask = TASK_GetCurrent();
|
||||||
|
|
||||||
if (!pCurTask) OldYield16();
|
if (!pCurTask || (pCurTask->flags & TDBF_WIN32)) OldYield16();
|
||||||
else
|
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 );
|
TRACE("%04x: DirectedYield(%04x)\n", pCurTask->hSelf, hTask );
|
||||||
pCurTask->hYieldTo = hTask;
|
pCurTask->hYieldTo = hTask;
|
||||||
OldYield16();
|
OldYield16();
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
Makefile
|
Makefile
|
||||||
wine
|
wine
|
||||||
wine.spec.c
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ TOPOBJDIR = ..
|
||||||
SRCDIR = @srcdir@
|
SRCDIR = @srcdir@
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
MODULE = wine
|
MODULE = wine
|
||||||
IMPORTS = ntdll
|
|
||||||
LDIMPORTS = ntdll.dll
|
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
main.c
|
main.c
|
||||||
|
@ -13,14 +11,10 @@ all: $(MODULE)
|
||||||
|
|
||||||
@MAKE_RULES@
|
@MAKE_RULES@
|
||||||
|
|
||||||
ALL_OBJS = $(MODULE).spec.o $(OBJS)
|
|
||||||
LDEXECFLAGS = @LDEXECFLAGS@
|
LDEXECFLAGS = @LDEXECFLAGS@
|
||||||
|
|
||||||
$(MODULE): $(ALL_OBJS)
|
$(MODULE): $(OBJS)
|
||||||
$(CC) -o $@ $(LDEXECFLAGS) $(ALL_OBJS) -L$(DLLDIR) $(LDIMPORTS:%=-l%) $(LIBWINE) $(LIBUNICODE) $(LIBPORT) $(LIBS) $(LDFLAGS)
|
$(CC) -o $@ $(LDEXECFLAGS) $(OBJS) $(LIBWINE) $(LIBPORT) $(LDFLAGS)
|
||||||
|
|
||||||
$(MODULE).spec.c: $(WINEBUILD)
|
|
||||||
$(WINEBUILD) $(DEFS) -o $@ --exe $(MODULE) --exe-mode gui --entry wine_initial_task -L$(DLLDIR) $(IMPORTS:%=-l%)
|
|
||||||
|
|
||||||
install:: $(MODULE)
|
install:: $(MODULE)
|
||||||
$(MKINSTALLDIRS) $(bindir)
|
$(MKINSTALLDIRS) $(bindir)
|
||||||
|
|
|
@ -18,87 +18,18 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "winbase.h"
|
#include <stdio.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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
extern void wine_init( int argc, char *argv[], char *error, int error_size );
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* main
|
* main
|
||||||
*/
|
*/
|
||||||
int main( int argc, char *argv[] )
|
int main( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
PROCESS_InitWine( argc, argv, main_exe_name, &main_exe_file );
|
char error[1024];
|
||||||
return 1; /* not reached */
|
|
||||||
|
wine_init( argc, argv, error, sizeof(error) );
|
||||||
|
fprintf( stderr, "wine: failed to initialize: %s\n", error );
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,6 @@ BOOL DPMI_LoadDosSystem(void)
|
||||||
}
|
}
|
||||||
#define GET_ADDR(func) Dosvm.func = (void *)GetProcAddress(DosModule, #func);
|
#define GET_ADDR(func) Dosvm.func = (void *)GetProcAddress(DosModule, #func);
|
||||||
|
|
||||||
GET_ADDR(LoadDosExe);
|
|
||||||
GET_ADDR(SetTimer);
|
GET_ADDR(SetTimer);
|
||||||
GET_ADDR(GetTimer);
|
GET_ADDR(GetTimer);
|
||||||
GET_ADDR(inport);
|
GET_ADDR(inport);
|
||||||
|
|
|
@ -30,6 +30,7 @@ SUBDIRS = \
|
||||||
winefile \
|
winefile \
|
||||||
winemine \
|
winemine \
|
||||||
winepath \
|
winepath \
|
||||||
|
winevdm \
|
||||||
winhelp \
|
winhelp \
|
||||||
winver
|
winver
|
||||||
|
|
||||||
|
@ -82,6 +83,7 @@ SYMLINKS = \
|
||||||
wcmd.exe \
|
wcmd.exe \
|
||||||
wineconsole.exe \
|
wineconsole.exe \
|
||||||
winedbg.exe \
|
winedbg.exe \
|
||||||
|
winevdm.exe \
|
||||||
winhelp.exe
|
winhelp.exe
|
||||||
|
|
||||||
@MAKE_RULES@
|
@MAKE_RULES@
|
||||||
|
@ -139,12 +141,16 @@ wineconsole.exe$(DLLEXT): wineconsole/wineconsole.exe$(DLLEXT)
|
||||||
winedbg.exe$(DLLEXT): winedbg/winedbg.exe$(DLLEXT)
|
winedbg.exe$(DLLEXT): winedbg/winedbg.exe$(DLLEXT)
|
||||||
$(RM) $@ && $(LN_S) 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)
|
winhelp.exe$(DLLEXT): winhelp/winhelp.exe$(DLLEXT)
|
||||||
$(RM) $@ && $(LN_S) winhelp/winhelp.exe$(DLLEXT) $@
|
$(RM) $@ && $(LN_S) winhelp/winhelp.exe$(DLLEXT) $@
|
||||||
|
|
||||||
wcmd/wcmd.exe$(DLLEXT): wcmd
|
wcmd/wcmd.exe$(DLLEXT): wcmd
|
||||||
wineconsole/wineconsole.exe$(DLLEXT): wineconsole
|
wineconsole/wineconsole.exe$(DLLEXT): wineconsole
|
||||||
winedbg/winedbg.exe$(DLLEXT): winedbg
|
winedbg/winedbg.exe$(DLLEXT): winedbg
|
||||||
|
winevdm/winevdm.exe$(DLLEXT): winevdm
|
||||||
winhelp/winhelp.exe$(DLLEXT): winhelp
|
winhelp/winhelp.exe$(DLLEXT): winhelp
|
||||||
|
|
||||||
### Dependencies:
|
### Dependencies:
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Makefile
|
||||||
|
winevdm.exe.dbg.c
|
||||||
|
winevdm.exe.spec.c
|
|
@ -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:
|
|
@ -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;
|
||||||
|
}
|
|
@ -572,11 +572,11 @@ static void start_process(void)
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* PROCESS_InitWine
|
* __wine_process_init
|
||||||
*
|
*
|
||||||
* Wine initialisation: load and start the main exe file.
|
* 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;
|
char error[1024], *p;
|
||||||
DWORD stack_size = 0;
|
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_WIN16:
|
||||||
case BINARY_DOS:
|
case BINARY_DOS:
|
||||||
TRACE( "starting Win16/DOS binary %s\n", debugstr_a(main_exe_name) );
|
TRACE( "starting Win16/DOS binary %s\n", debugstr_a(main_exe_name) );
|
||||||
NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
|
CloseHandle( main_exe_file );
|
||||||
current_process.flags |= PDB32_WIN16_PROC;
|
|
||||||
strcpy( win16_exe_name, main_exe_name );
|
|
||||||
main_exe_name[0] = 0;
|
|
||||||
*win16_exe_file = main_exe_file;
|
|
||||||
main_exe_file = 0;
|
main_exe_file = 0;
|
||||||
_EnterWin16Lock();
|
argv--;
|
||||||
goto found;
|
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:
|
case BINARY_OS216:
|
||||||
MESSAGE( "%s: '%s' is an OS/2 binary, not supported\n", argv0, main_exe_name );
|
MESSAGE( "%s: '%s' is an OS/2 binary, not supported\n", argv0, main_exe_name );
|
||||||
ExitProcess(1);
|
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
|
* get_file_name
|
||||||
*
|
*
|
||||||
|
@ -1310,12 +1337,16 @@ BOOL WINAPI CreateProcessA( LPCSTR app_name, LPSTR cmd_line, LPSECURITY_ATTRIBUT
|
||||||
switch( MODULE_GetBinaryType( hFile ))
|
switch( MODULE_GetBinaryType( hFile ))
|
||||||
{
|
{
|
||||||
case BINARY_PE_EXE:
|
case BINARY_PE_EXE:
|
||||||
case BINARY_WIN16:
|
TRACE( "starting %s as Win32 binary\n", debugstr_a(name) );
|
||||||
case BINARY_DOS:
|
|
||||||
TRACE( "starting %s as Windows binary\n", debugstr_a(name) );
|
|
||||||
retv = create_process( hFile, name, tidy_cmdline, env, process_attr, thread_attr,
|
retv = create_process( hFile, name, tidy_cmdline, env, process_attr, thread_attr,
|
||||||
inherit, flags, startup_info, info, unixdir );
|
inherit, flags, startup_info, info, unixdir );
|
||||||
break;
|
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:
|
case BINARY_OS216:
|
||||||
FIXME( "%s is OS/2 binary, not supported\n", debugstr_a(name) );
|
FIXME( "%s is OS/2 binary, not supported\n", debugstr_a(name) );
|
||||||
SetLastError( ERROR_BAD_EXE_FORMAT );
|
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" ))
|
if (!FILE_strcasecmp( p, ".com" ))
|
||||||
{
|
{
|
||||||
TRACE( "starting %s as DOS binary\n", debugstr_a(name) );
|
TRACE( "starting %s as DOS binary\n", debugstr_a(name) );
|
||||||
retv = create_process( hFile, name, tidy_cmdline, env, process_attr, thread_attr,
|
retv = create_vdm_process( name, tidy_cmdline, env, process_attr, thread_attr,
|
||||||
inherit, flags, startup_info, info, unixdir );
|
inherit, flags, startup_info, info, unixdir );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!FILE_strcasecmp( p, ".bat" ))
|
if (!FILE_strcasecmp( p, ".bat" ))
|
||||||
|
|
Loading…
Reference in New Issue