From: Mykola Mykhno <klimmihno5+wine+gitlab@gmail.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=37789 --- programs/cmd/tests/test_cmdline.cmd | 8 ++++++++ programs/cmd/tests/test_cmdline.cmd.exp | 2 ++ programs/cmd/wcmdmain.c | 20 ++++++++++++++------ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/programs/cmd/tests/test_cmdline.cmd b/programs/cmd/tests/test_cmdline.cmd index 8f3143d0700..a31c248012d 100644 --- a/programs/cmd/tests/test_cmdline.cmd +++ b/programs/cmd/tests/test_cmdline.cmd @@ -101,6 +101,8 @@ echo @echo 2 > "saytwo.bat" echo @echo 3 > "say (3).bat" echo @echo 4 > "say .bat" echo @echo 5 > "bazbaz(5).bat" +mkdir "foo (1)" +echo @echo 6 > "foo (1)\saysix.bat" echo ------ Testing invocation of batch files ---------- call say one @@ -145,6 +147,9 @@ cmd /c s"aytwo if errorlevel 2 echo error %ErrorLevel% cmd /c say (3) call :setError 0 +cmd /c "say (3)" +if errorlevel 2 echo error %ErrorLevel% +call :setError 0 cmd /c say" (3)" if errorlevel 2 echo error %ErrorLevel% call :setError 0 @@ -155,6 +160,7 @@ rem Deliberately invoking a fully qualified batch name containing a bracket rem should fail, as a bracket is a command delimiter. cmd /c "bazbaz(5).bat" if errorlevel 1 echo Passed +cmd /c "foo (1)\saysix.bat" echo ---------- Testing CMD /C quoting ----------------- cmd /c @echo "hi" @@ -284,6 +290,8 @@ call tell(12(34) call tell(12;34) echo --------- Finished -------------- del tell.bat say*.* bazbaz*.bat +del "foo (1)\saysix.bat" +rmdir "foo (1)" exit :setError exit /B %1 diff --git a/programs/cmd/tests/test_cmdline.cmd.exp b/programs/cmd/tests/test_cmdline.cmd.exp index cb9d306b487..e431bb14d85 100644 --- a/programs/cmd/tests/test_cmdline.cmd.exp +++ b/programs/cmd/tests/test_cmdline.cmd.exp @@ -71,8 +71,10 @@ var=33@space@ 2@space@ 0@space@ 3@space@ +3@space@ 4@space@ Passed +6@space@ ---------- Testing CMD /C quoting ----------------- "hi" 1@space@ diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 4aec2e882e9..4f38ebafd31 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -59,6 +59,7 @@ int errorlevel; WCHAR quals[MAXSTRING], param1[MAXSTRING], param2[MAXSTRING]; FOR_CONTEXT *forloopcontext; /* The 'for' loop context */ BOOL delayedsubst = FALSE; /* The current delayed substitution setting */ +RTL_OSVERSIONINFOEXW os_version; WCHAR anykey[100], version_string[100]; @@ -4842,6 +4843,9 @@ static void parse_command_line_parameters(struct cmd_parameters *parameters) if (parameters->opt_c || parameters->opt_k) { WCHAR *q1 = NULL, *q2 = NULL, *p; + BOOL is_version_before_64_bit_support = (os_version.dwMajorVersion < 6) || + (os_version.dwMajorVersion == 5 && os_version.dwMinorVersion <= 1); + WCHAR illegal_characters[9] = L"&<>@^'"; /* Take a copy */ parameters->initial_command = xstrdupW(arg); @@ -4849,8 +4853,13 @@ static void parse_command_line_parameters(struct cmd_parameters *parameters) /* opt_s left unflagged if the command starts with and contains exactly * one quoted string (exactly two quote characters). The quoted string * must be an executable name that has whitespace and must not have the - * following characters: &<>()@^| + * following characters: + * &<>()@^| - prior 5.2 version (only 32-bit systems supported) + * &<>@^| - after 5.2 version (64-bit support added) */ + if (is_version_before_64_bit_support) { + wcscat(illegal_characters, L"()"); + } /* 1. Confirm there is at least one quote */ if (!opt_s && !(q1 = wcschr(arg, L'"'))) opt_s = TRUE; @@ -4867,7 +4876,7 @@ static void parse_command_line_parameters(struct cmd_parameters *parameters) opt_s = TRUE; for (p = q1; p != q2; p++) { - if (wcschr(L"&<>()@^'", *p)) + if (wcschr(illegal_characters, *p)) { opt_s = TRUE; break; @@ -4902,7 +4911,6 @@ static void parse_command_line_parameters(struct cmd_parameters *parameters) static void WCMD_setup(void) { WCHAR string[MAX_PATH]; - RTL_OSVERSIONINFOEXW osv; char osver[50]; WCHAR *cmd; @@ -4928,12 +4936,12 @@ static void WCMD_setup(void) } /* Get the windows version being emulated */ - osv.dwOSVersionInfoSize = sizeof(osv); - RtlGetVersion(&osv); + os_version.dwOSVersionInfoSize = sizeof(os_version); + RtlGetVersion(&os_version); /* Pre initialize some messages */ lstrcpyW(anykey, WCMD_LoadMessage(WCMD_ANYKEY)); - sprintf(osver, "%ld.%ld.%ld", osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber); + sprintf(osver, "%ld.%ld.%ld", os_version.dwMajorVersion, os_version.dwMinorVersion, os_version.dwBuildNumber); cmd = WCMD_format_string(WCMD_LoadMessage(WCMD_VERSION), osver); lstrcpyW(version_string, cmd); LocalFree(cmd); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10797