Alexandre Julliard : msvcrt: Rebuild the argv array instead of getting it from libwine.
Alexandre Julliard
julliard at winehq.org
Wed Apr 8 15:48:32 CDT 2020
Module: wine
Branch: master
Commit: e9d2b31c87ef9195280ebaa6c21855e7ad19e747
URL: https://source.winehq.org/git/wine.git/?a=commit;h=e9d2b31c87ef9195280ebaa6c21855e7ad19e747
Author: Alexandre Julliard <julliard at 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 at 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;
More information about the wine-cvs
mailing list