keeping BATCH_CONTEXT as the execution context of a BATCH_FILE
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/cmd/batch.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ programs/cmd/wcmd.h | 10 ++++++++-- 2 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 9a262c5fec5..ab9b90e48ca 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -26,6 +26,40 @@ extern struct env_stack *saved_environment;
WINE_DEFAULT_DEBUG_CHANNEL(cmd);
+static BATCH_FILE *linkto_batch_file( const WCHAR *file, HANDLE h ) +{ + BATCH_FILE *batchfile; + BATCH_CONTEXT *ctx; + FILETIME last; + + GetFileTime(h, NULL, NULL, &last); + for (ctx = context; ctx; ctx = ctx->prev_context) + { + if (ctx->file && !wcscmp( ctx->file->batchfileW, file ) && + !CompareFileTime( &last, &ctx->file->last_modified )) + { + ctx->file->ref_count++; + return ctx->file; + } + } + batchfile = malloc( sizeof(*batchfile) ); + batchfile->ref_count = 1; + batchfile->batchfileW = heap_strdupW( file ); + batchfile->last_modified = last; + + return batchfile; +} + +static void unref_batch_file( BATCH_CONTEXT *ctx ) +{ + BATCH_FILE *batchfile = ctx->file; + if (--batchfile->ref_count == 0) { + heap_free( batchfile->batchfileW ); + free( batchfile ); + ctx->file = NULL; + } +} + /**************************************************************************** * WCMD_batch * @@ -46,6 +80,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA { HANDLE h = INVALID_HANDLE_VALUE; BATCH_CONTEXT *prev_context; + BATCH_FILE *batchfile;
if (startLabel == NULL) { h = CreateFileW (file, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, @@ -65,14 +100,15 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA * Create a context structure for this batch file. */
+ batchfile = linkto_batch_file( file, h ); prev_context = context; - context = LocalAlloc (LMEM_FIXED, sizeof (BATCH_CONTEXT)); + context = malloc(sizeof(BATCH_CONTEXT)); context -> h = h; - context->batchfileW = heap_strdupW(file); context -> command = command; memset(context -> shift_count, 0x00, sizeof(context -> shift_count)); context -> prev_context = prev_context; context -> skip_rest = FALSE; + context -> file = batchfile;
/* If processing a call :label, 'goto' the label in question */ if (startLabel) { @@ -110,8 +146,8 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA * to the caller's caller. */
- heap_free(context->batchfileW); - LocalFree (context); + unref_batch_file( context ); + free(context); if ((prev_context != NULL) && (!called)) { WINE_TRACE("Batch completed, but was not 'called' so skipping outer batch too\n"); prev_context -> skip_rest = TRUE; @@ -417,7 +453,7 @@ void WCMD_HandleTildeModifiers(WCHAR **start, BOOL atExecute) whereas if you start applying other modifiers to it, you get the filename the batch label is in */ if (*lastModifier == '0' && modifierLen > 1) { - lstrcpyW(outputparam, context->batchfileW); + lstrcpyW(outputparam, context->file->batchfileW); } else if ((*lastModifier >= '0' && *lastModifier <= '9')) { lstrcpyW(outputparam, WCMD_parameter (context -> command, @@ -675,7 +711,7 @@ void WCMD_call (WCHAR *command) { li.QuadPart = 0; li.u.LowPart = SetFilePointer(context -> h, li.u.LowPart, &li.u.HighPart, FILE_CURRENT); - WCMD_batch (context->batchfileW, command, TRUE, gotoLabel, context->h); + WCMD_batch (context->file->batchfileW, command, TRUE, gotoLabel, context->h); SetFilePointer(context -> h, li.u.LowPart, &li.u.HighPart, FILE_BEGIN);
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 234c253b49a..ebce5359eb8 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -149,16 +149,22 @@ static inline BOOL ends_with_backslash( const WCHAR *path )
int evaluate_if_condition(WCHAR *p, WCHAR **command, int *test, int *negate);
-/* Data structure to hold context when executing batch files */ +/* Data structure to store information about a batch file */ +typedef struct _BATCH_FILE { + unsigned ref_count; /* number of BATCH_CONTEXT attached to this */ + WCHAR *batchfileW; /* Name of self */ + FILETIME last_modified;/* last modified date of the file */ +} BATCH_FILE;
+/* Data structure to hold context when executing batch files */ typedef struct _BATCH_CONTEXT { WCHAR *command; /* The command which invoked the batch file */ HANDLE h; /* Handle to the open batch file */ - WCHAR *batchfileW; /* Name of same */ int shift_count[10]; /* Offset in terms of shifts for %0 - %9 */ struct _BATCH_CONTEXT *prev_context; /* Pointer to the previous context block */ BOOL skip_rest; /* Skip the rest of the batch program and exit */ CMD_LIST *toExecute; /* Commands left to be executed */ + BATCH_FILE *file; /* Reference to the file itself */ } BATCH_CONTEXT;
/* Data structure to handle building lists during recursive calls */