diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index febf6ba94b6..bf089a8b9f5 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -2298,33 +2298,40 @@ static WCHAR *WCMD_dupenv( const WCHAR *env ) * setlocal pushes the environment onto a stack * Save the environment as unicode so we don't screw anything up. */ -void WCMD_setlocal (const WCHAR *s) { +RETURN_CODE WCMD_setlocal(WCHAR *args) +{ WCHAR *env; struct env_stack *env_copy; WCHAR cwd[MAX_PATH]; BOOL newdelay; + int argno = 0; + WCHAR *argN = args; /* setlocal does nothing outside of batch programs */ - if (!context) return; - - /* DISABLEEXTENSIONS ignored */ - - /* ENABLEDELAYEDEXPANSION / DISABLEDELAYEDEXPANSION could be parm1 or parm2 - (if both ENABLEEXTENSIONS and ENABLEDELAYEDEXPANSION supplied for example) */ - if (!wcsicmp(param1, L"ENABLEDELAYEDEXPANSION") || !wcsicmp(param2, L"ENABLEDELAYEDEXPANSION")) { - newdelay = TRUE; - } else if (!wcsicmp(param1, L"DISABLEDELAYEDEXPANSION") || !wcsicmp(param2, L"DISABLEDELAYEDEXPANSION")) { - newdelay = FALSE; - } else { - newdelay = delayedsubst; + if (!context) + return NO_ERROR; + newdelay = delayedsubst; + while (argN) + { + WCHAR *thisArg = WCMD_parameter (args, argno++, &argN, FALSE, FALSE); + if (!thisArg || !*thisArg) break; + if (!wcsicmp(thisArg, L"ENABLEDELAYEDEXPANSION")) + newdelay = TRUE; + else if (!wcsicmp(thisArg, L"DISABLEDELAYEDEXPANSION")) + newdelay = FALSE; + /* ENABLE/DISABLE EXTENSIONS ignored for now */ + else if (!wcsicmp(thisArg, L"ENABLEEXTENSIONS") || !wcsicmp(thisArg, L"DISABLEEXTENSIONS")) + {} + else + return errorlevel = ERROR_INVALID_FUNCTION; + TRACE("Setting delayed expansion to %d\n", newdelay); } - WINE_TRACE("Setting delayed expansion to %d\n", newdelay); env_copy = LocalAlloc (LMEM_FIXED, sizeof (struct env_stack)); if( !env_copy ) { - WINE_ERR ("out of memory\n"); - return; + ERR("out of memory\n"); + return errorlevel = ERROR_OUTOFMEMORY; } env = GetEnvironmentStringsW (); @@ -2345,7 +2352,7 @@ void WCMD_setlocal (const WCHAR *s) { LocalFree (env_copy); FreeEnvironmentStringsW (env); - + return errorlevel = NO_ERROR; } /***************************************************************************** @@ -2355,18 +2362,19 @@ void WCMD_setlocal (const WCHAR *s) { * Note: When searching for '=', search from WCHAR position 1, to handle * special internal environment variables =C:, =D: etc */ -void WCMD_endlocal (void) { +RETURN_CODE WCMD_endlocal(void) +{ WCHAR *env, *old, *p; struct env_stack *temp; int len, n; /* setlocal does nothing outside of batch programs */ - if (!context) return; + if (!context) return NO_ERROR; /* setlocal needs a saved environment from within the same context (batch program) as it was saved in */ if (!saved_environment || saved_environment->batchhandle != context->h) - return; + return ERROR_INVALID_FUNCTION; /* pop the old environment from the stack */ temp = saved_environment; @@ -2419,6 +2427,7 @@ void WCMD_endlocal (void) { LocalFree (env); LocalFree (temp); + return NO_ERROR; } /***************************************************************************** diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index 75152663850..c883758cf32 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -536,11 +536,11 @@ ERRORLEVEL 666 ERRORLEVEL 666 ERRORLEVEL 666 --- success/failure for SETLOCAL/ENDLOCAL commands -@todo_wine@FAILURE 1 -@todo_wine@SUCCESS 0 +FAILURE 1 +SUCCESS 0 SUCCESS 666 @todo_wine@SUCCESS@space@ -@todo_wine@SUCCESS 0 +SUCCESS 0 --- success/failure for DATE command @todo_wine@SUCCESS 0 @todo_wine@FAILURE 1 @@ -739,7 +739,7 @@ foo bar@or_broken@foo gotitright 33 -@todo_wine@0@or_broken@1 +0@or_broken@1 foo !WINE_FOO! not empty diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 5f51a4e1f3a..3c259ec0eb9 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -171,7 +171,7 @@ RETURN_CODE WCMD_create_dir(WCHAR *); RETURN_CODE WCMD_delete(WCHAR *); RETURN_CODE WCMD_directory(WCHAR *); RETURN_CODE WCMD_echo(const WCHAR *); -void WCMD_endlocal (void); +RETURN_CODE WCMD_endlocal(void); void WCMD_enter_paged_mode(const WCHAR *); RETURN_CODE WCMD_exit(void); BOOL WCMD_get_fullpath(const WCHAR *, SIZE_T, WCHAR *, WCHAR **); @@ -192,7 +192,7 @@ RETURN_CODE WCMD_pushd(const WCHAR *args); 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); +RETURN_CODE WCMD_setlocal(WCHAR *args); void WCMD_setshow_date (void); RETURN_CODE WCMD_setshow_default(const WCHAR *args); void WCMD_setshow_env (WCHAR *command); diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index ce48b16d7ec..feb5e75281e 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1878,10 +1878,10 @@ static RETURN_CODE execute_single_command(const WCHAR *command) return_code = WCMD_remove_dir(parms_start); break; case WCMD_SETLOCAL: - WCMD_setlocal(parms_start); + return_code = WCMD_setlocal(parms_start); break; case WCMD_ENDLOCAL: - WCMD_endlocal(); + return_code = WCMD_endlocal(); break; case WCMD_SET: WCMD_setshow_env (parms_start);