Skip to content

Commit ff7fdcf

Browse files
committed
[MSVCRT] Fix __gemainargs
- Fix a quote character parsing bug in cmdline_to_argv- Implement ansi version of cmdline_to_argv - Use cmdline_to_argv(A) in __(w)getmainargs to reparse the command line from _(w)cmdln Fixes 30 failures in msvcrt_apitest:__getmainargs
1 parent 326786b commit ff7fdcf

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

dll/win32/msvcrt/data.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,11 @@ static WCHAR **cmdline_to_argv( const WCHAR *src, int *ret_argc )
120120
dst -= bcount / 2;
121121
src++;
122122
if (in_quotes && *src == '"') *dst++ = *src++;
123+
#ifdef __REACTOS__
124+
in_quotes = !in_quotes;
125+
#else
123126
else in_quotes = !in_quotes;
127+
#endif
124128
}
125129
else
126130
{
@@ -145,6 +149,75 @@ static WCHAR **cmdline_to_argv( const WCHAR *src, int *ret_argc )
145149
return argv;
146150
}
147151

152+
#ifdef __REACTOS__
153+
static CHAR **cmdline_to_argvA( const CHAR *src, int *ret_argc )
154+
{
155+
CHAR **argv, *arg, *dst;
156+
int argc, in_quotes = 0, bcount = 0, len = strlen(src) + 1;
157+
158+
argc = 2 + len / 2;
159+
argv = HeapAlloc( GetProcessHeap(), 0, argc * sizeof(*argv) + len * sizeof(CHAR) );
160+
arg = dst = (CHAR *)(argv + argc);
161+
argc = 0;
162+
while (*src)
163+
{
164+
if ((*src == ' ' || *src == '\t') && !in_quotes)
165+
{
166+
/* skip the remaining spaces */
167+
while (*src == ' ' || *src == '\t') src++;
168+
if (!*src) break;
169+
/* close the argument and copy it */
170+
*dst++ = 0;
171+
argv[argc++] = arg;
172+
/* start with a new argument */
173+
arg = dst;
174+
bcount = 0;
175+
}
176+
else if (*src == '\\')
177+
{
178+
*dst++ = *src++;
179+
bcount++;
180+
}
181+
else if (*src == '"')
182+
{
183+
if ((bcount & 1) == 0)
184+
{
185+
/* Preceded by an even number of '\', this is half that
186+
* number of '\', plus a '"' which we discard.
187+
*/
188+
dst -= bcount / 2;
189+
src++;
190+
if (in_quotes && *src == '"') *dst++ = *src++;
191+
#ifdef __REACTOS__
192+
in_quotes = !in_quotes;
193+
#else
194+
else in_quotes = !in_quotes;
195+
#endif
196+
}
197+
else
198+
{
199+
/* Preceded by an odd number of '\', this is half that
200+
* number of '\' followed by a '"'
201+
*/
202+
dst -= bcount / 2 + 1;
203+
*dst++ = *src++;
204+
}
205+
bcount = 0;
206+
}
207+
else /* a regular character */
208+
{
209+
*dst++ = *src++;
210+
bcount = 0;
211+
}
212+
}
213+
*dst = 0;
214+
argv[argc++] = arg;
215+
argv[argc] = NULL;
216+
*ret_argc = argc;
217+
return argv;
218+
}
219+
#endif
220+
148221
typedef void (CDECL *_INITTERMFUN)(void);
149222
typedef int (CDECL *_INITTERM_E_FN)(void);
150223

@@ -479,8 +552,15 @@ int CDECL __wgetmainargs(int *argc, wchar_t** *wargv, wchar_t** *wenvp,
479552
}
480553
}
481554
if (!expand_wildcards) {
555+
#ifdef __REACTOS__
556+
if ((MSVCRT___wargv == NULL) || (MSVCRT___argc == 0))
557+
{
558+
MSVCRT___wargv = cmdline_to_argv(MSVCRT__wcmdln, &MSVCRT___argc);
559+
}
560+
#else
482561
MSVCRT___argc = initial_argc;
483562
MSVCRT___wargv = initial_wargv;
563+
#endif
484564
}
485565

486566
env_init(TRUE, FALSE);
@@ -515,8 +595,15 @@ int CDECL __getmainargs(int *argc, char** *argv, char** *envp,
515595
}
516596
}
517597
if (!expand_wildcards) {
598+
#ifdef __REACTOS__
599+
if ((MSVCRT___argv == NULL) || (MSVCRT___argc == 0))
600+
{
601+
MSVCRT___argv = cmdline_to_argvA(MSVCRT__acmdln, &MSVCRT___argc);
602+
}
603+
#else
518604
MSVCRT___argc = initial_argc;
519605
MSVCRT___argv = build_argv( initial_wargv );
606+
#endif
520607
}
521608

522609
*argc = MSVCRT___argc;

0 commit comments

Comments
 (0)