From: Elizabeth zfigura@codeweavers.com
--- programs/cmd/tests/test_builtins.cmd | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd index 4880470b8bc..6f9e084ae35 100644 --- a/programs/cmd/tests/test_builtins.cmd +++ b/programs/cmd/tests/test_builtins.cmd @@ -581,10 +581,12 @@ call :setError 666 & (erase file* i\dont\exist\at\all.txt &&echo SUCCESS !errorl cd .. && rd /q /s foo
echo --- success/failure for change drive command +pushd C:\ call :setError 666 & (c: &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) call :setError 666 & (1: &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) call :setError 666 & (call c: &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) call :setError 666 & (call 1: &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) +popd
echo --- success/failure for MKDIR,MD command mkdir foo & cd foo
From: Elizabeth zfigura@codeweavers.com
This was introduced in bff25ffe7991bde75904d34ca733f2178b088316.
The commit aimed to fix command lines like `wine cmd /c "notepad test.txt"`. Such de-quoting is now handled at an earlier point.
Moreover, we explicitly only enter this path when we find an executable (which was not the case when the commit was written), so we cannot actually get ERROR_FILE_NOT_FOUND anymore anyway. --- programs/cmd/wcmdmain.c | 8 -------- 1 file changed, 8 deletions(-)
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 2c64785d44a..2fe18c8b391 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1611,14 +1611,6 @@ RETURN_CODE WCMD_run_program(WCHAR *command, BOOL called) status = CreateProcessW(thisDir, command, NULL, NULL, TRUE, 0, NULL, NULL, &st, &pe); free(st.lpReserved2); - if ((opt_c || opt_k) && !opt_s && !status - && GetLastError()==ERROR_FILE_NOT_FOUND && command[0]=='"') { - /* strip first and last quote WCHARacters and try again */ - WCMD_strip_quotes(command); - opt_s = TRUE; - return WCMD_run_program(command, called); - } - if (!status) break;
From: Elizabeth zfigura@codeweavers.com
--- programs/cmd/wcmdmain.c | 117 +++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 61 deletions(-)
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 2fe18c8b391..24b2b75307c 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1376,6 +1376,60 @@ static void init_msvcrt_io_block(STARTUPINFOW* st)
static RETURN_CODE execute_single_command(const WCHAR *command);
+/* Attempt to open a file at a known path. */ +static RETURN_CODE run_full_path(const WCHAR *file, WCHAR *full_cmdline, BOOL called) +{ + const WCHAR *ext = wcsrchr(file, '.'); + STARTUPINFOW si = {.cb = sizeof(si)}; + DWORD console, exit_code; + WCHAR exe_path[MAX_PATH]; + PROCESS_INFORMATION pi; + SHFILEINFOW psfi; + + TRACE("%s\n", debugstr_w(file)); + + if (ext && (!wcsicmp(ext, L".bat") || !wcsicmp(ext, L".cmd"))) + { + RETURN_CODE return_code; + BOOL oldinteractive = interactive; + + interactive = FALSE; + return_code = WCMD_call_batch(file, full_cmdline); + interactive = oldinteractive; + if (context && !called) + { + TRACE("Batch completed, but was not 'called' so skipping outer batch too\n"); + context->skip_rest = TRUE; + } + if (return_code != RETURN_CODE_ABORTED) + errorlevel = return_code; + return return_code; + } + + if ((INT_PTR)FindExecutableW(file, NULL, exe_path) < 32) + console = 0; + else + console = SHGetFileInfoW(exe_path, 0, &psfi, sizeof(psfi), SHGFI_EXETYPE); + + init_msvcrt_io_block(&si); + if (!CreateProcessW(file, full_cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) + { + errorlevel = GetLastError(); + free(si.lpReserved2); + return errorlevel; + } + free(si.lpReserved2); + + if (!interactive || (console && !HIWORD(console))) + WaitForSingleObject(pi.hProcess, INFINITE); + GetExitCodeProcess(pi.hProcess, &exit_code); + errorlevel = (exit_code == STILL_ACTIVE) ? NO_ERROR : exit_code; + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return errorlevel; +} + /****************************************************************************** * WCMD_run_program * @@ -1414,7 +1468,6 @@ RETURN_CODE WCMD_run_program(WCHAR *command, BOOL called) WCHAR *firstParam; BOOL extensionsupplied = FALSE; BOOL explicit_path = FALSE; - BOOL status; DWORD len;
/* Quick way to get the filename is to extract the first argument. */ @@ -1566,66 +1619,8 @@ RETURN_CODE WCMD_run_program(WCHAR *command, BOOL called) } }
- /* Once found, launch it */ - if (found) { - STARTUPINFOW st; - PROCESS_INFORMATION pe; - SHFILEINFOW psfi; - DWORD console; - HINSTANCE hinst; - WCHAR *ext = wcsrchr( thisDir, '.' ); - - WINE_TRACE("Found as %s\n", wine_dbgstr_w(thisDir)); - - /* Special case BAT and CMD */ - if (ext && (!wcsicmp(ext, L".bat") || !wcsicmp(ext, L".cmd"))) { - RETURN_CODE return_code; - BOOL oldinteractive = interactive; - - interactive = FALSE; - return_code = WCMD_call_batch(thisDir, command); - interactive = oldinteractive; - if (context && !called) { - TRACE("Batch completed, but was not 'called' so skipping outer batch too\n"); - context->skip_rest = TRUE; - } - if (return_code != RETURN_CODE_ABORTED) - errorlevel = return_code; - return return_code; - } else { - DWORD exit_code; - /* thisDir contains the file to be launched, but with what? - eg. a.exe will require a.exe to be launched, a.html may be iexplore */ - hinst = FindExecutableW (thisDir, NULL, temp); - if ((INT_PTR)hinst < 32) - console = 0; - else - console = SHGetFileInfoW(temp, 0, &psfi, sizeof(psfi), SHGFI_EXETYPE); - - ZeroMemory (&st, sizeof(STARTUPINFOW)); - st.cb = sizeof(STARTUPINFOW); - init_msvcrt_io_block(&st); - - /* Launch the process and if a CUI wait on it to complete - Note: Launching internal wine processes cannot specify a full path to exe */ - status = CreateProcessW(thisDir, - command, NULL, NULL, TRUE, 0, NULL, NULL, &st, &pe); - free(st.lpReserved2); - if (!status) - break; - - /* Always wait when non-interactive (cmd /c or in batch program), - or for console applications */ - if (!interactive || (console && !HIWORD(console))) - WaitForSingleObject (pe.hProcess, INFINITE); - GetExitCodeProcess (pe.hProcess, &exit_code); - errorlevel = (exit_code == STILL_ACTIVE) ? NO_ERROR : exit_code; - - CloseHandle(pe.hProcess); - CloseHandle(pe.hThread); - return errorlevel; - } - } + if (found) + return run_full_path(thisDir, command, called); }
/* Not found anywhere - were we called? */
From: Elizabeth zfigura@codeweavers.com
Based on a patch by Jason Edmeades.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=18154 --- programs/cmd/wcmdmain.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-)
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 24b2b75307c..320a6daf0a1 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1385,6 +1385,8 @@ static RETURN_CODE run_full_path(const WCHAR *file, WCHAR *full_cmdline, BOOL ca WCHAR exe_path[MAX_PATH]; PROCESS_INFORMATION pi; SHFILEINFOW psfi; + HANDLE handle; + BOOL ret;
TRACE("%s\n", debugstr_w(file));
@@ -1412,21 +1414,42 @@ static RETURN_CODE run_full_path(const WCHAR *file, WCHAR *full_cmdline, BOOL ca console = SHGetFileInfoW(exe_path, 0, &psfi, sizeof(psfi), SHGFI_EXETYPE);
init_msvcrt_io_block(&si); - if (!CreateProcessW(file, full_cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) + ret = CreateProcessW(file, full_cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); + free(si.lpReserved2); + + if (ret) { - errorlevel = GetLastError(); - free(si.lpReserved2); - return errorlevel; + CloseHandle(pi.hThread); + handle = pi.hProcess; + } + else + { + SHELLEXECUTEINFOW sei = {.cbSize = sizeof(sei)}; + WCHAR *args; + + WCMD_parameter(full_cmdline, 1, &args, FALSE, TRUE); + sei.fMask = SEE_MASK_NO_CONSOLE | SEE_MASK_NOCLOSEPROCESS; + sei.lpFile = file; + sei.lpParameters = args; + sei.nShow = SW_SHOWNORMAL; + + if (ShellExecuteExW(&sei) && (INT_PTR)sei.hInstApp >= 32) + { + handle = sei.hProcess; + } + else + { + errorlevel = GetLastError(); + return errorlevel; + } } - free(si.lpReserved2);
if (!interactive || (console && !HIWORD(console))) - WaitForSingleObject(pi.hProcess, INFINITE); - GetExitCodeProcess(pi.hProcess, &exit_code); + WaitForSingleObject(handle, INFINITE); + GetExitCodeProcess(handle, &exit_code); errorlevel = (exit_code == STILL_ACTIVE) ? NO_ERROR : exit_code;
- CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + CloseHandle(handle); return errorlevel; }
From: Jason Edmeades us@edmeades.me.uk
--- programs/cmd/tests/test_cmdline.cmd | 5 +++++ programs/cmd/tests/test_cmdline.cmd.exp | 2 ++ programs/cmd/wcmdmain.c | 7 +++++-- 3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/programs/cmd/tests/test_cmdline.cmd b/programs/cmd/tests/test_cmdline.cmd index 8712f05f87d..8f3143d0700 100644 --- a/programs/cmd/tests/test_cmdline.cmd +++ b/programs/cmd/tests/test_cmdline.cmd @@ -52,6 +52,11 @@ echo No prompts or I would not get here1 rem - Try cmd.exe /k as well cmd.exe /k "copy file1 file2 >nul && exit" echo No prompts or I would not get here2 +rem Directories are ignored when searching for executable files +mkdir cmd.exe +cmd.exe /c echo alabaster +cmd /c echo chrome +rmdir cmd.exe
rem Nonexistent variable expansion is as per command line, i.e. left as-is cmd.exe /c echo %%hello1%% diff --git a/programs/cmd/tests/test_cmdline.cmd.exp b/programs/cmd/tests/test_cmdline.cmd.exp index 58cd5480292..cb9d306b487 100644 --- a/programs/cmd/tests/test_cmdline.cmd.exp +++ b/programs/cmd/tests/test_cmdline.cmd.exp @@ -32,6 +32,8 @@ No whitespace --- Test 18 No prompts or I would not get here1 No prompts or I would not get here2 +alabaster +chrome %hello1% %hello2 %hello3:h=t% diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 320a6daf0a1..af38fc7f04e 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1546,6 +1546,7 @@ RETURN_CODE WCMD_run_program(WCHAR *command, BOOL called) WCHAR *pos = NULL; BOOL found = FALSE; BOOL inside_quotes = FALSE; + DWORD attribs;
if (explicit_path) { @@ -1604,7 +1605,8 @@ RETURN_CODE WCMD_run_program(WCHAR *command, BOOL called)
/* 1. If extension supplied, see if that file exists */ if (extensionsupplied) { - if (GetFileAttributesW(thisDir) != INVALID_FILE_ATTRIBUTES) { + attribs = GetFileAttributesW(thisDir); + if (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY)) { found = TRUE; } } @@ -1634,7 +1636,8 @@ RETURN_CODE WCMD_run_program(WCHAR *command, BOOL called) thisExt = NULL; }
- if (GetFileAttributesW(thisDir) != INVALID_FILE_ATTRIBUTES) { + attribs = GetFileAttributesW(thisDir); + if (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY)) { found = TRUE; thisExt = NULL; }