kernel32: Allow double quote style escape in argv.

Two quotes together (within outer quotes) represents a single
quote (with the first quote acting as an escape character)

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46721
Signed-off-by: Brendan McGrath <brendan@redmandi.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Brendan McGrath 2019-02-26 19:39:25 +11:00 committed by Alexandre Julliard
parent 922049a21d
commit 87917df887
3 changed files with 30 additions and 11 deletions

View File

@ -1505,9 +1505,13 @@ static char **build_argv( const UNICODE_STRING *cmdlineW, int reserved )
/* '\', count them */ /* '\', count them */
bcount++; bcount++;
} else if ((*s=='"') && ((bcount & 1)==0)) { } else if ((*s=='"') && ((bcount & 1)==0)) {
/* unescaped '"' */ if (in_quotes && s[1] == '"') {
in_quotes=!in_quotes; s++;
bcount=0; } else {
/* unescaped '"' */
in_quotes=!in_quotes;
bcount=0;
}
} else { } else {
/* a regular character */ /* a regular character */
bcount=0; bcount=0;
@ -1551,7 +1555,12 @@ static char **build_argv( const UNICODE_STRING *cmdlineW, int reserved )
*/ */
d-=bcount/2; d-=bcount/2;
s++; s++;
in_quotes=!in_quotes; if(in_quotes && *s == '"') {
*d++='"';
s++;
} else {
in_quotes=!in_quotes;
}
} else { } else {
/* Preceded by an odd number of '\', this is half that /* Preceded by an odd number of '\', this is half that
* number of '\' followed by a '"' * number of '\' followed by a '"'

View File

@ -896,7 +896,7 @@ static void test_CommandLine(void)
/* the basics */ /* the basics */
get_file_name(resfile); get_file_name(resfile);
sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" \"C:\\Program Files\\my nice app.exe\"", selfname, resfile); sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" \"C:\\Program Files\\my nice app.exe\" \"\"\"\"", selfname, resfile);
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
/* wait for child to terminate */ /* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@ -905,9 +905,10 @@ static void test_CommandLine(void)
CloseHandle(info.hThread); CloseHandle(info.hThread);
CloseHandle(info.hProcess); CloseHandle(info.hProcess);
okChildInt("Arguments", "argcA", 5); okChildInt("Arguments", "argcA", 6);
okChildString("Arguments", "argvA4", "C:\\Program Files\\my nice app.exe"); okChildString("Arguments", "argvA4", "C:\\Program Files\\my nice app.exe");
okChildString("Arguments", "argvA5", NULL); okChildString("Arguments", "argvA5", "\"");
okChildString("Arguments", "argvA6", NULL);
okChildString("Arguments", "CommandLineA", buffer); okChildString("Arguments", "CommandLineA", buffer);
release_memory(); release_memory();
DeleteFileA(resfile); DeleteFileA(resfile);

View File

@ -815,9 +815,13 @@ static char **build_argv( const UNICODE_STRING *cmdlineW, int reserved )
else if (*s == '\\') bcount++; /* '\', count them */ else if (*s == '\\') bcount++; /* '\', count them */
else if ((*s == '"') && ((bcount & 1) == 0)) else if ((*s == '"') && ((bcount & 1) == 0))
{ {
/* unescaped '"' */ if (in_quotes && s[1] == '"') s++;
in_quotes = !in_quotes; else
bcount = 0; {
/* unescaped '"' */
in_quotes = !in_quotes;
bcount = 0;
}
} }
else bcount = 0; /* a regular character */ else bcount = 0; /* a regular character */
s++; s++;
@ -864,7 +868,12 @@ static char **build_argv( const UNICODE_STRING *cmdlineW, int reserved )
*/ */
d -= bcount/2; d -= bcount/2;
s++; s++;
in_quotes = !in_quotes; if (in_quotes && *s == '"')
{
*d++ = '"';
s++;
}
else in_quotes = !in_quotes;
} }
else else
{ {