Module: wine Branch: master Commit: e9d2b31c87ef9195280ebaa6c21855e7ad19e747 URL: https://source.winehq.org/git/wine.git/?a=commit;h=e9d2b31c87ef9195280ebaa6c...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Apr 8 15:09:26 2020 +0200
msvcrt: Rebuild the argv array instead of getting it from libwine.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/msvcrt/data.c | 97 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 16 deletions(-)
diff --git a/dlls/msvcrt/data.c b/dlls/msvcrt/data.c index 9cc380f74a..26fb4a4510 100644 --- a/dlls/msvcrt/data.c +++ b/dlls/msvcrt/data.c @@ -23,12 +23,13 @@
#include <math.h> #include "msvcrt.h" -#include "wine/library.h" #include "wine/unicode.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
+static WCHAR **initial_wargv; +static int initial_argc; int MSVCRT___argc = 0; static int wargc_expand; unsigned int MSVCRT__commode = 0; @@ -159,6 +160,69 @@ static char **build_argv( WCHAR **wargv ) return argv; }
+static WCHAR **cmdline_to_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; +} + typedef void (CDECL *_INITTERMFUN)(void); typedef int (CDECL *_INITTERM_E_FN)(void);
@@ -348,9 +412,10 @@ void msvcrt_init_args(void)
MSVCRT__acmdln = MSVCRT__strdup( GetCommandLineA() ); MSVCRT__wcmdln = MSVCRT__wcsdup( GetCommandLineW() ); - MSVCRT___argc = __wine_main_argc; - MSVCRT___wargv = __wine_main_wargv; - MSVCRT___argv = build_argv( MSVCRT___wargv ); + initial_wargv = cmdline_to_argv( GetCommandLineW(), &initial_argc ); + MSVCRT___argc = initial_argc; + MSVCRT___wargv = initial_wargv; + MSVCRT___argv = build_argv( initial_wargv );
TRACE("got %s, wide = %s argc=%d\n", debugstr_a(MSVCRT__acmdln), debugstr_w(MSVCRT__wcmdln),MSVCRT___argc); @@ -419,21 +484,21 @@ static int build_expanded_wargv(int *argc, MSVCRT_wchar_t **argv) HANDLE h;
args_no = 0; - for(i=0; i<__wine_main_argc; i++) { + for(i=0; i < initial_argc; i++) { WIN32_FIND_DATAW data; int len = 0;
is_expandable = FALSE; - for(path_len = strlenW(__wine_main_wargv[i])-1; path_len>=0; path_len--) { - if(__wine_main_wargv[i][path_len]=='*' || __wine_main_wargv[i][path_len]=='?') + for(path_len = strlenW(initial_wargv[i])-1; path_len>=0; path_len--) { + if(initial_wargv[i][path_len]=='*' || initial_wargv[i][path_len]=='?') is_expandable = TRUE; - else if(__wine_main_wargv[i][path_len]=='\' || __wine_main_wargv[i][path_len]=='/') + else if(initial_wargv[i][path_len]=='\' || initial_wargv[i][path_len]=='/') break; } path_len++;
if(is_expandable) - h = FindFirstFileW(__wine_main_wargv[i], &data); + h = FindFirstFileW(initial_wargv[i], &data); else h = INVALID_HANDLE_VALUE;
@@ -446,7 +511,7 @@ static int build_expanded_wargv(int *argc, MSVCRT_wchar_t **argv) len = strlenW(data.cFileName)+1; if(argv) { argv[args_no] = (MSVCRT_wchar_t*)(argv+*argc+1)+size; - memcpy(argv[args_no], __wine_main_wargv[i], path_len*sizeof(MSVCRT_wchar_t)); + memcpy(argv[args_no], initial_wargv[i], path_len*sizeof(MSVCRT_wchar_t)); memcpy(argv[args_no]+path_len, data.cFileName, len*sizeof(MSVCRT_wchar_t)); } args_no++; @@ -456,10 +521,10 @@ static int build_expanded_wargv(int *argc, MSVCRT_wchar_t **argv) }
if(!len) { - len = strlenW(__wine_main_wargv[i])+1; + len = strlenW(initial_wargv[i])+1; if(argv) { argv[args_no] = (MSVCRT_wchar_t*)(argv+*argc+1)+size; - memcpy(argv[args_no], __wine_main_wargv[i], len*sizeof(MSVCRT_wchar_t)); + memcpy(argv[args_no], initial_wargv[i], len*sizeof(MSVCRT_wchar_t)); } args_no++; size += len; @@ -496,8 +561,8 @@ int CDECL __wgetmainargs(int *argc, MSVCRT_wchar_t** *wargv, MSVCRT_wchar_t** *w } } if (!expand_wildcards) { - MSVCRT___argc = __wine_main_argc; - MSVCRT___wargv = __wine_main_wargv; + MSVCRT___argc = initial_argc; + MSVCRT___wargv = initial_wargv; }
/* Initialize the _wenviron array if it's not already created. */ @@ -533,8 +598,8 @@ int CDECL __getmainargs(int *argc, char** *argv, char** *envp, } } if (!expand_wildcards) { - MSVCRT___argc = __wine_main_argc; - MSVCRT___argv = build_argv( __wine_main_wargv ); + MSVCRT___argc = initial_argc; + MSVCRT___argv = build_argv( initial_wargv ); }
*argc = MSVCRT___argc;