From: Eric Pouech epouech@codeweavers.com
Ensuring the batch file is opened/closed at each operation. This allows the batch file to delete itself.
Wine-Bug-Id: https://bugs.winehq.org/show_bug.cgi?id=55151
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/batch.c | 14 -------------- programs/cmd/builtins.c | 15 +++++++++++++-- programs/cmd/tests/test_builtins.cmd.exp | 2 +- programs/cmd/wcmd.h | 1 - programs/cmd/wcmdmain.c | 19 +++++++++++++++---- 5 files changed, 29 insertions(+), 22 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 0b93753eda8..0a1b364fe19 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -71,22 +71,12 @@ static RETURN_CODE WCMD_batch_main_loop(void)
RETURN_CODE WCMD_call_batch(const WCHAR *file, WCHAR *command) { - HANDLE h = INVALID_HANDLE_VALUE; BATCH_CONTEXT *prev_context; RETURN_CODE return_code = NO_ERROR;
- h = CreateFileW (file, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (h == INVALID_HANDLE_VALUE) { - SetLastError (ERROR_FILE_NOT_FOUND); - WCMD_print_error (); - return ERROR_INVALID_FUNCTION; - } - /* Create a context structure for this batch file. */ prev_context = context; context = malloc(sizeof (BATCH_CONTEXT)); - context->h = h; context->file_position.QuadPart = 0; context->batchfileW = xstrdupW(file); context->command = command; @@ -95,7 +85,6 @@ RETURN_CODE WCMD_call_batch(const WCHAR *file, WCHAR *command) context->skip_rest = FALSE;
return_code = WCMD_batch_main_loop(); - CloseHandle (h);
free(context->batchfileW); free(context); @@ -670,7 +659,6 @@ RETURN_CODE WCMD_call(WCHAR *command)
prev_context = context; context = malloc(sizeof (BATCH_CONTEXT)); - context->h = prev_context->h; context->file_position = prev_context->file_position; /* will be overwritten by WCMD_GOTO below */ context->batchfileW = prev_context->batchfileW; context->command = buffer; @@ -687,8 +675,6 @@ RETURN_CODE WCMD_call(WCHAR *command) free(context); context = prev_context; return_code = errorlevel; - if (!SetFilePointerEx(context->h, context->file_position, NULL, FILE_BEGIN)) - return ERROR_INVALID_FUNCTION;
/* Restore the for loop context */ WCMD_restore_for_loop_context(); diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 284cf1f84b6..f8ec0fbb6f4 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -1818,6 +1818,8 @@ RETURN_CODE WCMD_goto(void) if (context != NULL) { WCHAR *paramStart = param1; + HANDLE h; + BOOL ret;
if (!param1[0]) { @@ -1831,14 +1833,23 @@ RETURN_CODE WCMD_goto(void) context->skip_rest = TRUE; return RETURN_CODE_ABORTED; } + h = CreateFileW(context->batchfileW, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_FILE_NOT_FOUND); + WCMD_print_error(); + return ERROR_INVALID_FUNCTION; + }
/* Support goto :label as well as goto label plus remove trailing chars */ if (*paramStart == ':') paramStart++; WCMD_set_label_end(paramStart); TRACE("goto label: '%s'\n", wine_dbgstr_w(paramStart));
- if (WCMD_find_label(context->h, paramStart, &context->file_position)) - return RETURN_CODE_ABORTED; + ret = WCMD_find_label(h, paramStart, &context->file_position); + CloseHandle(h); + if (ret) return RETURN_CODE_ABORTED; WCMD_output_stderr(WCMD_LoadMessage(WCMD_NOTARGET)); context->skip_rest = TRUE; } diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index 6195e8b7644..d61d81fbfe5 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -2010,7 +2010,7 @@ Normal+tab+garbage Success @todo_wine@Success ---- Testing nasty bits ---- -@todo_wine@------------ Testing combined CALLs/GOTOs ------------ +------------ Testing combined CALLs/GOTOs ------------ world cheball barbare diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 3023afc1cb0..cf51a5e44de 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -259,7 +259,6 @@ int evaluate_if_condition(WCHAR *p, WCHAR **command, int *test, int *negate); typedef struct _BATCH_CONTEXT { WCHAR *command; /* The command which invoked the batch file */ - HANDLE h; /* Handle to the open batch file */ LARGE_INTEGER file_position; WCHAR *batchfileW; /* Name of same */ int shift_count[10]; /* Offset in terms of shifts for %0 - %9 */ diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index c4f58a422b9..2c64785d44a 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -2695,10 +2695,21 @@ static WCHAR *fetch_next_line(BOOL feed, BOOL first_line, WCHAR* buffer) if (context) { LARGE_INTEGER zeroli = {.QuadPart = 0}; - - ret = SetFilePointerEx(context->h, context->file_position, NULL, FILE_BEGIN) && - !!WCMD_fgets(buffer, MAXSTRING, context->h) && - SetFilePointerEx(context->h, zeroli, &context->file_position, FILE_CURRENT); + HANDLE h = CreateFileW(context->batchfileW, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_FILE_NOT_FOUND); + WCMD_print_error(); + ret = FALSE; + } + else + { + ret = SetFilePointerEx(h, context->file_position, NULL, FILE_BEGIN) && + !!WCMD_fgets(buffer, MAXSTRING, h) && + SetFilePointerEx(h, zeroli, &context->file_position, FILE_CURRENT); + CloseHandle(h); + } } else ret = !!WCMD_fgets(buffer, MAXSTRING, GetStdHandle(STD_INPUT_HANDLE));