From: Eric Pouech epouech@codeweavers.com
Manual testing show that native reports errorlevel as a signed entity.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/builtins.c | 13 +++++++------ programs/cmd/tests/test_builtins.cmd | 2 ++ programs/cmd/tests/test_builtins.cmd.exp | 1 + programs/cmd/wcmd.h | 2 +- programs/cmd/wcmdmain.c | 8 ++++---- 5 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index bc9ba9e5f11..b4c00de1e2b 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -402,7 +402,7 @@ void WCMD_choice (const WCHAR * args) { SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), oldmode);
errorlevel = (ptr - opt_c) + 1; - WINE_TRACE("answer: %ld\n", errorlevel); + TRACE("answer: %d\n", errorlevel); free(my_command); return; } @@ -2836,9 +2836,9 @@ int evaluate_if_condition(WCHAR *p, WCHAR **command, int *test, int *negate) if (!lstrcmpiW(condition, L"errorlevel")) { WCHAR *param = WCMD_parameter(p, 1+(*negate), NULL, FALSE, FALSE); WCHAR *endptr; - long int param_int = wcstol(param, &endptr, 10); - if (*endptr) goto syntax_err; - *test = ((long int)errorlevel >= param_int); + int param_int = wcstol(param, &endptr, 10); + if (endptr == param || *endptr) goto syntax_err; + *test = (errorlevel >= param_int); WCMD_parameter(p, 2+(*negate), command, FALSE, FALSE); } else if (!lstrcmpiW(condition, L"exist")) { @@ -4483,9 +4483,10 @@ void WCMD_start(WCHAR *args)
if (CreateProcessW( file, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &st, &pi )) { + DWORD exit_code; WaitForSingleObject( pi.hProcess, INFINITE ); - GetExitCodeProcess( pi.hProcess, &errorlevel ); - if (errorlevel == STILL_ACTIVE) errorlevel = 0; + GetExitCodeProcess( pi.hProcess, &exit_code ); + errorlevel = (exit_code == STILL_ACTIVE) ? 0 : exit_code; CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd index 8fa724c2682..02020a5a6ef 100644 --- a/programs/cmd/tests/test_builtins.cmd +++ b/programs/cmd/tests/test_builtins.cmd @@ -3310,6 +3310,8 @@ should_not_exist 2> nul > nul echo %ErrorLevel% rem nt 4.0 doesn't really support a way of setting errorlevel, so this is weak rem See http://www.robvanderwoude.com/exit.php +call :setError -9999 +echo %ErrorLevel% call :setError 1 echo %ErrorLevel% if errorlevel 2 echo errorlevel too high, bad diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index 76665765b26..0f33f2ae05e 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -1704,6 +1704,7 @@ value1 1 ------------ Testing Errorlevel ------------ 9009 +-9999 1 errorlevel just right, good errorlevel with leading zero just right, good diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 3ed98bcf73e..cd8d7bbdde7 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -251,7 +251,7 @@ typedef struct _FOR_CONTEXT { * variables and batch parameters substitution already done. */ extern WCHAR quals[MAXSTRING], param1[MAXSTRING], param2[MAXSTRING]; -extern DWORD errorlevel; +extern int errorlevel; extern BATCH_CONTEXT *context; extern FOR_CONTEXT forloopcontext; extern BOOL delayedsubst; diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 1a37e93ccc6..30362c4f963 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -36,7 +36,7 @@ extern const WCHAR inbuilt[][10]; extern struct env_stack *pushd_directories;
BATCH_CONTEXT *context = NULL; -DWORD errorlevel; +int errorlevel; WCHAR quals[MAXSTRING], param1[MAXSTRING], param2[MAXSTRING]; BOOL interactive; FOR_CONTEXT forloopcontext; /* The 'for' loop context */ @@ -1297,7 +1297,7 @@ void WCMD_run_program (WCHAR *command, BOOL called) interactive = oldinteractive; return; } 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); @@ -1331,8 +1331,8 @@ void WCMD_run_program (WCHAR *command, BOOL called) or for console applications */ if (!interactive || (console && !HIWORD(console))) WaitForSingleObject (pe.hProcess, INFINITE); - GetExitCodeProcess (pe.hProcess, &errorlevel); - if (errorlevel == STILL_ACTIVE) errorlevel = 0; + GetExitCodeProcess (pe.hProcess, &exit_code); + errorlevel = (exit_code == STILL_ACTIVE) ? 0 : exit_code;
CloseHandle(pe.hProcess); CloseHandle(pe.hThread);