Author: hbelusca
Date: Sun Jun 30 13:11:20 2013
New Revision: 59389
URL:
http://svn.reactos.org/svn/reactos?rev=59389&view=rev
Log:
[CMD]
And finally...
...
... fix whitespace, part 6/6 !!!! (convert tabs into 4-space indent).
Really, CMD is, together with win32k, the worst indented project I've ever seen.
You have lots of non-sensical extra newlines put in the middle of the code,
weird indentation made by a mix of tabs / spaces which take either 4 or 8 or even (!!)
2 spaces per indentation level; sometimes some guy mixed his space key with his tab key
to add a space between a word and another one; a mix of some sh*tty code styles (K&R
and personal ones),
many many times no space between a logical keyword and the operand on which it applies,
etc... etc...
I tried to put some sense in it, but I may have forgotten some insidious tabs
somewhere...
Modified:
trunk/reactos/base/shell/cmd/cmd.c
Modified: trunk/reactos/base/shell/cmd/cmd.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/cmd/cmd.c?rev=5…
==============================================================================
--- trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] (original)
+++ trunk/reactos/base/shell/cmd/cmd.c [iso-8859-1] Sun Jun 30 13:11:20 2013
@@ -184,34 +184,34 @@
INT
ConvertULargeInteger(ULONGLONG num, LPTSTR des, UINT len, BOOL bPutSeperator)
{
- TCHAR temp[39]; /* maximum length with nNumberGroups == 1 */
- UINT n, iTarget;
-
- if (len <= 1)
- return 0;
-
- n = 0;
- iTarget = nNumberGroups;
- if (!nNumberGroups)
- bPutSeperator = FALSE;
-
- do
- {
- if (iTarget == n && bPutSeperator)
- {
- iTarget += nNumberGroups + 1;
- temp[38 - n++] = cThousandSeparator;
- }
- temp[38 - n++] = (TCHAR)(num % 10) + _T('0');
- num /= 10;
- } while (num > 0);
- if (n > len-1)
- n = len-1;
-
- memcpy(des, temp + 39 - n, n * sizeof(TCHAR));
- des[n] = _T('\0');
-
- return n;
+ TCHAR temp[39]; /* maximum length with nNumberGroups == 1 */
+ UINT n, iTarget;
+
+ if (len <= 1)
+ return 0;
+
+ n = 0;
+ iTarget = nNumberGroups;
+ if (!nNumberGroups)
+ bPutSeperator = FALSE;
+
+ do
+ {
+ if (iTarget == n && bPutSeperator)
+ {
+ iTarget += nNumberGroups + 1;
+ temp[38 - n++] = cThousandSeparator;
+ }
+ temp[38 - n++] = (TCHAR)(num % 10) + _T('0');
+ num /= 10;
+ } while (num > 0);
+ if (n > len-1)
+ n = len-1;
+
+ memcpy(des, temp + 39 - n, n * sizeof(TCHAR));
+ des[n] = _T('\0');
+
+ return n;
}
/*
@@ -219,42 +219,42 @@
*/
static BOOL IsConsoleProcess(HANDLE Process)
{
- NTSTATUS Status;
- PROCESS_BASIC_INFORMATION Info;
- PEB ProcessPeb;
- ULONG BytesRead;
-
- if (NULL == NtQueryInformationProcessPtr || NULL == NtReadVirtualMemoryPtr)
- {
- return TRUE;
- }
-
- Status = NtQueryInformationProcessPtr (
- Process, ProcessBasicInformation,
- &Info, sizeof(PROCESS_BASIC_INFORMATION), NULL);
- if (! NT_SUCCESS(Status))
- {
- WARN ("NtQueryInformationProcess failed with status %08x\n", Status);
- return TRUE;
- }
- Status = NtReadVirtualMemoryPtr (
- Process, Info.PebBaseAddress, &ProcessPeb,
- sizeof(PEB), &BytesRead);
- if (! NT_SUCCESS(Status) || sizeof(PEB) != BytesRead)
- {
- WARN ("Couldn't read virt mem status %08x bytes read %lu\n", Status,
BytesRead);
- return TRUE;
- }
-
- return IMAGE_SUBSYSTEM_WINDOWS_CUI == ProcessPeb.ImageSubsystem;
+ NTSTATUS Status;
+ PROCESS_BASIC_INFORMATION Info;
+ PEB ProcessPeb;
+ ULONG BytesRead;
+
+ if (NULL == NtQueryInformationProcessPtr || NULL == NtReadVirtualMemoryPtr)
+ {
+ return TRUE;
+ }
+
+ Status = NtQueryInformationProcessPtr (
+ Process, ProcessBasicInformation,
+ &Info, sizeof(PROCESS_BASIC_INFORMATION), NULL);
+ if (! NT_SUCCESS(Status))
+ {
+ WARN ("NtQueryInformationProcess failed with status %08x\n", Status);
+ return TRUE;
+ }
+ Status = NtReadVirtualMemoryPtr (
+ Process, Info.PebBaseAddress, &ProcessPeb,
+ sizeof(PEB), &BytesRead);
+ if (! NT_SUCCESS(Status) || sizeof(PEB) != BytesRead)
+ {
+ WARN ("Couldn't read virt mem status %08x bytes read %lu\n",
Status, BytesRead);
+ return TRUE;
+ }
+
+ return IMAGE_SUBSYSTEM_WINDOWS_CUI == ProcessPeb.ImageSubsystem;
}
#ifdef _UNICODE
-#define SHELLEXECUTETEXT "ShellExecuteExW"
+#define SHELLEXECUTETEXT "ShellExecuteExW"
#else
-#define SHELLEXECUTETEXT "ShellExecuteExA"
+#define SHELLEXECUTETEXT "ShellExecuteExA"
#endif
typedef BOOL (WINAPI *MYEX)(LPSHELLEXECUTEINFO lpExecInfo);
@@ -262,42 +262,42 @@
HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params,
LPTSTR directory, INT show)
{
- SHELLEXECUTEINFO sei;
- HMODULE hShell32;
- MYEX hShExt;
- BOOL ret;
-
- TRACE ("RunFile(%s)\n", debugstr_aw(filename));
- hShell32 = LoadLibrary(_T("SHELL32.DLL"));
- if (!hShell32)
- {
- WARN ("RunFile: couldn't load SHELL32.DLL!\n");
- return NULL;
- }
-
- hShExt = (MYEX)(FARPROC)GetProcAddress(hShell32, SHELLEXECUTETEXT);
- if (!hShExt)
- {
- WARN ("RunFile: couldn't find ShellExecuteExA/W in SHELL32.DLL!\n");
- FreeLibrary(hShell32);
- return NULL;
- }
-
- TRACE ("RunFile: ShellExecuteExA/W is at %x\n", hShExt);
-
- memset(&sei, 0, sizeof sei);
- sei.cbSize = sizeof sei;
- sei.fMask = flags;
- sei.lpFile = filename;
- sei.lpParameters = params;
- sei.lpDirectory = directory;
- sei.nShow = show;
- ret = hShExt(&sei);
-
- TRACE ("RunFile: ShellExecuteExA/W returned 0x%p\n", ret);
-
- FreeLibrary(hShell32);
- return ret ? sei.hProcess : NULL;
+ SHELLEXECUTEINFO sei;
+ HMODULE hShell32;
+ MYEX hShExt;
+ BOOL ret;
+
+ TRACE ("RunFile(%s)\n", debugstr_aw(filename));
+ hShell32 = LoadLibrary(_T("SHELL32.DLL"));
+ if (!hShell32)
+ {
+ WARN ("RunFile: couldn't load SHELL32.DLL!\n");
+ return NULL;
+ }
+
+ hShExt = (MYEX)(FARPROC)GetProcAddress(hShell32, SHELLEXECUTETEXT);
+ if (!hShExt)
+ {
+ WARN ("RunFile: couldn't find ShellExecuteExA/W in
SHELL32.DLL!\n");
+ FreeLibrary(hShell32);
+ return NULL;
+ }
+
+ TRACE ("RunFile: ShellExecuteExA/W is at %x\n", hShExt);
+
+ memset(&sei, 0, sizeof sei);
+ sei.cbSize = sizeof sei;
+ sei.fMask = flags;
+ sei.lpFile = filename;
+ sei.lpParameters = params;
+ sei.lpDirectory = directory;
+ sei.nShow = show;
+ ret = hShExt(&sei);
+
+ TRACE ("RunFile: ShellExecuteExA/W returned 0x%p\n", ret);
+
+ FreeLibrary(hShell32);
+ return ret ? sei.hProcess : NULL;
}
@@ -309,175 +309,174 @@
* First - first word on command line
* Rest - rest of command line
*/
-
static INT
Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
{
- TCHAR szFullName[MAX_PATH];
- TCHAR *first, *rest, *dot;
- TCHAR szWindowTitle[MAX_PATH];
- DWORD dwExitCode = 0;
- TCHAR *FirstEnd;
- TCHAR szFullCmdLine [CMDLINE_LENGTH];
-
- TRACE ("Execute: \'%s\' \'%s\'\n", debugstr_aw(First),
debugstr_aw(Rest));
-
- /* Though it was already parsed once, we have a different set of rules
- for parsing before we pass to CreateProccess */
- if (First[0] == _T('/') || (First[0] && First[1] == _T(':')))
- {
- /* Use the entire first word as the program name (no change) */
- FirstEnd = First + _tcslen(First);
- }
- else
- {
- /* If present in the first word, spaces and ,;=/ end the program
- * name and become the beginning of its parameters. */
- BOOL bInside = FALSE;
- for (FirstEnd = First; *FirstEnd; FirstEnd++)
- {
- if (!bInside && (_istspace(*FirstEnd) || _tcschr(_T(",;=/"),
*FirstEnd)))
- break;
- bInside ^= *FirstEnd == _T('"');
- }
- }
-
- /* Copy the new first/rest into the buffer */
- first = Full;
- rest = &Full[FirstEnd - First + 1];
- _tcscpy(rest, FirstEnd);
- _tcscat(rest, Rest);
- *FirstEnd = _T('\0');
- _tcscpy(first, First);
-
- /* check for a drive change */
- if ((_istalpha (first[0])) && (!_tcscmp (first + 1, _T(":"))))
- {
- BOOL working = TRUE;
- if (!SetCurrentDirectory(first))
- /* Guess they changed disc or something, handle that gracefully and get to root */
- {
- TCHAR str[4];
- str[0]=first[0];
- str[1]=_T(':');
- str[2]=_T('\\');
- str[3]=0;
- working = SetCurrentDirectory(str);
- }
-
- if (!working) ConErrResPuts (STRING_FREE_ERROR1);
- return !working;
- }
-
- /* get the PATH environment variable and parse it */
- /* search the PATH environment variable for the binary */
- StripQuotes(First);
- if (!SearchForExecutable(First, szFullName))
- {
- error_bad_command(first);
- return 1;
- }
-
- GetConsoleTitle (szWindowTitle, MAX_PATH);
-
- /* check if this is a .BAT or .CMD file */
- dot = _tcsrchr (szFullName, _T('.'));
- if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot,
_T(".cmd"))))
- {
- while (*rest == _T(' '))
- rest++;
- TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
- dwExitCode = Batch(szFullName, first, rest, Cmd);
- }
- else
- {
- /* exec the program */
- PROCESS_INFORMATION prci;
- STARTUPINFO stui;
-
- /* build command line for CreateProcess(): FullName + " " + rest */
+ TCHAR szFullName[MAX_PATH];
+ TCHAR *first, *rest, *dot;
+ TCHAR szWindowTitle[MAX_PATH];
+ DWORD dwExitCode = 0;
+ TCHAR *FirstEnd;
+ TCHAR szFullCmdLine [CMDLINE_LENGTH];
+
+ TRACE ("Execute: \'%s\' \'%s\'\n", debugstr_aw(First),
debugstr_aw(Rest));
+
+ /* Though it was already parsed once, we have a different set of rules
+ for parsing before we pass to CreateProccess */
+ if (First[0] == _T('/') || (First[0] && First[1] ==
_T(':')))
+ {
+ /* Use the entire first word as the program name (no change) */
+ FirstEnd = First + _tcslen(First);
+ }
+ else
+ {
+ /* If present in the first word, spaces and ,;=/ end the program
+ * name and become the beginning of its parameters. */
+ BOOL bInside = FALSE;
+ for (FirstEnd = First; *FirstEnd; FirstEnd++)
+ {
+ if (!bInside && (_istspace(*FirstEnd) ||
_tcschr(_T(",;=/"), *FirstEnd)))
+ break;
+ bInside ^= *FirstEnd == _T('"');
+ }
+ }
+
+ /* Copy the new first/rest into the buffer */
+ first = Full;
+ rest = &Full[FirstEnd - First + 1];
+ _tcscpy(rest, FirstEnd);
+ _tcscat(rest, Rest);
+ *FirstEnd = _T('\0');
+ _tcscpy(first, First);
+
+ /* check for a drive change */
+ if ((_istalpha (first[0])) && (!_tcscmp (first + 1, _T(":"))))
+ {
+ BOOL working = TRUE;
+ if (!SetCurrentDirectory(first))
+ /* Guess they changed disc or something, handle that gracefully and get to root
*/
+ {
+ TCHAR str[4];
+ str[0]=first[0];
+ str[1]=_T(':');
+ str[2]=_T('\\');
+ str[3]=0;
+ working = SetCurrentDirectory(str);
+ }
+
+ if (!working) ConErrResPuts (STRING_FREE_ERROR1);
+ return !working;
+ }
+
+ /* get the PATH environment variable and parse it */
+ /* search the PATH environment variable for the binary */
+ StripQuotes(First);
+ if (!SearchForExecutable(First, szFullName))
+ {
+ error_bad_command(first);
+ return 1;
+ }
+
+ GetConsoleTitle (szWindowTitle, MAX_PATH);
+
+ /* check if this is a .BAT or .CMD file */
+ dot = _tcsrchr (szFullName, _T('.'));
+ if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot,
_T(".cmd"))))
+ {
+ while (*rest == _T(' '))
+ rest++;
+ TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName),
debugstr_aw(rest));
+ dwExitCode = Batch(szFullName, first, rest, Cmd);
+ }
+ else
+ {
+ /* exec the program */
+ PROCESS_INFORMATION prci;
+ STARTUPINFO stui;
+
+ /* build command line for CreateProcess(): FullName + " " + rest */
BOOL quoted = !!_tcschr(First, ' ');
- _tcscpy(szFullCmdLine, quoted ? _T("\"") : _T(""));
- _tcsncat(szFullCmdLine, First, CMDLINE_LENGTH - _tcslen(szFullCmdLine));
- _tcsncat(szFullCmdLine, quoted ? _T("\"") : _T(""),
CMDLINE_LENGTH - _tcslen(szFullCmdLine));
-
- if (*rest)
- {
- _tcsncat(szFullCmdLine, _T(" "), CMDLINE_LENGTH - _tcslen(szFullCmdLine));
- _tcsncat(szFullCmdLine, rest, CMDLINE_LENGTH - _tcslen(szFullCmdLine));
- }
-
- TRACE ("[EXEC: %s]\n", debugstr_aw(szFullCmdLine));
-
- /* fill startup info */
- memset (&stui, 0, sizeof (STARTUPINFO));
- stui.cb = sizeof (STARTUPINFO);
- stui.dwFlags = STARTF_USESHOWWINDOW;
- stui.wShowWindow = SW_SHOWDEFAULT;
-
- // return console to standard mode
- SetConsoleMode (GetStdHandle(STD_INPUT_HANDLE),
- ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
-
- if (CreateProcess (szFullName,
- szFullCmdLine,
- NULL,
- NULL,
- TRUE,
- 0, /* CREATE_NEW_PROCESS_GROUP */
- NULL,
- NULL,
- &stui,
- &prci))
-
- {
- CloseHandle(prci.hThread);
- }
- else
- {
- // See if we can run this with ShellExecute() ie myfile.xls
- prci.hProcess = RunFile(SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE,
- szFullName,
- rest,
- NULL,
- SW_SHOWNORMAL);
- }
-
- if (prci.hProcess != NULL)
- {
- if (IsConsoleProcess(prci.hProcess))
- {
- EnterCriticalSection(&ChildProcessRunningLock);
- dwChildProcessId = prci.dwProcessId;
-
- WaitForSingleObject (prci.hProcess, INFINITE);
-
- LeaveCriticalSection(&ChildProcessRunningLock);
-
- GetExitCodeProcess (prci.hProcess, &dwExitCode);
- nErrorLevel = (INT)dwExitCode;
- }
- CloseHandle (prci.hProcess);
- }
- else
- {
- TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full));
- error_bad_command (first);
- dwExitCode = 1;
- }
-
- // restore console mode
- SetConsoleMode (
- GetStdHandle( STD_INPUT_HANDLE ),
- ENABLE_PROCESSED_INPUT );
- }
-
- /* Get code page if it has been change */
- InputCodePage= GetConsoleCP();
- OutputCodePage = GetConsoleOutputCP();
- SetConsoleTitle (szWindowTitle);
-
- return dwExitCode;
+ _tcscpy(szFullCmdLine, quoted ? _T("\"") : _T(""));
+ _tcsncat(szFullCmdLine, First, CMDLINE_LENGTH - _tcslen(szFullCmdLine));
+ _tcsncat(szFullCmdLine, quoted ? _T("\"") : _T(""),
CMDLINE_LENGTH - _tcslen(szFullCmdLine));
+
+ if (*rest)
+ {
+ _tcsncat(szFullCmdLine, _T(" "), CMDLINE_LENGTH -
_tcslen(szFullCmdLine));
+ _tcsncat(szFullCmdLine, rest, CMDLINE_LENGTH - _tcslen(szFullCmdLine));
+ }
+
+ TRACE ("[EXEC: %s]\n", debugstr_aw(szFullCmdLine));
+
+ /* fill startup info */
+ memset (&stui, 0, sizeof (STARTUPINFO));
+ stui.cb = sizeof (STARTUPINFO);
+ stui.dwFlags = STARTF_USESHOWWINDOW;
+ stui.wShowWindow = SW_SHOWDEFAULT;
+
+ // return console to standard mode
+ SetConsoleMode (GetStdHandle(STD_INPUT_HANDLE),
+ ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT
);
+
+ if (CreateProcess (szFullName,
+ szFullCmdLine,
+ NULL,
+ NULL,
+ TRUE,
+ 0, /* CREATE_NEW_PROCESS_GROUP */
+ NULL,
+ NULL,
+ &stui,
+ &prci))
+
+ {
+ CloseHandle(prci.hThread);
+ }
+ else
+ {
+ // See if we can run this with ShellExecute() ie myfile.xls
+ prci.hProcess = RunFile(SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE,
+ szFullName,
+ rest,
+ NULL,
+ SW_SHOWNORMAL);
+ }
+
+ if (prci.hProcess != NULL)
+ {
+ if (IsConsoleProcess(prci.hProcess))
+ {
+ EnterCriticalSection(&ChildProcessRunningLock);
+ dwChildProcessId = prci.dwProcessId;
+
+ WaitForSingleObject (prci.hProcess, INFINITE);
+
+ LeaveCriticalSection(&ChildProcessRunningLock);
+
+ GetExitCodeProcess (prci.hProcess, &dwExitCode);
+ nErrorLevel = (INT)dwExitCode;
+ }
+ CloseHandle (prci.hProcess);
+ }
+ else
+ {
+ TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full));
+ error_bad_command (first);
+ dwExitCode = 1;
+ }
+
+ // restore console mode
+ SetConsoleMode (
+ GetStdHandle( STD_INPUT_HANDLE ),
+ ENABLE_PROCESSED_INPUT );
+ }
+
+ /* Get code page if it has been change */
+ InputCodePage= GetConsoleCP();
+ OutputCodePage = GetConsoleOutputCP();
+ SetConsoleTitle (szWindowTitle);
+
+ return dwExitCode;
}
@@ -489,70 +488,69 @@
* first - first word on command line
* rest - rest of command line
*/
-
INT
DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
{
- TCHAR *com;
- TCHAR *cp;
- LPTSTR param; /* pointer to command's parameters */
- INT cl;
- LPCOMMAND cmdptr;
- BOOL nointernal = FALSE;
- INT ret;
-
- TRACE ("DoCommand: (\'%s\' \'%s\')\n", debugstr_aw(first),
debugstr_aw(rest));
-
- /* full command line */
- com = cmd_alloc((_tcslen(first) + _tcslen(rest) + 2) * sizeof(TCHAR));
- if (com == NULL)
- {
- error_out_of_memory();
- return 1;
- }
-
- /* If present in the first word, these characters end the name of an
- * internal command and become the beginning of its parameters. */
- cp = first + _tcscspn(first, _T("\t +,/;=[]"));
-
- for (cl = 0; cl < (cp - first); cl++)
- {
- /* These characters do it too, but if one of them is present,
- * then we check to see if the word is a file name and skip
- * checking for internal commands if so.
- * This allows running programs with names like "echo.exe" */
- if (_tcschr(_T(".:\\"), first[cl]))
- {
- TCHAR tmp = *cp;
- *cp = _T('\0');
- nointernal = IsExistingFile(first);
- *cp = tmp;
- break;
- }
- }
-
- /* Scan internal command table */
- for (cmdptr = cmds; !nointernal && cmdptr->name; cmdptr++)
- {
- if (!_tcsnicmp(first, cmdptr->name, cl) && cmdptr->name[cl] ==
_T('\0'))
- {
- _tcscpy(com, first);
- _tcscat(com, rest);
- param = &com[cl];
-
- /* Skip over whitespace to rest of line, exclude 'echo' command */
- if (_tcsicmp(cmdptr->name, _T("echo")) != 0)
- while (_istspace(*param))
- param++;
- ret = cmdptr->func(param);
- cmd_free(com);
- return ret;
- }
- }
-
- ret = Execute(com, first, rest, Cmd);
- cmd_free(com);
- return ret;
+ TCHAR *com;
+ TCHAR *cp;
+ LPTSTR param; /* pointer to command's parameters */
+ INT cl;
+ LPCOMMAND cmdptr;
+ BOOL nointernal = FALSE;
+ INT ret;
+
+ TRACE ("DoCommand: (\'%s\' \'%s\')\n", debugstr_aw(first),
debugstr_aw(rest));
+
+ /* full command line */
+ com = cmd_alloc((_tcslen(first) + _tcslen(rest) + 2) * sizeof(TCHAR));
+ if (com == NULL)
+ {
+ error_out_of_memory();
+ return 1;
+ }
+
+ /* If present in the first word, these characters end the name of an
+ * internal command and become the beginning of its parameters. */
+ cp = first + _tcscspn(first, _T("\t +,/;=[]"));
+
+ for (cl = 0; cl < (cp - first); cl++)
+ {
+ /* These characters do it too, but if one of them is present,
+ * then we check to see if the word is a file name and skip
+ * checking for internal commands if so.
+ * This allows running programs with names like "echo.exe" */
+ if (_tcschr(_T(".:\\"), first[cl]))
+ {
+ TCHAR tmp = *cp;
+ *cp = _T('\0');
+ nointernal = IsExistingFile(first);
+ *cp = tmp;
+ break;
+ }
+ }
+
+ /* Scan internal command table */
+ for (cmdptr = cmds; !nointernal && cmdptr->name; cmdptr++)
+ {
+ if (!_tcsnicmp(first, cmdptr->name, cl) && cmdptr->name[cl] ==
_T('\0'))
+ {
+ _tcscpy(com, first);
+ _tcscat(com, rest);
+ param = &com[cl];
+
+ /* Skip over whitespace to rest of line, exclude 'echo' command */
+ if (_tcsicmp(cmdptr->name, _T("echo")) != 0)
+ while (_istspace(*param))
+ param++;
+ ret = cmdptr->func(param);
+ cmd_free(com);
+ return ret;
+ }
+ }
+
+ ret = Execute(com, first, rest, Cmd);
+ cmd_free(com);
+ return ret;
}
@@ -560,17 +558,16 @@
* process the command line and execute the appropriate functions
* full input/output redirection and piping are supported
*/
-
INT ParseCommandLine (LPTSTR cmd)
{
- INT Ret = 0;
- PARSED_COMMAND *Cmd = ParseCommand(cmd);
- if (Cmd)
- {
- Ret = ExecuteCommand(Cmd);
- FreeCommand(Cmd);
- }
- return Ret;
+ INT Ret = 0;
+ PARSED_COMMAND *Cmd = ParseCommand(cmd);
+ if (Cmd)
+ {
+ Ret = ExecuteCommand(Cmd);
+ FreeCommand(Cmd);
+ }
+ return Ret;
}
/* Execute a command without waiting for it to finish. If it's an internal
@@ -581,545 +578,545 @@
static HANDLE
ExecuteAsync(PARSED_COMMAND *Cmd)
{
- TCHAR CmdPath[MAX_PATH];
- TCHAR CmdParams[CMDLINE_LENGTH], *ParamsEnd;
- STARTUPINFO stui;
- PROCESS_INFORMATION prci;
-
- /* Get the path to cmd.exe */
- GetModuleFileName(NULL, CmdPath, MAX_PATH);
-
- /* Build the parameter string to pass to cmd.exe */
- ParamsEnd = _stpcpy(CmdParams, _T("/S/D/C\""));
- ParamsEnd = Unparse(Cmd, ParamsEnd, &CmdParams[CMDLINE_LENGTH - 2]);
- if (!ParamsEnd)
- {
- error_out_of_memory();
- return NULL;
- }
- _tcscpy(ParamsEnd, _T("\""));
-
- memset(&stui, 0, sizeof stui);
- stui.cb = sizeof(STARTUPINFO);
- if (!CreateProcess(CmdPath, CmdParams, NULL, NULL, TRUE, 0,
- NULL, NULL, &stui, &prci))
- {
- ErrorMessage(GetLastError(), NULL);
- return NULL;
- }
-
- CloseHandle(prci.hThread);
- return prci.hProcess;
+ TCHAR CmdPath[MAX_PATH];
+ TCHAR CmdParams[CMDLINE_LENGTH], *ParamsEnd;
+ STARTUPINFO stui;
+ PROCESS_INFORMATION prci;
+
+ /* Get the path to cmd.exe */
+ GetModuleFileName(NULL, CmdPath, MAX_PATH);
+
+ /* Build the parameter string to pass to cmd.exe */
+ ParamsEnd = _stpcpy(CmdParams, _T("/S/D/C\""));
+ ParamsEnd = Unparse(Cmd, ParamsEnd, &CmdParams[CMDLINE_LENGTH - 2]);
+ if (!ParamsEnd)
+ {
+ error_out_of_memory();
+ return NULL;
+ }
+ _tcscpy(ParamsEnd, _T("\""));
+
+ memset(&stui, 0, sizeof stui);
+ stui.cb = sizeof(STARTUPINFO);
+ if (!CreateProcess(CmdPath, CmdParams, NULL, NULL, TRUE, 0,
+ NULL, NULL, &stui, &prci))
+ {
+ ErrorMessage(GetLastError(), NULL);
+ return NULL;
+ }
+
+ CloseHandle(prci.hThread);
+ return prci.hProcess;
}
static VOID
ExecutePipeline(PARSED_COMMAND *Cmd)
{
#ifdef FEATURE_REDIRECTION
- HANDLE hInput = NULL;
- HANDLE hOldConIn = GetStdHandle(STD_INPUT_HANDLE);
- HANDLE hOldConOut = GetStdHandle(STD_OUTPUT_HANDLE);
- HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
- INT nProcesses = 0;
- DWORD dwExitCode;
-
- /* Do all but the last pipe command */
- do
- {
- HANDLE hPipeRead, hPipeWrite;
- if (nProcesses > (MAXIMUM_WAIT_OBJECTS - 2))
- {
- error_too_many_parameters(_T("|"));
- goto failed;
- }
-
- /* Create the pipe that this process will write into.
- * Make the handles non-inheritable initially, because this
- * process shouldn't inherit the reading handle. */
- if (!CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0))
- {
- error_no_pipe();
- goto failed;
- }
-
- /* The writing side of the pipe is STDOUT for this process */
- SetHandleInformation(hPipeWrite, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
- SetStdHandle(STD_OUTPUT_HANDLE, hPipeWrite);
-
- /* Execute it (error check is done later for easier cleanup) */
- hProcess[nProcesses] = ExecuteAsync(Cmd->Subcommands);
- CloseHandle(hPipeWrite);
- if (hInput)
- CloseHandle(hInput);
-
- /* The reading side of the pipe will be STDIN for the next process */
- SetHandleInformation(hPipeRead, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
- SetStdHandle(STD_INPUT_HANDLE, hPipeRead);
- hInput = hPipeRead;
-
- if (!hProcess[nProcesses])
- goto failed;
- nProcesses++;
-
- Cmd = Cmd->Subcommands->Next;
- } while (Cmd->Type == C_PIPE);
-
- /* The last process uses the original STDOUT */
- SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
- hProcess[nProcesses] = ExecuteAsync(Cmd);
- if (!hProcess[nProcesses])
- goto failed;
- nProcesses++;
- CloseHandle(hInput);
- SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
-
- /* Wait for all processes to complete */
- EnterCriticalSection(&ChildProcessRunningLock);
- WaitForMultipleObjects(nProcesses, hProcess, TRUE, INFINITE);
- LeaveCriticalSection(&ChildProcessRunningLock);
-
- /* Use the exit code of the last process in the pipeline */
- GetExitCodeProcess(hProcess[nProcesses - 1], &dwExitCode);
- nErrorLevel = (INT)dwExitCode;
-
- while (--nProcesses >= 0)
- CloseHandle(hProcess[nProcesses]);
- return;
+ HANDLE hInput = NULL;
+ HANDLE hOldConIn = GetStdHandle(STD_INPUT_HANDLE);
+ HANDLE hOldConOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ HANDLE hProcess[MAXIMUM_WAIT_OBJECTS];
+ INT nProcesses = 0;
+ DWORD dwExitCode;
+
+ /* Do all but the last pipe command */
+ do
+ {
+ HANDLE hPipeRead, hPipeWrite;
+ if (nProcesses > (MAXIMUM_WAIT_OBJECTS - 2))
+ {
+ error_too_many_parameters(_T("|"));
+ goto failed;
+ }
+
+ /* Create the pipe that this process will write into.
+ * Make the handles non-inheritable initially, because this
+ * process shouldn't inherit the reading handle. */
+ if (!CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0))
+ {
+ error_no_pipe();
+ goto failed;
+ }
+
+ /* The writing side of the pipe is STDOUT for this process */
+ SetHandleInformation(hPipeWrite, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
+ SetStdHandle(STD_OUTPUT_HANDLE, hPipeWrite);
+
+ /* Execute it (error check is done later for easier cleanup) */
+ hProcess[nProcesses] = ExecuteAsync(Cmd->Subcommands);
+ CloseHandle(hPipeWrite);
+ if (hInput)
+ CloseHandle(hInput);
+
+ /* The reading side of the pipe will be STDIN for the next process */
+ SetHandleInformation(hPipeRead, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
+ SetStdHandle(STD_INPUT_HANDLE, hPipeRead);
+ hInput = hPipeRead;
+
+ if (!hProcess[nProcesses])
+ goto failed;
+ nProcesses++;
+
+ Cmd = Cmd->Subcommands->Next;
+ } while (Cmd->Type == C_PIPE);
+
+ /* The last process uses the original STDOUT */
+ SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
+ hProcess[nProcesses] = ExecuteAsync(Cmd);
+ if (!hProcess[nProcesses])
+ goto failed;
+ nProcesses++;
+ CloseHandle(hInput);
+ SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
+
+ /* Wait for all processes to complete */
+ EnterCriticalSection(&ChildProcessRunningLock);
+ WaitForMultipleObjects(nProcesses, hProcess, TRUE, INFINITE);
+ LeaveCriticalSection(&ChildProcessRunningLock);
+
+ /* Use the exit code of the last process in the pipeline */
+ GetExitCodeProcess(hProcess[nProcesses - 1], &dwExitCode);
+ nErrorLevel = (INT)dwExitCode;
+
+ while (--nProcesses >= 0)
+ CloseHandle(hProcess[nProcesses]);
+ return;
failed:
- if (hInput)
- CloseHandle(hInput);
- while (--nProcesses >= 0)
- {
- TerminateProcess(hProcess[nProcesses], 0);
- CloseHandle(hProcess[nProcesses]);
- }
- SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
- SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
+ if (hInput)
+ CloseHandle(hInput);
+ while (--nProcesses >= 0)
+ {
+ TerminateProcess(hProcess[nProcesses], 0);
+ CloseHandle(hProcess[nProcesses]);
+ }
+ SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
+ SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
#endif
}
INT
ExecuteCommand(PARSED_COMMAND *Cmd)
{
- PARSED_COMMAND *Sub;
- LPTSTR First, Rest;
- INT Ret = 0;
-
- if (!PerformRedirection(Cmd->Redirections))
- return 1;
-
- switch (Cmd->Type)
- {
- case C_COMMAND:
- Ret = 1;
- First = DoDelayedExpansion(Cmd->Command.First);
- if (First)
- {
- Rest = DoDelayedExpansion(Cmd->Command.Rest);
- if (Rest)
- {
- Ret = DoCommand(First, Rest, Cmd);
- cmd_free(Rest);
- }
- cmd_free(First);
- }
- break;
- case C_QUIET:
- case C_BLOCK:
- case C_MULTI:
- for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
- Ret = ExecuteCommand(Sub);
- break;
- case C_IFFAILURE:
- Sub = Cmd->Subcommands;
- Ret = ExecuteCommand(Sub);
- if (Ret != 0)
- {
- nErrorLevel = Ret;
- Ret = ExecuteCommand(Sub->Next);
- }
- break;
- case C_IFSUCCESS:
- Sub = Cmd->Subcommands;
- Ret = ExecuteCommand(Sub);
- if (Ret == 0)
- Ret = ExecuteCommand(Sub->Next);
- break;
- case C_PIPE:
- ExecutePipeline(Cmd);
- break;
- case C_IF:
- Ret = ExecuteIf(Cmd);
- break;
- case C_FOR:
- Ret = ExecuteFor(Cmd);
- break;
- }
-
- UndoRedirection(Cmd->Redirections, NULL);
- return Ret;
+ PARSED_COMMAND *Sub;
+ LPTSTR First, Rest;
+ INT Ret = 0;
+
+ if (!PerformRedirection(Cmd->Redirections))
+ return 1;
+
+ switch (Cmd->Type)
+ {
+ case C_COMMAND:
+ Ret = 1;
+ First = DoDelayedExpansion(Cmd->Command.First);
+ if (First)
+ {
+ Rest = DoDelayedExpansion(Cmd->Command.Rest);
+ if (Rest)
+ {
+ Ret = DoCommand(First, Rest, Cmd);
+ cmd_free(Rest);
+ }
+ cmd_free(First);
+ }
+ break;
+ case C_QUIET:
+ case C_BLOCK:
+ case C_MULTI:
+ for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
+ Ret = ExecuteCommand(Sub);
+ break;
+ case C_IFFAILURE:
+ Sub = Cmd->Subcommands;
+ Ret = ExecuteCommand(Sub);
+ if (Ret != 0)
+ {
+ nErrorLevel = Ret;
+ Ret = ExecuteCommand(Sub->Next);
+ }
+ break;
+ case C_IFSUCCESS:
+ Sub = Cmd->Subcommands;
+ Ret = ExecuteCommand(Sub);
+ if (Ret == 0)
+ Ret = ExecuteCommand(Sub->Next);
+ break;
+ case C_PIPE:
+ ExecutePipeline(Cmd);
+ break;
+ case C_IF:
+ Ret = ExecuteIf(Cmd);
+ break;
+ case C_FOR:
+ Ret = ExecuteFor(Cmd);
+ break;
+ }
+
+ UndoRedirection(Cmd->Redirections, NULL);
+ return Ret;
}
LPTSTR
GetEnvVar(LPCTSTR varName)
{
- static LPTSTR ret = NULL;
- UINT size;
-
- cmd_free(ret);
- ret = NULL;
- size = GetEnvironmentVariable(varName, NULL, 0);
- if (size > 0)
- {
- ret = cmd_alloc(size * sizeof(TCHAR));
- if (ret != NULL)
- GetEnvironmentVariable(varName, ret, size + 1);
- }
- return ret;
+ static LPTSTR ret = NULL;
+ UINT size;
+
+ cmd_free(ret);
+ ret = NULL;
+ size = GetEnvironmentVariable(varName, NULL, 0);
+ if (size > 0)
+ {
+ ret = cmd_alloc(size * sizeof(TCHAR));
+ if (ret != NULL)
+ GetEnvironmentVariable(varName, ret, size + 1);
+ }
+ return ret;
}
LPCTSTR
GetEnvVarOrSpecial(LPCTSTR varName)
{
- static TCHAR ret[MAX_PATH];
-
- LPTSTR var = GetEnvVar(varName);
- if (var)
- return var;
-
- /* env var doesn't exist, look for a "special" one */
- /* %CD% */
- if (_tcsicmp(varName,_T("cd")) ==0)
- {
- GetCurrentDirectory(MAX_PATH, ret);
- return ret;
- }
- /* %TIME% */
- else if (_tcsicmp(varName,_T("time")) ==0)
- {
- return GetTimeString();
- }
- /* %DATE% */
- else if (_tcsicmp(varName,_T("date")) ==0)
- {
- return GetDateString();
- }
-
- /* %RANDOM% */
- else if (_tcsicmp(varName,_T("random")) ==0)
- {
- /* Get random number */
- _itot(rand(),ret,10);
- return ret;
- }
-
- /* %CMDCMDLINE% */
- else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
- {
- return GetCommandLine();
- }
-
- /* %CMDEXTVERSION% */
- else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
- {
- /* Set version number to 2 */
- _itot(2,ret,10);
- return ret;
- }
-
- /* %ERRORLEVEL% */
- else if (_tcsicmp(varName,_T("errorlevel")) ==0)
- {
- _itot(nErrorLevel,ret,10);
- return ret;
- }
-
- return NULL;
+ static TCHAR ret[MAX_PATH];
+
+ LPTSTR var = GetEnvVar(varName);
+ if (var)
+ return var;
+
+ /* env var doesn't exist, look for a "special" one */
+ /* %CD% */
+ if (_tcsicmp(varName,_T("cd")) ==0)
+ {
+ GetCurrentDirectory(MAX_PATH, ret);
+ return ret;
+ }
+ /* %TIME% */
+ else if (_tcsicmp(varName,_T("time")) ==0)
+ {
+ return GetTimeString();
+ }
+ /* %DATE% */
+ else if (_tcsicmp(varName,_T("date")) ==0)
+ {
+ return GetDateString();
+ }
+
+ /* %RANDOM% */
+ else if (_tcsicmp(varName,_T("random")) ==0)
+ {
+ /* Get random number */
+ _itot(rand(),ret,10);
+ return ret;
+ }
+
+ /* %CMDCMDLINE% */
+ else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
+ {
+ return GetCommandLine();
+ }
+
+ /* %CMDEXTVERSION% */
+ else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
+ {
+ /* Set version number to 2 */
+ _itot(2,ret,10);
+ return ret;
+ }
+
+ /* %ERRORLEVEL% */
+ else if (_tcsicmp(varName,_T("errorlevel")) ==0)
+ {
+ _itot(nErrorLevel,ret,10);
+ return ret;
+ }
+
+ return NULL;
}
/* Handle the %~var syntax */
static LPTSTR
GetEnhancedVar(TCHAR **pFormat, LPTSTR (*GetVar)(TCHAR, BOOL *))
{
- static const TCHAR ModifierTable[] = _T("dpnxfsatz");
- enum {
- M_DRIVE = 1, /* D: drive letter */
- M_PATH = 2, /* P: path */
- M_NAME = 4, /* N: filename */
- M_EXT = 8, /* X: extension */
- M_FULL = 16, /* F: full path (drive+path+name+ext) */
- M_SHORT = 32, /* S: full path (drive+path+name+ext), use short names */
- M_ATTR = 64, /* A: attributes */
- M_TIME = 128, /* T: modification time */
- M_SIZE = 256, /* Z: file size */
- } Modifiers = 0;
-
- TCHAR *Format, *FormatEnd;
- TCHAR *PathVarName = NULL;
- LPTSTR Variable;
- TCHAR *VarEnd;
- BOOL VariableIsParam0;
- TCHAR FullPath[MAX_PATH];
- TCHAR FixedPath[MAX_PATH], *Filename, *Extension;
- HANDLE hFind;
- WIN32_FIND_DATA w32fd;
- TCHAR *In, *Out;
-
- static TCHAR Result[CMDLINE_LENGTH];
-
- /* There is ambiguity between modifier characters and FOR variables;
- * the rule that cmd uses is to pick the longest possible match.
- * For example, if there is a %n variable, then out of %~anxnd,
- * %~anxn will be substituted rather than just %~an. */
-
- /* First, go through as many modifier characters as possible */
- FormatEnd = Format = *pFormat;
- while (*FormatEnd && _tcschr(ModifierTable, _totlower(*FormatEnd)))
- FormatEnd++;
-
- if (*FormatEnd == _T('$'))
- {
- /* $PATH: syntax */
- PathVarName = FormatEnd + 1;
- FormatEnd = _tcschr(PathVarName, _T(':'));
- if (!FormatEnd)
- return NULL;
-
- /* Must be immediately followed by the variable */
- Variable = GetVar(*++FormatEnd, &VariableIsParam0);
- if (!Variable)
- return NULL;
- }
- else
- {
- /* Backtrack if necessary to get a variable name match */
- while (!(Variable = GetVar(*FormatEnd, &VariableIsParam0)))
- {
- if (FormatEnd == Format)
- return NULL;
- FormatEnd--;
- }
- }
-
- for (; Format < FormatEnd && *Format != _T('$'); Format++)
- Modifiers |= 1 << (_tcschr(ModifierTable, _totlower(*Format)) - ModifierTable);
-
- *pFormat = FormatEnd + 1;
-
- /* Exclude the leading and trailing quotes */
- VarEnd = &Variable[_tcslen(Variable)];
- if (*Variable == _T('"'))
- {
- Variable++;
- if (VarEnd > Variable && VarEnd[-1] == _T('"'))
- VarEnd--;
- }
-
- if ((char *)VarEnd - (char *)Variable >= sizeof Result)
- return _T("");
- memcpy(Result, Variable, (char *)VarEnd - (char *)Variable);
- Result[VarEnd - Variable] = _T('\0');
-
- if (PathVarName)
- {
- /* $PATH: syntax - search the directories listed in the
- * specified environment variable for the file */
- LPTSTR PathVar;
- FormatEnd[-1] = _T('\0');
- PathVar = GetEnvVar(PathVarName);
- FormatEnd[-1] = _T(':');
- if (!PathVar ||
- !SearchPath(PathVar, Result, NULL, MAX_PATH, FullPath, NULL))
- {
- return _T("");
- }
- }
- else if (Modifiers == 0)
- {
- /* For plain %~var with no modifiers, just return the variable without quotes */
- return Result;
- }
- else if (VariableIsParam0)
- {
- /* Special case: If the variable is %0 and modifier characters are present,
- * use the batch file's path (which includes the .bat/.cmd extension)
- * rather than the actual %0 variable (which might not). */
- _tcscpy(FullPath, bc->BatchFilePath);
- }
- else
- {
- /* Convert the variable, now without quotes, to a full path */
- if (!GetFullPathName(Result, MAX_PATH, FullPath, NULL))
- return _T("");
- }
-
- /* Next step is to change the path to fix letter case (e.g.
- * C:\ReAcToS -> C:\ReactOS) and, if requested with the S modifier,
- * replace long filenames with short. */
-
- In = FullPath;
- Out = FixedPath;
-
- /* Copy drive letter */
- *Out++ = *In++;
- *Out++ = *In++;
- *Out++ = *In++;
- /* Loop over each \-separated component in the path */
- do {
- TCHAR *Next = _tcschr(In, _T('\\'));
- if (Next)
- *Next++ = _T('\0');
- /* Use FindFirstFile to get the correct name */
- if (Out + _tcslen(In) + 1 >= &FixedPath[MAX_PATH])
- return _T("");
- _tcscpy(Out, In);
- hFind = FindFirstFile(FixedPath, &w32fd);
- /* If it doesn't exist, just leave the name as it was given */
- if (hFind != INVALID_HANDLE_VALUE)
- {
- LPTSTR FixedComponent = w32fd.cFileName;
- if (*w32fd.cAlternateFileName &&
- ((Modifiers & M_SHORT) || !_tcsicmp(In, w32fd.cAlternateFileName)))
- {
- FixedComponent = w32fd.cAlternateFileName;
- }
- FindClose(hFind);
-
- if (Out + _tcslen(FixedComponent) + 1 >= &FixedPath[MAX_PATH])
- return _T("");
- _tcscpy(Out, FixedComponent);
- }
- Filename = Out;
- Out += _tcslen(Out);
- *Out++ = _T('\\');
-
- In = Next;
- } while (In != NULL);
- Out[-1] = _T('\0');
-
- /* Build the result string. Start with attributes, modification time, and
- * file size. If the file didn't exist, these fields will all be empty. */
- Out = Result;
- if (hFind != INVALID_HANDLE_VALUE)
- {
- if (Modifiers & M_ATTR)
- {
- static const struct {
- TCHAR Character;
- WORD Value;
- } *Attrib, Table[] = {
- { _T('d'), FILE_ATTRIBUTE_DIRECTORY },
- { _T('r'), FILE_ATTRIBUTE_READONLY },
- { _T('a'), FILE_ATTRIBUTE_ARCHIVE },
- { _T('h'), FILE_ATTRIBUTE_HIDDEN },
- { _T('s'), FILE_ATTRIBUTE_SYSTEM },
- { _T('c'), FILE_ATTRIBUTE_COMPRESSED },
- { _T('o'), FILE_ATTRIBUTE_OFFLINE },
- { _T('t'), FILE_ATTRIBUTE_TEMPORARY },
- { _T('l'), FILE_ATTRIBUTE_REPARSE_POINT },
- };
- for (Attrib = Table; Attrib != &Table[9]; Attrib++)
- {
- *Out++ = w32fd.dwFileAttributes & Attrib->Value
- ? Attrib->Character
- : _T('-');
- }
- *Out++ = _T(' ');
- }
- if (Modifiers & M_TIME)
- {
- FILETIME ft;
- SYSTEMTIME st;
- FileTimeToLocalFileTime(&w32fd.ftLastWriteTime, &ft);
- FileTimeToSystemTime(&ft, &st);
-
- Out += FormatDate(Out, &st, TRUE);
- *Out++ = _T(' ');
- Out += FormatTime(Out, &st);
- *Out++ = _T(' ');
- }
- if (Modifiers & M_SIZE)
- {
- ULARGE_INTEGER Size;
- Size.LowPart = w32fd.nFileSizeLow;
- Size.HighPart = w32fd.nFileSizeHigh;
- Out += _stprintf(Out, _T("%I64u "), Size.QuadPart);
- }
- }
-
- /* When using the path-searching syntax or the S modifier,
- * at least part of the file path is always included.
- * If none of the DPNX modifiers are present, include the full path */
- if (PathVarName || (Modifiers & M_SHORT))
- if ((Modifiers & (M_DRIVE | M_PATH | M_NAME | M_EXT)) == 0)
- Modifiers |= M_FULL;
-
- /* Now add the requested parts of the name.
- * With the F modifier, add all parts to form the full path. */
- Extension = _tcsrchr(Filename, _T('.'));
- if (Modifiers & (M_DRIVE | M_FULL))
- {
- *Out++ = FixedPath[0];
- *Out++ = FixedPath[1];
- }
- if (Modifiers & (M_PATH | M_FULL))
- {
- memcpy(Out, &FixedPath[2], (char *)Filename - (char *)&FixedPath[2]);
- Out += Filename - &FixedPath[2];
- }
- if (Modifiers & (M_NAME | M_FULL))
- {
- while (*Filename && Filename != Extension)
- *Out++ = *Filename++;
- }
- if (Modifiers & (M_EXT | M_FULL))
- {
- if (Extension)
- Out = _stpcpy(Out, Extension);
- }
-
- /* Trim trailing space which otherwise would appear as a
- * result of using the A/T/Z modifiers but no others. */
- while (Out != &Result[0] && Out[-1] == _T(' '))
- Out--;
- *Out = _T('\0');
-
- return Result;
+ static const TCHAR ModifierTable[] = _T("dpnxfsatz");
+ enum {
+ M_DRIVE = 1, /* D: drive letter */
+ M_PATH = 2, /* P: path */
+ M_NAME = 4, /* N: filename */
+ M_EXT = 8, /* X: extension */
+ M_FULL = 16, /* F: full path (drive+path+name+ext) */
+ M_SHORT = 32, /* S: full path (drive+path+name+ext), use short names */
+ M_ATTR = 64, /* A: attributes */
+ M_TIME = 128, /* T: modification time */
+ M_SIZE = 256, /* Z: file size */
+ } Modifiers = 0;
+
+ TCHAR *Format, *FormatEnd;
+ TCHAR *PathVarName = NULL;
+ LPTSTR Variable;
+ TCHAR *VarEnd;
+ BOOL VariableIsParam0;
+ TCHAR FullPath[MAX_PATH];
+ TCHAR FixedPath[MAX_PATH], *Filename, *Extension;
+ HANDLE hFind;
+ WIN32_FIND_DATA w32fd;
+ TCHAR *In, *Out;
+
+ static TCHAR Result[CMDLINE_LENGTH];
+
+ /* There is ambiguity between modifier characters and FOR variables;
+ * the rule that cmd uses is to pick the longest possible match.
+ * For example, if there is a %n variable, then out of %~anxnd,
+ * %~anxn will be substituted rather than just %~an. */
+
+ /* First, go through as many modifier characters as possible */
+ FormatEnd = Format = *pFormat;
+ while (*FormatEnd && _tcschr(ModifierTable, _totlower(*FormatEnd)))
+ FormatEnd++;
+
+ if (*FormatEnd == _T('$'))
+ {
+ /* $PATH: syntax */
+ PathVarName = FormatEnd + 1;
+ FormatEnd = _tcschr(PathVarName, _T(':'));
+ if (!FormatEnd)
+ return NULL;
+
+ /* Must be immediately followed by the variable */
+ Variable = GetVar(*++FormatEnd, &VariableIsParam0);
+ if (!Variable)
+ return NULL;
+ }
+ else
+ {
+ /* Backtrack if necessary to get a variable name match */
+ while (!(Variable = GetVar(*FormatEnd, &VariableIsParam0)))
+ {
+ if (FormatEnd == Format)
+ return NULL;
+ FormatEnd--;
+ }
+ }
+
+ for (; Format < FormatEnd && *Format != _T('$'); Format++)
+ Modifiers |= 1 << (_tcschr(ModifierTable, _totlower(*Format)) -
ModifierTable);
+
+ *pFormat = FormatEnd + 1;
+
+ /* Exclude the leading and trailing quotes */
+ VarEnd = &Variable[_tcslen(Variable)];
+ if (*Variable == _T('"'))
+ {
+ Variable++;
+ if (VarEnd > Variable && VarEnd[-1] == _T('"'))
+ VarEnd--;
+ }
+
+ if ((char *)VarEnd - (char *)Variable >= sizeof Result)
+ return _T("");
+ memcpy(Result, Variable, (char *)VarEnd - (char *)Variable);
+ Result[VarEnd - Variable] = _T('\0');
+
+ if (PathVarName)
+ {
+ /* $PATH: syntax - search the directories listed in the
+ * specified environment variable for the file */
+ LPTSTR PathVar;
+ FormatEnd[-1] = _T('\0');
+ PathVar = GetEnvVar(PathVarName);
+ FormatEnd[-1] = _T(':');
+ if (!PathVar ||
+ !SearchPath(PathVar, Result, NULL, MAX_PATH, FullPath, NULL))
+ {
+ return _T("");
+ }
+ }
+ else if (Modifiers == 0)
+ {
+ /* For plain %~var with no modifiers, just return the variable without quotes */
+ return Result;
+ }
+ else if (VariableIsParam0)
+ {
+ /* Special case: If the variable is %0 and modifier characters are present,
+ * use the batch file's path (which includes the .bat/.cmd extension)
+ * rather than the actual %0 variable (which might not). */
+ _tcscpy(FullPath, bc->BatchFilePath);
+ }
+ else
+ {
+ /* Convert the variable, now without quotes, to a full path */
+ if (!GetFullPathName(Result, MAX_PATH, FullPath, NULL))
+ return _T("");
+ }
+
+ /* Next step is to change the path to fix letter case (e.g.
+ * C:\ReAcToS -> C:\ReactOS) and, if requested with the S modifier,
+ * replace long filenames with short. */
+
+ In = FullPath;
+ Out = FixedPath;
+
+ /* Copy drive letter */
+ *Out++ = *In++;
+ *Out++ = *In++;
+ *Out++ = *In++;
+ /* Loop over each \-separated component in the path */
+ do {
+ TCHAR *Next = _tcschr(In, _T('\\'));
+ if (Next)
+ *Next++ = _T('\0');
+ /* Use FindFirstFile to get the correct name */
+ if (Out + _tcslen(In) + 1 >= &FixedPath[MAX_PATH])
+ return _T("");
+ _tcscpy(Out, In);
+ hFind = FindFirstFile(FixedPath, &w32fd);
+ /* If it doesn't exist, just leave the name as it was given */
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ LPTSTR FixedComponent = w32fd.cFileName;
+ if (*w32fd.cAlternateFileName &&
+ ((Modifiers & M_SHORT) || !_tcsicmp(In, w32fd.cAlternateFileName)))
+ {
+ FixedComponent = w32fd.cAlternateFileName;
+ }
+ FindClose(hFind);
+
+ if (Out + _tcslen(FixedComponent) + 1 >= &FixedPath[MAX_PATH])
+ return _T("");
+ _tcscpy(Out, FixedComponent);
+ }
+ Filename = Out;
+ Out += _tcslen(Out);
+ *Out++ = _T('\\');
+
+ In = Next;
+ } while (In != NULL);
+ Out[-1] = _T('\0');
+
+ /* Build the result string. Start with attributes, modification time, and
+ * file size. If the file didn't exist, these fields will all be empty. */
+ Out = Result;
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ if (Modifiers & M_ATTR)
+ {
+ static const struct {
+ TCHAR Character;
+ WORD Value;
+ } *Attrib, Table[] = {
+ { _T('d'), FILE_ATTRIBUTE_DIRECTORY },
+ { _T('r'), FILE_ATTRIBUTE_READONLY },
+ { _T('a'), FILE_ATTRIBUTE_ARCHIVE },
+ { _T('h'), FILE_ATTRIBUTE_HIDDEN },
+ { _T('s'), FILE_ATTRIBUTE_SYSTEM },
+ { _T('c'), FILE_ATTRIBUTE_COMPRESSED },
+ { _T('o'), FILE_ATTRIBUTE_OFFLINE },
+ { _T('t'), FILE_ATTRIBUTE_TEMPORARY },
+ { _T('l'), FILE_ATTRIBUTE_REPARSE_POINT },
+ };
+ for (Attrib = Table; Attrib != &Table[9]; Attrib++)
+ {
+ *Out++ = w32fd.dwFileAttributes & Attrib->Value
+ ? Attrib->Character
+ : _T('-');
+ }
+ *Out++ = _T(' ');
+ }
+ if (Modifiers & M_TIME)
+ {
+ FILETIME ft;
+ SYSTEMTIME st;
+ FileTimeToLocalFileTime(&w32fd.ftLastWriteTime, &ft);
+ FileTimeToSystemTime(&ft, &st);
+
+ Out += FormatDate(Out, &st, TRUE);
+ *Out++ = _T(' ');
+ Out += FormatTime(Out, &st);
+ *Out++ = _T(' ');
+ }
+ if (Modifiers & M_SIZE)
+ {
+ ULARGE_INTEGER Size;
+ Size.LowPart = w32fd.nFileSizeLow;
+ Size.HighPart = w32fd.nFileSizeHigh;
+ Out += _stprintf(Out, _T("%I64u "), Size.QuadPart);
+ }
+ }
+
+ /* When using the path-searching syntax or the S modifier,
+ * at least part of the file path is always included.
+ * If none of the DPNX modifiers are present, include the full path */
+ if (PathVarName || (Modifiers & M_SHORT))
+ if ((Modifiers & (M_DRIVE | M_PATH | M_NAME | M_EXT)) == 0)
+ Modifiers |= M_FULL;
+
+ /* Now add the requested parts of the name.
+ * With the F modifier, add all parts to form the full path. */
+ Extension = _tcsrchr(Filename, _T('.'));
+ if (Modifiers & (M_DRIVE | M_FULL))
+ {
+ *Out++ = FixedPath[0];
+ *Out++ = FixedPath[1];
+ }
+ if (Modifiers & (M_PATH | M_FULL))
+ {
+ memcpy(Out, &FixedPath[2], (char *)Filename - (char *)&FixedPath[2]);
+ Out += Filename - &FixedPath[2];
+ }
+ if (Modifiers & (M_NAME | M_FULL))
+ {
+ while (*Filename && Filename != Extension)
+ *Out++ = *Filename++;
+ }
+ if (Modifiers & (M_EXT | M_FULL))
+ {
+ if (Extension)
+ Out = _stpcpy(Out, Extension);
+ }
+
+ /* Trim trailing space which otherwise would appear as a
+ * result of using the A/T/Z modifiers but no others. */
+ while (Out != &Result[0] && Out[-1] == _T(' '))
+ Out--;
+ *Out = _T('\0');
+
+ return Result;
}
LPCTSTR
GetBatchVar(TCHAR *varName, UINT *varNameLen)
{
- LPCTSTR ret;
- TCHAR *varNameEnd;
- BOOL dummy;
-
- *varNameLen = 1;
-
- switch ( *varName )
- {
- case _T('~'):
- varNameEnd = varName + 1;
- ret = GetEnhancedVar(&varNameEnd, FindArg);
- if (!ret)
- {
- error_syntax(varName);
- return NULL;
- }
- *varNameLen = varNameEnd - varName;
- return ret;
- case _T('0'):
- case _T('1'):
- case _T('2'):
- case _T('3'):
- case _T('4'):
- case _T('5'):
- case _T('6'):
- case _T('7'):
- case _T('8'):
- case _T('9'):
- return FindArg(*varName, &dummy);
+ LPCTSTR ret;
+ TCHAR *varNameEnd;
+ BOOL dummy;
+
+ *varNameLen = 1;
+
+ switch ( *varName )
+ {
+ case _T('~'):
+ varNameEnd = varName + 1;
+ ret = GetEnhancedVar(&varNameEnd, FindArg);
+ if (!ret)
+ {
+ error_syntax(varName);
+ return NULL;
+ }
+ *varNameLen = varNameEnd - varName;
+ return ret;
+ case _T('0'):
+ case _T('1'):
+ case _T('2'):
+ case _T('3'):
+ case _T('4'):
+ case _T('5'):
+ case _T('6'):
+ case _T('7'):
+ case _T('8'):
+ case _T('9'):
+ return FindArg(*varName, &dummy);
case _T('*'):
//
@@ -1127,161 +1124,161 @@
//
return bc->raw_params;
- case _T('%'):
- return _T("%");
- }
- return NULL;
+ case _T('%'):
+ return _T("%");
+ }
+ return NULL;
}
BOOL
SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim)
{
#define APPEND(From, Length) { \
- if (Dest + (Length) > DestEnd) \
- goto too_long; \
- memcpy(Dest, From, (Length) * sizeof(TCHAR)); \
- Dest += Length; }
+ if (Dest + (Length) > DestEnd) \
+ goto too_long; \
+ memcpy(Dest, From, (Length) * sizeof(TCHAR)); \
+ Dest += Length; }
#define APPEND1(Char) { \
- if (Dest >= DestEnd) \
- goto too_long; \
- *Dest++ = Char; }
-
- TCHAR *DestEnd = Dest + CMDLINE_LENGTH - 1;
- const TCHAR *Var;
- int VarLength;
- TCHAR *SubstStart;
- TCHAR EndChr;
- while (*Src)
- {
- if (*Src != Delim)
- {
- APPEND1(*Src++)
- continue;
- }
-
- Src++;
- if (bc && Delim == _T('%'))
- {
- UINT NameLen;
- Var = GetBatchVar(Src, &NameLen);
- if (Var != NULL)
- {
- VarLength = _tcslen(Var);
- APPEND(Var, VarLength)
- Src += NameLen;
- continue;
- }
- }
-
- /* Find the end of the variable name. A colon (:) will usually
- * end the name and begin the optional modifier, but not if it
- * is immediately followed by the delimiter (%VAR:%). */
- SubstStart = Src;
- while (*Src != Delim && !(*Src == _T(':') && Src[1] != Delim))
- {
- if (!*Src)
- goto bad_subst;
- Src++;
- }
-
- EndChr = *Src;
- *Src = _T('\0');
- Var = GetEnvVarOrSpecial(SubstStart);
- *Src++ = EndChr;
- if (Var == NULL)
- {
- /* In a batch file, %NONEXISTENT% "expands" to an empty string */
- if (bc)
- continue;
- goto bad_subst;
- }
- VarLength = _tcslen(Var);
-
- if (EndChr == Delim)
- {
- /* %VAR% - use as-is */
- APPEND(Var, VarLength)
- }
- else if (*Src == _T('~'))
- {
- /* %VAR:~[start][,length]% - substring
- * Negative values are offsets from the end */
- int Start = _tcstol(Src + 1, &Src, 0);
- int End = VarLength;
- if (Start < 0)
- Start += VarLength;
- Start = max(Start, 0);
- Start = min(Start, VarLength);
- if (*Src == _T(','))
- {
- End = _tcstol(Src + 1, &Src, 0);
- End += (End < 0) ? VarLength : Start;
- End = max(End, Start);
- End = min(End, VarLength);
- }
- if (*Src++ != Delim)
- goto bad_subst;
- APPEND(&Var[Start], End - Start);
- }
- else
- {
- /* %VAR:old=new% - replace all occurrences of old with new
- * %VAR:*old=new% - replace first occurrence only,
- * and remove everything before it */
- TCHAR *Old, *New;
- DWORD OldLength, NewLength;
- BOOL Star = FALSE;
- int LastMatch = 0, i = 0;
-
- if (*Src == _T('*'))
- {
- Star = TRUE;
- Src++;
- }
-
- /* the string to replace may contain the delimiter */
- Src = _tcschr(Old = Src, _T('='));
- if (Src == NULL)
- goto bad_subst;
- OldLength = Src++ - Old;
- if (OldLength == 0)
- goto bad_subst;
-
- Src = _tcschr(New = Src, Delim);
- if (Src == NULL)
- goto bad_subst;
- NewLength = Src++ - New;
-
- while (i < VarLength)
- {
- if (_tcsnicmp(&Var[i], Old, OldLength) == 0)
- {
- if (!Star)
- APPEND(&Var[LastMatch], i - LastMatch)
- APPEND(New, NewLength)
- i += OldLength;
- LastMatch = i;
- if (Star)
- break;
- continue;
- }
- i++;
- }
- APPEND(&Var[LastMatch], VarLength - LastMatch)
- }
- continue;
-
- bad_subst:
- Src = SubstStart;
- if (!bc)
- APPEND1(Delim)
- }
- *Dest = _T('\0');
- return TRUE;
+ if (Dest >= DestEnd) \
+ goto too_long; \
+ *Dest++ = Char; }
+
+ TCHAR *DestEnd = Dest + CMDLINE_LENGTH - 1;
+ const TCHAR *Var;
+ int VarLength;
+ TCHAR *SubstStart;
+ TCHAR EndChr;
+ while (*Src)
+ {
+ if (*Src != Delim)
+ {
+ APPEND1(*Src++)
+ continue;
+ }
+
+ Src++;
+ if (bc && Delim == _T('%'))
+ {
+ UINT NameLen;
+ Var = GetBatchVar(Src, &NameLen);
+ if (Var != NULL)
+ {
+ VarLength = _tcslen(Var);
+ APPEND(Var, VarLength)
+ Src += NameLen;
+ continue;
+ }
+ }
+
+ /* Find the end of the variable name. A colon (:) will usually
+ * end the name and begin the optional modifier, but not if it
+ * is immediately followed by the delimiter (%VAR:%). */
+ SubstStart = Src;
+ while (*Src != Delim && !(*Src == _T(':') && Src[1] !=
Delim))
+ {
+ if (!*Src)
+ goto bad_subst;
+ Src++;
+ }
+
+ EndChr = *Src;
+ *Src = _T('\0');
+ Var = GetEnvVarOrSpecial(SubstStart);
+ *Src++ = EndChr;
+ if (Var == NULL)
+ {
+ /* In a batch file, %NONEXISTENT% "expands" to an empty string */
+ if (bc)
+ continue;
+ goto bad_subst;
+ }
+ VarLength = _tcslen(Var);
+
+ if (EndChr == Delim)
+ {
+ /* %VAR% - use as-is */
+ APPEND(Var, VarLength)
+ }
+ else if (*Src == _T('~'))
+ {
+ /* %VAR:~[start][,length]% - substring
+ * Negative values are offsets from the end */
+ int Start = _tcstol(Src + 1, &Src, 0);
+ int End = VarLength;
+ if (Start < 0)
+ Start += VarLength;
+ Start = max(Start, 0);
+ Start = min(Start, VarLength);
+ if (*Src == _T(','))
+ {
+ End = _tcstol(Src + 1, &Src, 0);
+ End += (End < 0) ? VarLength : Start;
+ End = max(End, Start);
+ End = min(End, VarLength);
+ }
+ if (*Src++ != Delim)
+ goto bad_subst;
+ APPEND(&Var[Start], End - Start);
+ }
+ else
+ {
+ /* %VAR:old=new% - replace all occurrences of old with new
+ * %VAR:*old=new% - replace first occurrence only,
+ * and remove everything before it */
+ TCHAR *Old, *New;
+ DWORD OldLength, NewLength;
+ BOOL Star = FALSE;
+ int LastMatch = 0, i = 0;
+
+ if (*Src == _T('*'))
+ {
+ Star = TRUE;
+ Src++;
+ }
+
+ /* the string to replace may contain the delimiter */
+ Src = _tcschr(Old = Src, _T('='));
+ if (Src == NULL)
+ goto bad_subst;
+ OldLength = Src++ - Old;
+ if (OldLength == 0)
+ goto bad_subst;
+
+ Src = _tcschr(New = Src, Delim);
+ if (Src == NULL)
+ goto bad_subst;
+ NewLength = Src++ - New;
+
+ while (i < VarLength)
+ {
+ if (_tcsnicmp(&Var[i], Old, OldLength) == 0)
+ {
+ if (!Star)
+ APPEND(&Var[LastMatch], i - LastMatch)
+ APPEND(New, NewLength)
+ i += OldLength;
+ LastMatch = i;
+ if (Star)
+ break;
+ continue;
+ }
+ i++;
+ }
+ APPEND(&Var[LastMatch], VarLength - LastMatch)
+ }
+ continue;
+
+ bad_subst:
+ Src = SubstStart;
+ if (!bc)
+ APPEND1(Delim)
+ }
+ *Dest = _T('\0');
+ return TRUE;
too_long:
- ConOutResPrintf(STRING_ALIAS_ERROR);
- nErrorLevel = 9023;
- return FALSE;
+ ConOutResPrintf(STRING_ALIAS_ERROR);
+ nErrorLevel = 9023;
+ return FALSE;
#undef APPEND
#undef APPEND1
}
@@ -1289,69 +1286,71 @@
/* Search the list of FOR contexts for a variable */
static LPTSTR FindForVar(TCHAR Var, BOOL *IsParam0)
{
- FOR_CONTEXT *Ctx;
- *IsParam0 = FALSE;
- for (Ctx = fc; Ctx != NULL; Ctx = Ctx->prev)
- if ((UINT)(Var - Ctx->firstvar) < Ctx->varcount)
- return Ctx->values[Var - Ctx->firstvar];
- return NULL;
+ FOR_CONTEXT *Ctx;
+ *IsParam0 = FALSE;
+ for (Ctx = fc; Ctx != NULL; Ctx = Ctx->prev)
+ {
+ if ((UINT)(Var - Ctx->firstvar) < Ctx->varcount)
+ return Ctx->values[Var - Ctx->firstvar];
+ }
+ return NULL;
}
BOOL
SubstituteForVars(TCHAR *Src, TCHAR *Dest)
{
- TCHAR *DestEnd = &Dest[CMDLINE_LENGTH - 1];
- while (*Src)
- {
- if (Src[0] == _T('%'))
- {
- BOOL Dummy;
- LPTSTR End = &Src[2];
- LPTSTR Value = NULL;
-
- if (Src[1] == _T('~'))
- Value = GetEnhancedVar(&End, FindForVar);
-
- if (!Value)
- Value = FindForVar(Src[1], &Dummy);
-
- if (Value)
- {
- if (Dest + _tcslen(Value) > DestEnd)
- return FALSE;
- Dest = _stpcpy(Dest, Value);
- Src = End;
- continue;
- }
- }
- /* Not a variable; just copy the character */
- if (Dest >= DestEnd)
- return FALSE;
- *Dest++ = *Src++;
- }
- *Dest = _T('\0');
- return TRUE;
+ TCHAR *DestEnd = &Dest[CMDLINE_LENGTH - 1];
+ while (*Src)
+ {
+ if (Src[0] == _T('%'))
+ {
+ BOOL Dummy;
+ LPTSTR End = &Src[2];
+ LPTSTR Value = NULL;
+
+ if (Src[1] == _T('~'))
+ Value = GetEnhancedVar(&End, FindForVar);
+
+ if (!Value)
+ Value = FindForVar(Src[1], &Dummy);
+
+ if (Value)
+ {
+ if (Dest + _tcslen(Value) > DestEnd)
+ return FALSE;
+ Dest = _stpcpy(Dest, Value);
+ Src = End;
+ continue;
+ }
+ }
+ /* Not a variable; just copy the character */
+ if (Dest >= DestEnd)
+ return FALSE;
+ *Dest++ = *Src++;
+ }
+ *Dest = _T('\0');
+ return TRUE;
}
LPTSTR
DoDelayedExpansion(LPTSTR Line)
{
- TCHAR Buf1[CMDLINE_LENGTH];
- TCHAR Buf2[CMDLINE_LENGTH];
-
- /* First, substitute FOR variables */
- if (!SubstituteForVars(Line, Buf1))
- return NULL;
-
- if (!bDelayedExpansion || !_tcschr(Buf1, _T('!')))
- return cmd_dup(Buf1);
-
- /* FIXME: Delayed substitutions actually aren't quite the same as
- * immediate substitutions. In particular, it's possible to escape
- * the exclamation point using ^. */
- if (!SubstituteVars(Buf1, Buf2, _T('!')))
- return NULL;
- return cmd_dup(Buf2);
+ TCHAR Buf1[CMDLINE_LENGTH];
+ TCHAR Buf2[CMDLINE_LENGTH];
+
+ /* First, substitute FOR variables */
+ if (!SubstituteForVars(Line, Buf1))
+ return NULL;
+
+ if (!bDelayedExpansion || !_tcschr(Buf1, _T('!')))
+ return cmd_dup(Buf1);
+
+ /* FIXME: Delayed substitutions actually aren't quite the same as
+ * immediate substitutions. In particular, it's possible to escape
+ * the exclamation point using ^. */
+ if (!SubstituteVars(Buf1, Buf2, _T('!')))
+ return NULL;
+ return cmd_dup(Buf2);
}
@@ -1363,64 +1362,64 @@
BOOL
ReadLine (TCHAR *commandline, BOOL bMore)
{
- TCHAR readline[CMDLINE_LENGTH];
- LPTSTR ip;
-
- /* if no batch input then... */
- if (bc == NULL)
- {
- if (bMore)
- {
- ConOutResPrintf(STRING_MORE);
- }
- else
- {
- /* JPP 19980807 - if echo off, don't print prompt */
- if (bEcho)
- {
- if (!bIgnoreEcho)
- ConOutChar('\n');
- PrintPrompt();
- }
- }
-
- if (!ReadCommand(readline, CMDLINE_LENGTH - 1))
- {
- bExit = TRUE;
- return FALSE;
- }
-
- if (CheckCtrlBreak(BREAK_INPUT))
- {
- ConOutPuts(_T("\n"));
- return FALSE;
- }
- ip = readline;
- }
- else
- {
- ip = ReadBatchLine();
- if (!ip)
- return FALSE;
- }
-
- return SubstituteVars(ip, commandline, _T('%'));
+ TCHAR readline[CMDLINE_LENGTH];
+ LPTSTR ip;
+
+ /* if no batch input then... */
+ if (bc == NULL)
+ {
+ if (bMore)
+ {
+ ConOutResPrintf(STRING_MORE);
+ }
+ else
+ {
+ /* JPP 19980807 - if echo off, don't print prompt */
+ if (bEcho)
+ {
+ if (!bIgnoreEcho)
+ ConOutChar('\n');
+ PrintPrompt();
+ }
+ }
+
+ if (!ReadCommand(readline, CMDLINE_LENGTH - 1))
+ {
+ bExit = TRUE;
+ return FALSE;
+ }
+
+ if (CheckCtrlBreak(BREAK_INPUT))
+ {
+ ConOutPuts(_T("\n"));
+ return FALSE;
+ }
+ ip = readline;
+ }
+ else
+ {
+ ip = ReadBatchLine();
+ if (!ip)
+ return FALSE;
+ }
+
+ return SubstituteVars(ip, commandline, _T('%'));
}
static VOID
ProcessInput()
{
- PARSED_COMMAND *Cmd;
-
- while (!bCanExit || !bExit)
- {
- Cmd = ParseCommand(NULL);
- if (!Cmd)
- continue;
-
- ExecuteCommand(Cmd);
- FreeCommand(Cmd);
- }
+ PARSED_COMMAND *Cmd;
+
+ while (!bCanExit || !bExit)
+ {
+ Cmd = ParseCommand(NULL);
+ if (!Cmd)
+ continue;
+
+ ExecuteCommand(Cmd);
+ FreeCommand(Cmd);
+ }
}
@@ -1429,35 +1428,34 @@
*/
BOOL WINAPI BreakHandler (DWORD dwCtrlType)
{
-
- DWORD dwWritten;
- INPUT_RECORD rec;
- static BOOL SelfGenerated = FALSE;
-
- if ((dwCtrlType != CTRL_C_EVENT) &&
- (dwCtrlType != CTRL_BREAK_EVENT))
- {
- return FALSE;
- }
- else
- {
- if(SelfGenerated)
- {
- SelfGenerated = FALSE;
- return TRUE;
- }
- }
-
- if (!TryEnterCriticalSection(&ChildProcessRunningLock))
- {
- SelfGenerated = TRUE;
- GenerateConsoleCtrlEvent (dwCtrlType, 0);
- return TRUE;
- }
- else
- {
- LeaveCriticalSection(&ChildProcessRunningLock);
- }
+ DWORD dwWritten;
+ INPUT_RECORD rec;
+ static BOOL SelfGenerated = FALSE;
+
+ if ((dwCtrlType != CTRL_C_EVENT) &&
+ (dwCtrlType != CTRL_BREAK_EVENT))
+ {
+ return FALSE;
+ }
+ else
+ {
+ if(SelfGenerated)
+ {
+ SelfGenerated = FALSE;
+ return TRUE;
+ }
+ }
+
+ if (!TryEnterCriticalSection(&ChildProcessRunningLock))
+ {
+ SelfGenerated = TRUE;
+ GenerateConsoleCtrlEvent (dwCtrlType, 0);
+ return TRUE;
+ }
+ else
+ {
+ LeaveCriticalSection(&ChildProcessRunningLock);
+ }
rec.EventType = KEY_EVENT;
rec.Event.KeyEvent.bKeyDown = TRUE;
@@ -1468,31 +1466,29 @@
rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
rec.Event.KeyEvent.dwControlKeyState = RIGHT_CTRL_PRESSED;
- WriteConsoleInput(
- hIn,
- &rec,
- 1,
- &dwWritten);
-
- bCtrlBreak = TRUE;
- /* FIXME: Handle batch files */
-
- //ConOutPrintf(_T("^C"));
-
-
- return TRUE;
+ WriteConsoleInput(hIn,
+ &rec,
+ 1,
+ &dwWritten);
+
+ bCtrlBreak = TRUE;
+ /* FIXME: Handle batch files */
+
+ //ConOutPrintf(_T("^C"));
+
+ return TRUE;
}
VOID AddBreakHandler (VOID)
{
- SetConsoleCtrlHandler ((PHANDLER_ROUTINE)BreakHandler, TRUE);
+ SetConsoleCtrlHandler ((PHANDLER_ROUTINE)BreakHandler, TRUE);
}
VOID RemoveBreakHandler (VOID)
{
- SetConsoleCtrlHandler ((PHANDLER_ROUTINE)BreakHandler, FALSE);
+ SetConsoleCtrlHandler ((PHANDLER_ROUTINE)BreakHandler, FALSE);
}
@@ -1504,56 +1500,56 @@
static VOID
ShowCommands (VOID)
{
- /* print command list */
- ConOutResPuts(STRING_CMD_HELP1);
- PrintCommandList();
-
- /* print feature list */
- ConOutResPuts(STRING_CMD_HELP2);
+ /* print command list */
+ ConOutResPuts(STRING_CMD_HELP1);
+ PrintCommandList();
+
+ /* print feature list */
+ ConOutResPuts(STRING_CMD_HELP2);
#ifdef FEATURE_ALIASES
- ConOutResPuts(STRING_CMD_HELP3);
+ ConOutResPuts(STRING_CMD_HELP3);
#endif
#ifdef FEATURE_HISTORY
- ConOutResPuts(STRING_CMD_HELP4);
+ ConOutResPuts(STRING_CMD_HELP4);
#endif
#ifdef FEATURE_UNIX_FILENAME_COMPLETION
- ConOutResPuts(STRING_CMD_HELP5);
+ ConOutResPuts(STRING_CMD_HELP5);
#endif
#ifdef FEATURE_DIRECTORY_STACK
- ConOutResPuts(STRING_CMD_HELP6);
+ ConOutResPuts(STRING_CMD_HELP6);
#endif
#ifdef FEATURE_REDIRECTION
- ConOutResPuts(STRING_CMD_HELP7);
+ ConOutResPuts(STRING_CMD_HELP7);
#endif
- ConOutChar(_T('\n'));
+ ConOutChar(_T('\n'));
}
#endif
static VOID
ExecuteAutoRunFile(HKEY hkeyRoot)
{
- TCHAR autorun[2048];
- DWORD len = sizeof autorun;
- HKEY hkey;
+ TCHAR autorun[2048];
+ DWORD len = sizeof autorun;
+ HKEY hkey;
if (RegOpenKeyEx(hkeyRoot,
- _T("SOFTWARE\\Microsoft\\Command Processor"),
- 0,
- KEY_READ,
- &hkey ) == ERROR_SUCCESS)
- {
- if(RegQueryValueEx(hkey,
+ _T("SOFTWARE\\Microsoft\\Command Processor"),
+ 0,
+ KEY_READ,
+ &hkey) == ERROR_SUCCESS)
+ {
+ if(RegQueryValueEx(hkey,
_T("AutoRun"),
0,
0,
(LPBYTE)autorun,
&len) == ERROR_SUCCESS)
- {
- if (*autorun)
- ParseCommandLine(autorun);
- }
- RegCloseKey(hkey);
+ {
+ if (*autorun)
+ ParseCommandLine(autorun);
+ }
+ RegCloseKey(hkey);
}
}
@@ -1561,53 +1557,53 @@
static VOID
GetCmdLineCommand(TCHAR *commandline, TCHAR *ptr, BOOL AlwaysStrip)
{
- TCHAR *LastQuote;
-
- while (_istspace(*ptr))
- ptr++;
-
- /* Remove leading quote, find final quote */
- if (*ptr == _T('"') &&
- (LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
- {
- TCHAR *Space;
- /* Under certain circumstances, all quotes are preserved.
- * CMD /? documents these conditions as follows:
- * 1. No /S switch
- * 2. Exactly two quotes
- * 3. No "special characters" between the quotes
- * (CMD /? says &<>()@^| but parentheses did not
- * trigger this rule when I tested them.)
- * 4. Whitespace exists between the quotes
- * 5. Enclosed string is an executable filename
- */
- *LastQuote = _T('\0');
- for (Space = ptr + 1; Space < LastQuote; Space++)
- {
- if (_istspace(*Space)) /* Rule 4 */
- {
- if (!AlwaysStrip && /* Rule 1 */
- !_tcspbrk(ptr, _T("\"&<>@^|")) && /* Rules
2, 3 */
- SearchForExecutable(ptr, commandline)) /* Rule 5 */
- {
- /* All conditions met: preserve both the quotes */
- *LastQuote = _T('"');
- _tcscpy(commandline, ptr - 1);
- return;
- }
- break;
- }
- }
-
- /* The conditions were not met: remove both the
- * leading quote and the last quote */
- _tcscpy(commandline, ptr);
- _tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
- return;
- }
-
- /* No quotes; just copy */
- _tcscpy(commandline, ptr);
+ TCHAR *LastQuote;
+
+ while (_istspace(*ptr))
+ ptr++;
+
+ /* Remove leading quote, find final quote */
+ if (*ptr == _T('"') &&
+ (LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
+ {
+ TCHAR *Space;
+ /* Under certain circumstances, all quotes are preserved.
+ * CMD /? documents these conditions as follows:
+ * 1. No /S switch
+ * 2. Exactly two quotes
+ * 3. No "special characters" between the quotes
+ * (CMD /? says &<>()@^| but parentheses did not
+ * trigger this rule when I tested them.)
+ * 4. Whitespace exists between the quotes
+ * 5. Enclosed string is an executable filename
+ */
+ *LastQuote = _T('\0');
+ for (Space = ptr + 1; Space < LastQuote; Space++)
+ {
+ if (_istspace(*Space)) /* Rule 4 */
+ {
+ if (!AlwaysStrip && /* Rule 1 */
+ !_tcspbrk(ptr, _T("\"&<>@^|")) &&
/* Rules 2, 3 */
+ SearchForExecutable(ptr, commandline)) /* Rule 5 */
+ {
+ /* All conditions met: preserve both the quotes */
+ *LastQuote = _T('"');
+ _tcscpy(commandline, ptr - 1);
+ return;
+ }
+ break;
+ }
+ }
+
+ /* The conditions were not met: remove both the
+ * leading quote and the last quote */
+ _tcscpy(commandline, ptr);
+ _tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
+ return;
+ }
+
+ /* No quotes; just copy */
+ _tcscpy(commandline, ptr);
}
/*
@@ -1616,200 +1612,199 @@
static VOID
Initialize()
{
- HMODULE NtDllModule;
- TCHAR commandline[CMDLINE_LENGTH];
- TCHAR ModuleName[_MAX_PATH + 1];
- TCHAR lpBuffer[2];
- INT nExitCode;
-
- //INT len;
- TCHAR *ptr, *cmdLine, option = 0;
- BOOL AlwaysStrip = FALSE;
- BOOL AutoRun = TRUE;
-
- /* get version information */
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx (&osvi);
-
- /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
- * build process. So don't link implicitly against ntdll.dll, load it
- * dynamically instead */
- NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
- if (NtDllModule != NULL)
- {
- NtQueryInformationProcessPtr =
(NtQueryInformationProcessProc)GetProcAddress(NtDllModule,
"NtQueryInformationProcess");
- NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule,
"NtReadVirtualMemory");
- }
-
- InitLocale ();
-
- /* get default input and output console handles */
- hOut = GetStdHandle (STD_OUTPUT_HANDLE);
- hIn = GetStdHandle (STD_INPUT_HANDLE);
-
- /* Set EnvironmentVariable PROMPT if it does not exists any env value.
- for you can change the EnvirommentVariable for prompt before cmd start
- this patch are not 100% right, if it does not exists a PROMPT value cmd should use
- $P$G as defualt not set EnvirommentVariable PROMPT to $P$G if it does not exists */
- if (GetEnvironmentVariable(_T("PROMPT"),lpBuffer, sizeof(lpBuffer) /
sizeof(lpBuffer[0])) == 0)
- SetEnvironmentVariable (_T("PROMPT"), _T("$P$G"));
+ HMODULE NtDllModule;
+ TCHAR commandline[CMDLINE_LENGTH];
+ TCHAR ModuleName[_MAX_PATH + 1];
+ TCHAR lpBuffer[2];
+ INT nExitCode;
+
+ //INT len;
+ TCHAR *ptr, *cmdLine, option = 0;
+ BOOL AlwaysStrip = FALSE;
+ BOOL AutoRun = TRUE;
+
+ /* get version information */
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx (&osvi);
+
+ /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
+ * build process. So don't link implicitly against ntdll.dll, load it
+ * dynamically instead */
+ NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
+ if (NtDllModule != NULL)
+ {
+ NtQueryInformationProcessPtr =
(NtQueryInformationProcessProc)GetProcAddress(NtDllModule,
"NtQueryInformationProcess");
+ NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule,
"NtReadVirtualMemory");
+ }
+
+ InitLocale ();
+
+ /* get default input and output console handles */
+ hOut = GetStdHandle (STD_OUTPUT_HANDLE);
+ hIn = GetStdHandle (STD_INPUT_HANDLE);
+
+ /* Set EnvironmentVariable PROMPT if it does not exists any env value.
+ for you can change the EnvirommentVariable for prompt before cmd start
+ this patch are not 100% right, if it does not exists a PROMPT value cmd should
use
+ $P$G as defualt not set EnvirommentVariable PROMPT to $P$G if it does not exists
*/
+ if (GetEnvironmentVariable(_T("PROMPT"),lpBuffer, sizeof(lpBuffer) /
sizeof(lpBuffer[0])) == 0)
+ SetEnvironmentVariable (_T("PROMPT"), _T("$P$G"));
#ifdef FEATURE_DIR_STACK
- /* initialize directory stack */
- InitDirectoryStack ();
+ /* initialize directory stack */
+ InitDirectoryStack ();
#endif
#ifdef FEATURE_HISTORY
- /*initialize history*/
- InitHistory();
+ /*initialize history*/
+ InitHistory();
#endif
- /* Set COMSPEC environment variable */
- if (0 != GetModuleFileName (NULL, ModuleName, _MAX_PATH + 1))
- {
- ModuleName[_MAX_PATH] = _T('\0');
- SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
- }
-
- /* add ctrl break handler */
- AddBreakHandler ();
-
-
- SetConsoleMode (hIn, ENABLE_PROCESSED_INPUT);
-
- cmdLine = GetCommandLine();
- TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
-
- for (ptr = cmdLine; *ptr; ptr++)
- {
- if (*ptr == _T('/'))
- {
- option = _totupper(ptr[1]);
- if (option == _T('?'))
- {
- ConOutResPaging(TRUE,STRING_CMD_HELP8);
- nErrorLevel = 1;
- bExit = TRUE;
- return;
- }
- else if (option == _T('P'))
- {
- if (!IsExistingFile (_T("\\autoexec.bat")))
- {
+ /* Set COMSPEC environment variable */
+ if (0 != GetModuleFileName (NULL, ModuleName, _MAX_PATH + 1))
+ {
+ ModuleName[_MAX_PATH] = _T('\0');
+ SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
+ }
+
+ /* add ctrl break handler */
+ AddBreakHandler ();
+
+ SetConsoleMode (hIn, ENABLE_PROCESSED_INPUT);
+
+ cmdLine = GetCommandLine();
+ TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
+
+ for (ptr = cmdLine; *ptr; ptr++)
+ {
+ if (*ptr == _T('/'))
+ {
+ option = _totupper(ptr[1]);
+ if (option == _T('?'))
+ {
+ ConOutResPaging(TRUE,STRING_CMD_HELP8);
+ nErrorLevel = 1;
+ bExit = TRUE;
+ return;
+ }
+ else if (option == _T('P'))
+ {
+ if (!IsExistingFile (_T("\\autoexec.bat")))
+ {
#ifdef INCLUDE_CMD_DATE
- cmd_date (_T(""));
+ cmd_date (_T(""));
#endif
#ifdef INCLUDE_CMD_TIME
- cmd_time (_T(""));
+ cmd_time (_T(""));
#endif
- }
- else
- {
- ParseCommandLine (_T("\\autoexec.bat"));
- }
- bCanExit = FALSE;
- }
- else if (option == _T('A'))
- {
- bUnicodeOutput = FALSE;
- }
- else if (option == _T('C') || option == _T('K') || option ==
_T('R'))
- {
- /* Remainder of command line is a command to be run */
- break;
- }
- else if (option == _T('D'))
- {
- AutoRun = FALSE;
- }
- else if (option == _T('Q'))
- {
- bDisableBatchEcho = TRUE;
- }
- else if (option == _T('S'))
- {
- AlwaysStrip = TRUE;
- }
+ }
+ else
+ {
+ ParseCommandLine (_T("\\autoexec.bat"));
+ }
+ bCanExit = FALSE;
+ }
+ else if (option == _T('A'))
+ {
+ bUnicodeOutput = FALSE;
+ }
+ else if (option == _T('C') || option == _T('K') || option ==
_T('R'))
+ {
+ /* Remainder of command line is a command to be run */
+ break;
+ }
+ else if (option == _T('D'))
+ {
+ AutoRun = FALSE;
+ }
+ else if (option == _T('Q'))
+ {
+ bDisableBatchEcho = TRUE;
+ }
+ else if (option == _T('S'))
+ {
+ AlwaysStrip = TRUE;
+ }
#ifdef INCLUDE_CMD_COLOR
- else if (!_tcsnicmp(ptr, _T("/T:"), 3))
- {
- /* process /T (color) argument */
- wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
- SetScreenColor(wDefColor, FALSE);
- }
+ else if (!_tcsnicmp(ptr, _T("/T:"), 3))
+ {
+ /* process /T (color) argument */
+ wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
+ SetScreenColor(wDefColor, FALSE);
+ }
#endif
- else if (option == _T('U'))
- {
- bUnicodeOutput = TRUE;
- }
- else if (option == _T('V'))
- {
- bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
- }
- }
- }
-
- if (!*ptr)
- {
- /* If neither /C or /K was given, display a simple version string */
- ConOutResPrintf(STRING_REACTOS_VERSION,
- _T(KERNEL_RELEASE_STR),
- _T(KERNEL_VERSION_BUILD_STR));
- ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS
Team.\n"));
- }
-
- if (AutoRun)
- {
- ExecuteAutoRunFile(HKEY_LOCAL_MACHINE);
- ExecuteAutoRunFile(HKEY_CURRENT_USER);
- }
-
- if (*ptr)
- {
- /* Do the /C or /K command */
- GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
- nExitCode = ParseCommandLine(commandline);
- if (option != _T('K'))
- {
- nErrorLevel = nExitCode;
- bExit = TRUE;
- }
- }
+ else if (option == _T('U'))
+ {
+ bUnicodeOutput = TRUE;
+ }
+ else if (option == _T('V'))
+ {
+ bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
+ }
+ }
+ }
+
+ if (!*ptr)
+ {
+ /* If neither /C or /K was given, display a simple version string */
+ ConOutResPrintf(STRING_REACTOS_VERSION,
+ _T(KERNEL_RELEASE_STR),
+ _T(KERNEL_VERSION_BUILD_STR));
+ ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T("
ReactOS Team.\n"));
+ }
+
+ if (AutoRun)
+ {
+ ExecuteAutoRunFile(HKEY_LOCAL_MACHINE);
+ ExecuteAutoRunFile(HKEY_CURRENT_USER);
+ }
+
+ if (*ptr)
+ {
+ /* Do the /C or /K command */
+ GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
+ nExitCode = ParseCommandLine(commandline);
+ if (option != _T('K'))
+ {
+ nErrorLevel = nExitCode;
+ bExit = TRUE;
+ }
+ }
}
static VOID Cleanup()
{
- /* run cmdexit.bat */
- if (IsExistingFile (_T("cmdexit.bat")))
- {
- ConErrResPuts(STRING_CMD_ERROR5);
-
- ParseCommandLine (_T("cmdexit.bat"));
- }
- else if (IsExistingFile (_T("\\cmdexit.bat")))
- {
- ConErrResPuts (STRING_CMD_ERROR5);
- ParseCommandLine (_T("\\cmdexit.bat"));
- }
+ /* run cmdexit.bat */
+ if (IsExistingFile (_T("cmdexit.bat")))
+ {
+ ConErrResPuts(STRING_CMD_ERROR5);
+
+ ParseCommandLine (_T("cmdexit.bat"));
+ }
+ else if (IsExistingFile (_T("\\cmdexit.bat")))
+ {
+ ConErrResPuts (STRING_CMD_ERROR5);
+ ParseCommandLine (_T("\\cmdexit.bat"));
+ }
#ifdef FEATURE_DIECTORY_STACK
- /* destroy directory stack */
- DestroyDirectoryStack ();
+ /* destroy directory stack */
+ DestroyDirectoryStack ();
#endif
#ifdef FEATURE_HISTORY
- CleanHistory();
+ CleanHistory();
#endif
- /* free GetEnvVar's buffer */
- GetEnvVar(NULL);
-
- /* remove ctrl break handler */
- RemoveBreakHandler ();
- SetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ),
- ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
- DeleteCriticalSection(&ChildProcessRunningLock);
+ /* free GetEnvVar's buffer */
+ GetEnvVar(NULL);
+
+ /* remove ctrl break handler */
+ RemoveBreakHandler ();
+ SetConsoleMode(GetStdHandle( STD_INPUT_HANDLE ),
+ ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT);
+ DeleteCriticalSection(&ChildProcessRunningLock);
}
/*
@@ -1817,51 +1812,51 @@
*/
int _tmain(int argc, const TCHAR *argv[])
{
- HANDLE hConsole;
- TCHAR startPath[MAX_PATH];
- CONSOLE_SCREEN_BUFFER_INFO Info;
-
- InitializeCriticalSection(&ChildProcessRunningLock);
- lpOriginalEnvironment = DuplicateEnvironment();
-
- GetCurrentDirectory(MAX_PATH,startPath);
- _tchdir(startPath);
-
- SetFileApisToOEM();
- InputCodePage = 0;
- OutputCodePage = 0;
-
- hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
- OPEN_EXISTING, 0, NULL);
- if (hConsole != INVALID_HANDLE_VALUE)
- {
- if (!GetConsoleScreenBufferInfo(hConsole, &Info))
- {
- ConErrFormatMessage(GetLastError());
- return(1);
- }
- wDefColor = Info.wAttributes;
- CloseHandle(hConsole);
- }
-
- InputCodePage = GetConsoleCP();
- OutputCodePage = GetConsoleOutputCP();
- CMD_ModuleHandle = GetModuleHandle(NULL);
-
- /* check switches on command-line */
- Initialize();
-
- /* call prompt routine */
- ProcessInput();
-
- /* do the cleanup */
- Cleanup();
-
- cmd_free(lpOriginalEnvironment);
-
- cmd_exit(nErrorLevel);
- return(nErrorLevel);
+ HANDLE hConsole;
+ TCHAR startPath[MAX_PATH];
+ CONSOLE_SCREEN_BUFFER_INFO Info;
+
+ InitializeCriticalSection(&ChildProcessRunningLock);
+ lpOriginalEnvironment = DuplicateEnvironment();
+
+ GetCurrentDirectory(MAX_PATH,startPath);
+ _tchdir(startPath);
+
+ SetFileApisToOEM();
+ InputCodePage = 0;
+ OutputCodePage = 0;
+
+ hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, 0, NULL);
+ if (hConsole != INVALID_HANDLE_VALUE)
+ {
+ if (!GetConsoleScreenBufferInfo(hConsole, &Info))
+ {
+ ConErrFormatMessage(GetLastError());
+ return(1);
+ }
+ wDefColor = Info.wAttributes;
+ CloseHandle(hConsole);
+ }
+
+ InputCodePage = GetConsoleCP();
+ OutputCodePage = GetConsoleOutputCP();
+ CMD_ModuleHandle = GetModuleHandle(NULL);
+
+ /* check switches on command-line */
+ Initialize();
+
+ /* call prompt routine */
+ ProcessInput();
+
+ /* do the cleanup */
+ Cleanup();
+
+ cmd_free(lpOriginalEnvironment);
+
+ cmd_exit(nErrorLevel);
+ return(nErrorLevel);
}
/* EOF */