Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/wineconsole/Makefile.in | 3 - programs/wineconsole/wineconsole.c | 95 ++++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 7 deletions(-)
diff --git a/programs/wineconsole/Makefile.in b/programs/wineconsole/Makefile.in index b859ef8a27a..08ad51d2b6a 100644 --- a/programs/wineconsole/Makefile.in +++ b/programs/wineconsole/Makefile.in @@ -1,6 +1,5 @@ MODULE = wineconsole.exe -IMPORTS = advapi32 -DELAYIMPORTS = comctl32 user32 gdi32 +DELAYIMPORTS = user32
EXTRADLLFLAGS = -mwindows -municode
diff --git a/programs/wineconsole/wineconsole.c b/programs/wineconsole/wineconsole.c index 1924bf791e6..c703127c238 100644 --- a/programs/wineconsole/wineconsole.c +++ b/programs/wineconsole/wineconsole.c @@ -32,14 +32,101 @@
WINE_DEFAULT_DEBUG_CHANNEL(console);
-int WINAPI wWinMain( HINSTANCE inst, HINSTANCE prev, WCHAR *cmdline, INT show ) +static const unsigned int EC_INTERNAL = 255; /* value of exit_code for internal errors */ + +/*********************************************************************** + * build_command_line + * + * Build the command line of a process from the argv array. + * (copied from dlls/ntdll/unix/env.c) + * + * We must quote and escape characters so that the argv array can be rebuilt + * from the command line: + * - spaces and tabs must be quoted + * 'a b' -> '"a b"' + * - quotes must be escaped + * '"' -> '"' + * - if ''s are followed by a '"', they must be doubled and followed by '"', + * resulting in an odd number of '' followed by a '"' + * '"' -> '\"' + * '\"' -> '\\"' + * - ''s are followed by the closing '"' must be doubled, + * resulting in an even number of '' followed by a '"' + * ' ' -> '" \"' + * ' \' -> '" \\"' + * - ''s that are not followed by a '"' can be left as is + * 'a\b' == 'a\b' + * 'a\b' == 'a\b' + */ +static WCHAR *build_command_line( WCHAR **wargv ) +{ + int len; + WCHAR **arg, *ret; + LPWSTR p; + + len = 1; + for (arg = wargv; *arg; arg++) len += 3 + 2 * wcslen( *arg ); + if (!(ret = malloc( len * sizeof(WCHAR) ))) return NULL; + + p = ret; + for (arg = wargv; *arg; arg++) + { + BOOL has_space, has_quote; + int i, bcount; + WCHAR *a; + + /* check for quotes and spaces in this argument (first arg is always quoted) */ + has_space = (arg == wargv) || !**arg || wcschr( *arg, ' ' ) || wcschr( *arg, '\t' ); + has_quote = wcschr( *arg, '"' ) != NULL; + + /* now transfer it to the command line */ + if (has_space) *p++ = '"'; + if (has_quote || has_space) + { + bcount = 0; + for (a = *arg; *a; a++) + { + if (*a == '\') bcount++; + else + { + if (*a == '"') /* double all the '\' preceding this '"', plus one */ + for (i = 0; i <= bcount; i++) *p++ = '\'; + bcount = 0; + } + *p++ = *a; + } + } + else + { + wcscpy( p, *arg ); + p += wcslen( p ); + } + if (has_space) + { + /* Double all the '' preceding the closing quote */ + for (i = 0; i < bcount; i++) *p++ = '\'; + *p++ = '"'; + } + *p++ = ' '; + } + if (p > ret) p--; /* remove last space */ + *p = 0; + if (p - ret >= 32767) + { + ERR( "command line too long (%Iu)\n", p - ret ); + exit( EC_INTERNAL ); + } + return ret; +} + +int wmain( int argc, WCHAR *argv[] ) { STARTUPINFOW startup = { sizeof(startup) }; PROCESS_INFORMATION info; - WCHAR *cmd = cmdline; + WCHAR *cmd; DWORD exit_code;
- static WCHAR default_cmd[] = L"cmd"; + cmd = argc > 1 ? build_command_line( &argv[1] ) : wcsdup( L"cmd.exe" );
FreeConsole(); /* make sure we're not connected to inherited console */ if (!AllocConsole()) @@ -48,8 +135,6 @@ int WINAPI wWinMain( HINSTANCE inst, HINSTANCE prev, WCHAR *cmdline, INT show ) return 1; }
- if (!*cmd) cmd = default_cmd; - startup.dwFlags = STARTF_USESTDHANDLES; startup.hStdInput = CreateFileW( L"CONIN$", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );