2 * Wine virtual DOS machine
4 * Copyright 2003 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/winbase16.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(winevdm);
31 extern void WINAPI wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline );
34 /***********************************************************************
37 * Build the command line of a process from the argv array.
38 * Copied from ENV_BuildCommandLine.
40 static char *build_command_line( char **argv )
43 char *p, **arg, *cmd_line;
46 for (arg = argv; *arg; arg++)
54 if( !*a ) has_space=1;
59 if (*a==' ' || *a=='\t') {
62 /* doubling of '\' preceeding a '"',
63 * plus escaping of said '"'
71 len+=(a-*arg)+1 /* for the separating space */;
73 len+=2; /* for the quotes */
76 if (!(cmd_line = HeapAlloc( GetProcessHeap(), 0, len ? len + 1 : 2 )))
80 *p++ = (len < 256) ? len : 255;
81 for (arg = argv; *arg; arg++)
83 int has_space,has_quote;
86 /* Check for quotes and spaces in this argument */
87 has_space=has_quote=0;
89 if( !*a ) has_space=1;
91 if (*a==' ' || *a=='\t') {
103 /* Now transfer it to the command line */
120 /* Double all the '\\' preceeding this '"', plus one */
121 for (i=0;i<=bcount;i++)
139 if (len) p--; /* remove last space */
145 /***********************************************************************
148 static void usage(void)
150 WINE_MESSAGE( "Usage: winevdm.exe [--app-name app.exe] command line\n\n" );
155 /***********************************************************************
158 int main( int argc, char *argv[] )
161 HINSTANCE16 instance;
164 char buffer[MAX_PATH];
166 char *cmdline, *appname, **first_arg;
168 if (!argv[1]) usage();
170 if (!strcmp( argv[1], "--app-name" ))
172 if (!(appname = argv[2])) usage();
173 first_arg = argv + 3;
177 if (!SearchPathA( NULL, argv[1], ".exe", sizeof(buffer), buffer, NULL ))
179 WINE_MESSAGE( "winevdm: can't exec '%s': file not found\n", argv[1] );
183 first_arg = argv + 1;
186 if (*first_arg) first_arg++; /* skip program name */
187 cmdline = build_command_line( first_arg );
189 if (WINE_TRACE_ON(winevdm))
192 WINE_TRACE( "GetCommandLine = '%s'\n", GetCommandLineA() );
193 WINE_TRACE( "appname = '%s'\n", appname );
194 WINE_TRACE( "cmdline = '%.*s'\n", cmdline[0], cmdline+1 );
195 for (i = 0; argv[i]; i++) WINE_TRACE( "argv[%d]: '%s'\n", i, argv[i] );
198 GetStartupInfoA( &info );
200 showCmd[1] = (info.dwFlags & STARTF_USESHOWWINDOW) ? info.wShowWindow : SW_SHOWNORMAL;
202 params.hEnvironment = 0;
203 params.cmdLine = MapLS( cmdline );
204 params.showCmd = MapLS( showCmd );
207 RestoreThunkLock(1); /* grab the Win16 lock */
209 /* some programs assume mmsystem is always present */
210 LoadLibrary16( "mmsystem.dll" );
212 /* make sure system drivers are loaded */
213 LoadLibrary16( "comm.drv" );
214 LoadLibrary16( "display.drv" );
215 LoadLibrary16( "keyboard.drv" );
216 LoadLibrary16( "mouse.drv" );
218 if ((instance = LoadModule16( appname, ¶ms )) < 32)
220 if (instance == 11) /* try DOS format */
222 /* loader expects arguments to be regular C strings */
223 wine_load_dos_exe( appname, cmdline + 1 );
224 /* if we get back here it failed */
225 instance = GetLastError();
228 WINE_MESSAGE( "winevdm: can't exec '%s': ", appname );
231 case 2: WINE_MESSAGE("file not found\n" ); break;
232 case 11: WINE_MESSAGE("invalid exe file\n" ); break;
233 default: WINE_MESSAGE("error=%d\n", instance ); break;
235 ExitProcess(instance);
238 /* wait forever; the process will be killed when the last task exits */
239 ReleaseThunkLock( &count );