Module: wine Branch: master Commit: 036f4dca3c7f9ee8964bb4ae0c4bcd106a347c7b URL: https://source.winehq.org/git/wine.git/?a=commit;h=036f4dca3c7f9ee8964bb4ae0...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Apr 8 15:09:00 2020 +0200
winecrt0: Rebuild the argv array instead of getting it from libwine.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/winecrt0/exe_entry.c | 78 +++++++++++++++++++++++++++++++++++----------- dlls/winecrt0/exe_wentry.c | 68 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 21 deletions(-)
diff --git a/dlls/winecrt0/exe_entry.c b/dlls/winecrt0/exe_entry.c index 9ae45f9f04..803d56e10e 100644 --- a/dlls/winecrt0/exe_entry.c +++ b/dlls/winecrt0/exe_entry.c @@ -25,43 +25,83 @@ #include <stdarg.h> #include "windef.h" #include "winbase.h" -#include "winnls.h" #include "winternl.h" -#include "wine/library.h" #include "crt0_private.h"
extern int __cdecl main( int argc, char *argv[] );
-static char **build_argv( WCHAR **wargv ) +static char **build_argv( const char *src, int *ret_argc ) { - int argc; - char *p, **argv; - DWORD total = 0; - - for (argc = 0; wargv[argc]; argc++) - total += WideCharToMultiByte( CP_ACP, 0, wargv[argc], -1, NULL, 0, NULL, NULL ); + char **argv, *arg, *dst; + int argc, in_quotes = 0, bcount = 0, len = strlen(src) + 1;
- argv = HeapAlloc( GetProcessHeap(), 0, total + (argc + 1) * sizeof(*argv) ); - p = (char *)(argv + argc + 1); - for (argc = 0; wargv[argc]; argc++) + argc = 2 + len / 2; + argv = HeapAlloc( GetProcessHeap(), 0, argc * sizeof(*argv) + len ); + arg = dst = (char *)(argv + argc); + argc = 0; + while (*src) { - DWORD reslen = WideCharToMultiByte( CP_ACP, 0, wargv[argc], -1, p, total, NULL, NULL ); - argv[argc] = p; - p += reslen; - total -= reslen; + if ((*src == ' ' || *src == '\t') && !in_quotes) + { + /* skip the remaining spaces */ + while (*src == ' ' || *src == '\t') src++; + if (!*src) break; + /* close the argument and copy it */ + *dst++ = 0; + argv[argc++] = arg; + /* start with a new argument */ + arg = dst; + bcount = 0; + } + else if (*src == '\') + { + *dst++ = *src++; + bcount++; + } + else if (*src == '"') + { + if ((bcount & 1) == 0) + { + /* Preceded by an even number of '', this is half that + * number of '', plus a '"' which we discard. + */ + dst -= bcount / 2; + src++; + if (in_quotes && *src == '"') *dst++ = *src++; + else in_quotes = !in_quotes; + } + else + { + /* Preceded by an odd number of '', this is half that + * number of '' followed by a '"' + */ + dst -= bcount / 2 + 1; + *dst++ = *src++; + } + bcount = 0; + } + else /* a regular character */ + { + *dst++ = *src++; + bcount = 0; + } } + *dst = 0; + argv[argc++] = arg; argv[argc] = NULL; + *ret_argc = argc; return argv; }
DWORD WINAPI DECLSPEC_HIDDEN __wine_spec_exe_entry( PEB *peb ) { + int argc; BOOL needs_init = (__wine_spec_init_state != CONSTRUCTORS_DONE); - char **argv = build_argv( __wine_main_wargv ); + char **argv = build_argv( GetCommandLineA(), &argc ); DWORD ret;
- if (needs_init) _init( __wine_main_argc, argv, NULL ); - ret = main( __wine_main_argc, argv ); + if (needs_init) _init( argc, argv, NULL ); + ret = main( argc, argv ); if (needs_init) _fini(); ExitProcess( ret ); } diff --git a/dlls/winecrt0/exe_wentry.c b/dlls/winecrt0/exe_wentry.c index b889e5a102..b01bfd6210 100644 --- a/dlls/winecrt0/exe_wentry.c +++ b/dlls/winecrt0/exe_wentry.c @@ -26,18 +26,82 @@ #include "windef.h" #include "winbase.h" #include "winternl.h" -#include "wine/library.h" #include "crt0_private.h"
extern int __cdecl wmain( int argc, WCHAR *argv[] );
+static WCHAR **build_argv( const WCHAR *src, int *ret_argc ) +{ + WCHAR **argv, *arg, *dst; + int argc, in_quotes = 0, bcount = 0, len = lstrlenW(src) + 1; + + argc = 2 + len / 2; + argv = HeapAlloc( GetProcessHeap(), 0, argc * sizeof(*argv) + len * sizeof(WCHAR) ); + arg = dst = (WCHAR *)(argv + argc); + argc = 0; + while (*src) + { + if ((*src == ' ' || *src == '\t') && !in_quotes) + { + /* skip the remaining spaces */ + while (*src == ' ' || *src == '\t') src++; + if (!*src) break; + /* close the argument and copy it */ + *dst++ = 0; + argv[argc++] = arg; + /* start with a new argument */ + arg = dst; + bcount = 0; + } + else if (*src == '\') + { + *dst++ = *src++; + bcount++; + } + else if (*src == '"') + { + if ((bcount & 1) == 0) + { + /* Preceded by an even number of '', this is half that + * number of '', plus a '"' which we discard. + */ + dst -= bcount / 2; + src++; + if (in_quotes && *src == '"') *dst++ = *src++; + else in_quotes = !in_quotes; + } + else + { + /* Preceded by an odd number of '', this is half that + * number of '' followed by a '"' + */ + dst -= bcount / 2 + 1; + *dst++ = *src++; + } + bcount = 0; + } + else /* a regular character */ + { + *dst++ = *src++; + bcount = 0; + } + } + *dst = 0; + argv[argc++] = arg; + argv[argc] = NULL; + *ret_argc = argc; + return argv; +} + DWORD WINAPI DECLSPEC_HIDDEN __wine_spec_exe_wentry( PEB *peb ) { + int argc; BOOL needs_init = (__wine_spec_init_state != CONSTRUCTORS_DONE); + WCHAR **argv = build_argv( GetCommandLineW(), &argc ); DWORD ret;
if (needs_init) _init( 0, NULL, NULL ); - ret = wmain( __wine_main_argc, __wine_main_wargv ); + ret = wmain( argc, argv ); if (needs_init) _fini(); ExitProcess( ret ); }