From: Qian Hong Subject: [PATCH 1/2] cmd: Encapsulate errorlevel. Message-Id: <5706BDA4.7080700@codeweavers.com> Date: Fri, 08 Apr 2016 04:05:56 +0800 Signed-off-by: Qian Hong --- programs/cmd/batch.c | 2 +- programs/cmd/builtins.c | 88 +++++++++++++++++++++++++----------------------- programs/cmd/directory.c | 20 +++++------ programs/cmd/wcmd.h | 3 +- programs/cmd/wcmdmain.c | 27 +++++++++++---- 5 files changed, 79 insertions(+), 61 deletions(-) diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 1a78b55..c6ed196 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -697,7 +697,7 @@ void WCMD_call (WCHAR *command) { if (*command != ':') { WCMD_run_program(command, TRUE); /* If the thing we try to run does not exist, call returns 1 */ - if (errorlevel) errorlevel=1; + if (get_errorlevel()) set_errorlevel(1); } else { WCHAR gotoLabel[MAX_PATH]; diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index a444330..deaa831 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -285,7 +285,7 @@ void WCMD_choice (const WCHAR * args) { BOOL opt_s = FALSE; have_console = GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &oldmode); - errorlevel = 0; + set_errorlevel(0); my_command = heap_strdupW(WCMD_skip_leading_spaces((WCHAR*) args)); @@ -413,8 +413,8 @@ void WCMD_choice (const WCHAR * args) { if (have_console) SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), oldmode); - errorlevel = (ptr - opt_c) + 1; - WINE_TRACE("answer: %d\n", errorlevel); + set_errorlevel((ptr - opt_c) + 1); + WINE_TRACE("answer: %d\n", get_errorlevel()); heap_free(my_command); return; } @@ -589,12 +589,12 @@ void WCMD_copy(WCHAR * args) { COPY_FILES *prevcopy = NULL; /* Assume we were successful! */ - errorlevel = 0; + set_errorlevel(0); /* If no args supplied at all, report an error */ if (param1[0] == 0x00) { WCMD_output_stderr (WCMD_LoadMessage(WCMD_NOARG)); - errorlevel = 1; + set_errorlevel(1); return; } @@ -674,7 +674,7 @@ void WCMD_copy(WCHAR * args) { if (*thisparam=='+') { if (lastcopyentry == NULL) { WCMD_output_stderr(WCMD_LoadMessage(WCMD_SYNTAXERR)); - errorlevel = 1; + set_errorlevel(1); goto exitreturn; } else { concatnextfilename = TRUE; @@ -729,7 +729,7 @@ void WCMD_copy(WCHAR * args) { } else { /* We have processed sources and destinations and still found more to do - invalid */ WCMD_output_stderr(WCMD_LoadMessage(WCMD_SYNTAXERR)); - errorlevel = 1; + set_errorlevel(1); goto exitreturn; } concatnextfilename = FALSE; @@ -746,7 +746,7 @@ void WCMD_copy(WCHAR * args) { /* Ensure we have at least one source file */ if (!sourcelist) { WCMD_output_stderr(WCMD_LoadMessage(WCMD_SYNTAXERR)); - errorlevel = 1; + set_errorlevel(1); goto exitreturn; } @@ -984,7 +984,7 @@ void WCMD_copy(WCHAR * args) { } if (!status) { WCMD_print_error (); - errorlevel = 1; + set_errorlevel(1); } else { WINE_TRACE("Copied successfully\n"); if (anyconcats) writtenoneconcat = TRUE; @@ -996,7 +996,7 @@ void WCMD_copy(WCHAR * args) { if (!destination->binarycopy && !anyconcats && !thiscopy->binarycopy) { if (!WCMD_AppendEOF(outname)) { WCMD_print_error (); - errorlevel = 1; + set_errorlevel(1); } } } @@ -1008,7 +1008,7 @@ void WCMD_copy(WCHAR * args) { /* Error if the first file was not found */ if (!anyconcats || !writtenoneconcat) { WCMD_print_error (); - errorlevel = 1; + set_errorlevel(1); } } @@ -1017,10 +1017,10 @@ void WCMD_copy(WCHAR * args) { } /* Append EOF if ascii destination and we were concatenating */ - if (!errorlevel && !destination->binarycopy && anyconcats && writtenoneconcat) { + if (!get_errorlevel() && !destination->binarycopy && anyconcats && writtenoneconcat) { if (!WCMD_AppendEOF(destination->name)) { WCMD_print_error (); - errorlevel = 1; + set_errorlevel(1); } } @@ -1103,7 +1103,7 @@ void WCMD_create_dir (WCHAR *args) { if (!argN) break; if (!create_full_path(thisArg)) { WCMD_print_error (); - errorlevel = 1; + set_errorlevel(1); } } } @@ -1395,7 +1395,7 @@ BOOL WCMD_delete (WCHAR *args) { BOOL argsProcessed = FALSE; BOOL foundAny = FALSE; - errorlevel = 0; + set_errorlevel(0); for (argno=0; ; argno++) { BOOL found; @@ -2340,7 +2340,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) { if (input == INVALID_HANDLE_VALUE) { WCMD_print_error (); WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), item); - errorlevel = 1; + set_errorlevel(1); return; /* FOR loop aborts at first failure here */ } else { @@ -2592,9 +2592,9 @@ void WCMD_pushd (const WCHAR *args) /* Change directory using CD code with /D parameter */ strcpyW(quals, parmD); GetCurrentDirectoryW (1024, thisdir); - errorlevel = 0; + set_errorlevel(0); WCMD_setshow_default(args); - if (errorlevel) { + if (get_errorlevel()) { LocalFree(curdir); LocalFree(thisdir); return; @@ -2756,7 +2756,7 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) WCHAR *endptr; long int param_int = strtolW(param, &endptr, 10); if (*endptr) goto syntax_err; - test = ((long int)errorlevel >= param_int); + test = ((long int)get_errorlevel() >= param_int); WCMD_parameter(p, 2+negate, &command, FALSE, FALSE); } else if (!lstrcmpiW (condition, existW)) { @@ -2912,7 +2912,7 @@ void WCMD_move (void) if (ok) { if (!DeleteFileW(dest)) { WCMD_print_error (); - errorlevel = 1; + set_errorlevel(1); ok = FALSE; } } @@ -2927,7 +2927,7 @@ void WCMD_move (void) if (!status) { WCMD_print_error (); - errorlevel = 1; + set_errorlevel(1); } } while (FindNextFileW(hff, &fd) != 0); @@ -3045,12 +3045,12 @@ void WCMD_rename (void) WCHAR fname[MAX_PATH]; WCHAR ext[MAX_PATH]; - errorlevel = 0; + set_errorlevel(0); /* Must be at least two args */ if (param1[0] == 0x00 || param2[0] == 0x00) { WCMD_output_stderr(WCMD_LoadMessage(WCMD_NOARG)); - errorlevel = 1; + set_errorlevel(1); return; } @@ -3058,7 +3058,7 @@ void WCMD_rename (void) if ((strchrW(param2,':') != NULL) || (strchrW(param2,'\\') != NULL)) { SetLastError(ERROR_INVALID_PARAMETER); WCMD_print_error(); - errorlevel = 1; + set_errorlevel(1); return; } @@ -3121,7 +3121,7 @@ void WCMD_rename (void) if (!status) { WCMD_print_error (); - errorlevel = 1; + set_errorlevel(1); } } while (FindNextFileW(hff, &fd) != 0); @@ -3368,7 +3368,7 @@ void WCMD_setshow_default (const WCHAR *args) { status = SetCurrentDirectoryW(string); if (!status) { - errorlevel = 1; + set_errorlevel(1); WCMD_print_error (); return; } else { @@ -4127,7 +4127,7 @@ void WCMD_setshow_env (WCHAR *s) { env = GetEnvironmentStringsW(); if (WCMD_setshow_sortenv( env, s ) == 0) { WCMD_output_stderr(WCMD_LoadMessage(WCMD_MISSINGENV), s); - errorlevel = 1; + set_errorlevel(1); } return; } @@ -4139,9 +4139,9 @@ void WCMD_setshow_env (WCHAR *s) { status = SetEnvironmentVariableW(s, p); gle = GetLastError(); if ((!status) & (gle == ERROR_ENVVAR_NOT_FOUND)) { - errorlevel = 1; + set_errorlevel(1); } else if (!status) WCMD_print_error(); - else errorlevel = 0; + else set_errorlevel(0); } } @@ -4291,9 +4291,11 @@ void WCMD_start(const 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 ); + if (exit_code == STILL_ACTIVE) exit_code = 0; + set_errorlevel(exit_code); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } @@ -4301,7 +4303,7 @@ void WCMD_start(const WCHAR *args) { SetLastError(ERROR_FILE_NOT_FOUND); WCMD_print_error (); - errorlevel = 9009; + set_errorlevel(9009); } heap_free(cmdline); } @@ -4335,7 +4337,7 @@ void WCMD_type (WCHAR *args) { if (param2[0] != 0x00) writeHeaders = TRUE; /* Loop through all args */ - errorlevel = 0; + set_errorlevel(0); while (argN) { WCHAR *thisArg = WCMD_parameter (args, argno++, &argN, FALSE, FALSE); @@ -4351,7 +4353,7 @@ void WCMD_type (WCHAR *args) { if (h == INVALID_HANDLE_VALUE) { WCMD_print_error (); WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), thisArg); - errorlevel = 1; + set_errorlevel(1); } else { if (writeHeaders) { static const WCHAR fmt[] = {'\n','%','1','\n','\n','\0'}; @@ -4388,7 +4390,7 @@ void WCMD_more (WCHAR *args) { static const WCHAR conInW[] = {'C','O','N','I','N','$','\0'}; /* Prefix the NLS more with '-- ', then load the text */ - errorlevel = 0; + set_errorlevel(0); strcpyW(moreStr, moreStart); LoadStringW(hinst, WCMD_MORESTR, &moreStr[3], (sizeof(moreStr)/sizeof(WCHAR))-3); @@ -4453,7 +4455,7 @@ void WCMD_more (WCHAR *args) { if (h == INVALID_HANDLE_VALUE) { WCMD_print_error (); WCMD_output_stderr(WCMD_LoadMessage(WCMD_READFAIL), thisArg); - errorlevel = 1; + set_errorlevel(1); } else { ULONG64 curPos = 0; ULONG64 fileLen = 0; @@ -4601,7 +4603,7 @@ void WCMD_exit (CMD_LIST **cmdList) { int rc = atoiW(param1); /* Note: atoi of empty parameter is 0 */ if (context && lstrcmpiW(quals, parmB) == 0) { - errorlevel = rc; + set_errorlevel(rc); context -> skip_rest = TRUE; *cmdList = NULL; } else { @@ -4629,7 +4631,7 @@ void WCMD_assoc (const WCHAR *args, BOOL assoc) { 'O','p','e','n','\\','C','o','m','m','a','n','d','\0'}; /* See if parameter includes '=' */ - errorlevel = 0; + set_errorlevel(0); newValue = strchrW(args, '='); if (newValue) accessOptions |= KEY_WRITE; @@ -4717,7 +4719,7 @@ void WCMD_assoc (const WCHAR *args, BOOL assoc) { LoadStringW(hinst, WCMD_NOFTYPE, msgbuffer, sizeof(msgbuffer)/sizeof(WCHAR)); } WCMD_output_stderr(msgbuffer, keyValue); - errorlevel = 2; + set_errorlevel(2); } /* Not a query - it's a set or clear of a value */ @@ -4742,7 +4744,7 @@ void WCMD_assoc (const WCHAR *args, BOOL assoc) { } else if (assoc && rc != ERROR_FILE_NOT_FOUND) { WCMD_print_error(); - errorlevel = 2; + set_errorlevel(2); } else { WCHAR msgbuffer[MAXSTRING]; @@ -4756,7 +4758,7 @@ void WCMD_assoc (const WCHAR *args, BOOL assoc) { sizeof(msgbuffer)/sizeof(WCHAR)); } WCMD_output_stderr(msgbuffer, keyValue); - errorlevel = 2; + set_errorlevel(2); } /* It really is a set value = contents */ @@ -4772,7 +4774,7 @@ void WCMD_assoc (const WCHAR *args, BOOL assoc) { if (rc != ERROR_SUCCESS) { WCMD_print_error(); - errorlevel = 2; + set_errorlevel(2); } else { WCMD_output_asis(args); WCMD_output_asis(equalW); @@ -4823,7 +4825,7 @@ void WCMD_color (void) { /* Fail if fg == bg color */ if (((color & 0xF0) >> 4) == (color & 0x0F)) { - errorlevel = 1; + set_errorlevel(1); return; } diff --git a/programs/cmd/directory.c b/programs/cmd/directory.c index 91142be..be2cc58 100644 --- a/programs/cmd/directory.c +++ b/programs/cmd/directory.c @@ -302,7 +302,7 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le if (fd == NULL) { FindClose (hff); WINE_ERR("Out of memory\n"); - errorlevel = 1; + set_errorlevel(1); return parms->next; } } while (FindNextFileW(hff, &fd[entry_count]) != 0); @@ -543,7 +543,7 @@ static DIRECTORY_STACK *WCMD_list_directory (DIRECTORY_STACK *inputparms, int le if ((file_total + dir_total == 0) && (level == 0)) { SetLastError (ERROR_FILE_NOT_FOUND); WCMD_print_error (); - errorlevel = 1; + set_errorlevel(1); } return parms; @@ -564,7 +564,7 @@ static void WCMD_dir_trailer(WCHAR drive) { WINE_TRACE("Writing trailer for '%s' gave %d(%d)\n", wine_dbgstr_w(driveName), status, GetLastError()); - if (errorlevel==0 && !bare) { + if (!get_errorlevel() && !bare) { if (recurse) { static const WCHAR fmt1[] = {'\n',' ',' ',' ',' ',' ','T','o','t','a','l',' ','f','i','l','e','s', ' ','l','i','s','t','e','d',':','\n','%','1','!','8','d','!',' ','f','i','l','e', @@ -609,7 +609,7 @@ void WCMD_directory (WCHAR *args) WCHAR ext[MAX_PATH]; static const WCHAR dircmdW[] = {'D','I','R','C','M','D','\0'}; - errorlevel = 0; + set_errorlevel(0); /* Prefill quals with (uppercased) DIRCMD env var */ if (GetEnvironmentVariableW(dircmdW, string, sizeof(string)/sizeof(WCHAR))) { @@ -696,7 +696,7 @@ void WCMD_directory (WCHAR *args) } else { SetLastError(ERROR_INVALID_PARAMETER); WCMD_print_error(); - errorlevel = 1; + set_errorlevel(1); return; } break; @@ -716,7 +716,7 @@ void WCMD_directory (WCHAR *args) default: SetLastError(ERROR_INVALID_PARAMETER); WCMD_print_error(); - errorlevel = 1; + set_errorlevel(1); return; } p++; @@ -747,7 +747,7 @@ void WCMD_directory (WCHAR *args) default: SetLastError(ERROR_INVALID_PARAMETER); WCMD_print_error(); - errorlevel = 1; + set_errorlevel(1); return; } @@ -766,7 +766,7 @@ void WCMD_directory (WCHAR *args) default: SetLastError(ERROR_INVALID_PARAMETER); WCMD_print_error(); - errorlevel = 1; + set_errorlevel(1); return; } p = p + 1; @@ -903,7 +903,7 @@ void WCMD_directory (WCHAR *args) status = WCMD_volume (0, drive); trailerReqd = TRUE; if (!status) { - errorlevel = 1; + set_errorlevel(1); goto exit; } } @@ -913,7 +913,7 @@ void WCMD_directory (WCHAR *args) } /* Clear any errors from previous invocations, and process it */ - errorlevel = 0; + set_errorlevel(0); prevEntry = thisEntry; thisEntry = WCMD_list_directory (thisEntry, 0); } diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index c135621..5019f9e 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -204,7 +204,8 @@ typedef struct _FOR_CONTEXT { * variables and batch parameters substitution already done. */ extern WCHAR quals[MAX_PATH], param1[MAXSTRING], param2[MAXSTRING]; -extern DWORD errorlevel; +extern DWORD get_errorlevel(void); +extern DWORD set_errorlevel(DWORD); extern BATCH_CONTEXT *context; extern FOR_CONTEXT forloopcontext; extern BOOL delayedsubst; diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index de92e0a..feed9ca 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -37,7 +37,6 @@ extern const WCHAR inbuilt[][10]; extern struct env_stack *pushd_directories; BATCH_CONTEXT *context = NULL; -DWORD errorlevel; WCHAR quals[MAX_PATH], param1[MAXSTRING], param2[MAXSTRING]; BOOL interactive; FOR_CONTEXT forloopcontext; /* The 'for' loop context */ @@ -65,6 +64,20 @@ static int max_height; static int max_width; static int numChars; +struct errorlevel { + DWORD code; +} errorlevel = {0}; + +DWORD get_errorlevel(void) +{ + return errorlevel.code; +} + +DWORD set_errorlevel(DWORD code) +{ + return (errorlevel.code = code); +} + #define MAX_WRITECONSOLE_SIZE 65535 /* @@ -622,7 +635,7 @@ static WCHAR *WCMD_expand_envvar(WCHAR *start, WCHAR startchar) /* override if existing env var called that name */ if (WCMD_is_magic_envvar(thisVar, ErrorLvl)) { static const WCHAR fmt[] = {'%','d','\0'}; - wsprintfW(thisVarContents, fmt, errorlevel); + wsprintfW(thisVarContents, fmt, get_errorlevel()); len = strlenW(thisVarContents); } else if (WCMD_is_magic_envvar(thisVar, Date)) { GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, @@ -1186,6 +1199,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 */ @@ -1220,8 +1234,9 @@ 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); + if (exit_code == STILL_ACTIVE) exit_code = 0; + set_errorlevel(exit_code); CloseHandle(pe.hProcess); CloseHandle(pe.hThread); @@ -1247,7 +1262,7 @@ void WCMD_run_program (WCHAR *command, BOOL called) /* If a command fails to launch, it sets errorlevel 9009 - which does not seem to have any associated constant definition */ - errorlevel = 9009; + set_errorlevel(9009); return; } @@ -2595,7 +2610,7 @@ int wmain (int argc, WCHAR *argvW[]) toExecute = NULL; heap_free(cmd); - return errorlevel; + return get_errorlevel(); } SetConsoleTitleW(WCMD_LoadMessage(WCMD_CONSTITLE));