This is part XV of cmd engine rewrite.
This MR deals with returning the proper success/failure return code for POPD and RMDIR.
However, these commands never set ERRORLEVEL (all the commands we've handled so far always set ERRORLEVEL in case of failure, and some reset ERRORLEVEL in case of successs).
So this MR on top of returning the expected success/failure return code for these two commands, also: - extend tests to show that ERRORLEVEL isn't set - tweak internal call path to better handle return code vs ERRORLEVEL.
From: Eric Pouech epouech@codeweavers.com
Focusing on POPD and RMDIR/RD that don't set errorlevel in case of failure.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/tests/test_builtins.cmd | 25 ++++++++++++++++++++++++ programs/cmd/tests/test_builtins.cmd.exp | 15 ++++++++++++++ 2 files changed, 40 insertions(+)
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd index d5f8cef8eab..fed8c20c587 100644 --- a/programs/cmd/tests/test_builtins.cmd +++ b/programs/cmd/tests/test_builtins.cmd @@ -458,6 +458,7 @@ call :setError 0 &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel! call :setError 33 &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel! call :setError 666 & (echo foo &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) call :setError 666 & (echo foo >> h:\i\dont\exist\at\all.txt &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) +call :setError 666 & echo foo >> h:\i\dont\exist\at\all.txt & echo ERRORLEVEL !errorlevel! call :setError 666 & ((if 1==1 echo "">NUL) &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) call :setError 666 & ((if 1==0 echo "">NUL) &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) call :setError 666 & ((if 1==1 (call :setError 33)) &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) @@ -550,6 +551,7 @@ call :setError 666 & (pushd abc &&echo SUCCESS !errorlevel!||echo FAILURE !error call :setError 666 & (pushd abc &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) call :setError 666 & (popd abc &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) call :setError 666 & (popd &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) +call :setError 666 & popd & echo ERRORLEVEL !errorlevel! cd .. && rd /q /s foo
echo --- success/failure for DIR command @@ -565,6 +567,29 @@ call :setError 666 & (dir zzz fileA >NUL &&echo SUCCESS !errorlevel!||echo FAILU call :setError 666 & (dir dir\zzz >NUL &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) call :setError 666 & (dir file* >NUL &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) cd .. && rd /q /s foo +echo --- success/failure for RMDIR/RD command +mkdir foo & cd foo +mkdir abc +call :setError 666 & (rmdir &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) +echo "">abc\abc +call :setError 666 & (rmdir abc &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) +call :setError 666 & (rmdir abc\abc &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) +erase abc\abc +call :setError 666 & (rmdir abc &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) +call :setError 666 & (rmdir abc &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) +call :setError 666 & (rmdir @:\cba\abc &&echo SUCCESS !errorlevel!||echo FAILURE !errorlevel!) +cd .. && rd /q /s foo +mkdir foo & cd foo +mkdir abc +call :setError 666 & rmdir & echo ERRORLEVEL !errorlevel! +echo "">abc\abc +call :setError 666 & rmdir abc & echo ERRORLEVEL !errorlevel! +call :setError 666 & rmdir abc\abc & echo ERRORLEVEL !errorlevel! +erase abc\abc +call :setError 666 & rmdir abc & echo ERRORLEVEL !errorlevel! +call :setError 666 & rmdir abc & echo ERRORLEVEL !errorlevel! +call :setError 666 & rmdir @:\cba\abc & echo ERRORLEVEL !errorlevel! +cd .. && rd /q /s foo
echo --- setlocal DisableDelayedExpansion diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index eb6abb14dea..dc2288742da 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -456,6 +456,7 @@ FAILURE 33 foo@space@ SUCCESS 666 FAILURE 1 +@todo_wine@ERRORLEVEL 666 SUCCESS 666 SUCCESS 666 FAILURE 33 @@ -513,6 +514,7 @@ SUCCESS 0 FAILURE 1 SUCCESS 666 @todo_wine@FAILURE 1 +ERRORLEVEL 666 --- success/failure for DIR command FAILURE 1 FAILURE 1 @@ -520,6 +522,19 @@ SUCCESS 0 SUCCESS 0 FAILURE 1 SUCCESS 0 +--- success/failure for RMDIR/RD command +@todo_wine@FAILURE 1 +@todo_wine@FAILURE 145 +@todo_wine@FAILURE 267 +SUCCESS 666 +@todo_wine@FAILURE 2 +@todo_wine@FAILURE 3 +ERRORLEVEL 666 +ERRORLEVEL 666 +ERRORLEVEL 666 +ERRORLEVEL 666 +ERRORLEVEL 666 +ERRORLEVEL 666 @todo_wine@--- ------------ Testing 'set' ------------ 1
From: Eric Pouech epouech@codeweavers.com
And move handling of the syntax error cases in callers.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/batch.c | 31 ++++++++++++++------- programs/cmd/wcmd.h | 3 ++- programs/cmd/wcmdmain.c | 60 +++++++++++++++++++++++------------------ 3 files changed, 57 insertions(+), 37 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 37db7fb2b04..f350779a0db 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -46,6 +46,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, WCHAR *startLabel, HANDLE pgmHandl { HANDLE h = INVALID_HANDLE_VALUE; BATCH_CONTEXT *prev_context; + RETURN_CODE return_code = NO_ERROR;
if (startLabel == NULL) { h = CreateFileW (file, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, @@ -85,19 +86,29 @@ void WCMD_batch (WCHAR *file, WCHAR *command, WCHAR *startLabel, HANDLE pgmHandl * the rest are handled by the main command processor. */
- while (context -> skip_rest == FALSE) { - CMD_NODE *toExecute = NULL; /* Commands left to be executed */ - if (!WCMD_ReadAndParseLine(NULL, &toExecute, h)) - break; - /* Note: although this batch program itself may be called, we are not retrying - the command as a result of a call failing to find a program, hence the - retryCall parameter below is FALSE */ - node_execute(toExecute); - node_dispose_tree(toExecute); - toExecute = NULL; + while (!context->skip_rest) + { + CMD_NODE *node; + + switch (WCMD_ReadAndParseLine(NULL, &node, h)) + { + case RPL_EOF: + context->skip_rest = TRUE; + break; + case RPL_SUCCESS: + return_code = node_execute(node); + node_dispose_tree(node); + break; + case RPL_SYNTAXERROR: + return_code = RETURN_CODE_SYNTAX_ERROR; + break; + } } CloseHandle (h);
+ if (return_code != RETURN_CODE_ABORTED && return_code != RETURN_CODE_OLD_CHAINING) + errorlevel = return_code; + /* * If there are outstanding setlocal's to the current context, unwind them. */ diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 93620f05656..c778e6bae5b 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -221,7 +221,8 @@ WCHAR *WCMD_LoadMessage(UINT id); WCHAR *WCMD_strsubstW(WCHAR *start, const WCHAR* next, const WCHAR* insert, int len); BOOL WCMD_ReadFile(const HANDLE hIn, WCHAR *intoBuf, const DWORD maxChars, LPDWORD charsRead);
-WCHAR *WCMD_ReadAndParseLine(const WCHAR *initialcmd, CMD_NODE **output, HANDLE readFrom); +enum read_parse_line {RPL_SUCCESS, RPL_EOF, RPL_SYNTAXERROR}; +enum read_parse_line WCMD_ReadAndParseLine(const WCHAR *initialcmd, CMD_NODE **output, HANDLE readFrom); void node_dispose_tree(CMD_NODE *cmds); RETURN_CODE node_execute(CMD_NODE *node);
diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index f8a08878fcb..7c19011f664 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -2562,7 +2562,6 @@ static BOOL node_builder_generate(struct node_builder *builder, CMD_NODE **node) { TRACE("Brackets do not match, error out without executing.\n"); WCMD_output_stderr(WCMD_LoadMessage(WCMD_BADPAREN)); - errorlevel = RETURN_CODE_SYNTAX_ERROR; } else { @@ -2765,7 +2764,7 @@ static WCHAR *fetch_next_line(BOOL feed, BOOL first_line, HANDLE from, WCHAR* bu * - Anything else gets put into the command string (including * redirects) */ -WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_NODE **output, HANDLE readFrom) +enum read_parse_line WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_NODE **output, HANDLE readFrom) { WCHAR *curPos; int inQuotes = 0; @@ -2790,6 +2789,7 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_NODE **output, HANDLE /* handling brackets as a normal character */ BOOL acceptCommand = TRUE; struct node_builder builder; + BOOL ret;
*output = NULL; /* Allocate working space for a command read from keyboard, file etc */ @@ -2800,7 +2800,7 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_NODE **output, HANDLE if (optionalcmd) wcscpy(extraSpace, optionalcmd); if (!(curPos = fetch_next_line(optionalcmd == NULL, TRUE, readFrom, extraSpace))) - return NULL; + return RPL_EOF;
TRACE("About to parse line (%ls)\n", extraSpace);
@@ -2827,7 +2827,7 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_NODE **output, HANDLE /* Prevent overflow caused by the caret escape char */ if (*curLen >= MAXSTRING) { WINE_ERR("Overflow detected in command\n"); - return NULL; + return RPL_SYNTAXERROR; }
/* Certain commands need special handling */ @@ -3156,10 +3156,10 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_NODE **output, HANDLE } }
- node_builder_generate(&builder, output); + ret = node_builder_generate(&builder, output); node_builder_dispose(&builder);
- return extraSpace; + return ret ? RPL_SUCCESS : RPL_SYNTAXERROR; }
static BOOL if_condition_evaluate(CMD_IF_CONDITION *cond, int *test) @@ -3822,6 +3822,7 @@ int __cdecl wmain (int argc, WCHAR *argvW[]) char osver[50]; STARTUPINFOW startupInfo; const WCHAR *arg; + enum read_parse_line rpl_status;
if (!GetEnvironmentVariableW(L"COMSPEC", comspec, ARRAY_SIZE(comspec))) { @@ -4073,12 +4074,15 @@ int __cdecl wmain (int argc, WCHAR *argvW[]) */
/* Parse the command string, without reading any more input */ - WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE); - node_execute(toExecute); - node_dispose_tree(toExecute); - toExecute = NULL; + rpl_status = WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE); + if (rpl_status == RPL_SUCCESS && toExecute) + { + node_execute(toExecute); + node_dispose_tree(toExecute); + } + else if (rpl_status == RPL_SYNTAXERROR) + errorlevel = RETURN_CODE_SYNTAX_ERROR;
- free(cmd); return errorlevel; }
@@ -4152,12 +4156,17 @@ int __cdecl wmain (int argc, WCHAR *argvW[])
}
- if (opt_k) { + if (opt_k) + { + rpl_status = WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE); /* Parse the command string, without reading any more input */ - WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE); - node_execute(toExecute); - node_dispose_tree(toExecute); - toExecute = NULL; + if (rpl_status == RPL_SUCCESS && toExecute) + { + node_execute(toExecute); + node_dispose_tree(toExecute); + } + else if (rpl_status == RPL_SYNTAXERROR) + errorlevel = RETURN_CODE_SYNTAX_ERROR; free(cmd); }
@@ -4168,16 +4177,15 @@ int __cdecl wmain (int argc, WCHAR *argvW[]) interactive = TRUE; if (!opt_k) WCMD_version (); if (echo_mode) WCMD_output_asis(L"\r\n"); - while (TRUE) { - - /* Read until EOF (which for std input is never, but if redirect - in place, may occur */ - if (!WCMD_ReadAndParseLine(NULL, &toExecute, GetStdHandle(STD_INPUT_HANDLE))) - break; - node_execute(toExecute); - node_dispose_tree(toExecute); - if (toExecute && echo_mode) WCMD_output_asis(L"\r\n"); - toExecute = NULL; + /* Read until EOF (which for std input is never, but if redirect in place, may occur */ + while ((rpl_status = WCMD_ReadAndParseLine(NULL, &toExecute, GetStdHandle(STD_INPUT_HANDLE))) != RPL_EOF) + { + if (rpl_status == RPL_SUCCESS && toExecute) + { + node_execute(toExecute); + node_dispose_tree(toExecute); + if (echo_mode) WCMD_output_asis(L"\r\n"); + } } return 0; }
From: Eric Pouech epouech@codeweavers.com
Mainly for commands not setting ERRORLEVEL in case of failure.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/batch.c | 21 +++++++++++++-------- programs/cmd/wcmd.h | 2 +- programs/cmd/wcmdmain.c | 10 ++++++++-- 3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index f350779a0db..17ef569dc3f 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -42,7 +42,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(cmd); * a label to goto once opened. */
-void WCMD_batch (WCHAR *file, WCHAR *command, WCHAR *startLabel, HANDLE pgmHandle) +RETURN_CODE WCMD_batch(const WCHAR *file, WCHAR *command, const WCHAR *startLabel, HANDLE pgmHandle) { HANDLE h = INVALID_HANDLE_VALUE; BATCH_CONTEXT *prev_context; @@ -54,7 +54,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, WCHAR *startLabel, HANDLE pgmHandl if (h == INVALID_HANDLE_VALUE) { SetLastError (ERROR_FILE_NOT_FOUND); WCMD_print_error (); - return; + return ERROR_INVALID_FUNCTION; } } else { DuplicateHandle(GetCurrentProcess(), pgmHandle, @@ -106,9 +106,6 @@ void WCMD_batch (WCHAR *file, WCHAR *command, WCHAR *startLabel, HANDLE pgmHandl } CloseHandle (h);
- if (return_code != RETURN_CODE_ABORTED && return_code != RETURN_CODE_OLD_CHAINING) - errorlevel = return_code; - /* * If there are outstanding setlocal's to the current context, unwind them. */ @@ -124,6 +121,8 @@ void WCMD_batch (WCHAR *file, WCHAR *command, WCHAR *startLabel, HANDLE pgmHandl free(context->batchfileW); LocalFree(context); context = prev_context; + + return return_code; }
/******************************************************************* @@ -658,6 +657,7 @@ extern void WCMD_expand(const WCHAR *, WCHAR *); */ RETURN_CODE WCMD_call(WCHAR *command) { + RETURN_CODE return_code; WCHAR buffer[MAXSTRING]; WCMD_expand(command, buffer);
@@ -666,7 +666,9 @@ RETURN_CODE WCMD_call(WCHAR *command) { WCMD_run_program(buffer, TRUE); /* If the thing we try to run does not exist, call returns 1 */ - if (errorlevel) errorlevel = ERROR_INVALID_FUNCTION; + if (errorlevel == RETURN_CODE_CANT_LAUNCH) + errorlevel = ERROR_INVALID_FUNCTION; + return_code = errorlevel; } else if (context) { @@ -685,11 +687,14 @@ RETURN_CODE WCMD_call(WCHAR *command) li.u.LowPart = SetFilePointer(context->h, li.u.LowPart, &li.u.HighPart, FILE_CURRENT); WCMD_batch(context->batchfileW, buffer, gotoLabel, context->h); + return_code = errorlevel; SetFilePointer(context->h, li.u.LowPart, &li.u.HighPart, FILE_BEGIN);
/* Restore the for loop context */ WCMD_restore_for_loop_context(); - } else + } else { WCMD_output_asis_stderr(WCMD_LoadMessage(WCMD_CALLINSCRIPT)); - return errorlevel ? ERROR_INVALID_FUNCTION : NO_ERROR; + return_code = ERROR_INVALID_FUNCTION; + } + return return_code; } diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index c778e6bae5b..f79645495b3 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -160,7 +160,7 @@ typedef int RETURN_CODE; #define RETURN_CODE_OLD_CHAINING (-999998)
void WCMD_assoc (const WCHAR *, BOOL); -void WCMD_batch(WCHAR *, WCHAR *, WCHAR *, HANDLE); +RETURN_CODE WCMD_batch(const WCHAR *, WCHAR *, const WCHAR *, HANDLE); RETURN_CODE WCMD_call(WCHAR *command); void WCMD_change_tty (void); void WCMD_choice (const WCHAR *); diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 7c19011f664..0f4c3ae8e3f 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1592,14 +1592,18 @@ void WCMD_run_program (WCHAR *command, BOOL called)
/* Special case BAT and CMD */ if (ext && (!wcsicmp(ext, L".bat") || !wcsicmp(ext, L".cmd"))) { + RETURN_CODE return_code; BOOL oldinteractive = interactive; + interactive = FALSE; - WCMD_batch(thisDir, command, NULL, INVALID_HANDLE_VALUE); + return_code = WCMD_batch(thisDir, command, NULL, INVALID_HANDLE_VALUE); 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 && return_code != RETURN_CODE_OLD_CHAINING) + errorlevel = return_code; return; } else { DWORD exit_code; @@ -3713,8 +3717,10 @@ RETURN_CODE node_execute(CMD_NODE *node) case CMD_ONFAILURE: return_code = node_execute(node->left); return_code = temp_fixup_return_code(node->left, return_code, ERROR_INVALID_FUNCTION); - if (return_code != NO_ERROR) + if (return_code != NO_ERROR && return_code != RETURN_CODE_ABORTED) { + /* that's needed for commands (POPD, RMDIR) that don't set errorlevel in case of failure. */ + errorlevel = return_code; return_code = node_execute(node->right); temp_fixup_return_code(node->right, return_code, 0 /* not used */); }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/builtins.c | 6 ++++-- programs/cmd/tests/test_builtins.cmd.exp | 2 +- programs/cmd/wcmd.h | 2 +- programs/cmd/wcmdmain.c | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 6e0a7830900..9771511322c 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -1929,17 +1929,19 @@ RETURN_CODE WCMD_pushd(const WCHAR *args) * Pop a directory from the stack */
-void WCMD_popd (void) { +RETURN_CODE WCMD_popd(void) +{ struct env_stack *temp = pushd_directories;
if (!pushd_directories) - return; + return ERROR_INVALID_FUNCTION;
/* pop the old environment from the stack, and make it the current dir */ pushd_directories = temp->next; SetCurrentDirectoryW(temp->strings); LocalFree (temp->strings); LocalFree (temp); + return NO_ERROR; }
/**************************************************************************** diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index dc2288742da..501b27af725 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -513,7 +513,7 @@ SUCCESS 0 SUCCESS 0 FAILURE 1 SUCCESS 666 -@todo_wine@FAILURE 1 +FAILURE 1 ERRORLEVEL 666 --- success/failure for DIR command FAILURE 1 diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index f79645495b3..9e10069cdac 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -186,7 +186,7 @@ void WINAPIV WCMD_output_stderr (const WCHAR *format, ...); void WCMD_output_asis (const WCHAR *message); void WCMD_output_asis_stderr (const WCHAR *message); void WCMD_pause (void); -void WCMD_popd (void); +RETURN_CODE WCMD_popd(void); void WCMD_print_error (void); RETURN_CODE WCMD_pushd(const WCHAR *args); void WCMD_remove_dir (WCHAR *command); diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 0f4c3ae8e3f..2a814cfe7b0 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1916,7 +1916,7 @@ static RETURN_CODE execute_single_command(const WCHAR *command) return_code = WCMD_pushd(parms_start); break; case WCMD_POPD: - WCMD_popd(); + return_code = WCMD_popd(); break; case WCMD_ASSOC: WCMD_assoc(parms_start, TRUE);
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/builtins.c | 19 ++++++++++++------- programs/cmd/tests/test_builtins.cmd.exp | 12 ++++++------ programs/cmd/wcmd.h | 2 +- programs/cmd/wcmdmain.c | 2 +- 4 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 9771511322c..febf6ba94b6 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -2100,11 +2100,11 @@ void WCMD_pause (void) * Delete a directory. */
-void WCMD_remove_dir (WCHAR *args) { - +RETURN_CODE WCMD_remove_dir(WCHAR *args) +{ int argno = 0; int argsProcessed = 0; - WCHAR *argN = args; + WCHAR *argN = args;
/* Loop through all args */ while (argN) { @@ -2117,7 +2117,12 @@ void WCMD_remove_dir (WCHAR *args) { /* If subdirectory search not supplied, just try to remove and report error if it fails (eg if it contains a file) */ if (wcsstr(quals, L"/S") == NULL) { - if (!RemoveDirectoryW(thisArg)) WCMD_print_error (); + if (!RemoveDirectoryW(thisArg)) + { + RETURN_CODE return_code = GetLastError(); + WCMD_print_error(); + return return_code; + }
/* Otherwise use ShFileOp to recursively remove a directory */ } else { @@ -2134,7 +2139,7 @@ void WCMD_remove_dir (WCHAR *args) { ok = WCMD_ask_confirm(question, TRUE, NULL);
/* Abort if answer is 'N' */ - if (!ok) return; + if (!ok) return ERROR_INVALID_FUNCTION; }
/* Do the delete */ @@ -2155,9 +2160,9 @@ void WCMD_remove_dir (WCHAR *args) { /* Handle no valid args */ if (argsProcessed == 0) { WCMD_output_stderr(WCMD_LoadMessage(WCMD_NOARG)); - return; + return ERROR_INVALID_FUNCTION; } - + return NO_ERROR; }
/**************************************************************************** diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index 501b27af725..6a25fb3aab9 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -523,19 +523,19 @@ SUCCESS 0 FAILURE 1 SUCCESS 0 --- success/failure for RMDIR/RD command -@todo_wine@FAILURE 1 -@todo_wine@FAILURE 145 -@todo_wine@FAILURE 267 +FAILURE 1 +FAILURE 145 +FAILURE 267 SUCCESS 666 -@todo_wine@FAILURE 2 -@todo_wine@FAILURE 3 +FAILURE 2 +FAILURE 3 ERRORLEVEL 666 ERRORLEVEL 666 ERRORLEVEL 666 ERRORLEVEL 666 ERRORLEVEL 666 ERRORLEVEL 666 -@todo_wine@--- +--- ------------ Testing 'set' ------------ 1 0 diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 9e10069cdac..5f51a4e1f3a 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -189,7 +189,7 @@ void WCMD_pause (void); RETURN_CODE WCMD_popd(void); void WCMD_print_error (void); RETURN_CODE WCMD_pushd(const WCHAR *args); -void WCMD_remove_dir (WCHAR *command); +RETURN_CODE WCMD_remove_dir(WCHAR *command); RETURN_CODE WCMD_rename(void); void WCMD_run_program (WCHAR *command, BOOL called); void WCMD_setlocal (const WCHAR *args); diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 2a814cfe7b0..f5610a5934b 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1875,7 +1875,7 @@ static RETURN_CODE execute_single_command(const WCHAR *command) break; case WCMD_RD: case WCMD_RMDIR: - WCMD_remove_dir (parms_start); + return_code = WCMD_remove_dir(parms_start); break; case WCMD_SETLOCAL: WCMD_setlocal(parms_start);
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/tests/test_builtins.cmd.exp | 2 +- programs/cmd/wcmdmain.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index 6a25fb3aab9..c7119858d85 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -456,7 +456,7 @@ FAILURE 33 foo@space@ SUCCESS 666 FAILURE 1 -@todo_wine@ERRORLEVEL 666 +ERRORLEVEL 666 SUCCESS 666 SUCCESS 666 FAILURE 33 diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index f5610a5934b..ce48b16d7ec 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -3691,7 +3691,7 @@ RETURN_CODE node_execute(CMD_NODE *node) { WCMD_print_error(); /* FIXME potentially leaking here (if first redir created ok, and second failed */ - return errorlevel = ERROR_INVALID_FUNCTION; + return ERROR_INVALID_FUNCTION; } switch (node->op) {