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
);