These patches are meant to fix batch files that are using quoted arguments like this:
start /D "%~dp0" game.exe %*
cmd adds extra quotes around directory path, assuming it's a console title. Later this does not work with start.exe.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- programs/cmd/builtins.c | 53 +++++++++++++---------------------------- 1 file changed, 17 insertions(+), 36 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index dd3ae5b509b..afbbf682772 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -4371,10 +4371,10 @@ void WCMD_shift (const WCHAR *args) { */ void WCMD_start(WCHAR *args) { - int argno; int have_title; WCHAR file[MAX_PATH]; WCHAR *cmdline, *cmdline_params; + WCHAR *thisArg, *argN = NULL; STARTUPINFOW st; PROCESS_INFORMATION pi;
@@ -4419,46 +4419,27 @@ void WCMD_start(WCHAR *args) * WCMD_parameter_with_delims will take care of everything for us. */ have_title = FALSE; - for (argno=0; ; argno++) { - WCHAR *thisArg, *argN; - - argN = NULL; - thisArg = WCMD_parameter_with_delims(args, argno, &argN, FALSE, FALSE, L" \t/"); - - /* No more parameters */ - if (!argN) - break; - - /* Found the title */ - if (argN[0] == '"') { - TRACE("detected console title: %s\n", wine_dbgstr_w(thisArg)); - have_title = TRUE;
- /* Copy all of the cmdline processed */ - memcpy(cmdline_params, args, sizeof(WCHAR) * (argN - args)); - cmdline_params[argN - args] = '\0'; + argN = NULL; + thisArg = WCMD_parameter_with_delims(args, 0, &argN, FALSE, FALSE, L" \t/");
- /* Add quoted title */ - lstrcatW(cmdline_params, L""\""); - lstrcatW(cmdline_params, thisArg); - lstrcatW(cmdline_params, L"\"""); + if (argN && *argN == '"') + { + TRACE("detected console title: %s\n", wine_dbgstr_w(thisArg)); + have_title = TRUE;
- /* Concatenate remaining command-line */ - thisArg = WCMD_parameter_with_delims(args, argno, &argN, TRUE, FALSE, L" \t/"); - lstrcatW(cmdline_params, argN + lstrlenW(thisArg)); + /* Copy all of the cmdline processed */ + memcpy(cmdline_params, args, sizeof(WCHAR) * (argN - args)); + cmdline_params[argN - args] = '\0';
- break; - } + /* Add quoted title */ + lstrcatW(cmdline_params, L""\""); + lstrcatW(cmdline_params, thisArg); + lstrcatW(cmdline_params, L"\""");
- /* Skipping a regular argument? */ - else if (argN != args && argN[-1] == '/') { - continue; - - /* Not an argument nor the title, start of program arguments, - * stop looking for title. - */ - } else - break; + /* Concatenate remaining command-line */ + thisArg = WCMD_parameter_with_delims(args, 0, &argN, TRUE, FALSE, L" \t/"); + lstrcatW(cmdline_params, argN + lstrlenW(thisArg)); }
/* build command-line if not built yet */
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- programs/start/start.c | 97 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-)
diff --git a/programs/start/start.c b/programs/start/start.c index 62804917941..505b87b5ce4 100644 --- a/programs/start/start.c +++ b/programs/start/start.c @@ -387,6 +387,98 @@ static BOOL search_path(const WCHAR *firstParam, WCHAR **full_path) return FALSE; }
+static LPWSTR *get_args(LPWSTR cmdline, int *pargc) +{ + enum {OUTSIDE_ARG, INSIDE_ARG, INSIDE_QUOTED_ARG} state; + LPWSTR str; + int argc; + LPWSTR *argv; + int max_argc = 16; + BOOL new_arg; + + WINE_TRACE("cmdline: %s\n", wine_dbgstr_w(cmdline)); + str = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR)); + if(!str) return NULL; + lstrcpyW(str, cmdline); + argv = HeapAlloc(GetProcessHeap(), 0, (max_argc + 1) * sizeof(LPWSTR)); + if(!argv) + { + HeapFree(GetProcessHeap(), 0, str); + return NULL; + } + + /* Split command line to separate arg-strings and fill argv */ + state = OUTSIDE_ARG; + argc = 0; + while(*str) + { + new_arg = FALSE; + /* Check character */ + if(iswspace(*str)) /* white space */ + { + if(state == INSIDE_ARG) + { + state = OUTSIDE_ARG; + *str = 0; + } + } + else if(*str == '"') /* double quote */ + switch(state) + { + case INSIDE_QUOTED_ARG: + state = OUTSIDE_ARG; + *str = 0; + break; + case INSIDE_ARG: + *str = 0; + /* Fall through */ + case OUTSIDE_ARG: + if(!*++str) continue; + state = INSIDE_QUOTED_ARG; + new_arg = TRUE; + break; + } + else /* regular character */ + if(state == OUTSIDE_ARG) + { + state = INSIDE_ARG; + new_arg = TRUE; + } + + /* Add new argv entry, if need */ + if(new_arg) + { + if(argc >= max_argc - 1) + { + /* Realloc argv here because there always should be + at least one reserved cell for terminating NULL */ + max_argc *= 2; + argv = HeapReAlloc(GetProcessHeap(), 0, argv, + (max_argc + 1) * sizeof(LPWSTR)); + if(!argv) + { + HeapFree(GetProcessHeap(), 0, str); + return NULL; + } + } + argv[argc++] = str; + } + + str++; + } + + argv[argc] = NULL; + *pargc = argc; + + if (TRACE_ON(start)) + { + int i; + for(i = 0; i < argc; i++) + WINE_TRACE("arg %d: %s\n", i, wine_dbgstr_w(argv[i])); + } + return argv; +} + int __cdecl wmain (int argc, WCHAR *argv[]) { SHELLEXECUTEINFOW sei; @@ -394,13 +486,16 @@ int __cdecl wmain (int argc, WCHAR *argv[]) int i; BOOL unix_mode = FALSE; BOOL progid_open = FALSE; - WCHAR *title = NULL; + WCHAR *title = NULL, *cmdline; const WCHAR *file; WCHAR *dos_filename = NULL; WCHAR *fullpath = NULL; WCHAR *parent_directory = NULL; DWORD binary_type;
+ cmdline = GetCommandLineW(); + argv = get_args(cmdline, &argc); + memset(&sei, 0, sizeof(sei)); sei.cbSize = sizeof(sei); sei.lpVerb = L"open";
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=125758
Your paranoid android.
=== debian11 (32 bit report) ===
cmd.exe: batch.c:321: Test failed: unexpected char 0x66 position 9 in line 1682 (got 'start /W failed to wait', wanted 'start /W seems to really wait')
urlmon: protocol.c:3682: Test failed: wait timed out protocol: Timeout url: Timeout
=== debian11 (32 bit zh:CN report) ===
cmd.exe: batch.c:321: Test failed: unexpected char 0x66 position 9 in line 1682 (got 'start /W failed to wait', wanted 'start /W seems to really wait')
=== debian11b (64 bit WoW report) ===
cmd.exe: batch.c:321: Test failed: unexpected char 0x66 position 9 in line 1682 (got 'start /W failed to wait', wanted 'start /W seems to really wait')