[PATCH 1/2] programs/cmd: introduce structure BATCH_FILE to hold information about a .cmd file
Eric Pouech
eric.pouech at gmail.com
Sat Mar 26 03:51:01 CDT 2022
keeping BATCH_CONTEXT as the execution context of a BATCH_FILE
Signed-off-by: Eric Pouech <eric.pouech at 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 */
More information about the wine-devel
mailing list