Author: jmorlan Date: Thu Aug 21 10:33:59 2008 New Revision: 35508
URL: http://svn.reactos.org/svn/reactos?rev=35508&view=rev Log: - Implement X>&Y redirections. Hold redirections in a linked list structure, because order matters (>x 2>&1 is not the same as 2>&1 >x). Allow redirection of any handle number from 0 to 9. - Allow quotes around the redirection file name. - Batch: Fix buffer overflow bug (incorrect size for bc->BatchFilePath)
Modified: trunk/reactos/base/shell/cmd/batch.c trunk/reactos/base/shell/cmd/batch.h trunk/reactos/base/shell/cmd/call.c trunk/reactos/base/shell/cmd/cmd.c trunk/reactos/base/shell/cmd/cmd.h trunk/reactos/base/shell/cmd/for.c trunk/reactos/base/shell/cmd/misc.c trunk/reactos/base/shell/cmd/redir.c trunk/reactos/base/shell/cmd/start.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] Thu Aug 21 10:33:59 2008 @@ -193,6 +193,9 @@
if (bc->ffind) cmd_free(bc->ffind); + + UndoRedirection(bc->RedirList, NULL); + FreeRedirection(bc->RedirList);
/* Preserve echo state across batch calls */ bEcho = bc->bEcho; @@ -248,9 +251,7 @@
n->prev = bc; bc = n; - bc->In[0] = _T('\0'); - bc->Out[0] = _T('\0'); - bc->Err[0] = _T('\0'); + bc->RedirList = NULL; } else if (bc->hBatchFile != INVALID_HANDLE_VALUE) { @@ -263,7 +264,7 @@ cmd_free (bc->raw_params); }
- GetFullPathName(fullname, sizeof(bc->BatchFilePath), bc->BatchFilePath, &tmp); + GetFullPathName(fullname, sizeof(bc->BatchFilePath) / sizeof(TCHAR), bc->BatchFilePath, &tmp); *tmp = '\0';
bc->hBatchFile = hFile; @@ -300,17 +301,23 @@ return TRUE; }
-VOID AddBatchRedirection(TCHAR * ifn, TCHAR * ofn, TCHAR * efn) +VOID AddBatchRedirection(REDIRECTION **RedirList) { + REDIRECTION **ListEnd; + if(!bc) return; - if(_tcslen(ifn)) - _tcscpy(bc->In,ifn); - if(_tcslen(ofn)) - _tcscpy(bc->Out,ofn); - if(_tcslen(efn)) - _tcscpy(bc->Err,efn); - + + /* Prepend the list to the batch context's list */ + ListEnd = RedirList; + while (*ListEnd) + ListEnd = &(*ListEnd)->Next; + *ListEnd = bc->RedirList; + bc->RedirList = *RedirList; + + /* Null out the pointer so that the list will not be cleared prematurely. + * These redirections should persist until the batch file exits. */ + *RedirList = NULL; }
/*
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] Thu Aug 21 10:33:59 2008 @@ -19,9 +19,7 @@ INT shiftlevel; BOOL bEcho; /* Preserve echo flag across batch calls */ HANDLE hFind; /* Preserve find handle when doing a for */ - TCHAR In[MAX_PATH]; - TCHAR Out[MAX_PATH]; - TCHAR Err[MAX_PATH]; + REDIRECTION *RedirList; TCHAR forvar; INT bCmdBlock; BOOL bExecuteBlock[MAX_PATH]; @@ -47,6 +45,6 @@ VOID ExitBatch (LPTSTR); BOOL Batch (LPTSTR, LPTSTR, LPTSTR); LPTSTR ReadBatchLine (LPBOOL); -VOID AddBatchRedirection(TCHAR *, TCHAR *, TCHAR *); +VOID AddBatchRedirection(REDIRECTION **);
#endif /* _BATCH_H_INCLUDED_ */
Modified: trunk/reactos/base/shell/cmd/call.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/call.c?rev=3... ============================================================================== --- trunk/reactos/base/shell/cmd/call.c [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/call.c [iso-8859-1] Thu Aug 21 10:33:59 2008 @@ -76,19 +76,8 @@ bc->shiftlevel = 0; bc->forvar = 0; /* HBP004 */ bc->forproto = NULL; /* HBP004 */ + bc->RedirList = NULL; ParseCommandLine (param); - if (bc->prev) - { - _tcscpy(bc->In, bc->prev->In); - _tcscpy(bc->Out, bc->prev->Out); - _tcscpy(bc->Err, bc->prev->Err); - } - else - { - bc->In[0] = _T('\0'); - bc->Out[0] = _T('\0'); - bc->Err[0] = _T('\0'); - }
/* Wasn't a batch file so remove conext */
Modified: trunk/reactos/base/shell/cmd/cmd.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.c?rev=35... ============================================================================== --- trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] Thu Aug 21 10:33:59 2008 @@ -690,21 +690,16 @@ TCHAR cmdline[CMDLINE_LENGTH]; LPTSTR s; #ifdef FEATURE_REDIRECTION - TCHAR in[CMDLINE_LENGTH] = _T(""); - TCHAR out[CMDLINE_LENGTH] = _T(""); - TCHAR err[CMDLINE_LENGTH] = _T(""); + REDIRECTION *RedirList = NULL; TCHAR szTempPath[MAX_PATH] = _T(".\"); TCHAR szFileName[2][MAX_PATH] = {_T(""), _T("")}; HANDLE hFile[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; - LPTSTR t = NULL; INT num = 0; - INT nRedirFlags = 0; INT Length; UINT Attributes; BOOL bNewBatch = TRUE; HANDLE hOldConIn; HANDLE hOldConOut; - HANDLE hOldConErr; #endif /* FEATURE_REDIRECTION */
_tcscpy (cmdline, cmd); @@ -732,65 +727,18 @@ _tcscat (szTempPath, _T("\"));
/* get the redirections from the command line */ - num = GetRedirection (s, in, out, err, &nRedirFlags); - - /* more efficient, but do we really need to do this? */ - for (t = in; _istspace (*t); t++) - ; - _tcscpy (in, t); - - for (t = out; _istspace (*t); t++) - ; - _tcscpy (out, t); - - for (t = err; _istspace (*t); t++) - ; - _tcscpy (err, t); - - if(bc && !_tcslen (in) && _tcslen (bc->In)) - _tcscpy(in, bc->In); - if(bc && !out[0] && _tcslen(bc->Out)) - { - nRedirFlags |= OUTPUT_APPEND; - _tcscpy(out, bc->Out); - } - if(bc && !_tcslen (err) && _tcslen (bc->Err)) - { - nRedirFlags |= ERROR_APPEND; - _tcscpy(err, bc->Err); + num = GetRedirection (s, &RedirList); + + if (!PerformRedirection(RedirList)) + { + FreeRedirection(RedirList); + return; }
/* Set up the initial conditions ... */ - /* preserve STDIN, STDOUT and STDERR handles */ + /* preserve STDIN and STDOUT handles */ hOldConIn = GetStdHandle (STD_INPUT_HANDLE); hOldConOut = GetStdHandle (STD_OUTPUT_HANDLE); - hOldConErr = GetStdHandle (STD_ERROR_HANDLE); - - /* redirect STDIN */ - if (in[0]) - { - HANDLE hFile; - SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; - - /* we need make sure the LastError msg is zero before calling CreateFile */ - SetLastError(0); - - /* Set up pipe for the standard input handler */ - hFile = CreateFile (in, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - { - ConErrResPrintf(STRING_CMD_ERROR1, in); - return; - } - - if (!SetStdHandle (STD_INPUT_HANDLE, hFile)) - { - ConErrResPrintf(STRING_CMD_ERROR1, in); - return; - } - TRACE ("Input redirected from: %s\n", debugstr_aw(in)); - }
/* Now do all but the last pipe command */ *szFileName[0] = _T('\0'); @@ -855,123 +803,7 @@ }
/* Now set up the end conditions... */ - /* redirect STDOUT */ - if (out[0]) - { - /* Final output to here */ - HANDLE hFile; - SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; - - /* we need make sure the LastError msg is zero before calling CreateFile */ - SetLastError(0); - - hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa, - (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL); - - if (hFile == INVALID_HANDLE_VALUE) - { - INT size = _tcslen(out)-1; - - if (out[size] != _T(':')) - { - ConErrResPrintf(STRING_CMD_ERROR3, out); - return; - } - - out[size]=_T('\0'); - hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa, - (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL); - - if (hFile == INVALID_HANDLE_VALUE) - { - ConErrResPrintf(STRING_CMD_ERROR3, out); - return; - } - - } - - if (!SetStdHandle (STD_OUTPUT_HANDLE, hFile)) - { - ConErrResPrintf(STRING_CMD_ERROR3, out); - return; - } - - if (nRedirFlags & OUTPUT_APPEND) - { - LONG lHighPos = 0; - - if (GetFileType (hFile) == FILE_TYPE_DISK) - SetFilePointer (hFile, 0, &lHighPos, FILE_END); - } - TRACE ("Output redirected to: %s\n", debugstr_aw(out)); - } - else if (hOldConOut != INVALID_HANDLE_VALUE) - { - /* Restore original stdout */ - HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE); - SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut); - if (hOldConOut != hOut) - CloseHandle (hOut); - hOldConOut = INVALID_HANDLE_VALUE; - } - - /* redirect STDERR */ - if (err[0]) - { - /* Final output to here */ - HANDLE hFile; - SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; - - if (!_tcscmp (err, out)) - { - TRACE ("Stdout and stderr will use the same file!!\n"); - DuplicateHandle (GetCurrentProcess (), - GetStdHandle (STD_OUTPUT_HANDLE), - GetCurrentProcess (), - &hFile, 0, TRUE, DUPLICATE_SAME_ACCESS); - } - else - { - hFile = CreateFile (err, - GENERIC_WRITE, - FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, - &sa, - (nRedirFlags & ERROR_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, - NULL); - if (hFile == INVALID_HANDLE_VALUE) - { - ConErrResPrintf(STRING_CMD_ERROR3, err); - return; - } - } - - if (!SetStdHandle (STD_ERROR_HANDLE, hFile)) - { - ConErrResPrintf(STRING_CMD_ERROR3, err); - return; - } - - if (nRedirFlags & ERROR_APPEND) - { - LONG lHighPos = 0; - - if (GetFileType (hFile) == FILE_TYPE_DISK) - SetFilePointer (hFile, 0, &lHighPos, FILE_END); - } - TRACE ("Error redirected to: %s\n", debugstr_aw(err)); - } - else if (hOldConErr != INVALID_HANDLE_VALUE) - { - /* Restore original stderr */ - HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE); - SetStdHandle (STD_ERROR_HANDLE, hOldConErr); - if (hOldConErr != hErr) - CloseHandle (hErr); - hOldConErr = INVALID_HANDLE_VALUE; - } + SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
if(bc) bNewBatch = FALSE; @@ -982,7 +814,7 @@
#ifdef FEATURE_REDIRECTION if(bNewBatch && bc) - AddBatchRedirection(in, out, err); + AddBatchRedirection(&RedirList); /* close old stdin file */ #if 0 /* buggy implementation */ SetStdHandle (STD_INPUT_HANDLE, hOldConIn); @@ -1039,26 +871,8 @@ } }
- - /* Restore original STDOUT */ - if (hOldConOut != INVALID_HANDLE_VALUE) - { - HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE); - SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut); - if (hOldConOut != hOut) - CloseHandle (hOut); - hOldConOut = INVALID_HANDLE_VALUE; - } - - /* Restore original STDERR */ - if (hOldConErr != INVALID_HANDLE_VALUE) - { - HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE); - SetStdHandle (STD_ERROR_HANDLE, hOldConErr); - if (hOldConErr != hErr) - CloseHandle (hErr); - hOldConErr = INVALID_HANDLE_VALUE; - } + UndoRedirection(RedirList, NULL); + FreeRedirection(RedirList); #endif /* FEATURE_REDIRECTION */ }
Modified: trunk/reactos/base/shell/cmd/cmd.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.h?rev=35... ============================================================================== --- trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/cmd.h [iso-8859-1] Thu Aug 21 10:33:59 2008 @@ -301,6 +301,7 @@ LPTSTR *split (LPTSTR, LPINT, BOOL); VOID freep (LPTSTR *); LPTSTR _stpcpy (LPTSTR, LPCTSTR); +VOID StripQuotes(LPTSTR); BOOL IsValidPathName (LPCTSTR); BOOL IsExistingFile (LPCTSTR); BOOL IsExistingDirectory (LPCTSTR); @@ -335,12 +336,19 @@
/* Prototypes for REDIR.C */ -#define INPUT_REDIRECTION 1 -#define OUTPUT_REDIRECTION 2 -#define OUTPUT_APPEND 4 -#define ERROR_REDIRECTION 8 -#define ERROR_APPEND 16 -INT GetRedirection (LPTSTR, LPTSTR, LPTSTR, LPTSTR, LPINT); +enum { REDIR_READ, REDIR_WRITE, REDIR_APPEND }; +typedef struct _REDIRECTION +{ + struct _REDIRECTION *Next; + HANDLE OldHandle; + BYTE Number; + BYTE Type; + TCHAR Filename[]; +} REDIRECTION; +BOOL PerformRedirection(REDIRECTION *); +VOID UndoRedirection(REDIRECTION *, REDIRECTION *End); +INT GetRedirection(LPTSTR, REDIRECTION **); +VOID FreeRedirection(REDIRECTION *);
/* Prototypes for REN.C */
Modified: trunk/reactos/base/shell/cmd/for.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/for.c?rev=35... ============================================================================== --- trunk/reactos/base/shell/cmd/for.c [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/for.c [iso-8859-1] Thu Aug 21 10:33:59 2008 @@ -138,9 +138,7 @@ bc->bEcho = bc->prev->bEcho; else bc->bEcho = bEcho; - bc->In[0] = _T('\0'); - bc->Out[0] = _T('\0'); - bc->Err[0] = _T('\0'); + bc->RedirList = NULL;
return 0;
Modified: trunk/reactos/base/shell/cmd/misc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/misc.c?rev=3... ============================================================================== --- trunk/reactos/base/shell/cmd/misc.c [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/misc.c [iso-8859-1] Thu Aug 21 10:33:59 2008 @@ -411,6 +411,18 @@ return (dest + _tcslen (src)); }
+VOID +StripQuotes(TCHAR *in) +{ + TCHAR *out = in; + for (; *in; in++) + { + if (*in != _T('"')) + *out++ = *in; + } + *out = _T('\0'); +} +
/*
Modified: trunk/reactos/base/shell/cmd/redir.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/redir.c?rev=... ============================================================================== --- trunk/reactos/base/shell/cmd/redir.c [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/redir.c [iso-8859-1] Thu Aug 21 10:33:59 2008 @@ -51,11 +51,12 @@ * */
-INT GetRedirection (LPTSTR s, LPTSTR ifn, LPTSTR ofn, LPTSTR efn, LPINT lpnFlags) +INT GetRedirection (LPTSTR s, REDIRECTION **RedirList) { INT num = 1; LPTSTR dp = s; LPTSTR sp = s; + TCHAR Filename[MAX_PATH];
#ifdef INCLUDE_CMD_REM
@@ -68,10 +69,6 @@ /*first thing first. check to see if this is "rem" and hope out*/ if(!_tcsncmp (line, _T("rem "), 4)) { - lpnFlags = 0; - *ifn=('\0'); - *ofn=('\0'); - *efn=_T('\0'); return 1; } #endif @@ -94,148 +91,74 @@ while (*sp && *sp != qc);
*dp++ = *sp++; - } - else if ((*sp == _T('<')) || (*sp == _T('>')) || - (*sp == _T('1')) || (*sp == _T('2')) || (*sp == _T('&'))) - { - /* MS-DOS ignores multiple redirection symbols and uses the last */ - /* redirection, so we'll emulate that and not check */ + continue; + } + + int NumberGiven = (*sp >= _T('0') && *sp <= _T('9')) ? 1 : 0; + if (sp[NumberGiven] == _T('<') || sp[NumberGiven] == _T('>')) + { + BYTE HandleNumber; + BYTE Type; + BOOL bInQuote = FALSE; + TCHAR *fn = Filename; + REDIRECTION *Redir, **ListPtr; + + if (NumberGiven) + HandleNumber = *sp++ - _T('0'); + else + HandleNumber = *sp == _T('<') ? 0 : 1;
if (*sp == _T('<')) { /* input redirection */ - *lpnFlags |= INPUT_REDIRECTION; - do sp++; - while( _istspace (*sp) ); - - /* copy file name */ - while (*sp && !IsRedirection (*sp) && !_istspace (*sp)) - *ifn++ = *sp++; - *ifn = _T('\0'); - } - else if (*sp == _T('>')) + Type = REDIR_READ; + sp++; + } + else { /* output redirection */ - *lpnFlags |= OUTPUT_REDIRECTION; + Type = REDIR_WRITE; sp++;
/* append request ? */ if (*sp == _T('>')) { - *lpnFlags |= OUTPUT_APPEND; + Type = REDIR_APPEND; sp++; } - - while (_istspace (*sp)) - sp++; - - /* copy file name */ - while (*sp && !IsRedirection (*sp) && !_istspace (*sp)) - *ofn++ = *sp++; - *ofn = _T('\0'); - } - - else if (*sp == _T('1')) - { - /* output redirection */ + } + + while (_istspace(*sp)) sp++;
- if (*sp == _T('>')) + /* copy file name */ + while (*sp && (bInQuote || (!IsRedirection (*sp) && !_istspace (*sp)))) + { + bInQuote ^= (*sp == _T('"')); + *fn++ = *sp++; + } + *fn++ = _T('\0'); + + /* Delete any existing redirection for the same handle number */ + ListPtr = RedirList; + while ((Redir = *ListPtr)) + { + if (Redir->Number == HandleNumber) { - /* output redirection */ - *lpnFlags |= OUTPUT_REDIRECTION; - sp++; - - /* append request ? */ - if (*sp == _T('>')) - { - *lpnFlags |= OUTPUT_APPEND; - sp++; - } - } - else - { - /* no redirection!! copy the '1' character! */ - sp--; - *dp++ = *sp++; + *ListPtr = Redir->Next; + cmd_free(Redir); continue; } - - while (_istspace (*sp)) - sp++; - - /* copy file name */ - while (*sp && !IsRedirection (*sp) && !_istspace (*sp)) - *ofn++ = *sp++; - *ofn = _T('\0'); - } - - else if (*sp == _T('2')) - { - /* error redirection */ - sp++; - - if (*sp == _T('>')) - { - *lpnFlags |= ERROR_REDIRECTION; - sp++; - - /* append request ? */ - if (*sp == _T('>')) - { - *lpnFlags |= ERROR_APPEND; - sp++; - } - } - else - { - /* no redirection!! copy the '2' character! */ - sp--; - *dp++ = *sp++; - continue; - } - - while (_istspace (*sp)) - sp++; - - /* copy file name */ - while (*sp && !IsRedirection (*sp) && !_istspace (*sp)) - *efn++ = *sp++; - *efn = _T('\0'); - } - else if (*sp == _T('&')) - { - /* output AND error redirection */ - sp++; - - if (*sp == _T('>')) - { - *lpnFlags |= (ERROR_REDIRECTION | OUTPUT_REDIRECTION); - sp++; - - /* append request ? */ - if (*sp == _T('>')) - { - *lpnFlags |= (ERROR_APPEND | OUTPUT_APPEND); - sp++; - } - } - else - { - /* no redirection!! copy the '&' character! */ - sp--; - *dp++ = *sp++; - continue; - } - - while (_istspace (*sp)) - sp++; - - /* copy file name */ - while (*sp && !IsRedirection (*sp) && !_istspace (*sp)) - *ofn++ = *efn++ = *sp++; - *ofn = *efn = _T('\0'); - } + ListPtr = &Redir->Next; + } + + Redir = cmd_alloc(FIELD_OFFSET(REDIRECTION, Filename[fn - Filename])); + Redir->Next = NULL; + Redir->OldHandle = INVALID_HANDLE_VALUE; + Redir->Number = HandleNumber; + Redir->Type = Type; + _tcscpy(Redir->Filename, Filename); + *ListPtr = Redir; } else *dp++ = *sp++; @@ -276,4 +199,124 @@ return num; }
+/* cmd allows redirection of handles numbered 3-9 even though these don't + * correspond to any STD_ constant. */ +static HANDLE ExtraHandles[10 - 3]; + +static HANDLE GetHandle(UINT Number) +{ + if (Number < 3) + return GetStdHandle(STD_INPUT_HANDLE - Number); + else + return ExtraHandles[Number - 3]; +} + +static VOID SetHandle(UINT Number, HANDLE Handle) +{ + if (Number < 3) + SetStdHandle(STD_INPUT_HANDLE - Number, Handle); + else + ExtraHandles[Number - 3] = Handle; +} + +BOOL +PerformRedirection(REDIRECTION *RedirList) +{ + REDIRECTION *Redir; + TCHAR Filename[MAX_PATH]; + HANDLE hNew; + UINT DupNumber; + static SECURITY_ATTRIBUTES SecAttr = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + + /* Some parameters used for read, write, and append, respectively */ + static const DWORD dwAccess[] = { + GENERIC_READ, + GENERIC_WRITE, + GENERIC_WRITE + }; + static const DWORD dwShareMode[] = { + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SHARE_READ, + FILE_SHARE_READ + }; + static const DWORD dwCreationDisposition[] = { + OPEN_EXISTING, + CREATE_ALWAYS, + OPEN_ALWAYS + }; + + for (Redir = RedirList; Redir; Redir = Redir->Next) + { + *Filename = _T('\0'); + _tcsncat(Filename, Redir->Filename, MAX_PATH - 1); + StripQuotes(Filename); + + if (*Filename == _T('&')) + { + DupNumber = Filename[1] - _T('0'); + if (DupNumber >= 10 || + !DuplicateHandle(GetCurrentProcess(), + GetHandle(DupNumber), + GetCurrentProcess(), + &hNew, + 0, + TRUE, + DUPLICATE_SAME_ACCESS)) + { + hNew = INVALID_HANDLE_VALUE; + } + } + else + { + hNew = CreateFile(Filename, + dwAccess[Redir->Type], + dwShareMode[Redir->Type], + &SecAttr, + dwCreationDisposition[Redir->Type], + 0, + NULL); + } + + if (hNew == INVALID_HANDLE_VALUE) + { + ConErrResPrintf(Redir->Type == REDIR_READ ? STRING_CMD_ERROR1 : STRING_CMD_ERROR3, + Filename); + /* Undo all the redirections before this one */ + UndoRedirection(RedirList, Redir); + return FALSE; + } + + if (Redir->Type == REDIR_APPEND) + SetFilePointer(hNew, 0, NULL, FILE_END); + Redir->OldHandle = GetHandle(Redir->Number); + SetHandle(Redir->Number, hNew); + + TRACE("%d redirected to: %s\n", Redir->Number, debugstr_aw(Filename)); + } + return TRUE; +} + +VOID +UndoRedirection(REDIRECTION *Redir, REDIRECTION *End) +{ + for (; Redir != End; Redir = Redir->Next) + { + CloseHandle(GetHandle(Redir->Number)); + SetHandle(Redir->Number, Redir->OldHandle); + Redir->OldHandle = INVALID_HANDLE_VALUE; + } +} + +VOID +FreeRedirection(REDIRECTION *Redir) +{ + REDIRECTION *Next; + for (; Redir; Redir = Next) + { + Next = Redir->Next; + ASSERT(Redir->OldHandle == INVALID_HANDLE_VALUE); + cmd_free(Redir); + } +} + #endif /* FEATURE_REDIRECTION */
Modified: trunk/reactos/base/shell/cmd/start.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/start.c?rev=... ============================================================================== --- trunk/reactos/base/shell/cmd/start.c [iso-8859-1] (original) +++ trunk/reactos/base/shell/cmd/start.c [iso-8859-1] Thu Aug 21 10:33:59 2008 @@ -32,17 +32,6 @@ p[-1] = _T('\0'); *pPointer = p; return start - 1; -} - -static void StripQuotes(TCHAR *in) -{ - TCHAR *out = in; - for (; *in; in++) - { - if (*in != _T('"')) - *out++ = *in; - } - *out = _T('\0'); }
INT cmd_start (LPTSTR First, LPTSTR Rest)