Index: batch.c =================================================================== --- batch.c (revision 50273) +++ batch.c (working copy) @@ -156,7 +156,23 @@ return dp; } +/* + * free the allocated memory of a batch file + */ +VOID ClearBatch() +{ + TRACE ("ClearBatch mem = %08x free = %d\n", bc->mem, bc->memfree); + if (bc->mem && bc->memfree) + cmd_free(bc->mem); + + if (bc->raw_params) + cmd_free(bc->raw_params); + + if (bc->params) + cmd_free(bc->params); +} + /* * If a batch file is current, exits it, freeing the context block and * chaining back to the previous one. @@ -169,20 +185,10 @@ VOID ExitBatch() { + ClearBatch(); + TRACE ("ExitBatch\n"); - if (bc->hBatchFile) - { - CloseHandle (bc->hBatchFile); - bc->hBatchFile = INVALID_HANDLE_VALUE; - } - - if (bc->raw_params) - cmd_free(bc->raw_params); - - if (bc->params) - cmd_free(bc->params); - UndoRedirection(bc->RedirList, NULL); FreeRedirection(bc->RedirList); @@ -195,7 +201,34 @@ bc = bc->prev; } +/* + * Load batch file into memory + * + */ +void BatchFile2Mem(HANDLE hBatchFile) +{ + TRACE ("BatchFile2Mem ()\n"); + bc->memsize = GetFileSize(hBatchFile, NULL); + bc->mem = (char *)cmd_alloc(bc->memsize+1); /* 1 extra for '\0' */ + + /* if memory is available, read it in and close the file */ + if (bc->mem != NULL) + { + TRACE ("BatchFile2Mem memory %08x - %08x\n",bc->mem,bc->memsize); + SetFilePointer (hBatchFile, 0, NULL, FILE_BEGIN); + ReadFile(hBatchFile, (LPVOID)bc->mem, bc->memsize, &bc->memsize, NULL); + bc->mem[bc->memsize]='\0'; /* end this, so you can dump it as a string */ + bc->memfree=TRUE; /* this one needs to be freed */ + } + else + { + bc->memsize=0; /* this will prevent mem being accessed */ + bc->memfree=FALSE; + } + bc->mempos = 0; /* set position to the start */ +} + /* * Start batch file execution * @@ -209,31 +242,37 @@ LPFOR_CONTEXT saved_fc; INT i; INT ret = 0; + BOOL same_fn = FALSE; - HANDLE hFile; + HANDLE hFile = 0; SetLastError(0); - hFile = CreateFile (fullname, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | - FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (bc && bc->mem) + { + TCHAR fpname[MAX_PATH]; + GetFullPathName(fullname, sizeof(fpname) / sizeof(TCHAR), fpname, NULL); + if (_tcsicmp(bc->BatchFilePath,fpname)==0) + same_fn=TRUE; + } + TRACE ("Batch: (\'%s\', \'%s\', \'%s\') same_fn = %d\n", + debugstr_aw(fullname), debugstr_aw(firstword), debugstr_aw(param), same_fn); - TRACE ("Batch: (\'%s\', \'%s\', \'%s\') hFile = %x\n", - debugstr_aw(fullname), debugstr_aw(firstword), debugstr_aw(param), hFile); + if (!same_fn) + { + hFile = CreateFile (fullname, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | + FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if (hFile == INVALID_HANDLE_VALUE) - { - ConErrResPuts(STRING_BATCH_ERROR); - return 1; + if (hFile == INVALID_HANDLE_VALUE) + { + ConErrResPuts(STRING_BATCH_ERROR); + return 1; + } } - + if (bc != NULL && Cmd == bc->current) { /* Then we are transferring to another batch */ - CloseHandle (bc->hBatchFile); - bc->hBatchFile = INVALID_HANDLE_VALUE; - if (bc->params) - cmd_free (bc->params); - if (bc->raw_params) - cmd_free (bc->raw_params); + ClearBatch(); AddBatchRedirection(&Cmd->Redirections); } else @@ -261,15 +300,27 @@ /* Create a new context. This function will not * return until this context has been exited */ new.prev = bc; + /* copy some fields in the new structure if it is the same file */ + if (same_fn) { + new.mem = bc->mem; + new.memsize = bc->memsize; + new.mempos = 0; + new.memfree = FALSE; /* don't free this, being used before this */ + } bc = &new; bc->RedirList = NULL; bc->setlocal = setlocal; } GetFullPathName(fullname, sizeof(bc->BatchFilePath) / sizeof(TCHAR), bc->BatchFilePath, NULL); - - bc->hBatchFile = hFile; - SetFilePointer (bc->hBatchFile, 0, NULL, FILE_BEGIN); + /* if a new batch file, load it into memory and close the file */ + if (!same_fn) + { + BatchFile2Mem(hFile); + CloseHandle(hFile); + } + + bc->mempos = 0; /* goto begin of batch file */ bc->bEcho = bEcho; /* Preserve echo across batch calls */ for (i = 0; i < 10; i++) bc->shiftlevel[i] = i; @@ -340,6 +391,49 @@ } /* + * Read a single line from the batch file from the current batch/memory position. + * Almost a copy of FileGetString with same UNICODE handling + */ +BOOL BatchGetString (LPTSTR lpBuffer, INT nBufferLength) +{ + LPSTR lpString; + INT len = 0; +#ifdef _UNICODE + lpString = cmd_alloc(nBufferLength); +#else + lpString = lpBuffer; +#endif + /* read all chars from memory until a '\n' is encountered */ + if (bc->mem) + { + for (; (bc->mempos < bc->memsize && len < (nBufferLength-1)); len++) + { + lpString[len] = bc->mem[bc->mempos++]; + if (lpString[len] == '\n' ) + { + len++; + break; + } + } + } + + if (!len) + { +#ifdef _UNICODE + cmd_free(lpString); +#endif + return FALSE; + } + + lpString[len++] = '\0'; +#ifdef _UNICODE + MultiByteToWideChar(OutputCodePage, 0, lpString, -1, lpBuffer, len); + cmd_free(lpString); +#endif + return TRUE; +} + +/* * Read and return the next executable line form the current batch file * * If no batch file is current or no further executable lines are found @@ -347,7 +441,6 @@ * * Set eflag to 0 if line is not to be echoed else 1 */ - LPTSTR ReadBatchLine () { TRACE ("ReadBatchLine ()\n"); @@ -360,7 +453,7 @@ return NULL; } - if (!FileGetString (bc->hBatchFile, textline, sizeof (textline) / sizeof (textline[0]) - 1)) + if (!BatchGetString (textline, sizeof (textline) / sizeof (textline[0]) - 1)) { TRACE ("ReadBatchLine(): Reached EOF!\n"); /* End of file.... */ Index: batch.h =================================================================== --- batch.h (revision 50273) +++ batch.h (working copy) @@ -9,7 +9,10 @@ typedef struct tagBATCHCONTEXT { struct tagBATCHCONTEXT *prev; - HANDLE hBatchFile; + char *mem; /* batchfile content in memory */ + DWORD memsize; /* size of batchfile */ + DWORD mempos; /* current position to read from */ + BOOL memfree; /* true if it need to be freed when exitbatch is called */ TCHAR BatchFilePath[MAX_PATH]; LPTSTR params; LPTSTR raw_params; /* Holds the raw params given by the input */ @@ -47,5 +50,6 @@ LPTSTR BatchParams (LPTSTR, LPTSTR); VOID ExitBatch (); INT Batch (LPTSTR, LPTSTR, LPTSTR, PARSED_COMMAND *); +BOOL BatchGetString (LPTSTR lpBuffer, INT nBufferLength); LPTSTR ReadBatchLine(); -VOID AddBatchRedirection(REDIRECTION **); +VOID AddBatchRedirection(REDIRECTION **); Index: goto.c =================================================================== --- goto.c (revision 50273) +++ goto.c (working copy) @@ -74,14 +74,14 @@ /* jump to end of the file */ if ( _tcsicmp( param, _T(":eof"))==0) { - SetFilePointer (bc->hBatchFile, 0, &lNewPosHigh, FILE_END); + bc->mempos=bc->memsize; /* position at the end of the batchfile */ return 0; } /* jump to begin of the file */ - SetFilePointer (bc->hBatchFile, 0, &lNewPosHigh, FILE_BEGIN); + bc->mempos=0; - while (FileGetString (bc->hBatchFile, textline, sizeof(textline) / sizeof(textline[0]))) + while (BatchGetString (textline, sizeof(textline) / sizeof(textline[0]))) { int pos; int size;