msvcrt: Rebuild the argv array instead of getting it from libwine.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Alexandre Julliard 2020-04-08 15:09:26 +02:00
parent 036f4dca3c
commit e9d2b31c87
1 changed files with 81 additions and 16 deletions

View File

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