Author: tkreuzer
Date: Wed Jun 1 19:33:20 2011
New Revision: 52047
URL:
http://svn.reactos.org/svn/reactos?rev=52047&view=rev
Log:
[CMD]
replace FILE IO with Memory IO functions for batch files
Patch by HansH (hans at atbas dot org)
See issue #5807 for more details.
Modified:
trunk/reactos/base/shell/cmd/batch.c
trunk/reactos/base/shell/cmd/batch.h
trunk/reactos/base/shell/cmd/goto.c
Modified: trunk/reactos/base/shell/cmd/batch.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/batch.c?rev…
==============================================================================
--- trunk/reactos/base/shell/cmd/batch.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/batch.c [iso-8859-1] Wed Jun 1 19:33:20 2011
@@ -156,6 +156,22 @@
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
@@ -169,19 +185,9 @@
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,6 +201,33 @@
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;
-
- HANDLE hFile;
+ BOOL same_fn = FALSE;
+
+ 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);
-
- TRACE ("Batch: (\'%s\', \'%s\', \'%s\') hFile =
%x\n",
- debugstr_aw(fullname), debugstr_aw(firstword), debugstr_aw(param), hFile);
-
- if (hFile == INVALID_HANDLE_VALUE)
- {
- ConErrResPuts(STRING_BATCH_ERROR);
- return 1;
- }
-
+ 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);
+
+ 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 (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.... */
Modified: trunk/reactos/base/shell/cmd/batch.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/batch.h?rev…
==============================================================================
--- trunk/reactos/base/shell/cmd/batch.h [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/batch.h [iso-8859-1] Wed Jun 1 19:33:20 2011
@@ -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 (VOID);
INT Batch (LPTSTR, LPTSTR, LPTSTR, PARSED_COMMAND *);
+BOOL BatchGetString (LPTSTR lpBuffer, INT nBufferLength);
LPTSTR ReadBatchLine(VOID);
-VOID AddBatchRedirection(REDIRECTION **);
+VOID AddBatchRedirection(REDIRECTION **);
Modified: trunk/reactos/base/shell/cmd/goto.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/goto.c?rev=…
==============================================================================
--- trunk/reactos/base/shell/cmd/goto.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/goto.c [iso-8859-1] Wed Jun 1 19:33:20 2011
@@ -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;