ReactOS 0.4.15-dev-6055-g36cdd34
cmd.c File Reference
#include "precomp.h"
#include <reactos/buildno.h>
#include <reactos/version.h>
Include dependency graph for cmd.c:

Go to the source code of this file.

Macros

#define SHELLEXECUTETEXT   "ShellExecuteExA"
 
#define SeenGoto()    (bc && bc->current == NULL)
 
#define APPEND(From, Length)
 
#define APPEND1(Char)
 
#define APPEND(From, Length)
 
#define APPEND1(Char)
 
#define APPEND1(Char)
 

Typedefs

typedef NTSTATUS(WINAPINtQueryInformationProcessProc) (HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG)
 
typedef NTSTATUS(WINAPINtReadVirtualMemoryProc) (HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T)
 
typedef BOOL(WINAPIMYEX) (LPSHELLEXECUTEINFO lpExecInfo)
 

Functions

INT ConvertULargeInteger (ULONGLONG num, LPTSTR des, UINT len, BOOL bPutSeparator)
 
static BOOL IsConsoleProcess (HANDLE Process)
 
HANDLE RunFile (DWORD flags, LPTSTR filename, LPTSTR params, LPTSTR directory, INT show)
 
static VOID SetConTitle (LPCTSTR pszTitle)
 
static VOID ResetConTitle (VOID)
 
static INT Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
 
INT DoCommand (LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
 
INT ParseCommandLine (LPTSTR cmd)
 
static HANDLE ExecuteAsync (PARSED_COMMAND *Cmd)
 
static INT ExecutePipeline (PARSED_COMMAND *Cmd)
 
INT ExecuteCommand (IN PARSED_COMMAND *Cmd)
 
INT ExecuteCommandWithEcho (IN PARSED_COMMAND *Cmd)
 
LPTSTR GetEnvVar (LPCTSTR varName)
 
LPCTSTR GetEnvVarOrSpecial (LPCTSTR varName)
 
static PCTSTR GetEnhancedVar (IN OUT PCTSTR *pFormat, IN BOOL(*GetVar)(TCHAR, PCTSTR *, BOOL *))
 
static PCTSTR GetBatchVar (IN PCTSTR varName, OUT PUINT varNameLen)
 
BOOL SubstituteVar (IN PCTSTR Src, OUT size_t *SrcIncLen, OUT PTCHAR Dest, IN PTCHAR DestEnd, OUT size_t *DestIncLen, IN TCHAR Delim)
 
BOOL SubstituteVars (IN PCTSTR Src, OUT PTSTR Dest, IN TCHAR Delim)
 
static BOOL FindForVar (IN TCHAR Var, OUT PCTSTR *VarPtr, OUT BOOL *IsParam0)
 
BOOL SubstituteForVars (IN PCTSTR Src, OUT PTSTR Dest)
 
PTSTR DoDelayedExpansion (IN PCTSTR Line)
 
BOOL ReadLine (TCHAR *commandline, BOOL bMore)
 
static INT ProcessInput (VOID)
 
static BOOL WINAPI BreakHandler (IN DWORD dwCtrlType)
 
VOID AddBreakHandler (VOID)
 
VOID RemoveBreakHandler (VOID)
 
static VOID LoadRegistrySettings (HKEY hKeyRoot)
 
static VOID ExecuteAutoRunFile (HKEY hKeyRoot)
 
static VOID GetCmdLineCommand (OUT LPTSTR commandline, IN LPCTSTR ptr, IN BOOL AlwaysStrip)
 
static LPCTSTR Initialize (VOID)
 
static VOID Cleanup (VOID)
 
int _tmain (int argc, const TCHAR *argv[])
 

Variables

BOOL bExit = FALSE
 
BOOL bCanExit = TRUE
 
BOOL bCtrlBreak = FALSE
 
BOOL bIgnoreEcho = FALSE
 
static BOOL fSingleCommand = 0
 
static BOOL bAlwaysStrip = FALSE
 
INT nErrorLevel = 0
 
CRITICAL_SECTION ChildProcessRunningLock
 
BOOL bDisableBatchEcho = FALSE
 
BOOL bEnableExtensions = TRUE
 
BOOL bDelayedExpansion = FALSE
 
DWORD dwChildProcessId = 0
 
LPTSTR lpOriginalEnvironment
 
HANDLE CMD_ModuleHandle
 
BOOL bTitleSet = FALSE
 
TCHAR szCurTitle [MAX_PATH]
 
static NtQueryInformationProcessProc NtQueryInformationProcessPtr = NULL
 
static NtReadVirtualMemoryProc NtReadVirtualMemoryPtr = NULL
 
CON_STREAM_MODE OutputStreamMode = UTF8Text
 
WORD wDefColor = 0
 

Macro Definition Documentation

◆ APPEND [1/2]

#define APPEND (   From,
  Length 
)
Value:
do { \
if (Dest + (Length) > DestEnd) \
goto too_long; \
memcpy(Dest, (From), (Length) * sizeof(TCHAR)); \
Dest += (Length); \
} while (0)
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
char TCHAR
Definition: xmlstorage.h:189

◆ APPEND [2/2]

#define APPEND (   From,
  Length 
)
Value:
do { \
if (Dest + (Length) > DestEnd) \
goto too_long; \
memcpy(Dest, (From), (Length) * sizeof(TCHAR)); \
Dest += (Length); \
} while (0)

◆ APPEND1 [1/3]

#define APPEND1 (   Char)
Value:
do { \
if (Dest >= DestEnd) \
goto too_long; \
*Dest++ = (Char); \
} while (0)

◆ APPEND1 [2/3]

#define APPEND1 (   Char)
Value:
do { \
if (Dest >= DestEnd) \
goto too_long; \
*Dest++ = (Char); \
} while (0)

◆ APPEND1 [3/3]

#define APPEND1 (   Char)
Value:
do { \
if (Dst >= DestEnd) \
goto too_long; \
*Dst++ = (Char); \
} while (0)
#define Dst
Definition: mesh.h:153

◆ SeenGoto

#define SeenGoto ( )     (bc && bc->current == NULL)

◆ SHELLEXECUTETEXT

#define SHELLEXECUTETEXT   "ShellExecuteExA"

Definition at line 261 of file cmd.c.

Typedef Documentation

◆ MYEX

typedef BOOL(WINAPI * MYEX) (LPSHELLEXECUTEINFO lpExecInfo)

Definition at line 264 of file cmd.c.

◆ NtQueryInformationProcessProc

typedef NTSTATUS(WINAPI * NtQueryInformationProcessProc) (HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG)

Definition at line 148 of file cmd.c.

◆ NtReadVirtualMemoryProc

typedef NTSTATUS(WINAPI * NtReadVirtualMemoryProc) (HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T)

Definition at line 150 of file cmd.c.

Function Documentation

◆ _tmain()

int _tmain ( int  argc,
const TCHAR argv[] 
)

Definition at line 2366 of file cmd.c.

2367{
2368 INT nExitCode;
2369 LPCTSTR pCmdLine;
2370 TCHAR startPath[MAX_PATH];
2371
2374
2375 GetCurrentDirectory(ARRAYSIZE(startPath), startPath);
2376 _tchdir(startPath);
2377
2381
2382 /* Initialize the Console Standard Streams */
2386 /* Reset the current thread UI language */
2389 {
2391 }
2392
2394
2395 /*
2396 * Perform general initialization, parse switches on command-line.
2397 * Initialize the exit code with the errorlevel as Initialize() can set it.
2398 */
2399 pCmdLine = Initialize();
2400 nExitCode = nErrorLevel;
2401
2402 if (pCmdLine && *pCmdLine)
2403 {
2404 TCHAR commandline[CMDLINE_LENGTH];
2405
2406 /* Do the /C or /K command */
2407 GetCmdLineCommand(commandline, &pCmdLine[2], bAlwaysStrip);
2408 nExitCode = ParseCommandLine(commandline);
2409 if (fSingleCommand == 1)
2410 {
2411 // nErrorLevel = nExitCode;
2412 bExit = TRUE;
2413 }
2414 fSingleCommand = 0;
2415 }
2416 if (!bExit)
2417 {
2418 /* Call prompt routine */
2419 nExitCode = ProcessInput();
2420 }
2421
2422 /* Do the cleanup */
2423 Cleanup();
2425
2426 cmd_exit(nExitCode);
2427 return nExitCode;
2428}
#define StdOut
Definition: fc.c:14
#define StdErr
Definition: fc.c:15
#define CMDLINE_LENGTH
Definition: help.h:12
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
CRITICAL_SECTION ChildProcessRunningLock
Definition: cmd.c:159
INT nErrorLevel
Definition: cmd.c:158
HANDLE CMD_ModuleHandle
Definition: cmd.c:165
LPTSTR lpOriginalEnvironment
Definition: cmd.c:164
BOOL bExit
Definition: cmd.c:152
CON_STREAM_MODE OutputStreamMode
Definition: cmd.c:177
static INT ProcessInput(VOID)
Definition: cmd.c:1774
static VOID GetCmdLineCommand(OUT LPTSTR commandline, IN LPCTSTR ptr, IN BOOL AlwaysStrip)
Definition: cmd.c:2075
INT ParseCommandLine(LPTSTR cmd)
Definition: cmd.c:636
static BOOL fSingleCommand
Definition: cmd.c:156
static BOOL bAlwaysStrip
Definition: cmd.c:157
LPTSTR DuplicateEnvironment(VOID)
Definition: setlocal.c:25
UINT InputCodePage
Definition: console.c:25
UINT OutputCodePage
Definition: console.c:26
#define cmd_free(ptr)
Definition: cmddbg.h:31
#define cmd_exit(code)
Definition: cmddbg.h:34
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define MAX_PATH
Definition: compat.h:34
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2451
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(VOID)
Definition: console.c:2391
static const WCHAR Cleanup[]
Definition: register.c:80
#define _tchdir
Definition: tchar.h:672
#define IsConsoleHandle(h)
Definition: console.h:14
BOOL ConStreamInit(OUT PCON_STREAM Stream, IN PVOID Handle, IN CON_STREAM_MODE Mode, IN UINT CacheCodePage OPTIONAL)
Definition: stream.c:185
HANDLE ConStreamGetOSHandle(IN PCON_STREAM Stream)
Definition: stream.c:240
#define StdIn
Definition: stream.h:81
@ AnsiText
Definition: stream.h:47
LANGID ConSetThreadUILanguage(IN LANGID LangId OPTIONAL)
Definition: utils.c:352
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
int32_t INT
Definition: typedefs.h:58
#define STD_OUTPUT_HANDLE
Definition: winbase.h:268
#define STD_INPUT_HANDLE
Definition: winbase.h:267
#define STD_ERROR_HANDLE
Definition: winbase.h:269
#define GetModuleHandle
Definition: winbase.h:3698
VOID WINAPI SetFileApisToOEM(void)
Definition: utils.c:831
#define GetCurrentDirectory
Definition: winbase.h:3676
static void Initialize()
Definition: xlate.c:212
const CHAR * LPCTSTR
Definition: xmlstorage.h:193

◆ AddBreakHandler()

VOID AddBreakHandler ( VOID  )

Definition at line 1846 of file cmd.c.

1847{
1849}
static BOOL WINAPI BreakHandler(IN DWORD dwCtrlType)
Definition: cmd.c:1801
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2109

Referenced by FilePromptYN(), FilePromptYNA(), Initialize(), and PagePrompt().

◆ BreakHandler()

static BOOL WINAPI BreakHandler ( IN DWORD  dwCtrlType)
static

Definition at line 1801 of file cmd.c.

1802{
1803 DWORD dwWritten;
1804 INPUT_RECORD rec;
1805
1806 if ((dwCtrlType != CTRL_C_EVENT) &&
1807 (dwCtrlType != CTRL_BREAK_EVENT))
1808 {
1809 return FALSE;
1810 }
1811
1813 {
1814 /* Child process is running and will have received the control event */
1815 return TRUE;
1816 }
1817 else
1818 {
1820 }
1821
1822 bCtrlBreak = TRUE;
1823
1824 rec.EventType = KEY_EVENT;
1826 rec.Event.KeyEvent.wRepeatCount = 1;
1827 rec.Event.KeyEvent.wVirtualKeyCode = _T('C');
1828 rec.Event.KeyEvent.wVirtualScanCode = _T('C') - 35;
1829 rec.Event.KeyEvent.uChar.AsciiChar = _T('C');
1830 rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
1832
1834 &rec,
1835 1,
1836 &dwWritten);
1837
1838 /* FIXME: Handle batch files */
1839
1840 // ConOutPrintf(_T("^C"));
1841
1842 return TRUE;
1843}
BOOL bCtrlBreak
Definition: cmd.c:154
#define FALSE
Definition: types.h:117
unsigned long DWORD
Definition: ntddk_ex.h:95
union _INPUT_RECORD::@3259 Event
WORD EventType
Definition: wincon.h:273
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:275
WORD wVirtualScanCode
Definition: wincon.h:243
union _KEY_EVENT_RECORD::@3258 uChar
DWORD dwControlKeyState
Definition: wincon.h:248
WORD wVirtualKeyCode
Definition: wincon.h:242
WORD wRepeatCount
Definition: wincon.h:241
WCHAR UnicodeChar
Definition: wincon.h:245
#define _T(x)
Definition: vfdio.h:22
BOOL WINAPI TryEnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define CTRL_C_EVENT
Definition: wincon.h:68
#define KEY_EVENT
Definition: wincon.h:128
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:139
#define CTRL_BREAK_EVENT
Definition: wincon.h:69
#define WriteConsoleInput
Definition: wincon.h:785

Referenced by AddBreakHandler(), and RemoveBreakHandler().

◆ Cleanup()

static VOID Cleanup ( VOID  )
static

Definition at line 2322 of file cmd.c.

2323{
2324 /* Run cmdexit.bat */
2325 if (IsExistingFile(_T("cmdexit.bat")))
2326 {
2328 ParseCommandLine(_T("cmdexit.bat"));
2329 }
2330 else if (IsExistingFile(_T("\\cmdexit.bat")))
2331 {
2333 ParseCommandLine(_T("\\cmdexit.bat"));
2334 }
2335
2336 /* Remove ctrl break handler */
2338
2339 /* Restore the default console mode */
2344
2345
2346#ifdef _DEBUG_MEM
2347#ifdef FEATURE_DIRECTORY_STACK
2348 /* Destroy directory stack */
2350#endif
2351
2352#ifdef FEATURE_HISTORY
2353 CleanHistory();
2354#endif
2355
2356 /* Free GetEnvVar's buffer */
2357 GetEnvVar(NULL);
2358#endif /* _DEBUG_MEM */
2359
2361}
LPTSTR GetEnvVar(LPCTSTR varName)
Definition: cmd.c:886
VOID RemoveBreakHandler(VOID)
Definition: cmd.c:1852
BOOL IsExistingFile(IN LPCTSTR pszPath)
Definition: misc.c:498
VOID DestroyDirectoryStack(VOID)
Definition: dirstack.c:91
#define ConErrResPuts(uID)
Definition: console.h:39
VOID CleanHistory(VOID)
Definition: history.c:163
#define STRING_CMD_ERROR5
Definition: resource.h:31
#define ENABLE_WRAP_AT_EOL_OUTPUT
Definition: blue.h:54
#define ENABLE_PROCESSED_OUTPUT
Definition: blue.h:53
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1606
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define ENABLE_ECHO_INPUT
Definition: wincon.h:80
#define ENABLE_LINE_INPUT
Definition: wincon.h:79
#define ENABLE_PROCESSED_INPUT
Definition: wincon.h:78

◆ ConvertULargeInteger()

INT ConvertULargeInteger ( ULONGLONG  num,
LPTSTR  des,
UINT  len,
BOOL  bPutSeparator 
)

Definition at line 189 of file cmd.c.

190{
191 TCHAR temp[39]; /* maximum length with nNumberGroups == 1 */
192 UINT n, iTarget;
193
194 if (len <= 1)
195 return 0;
196
197 n = 0;
198 iTarget = nNumberGroups;
199 if (!nNumberGroups)
200 bPutSeparator = FALSE;
201
202 do
203 {
204 if (iTarget == n && bPutSeparator)
205 {
206 iTarget += nNumberGroups + 1;
207 temp[38 - n++] = cThousandSeparator;
208 }
209 temp[38 - n++] = (TCHAR)(num % 10) + _T('0');
210 num /= 10;
211 } while (num > 0);
212 if (n > len-1)
213 n = len-1;
214
215 memcpy(des, temp + 39 - n, n * sizeof(TCHAR));
216 des[n] = _T('\0');
217
218 return n;
219}
INT nNumberGroups
Definition: locale.c:22
TCHAR cThousandSeparator
Definition: locale.c:18
static const WCHAR des[]
Definition: oid.c:1212
GLdouble n
Definition: glext.h:7729
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned int UINT
Definition: ndis.h:50
static calc_node_t temp
Definition: rpn_ieee.c:38

Referenced by CommandMemory(), DirPrintNewList(), DirPrintOldList(), PrintDiskInfo(), and PrintSummary().

◆ DoCommand()

INT DoCommand ( LPTSTR  first,
LPTSTR  rest,
PARSED_COMMAND Cmd 
)

Definition at line 557 of file cmd.c.

558{
559 TCHAR *com;
560 TCHAR *cp;
561 LPTSTR param; /* Pointer to command's parameters */
562 INT cl;
563 LPCOMMAND cmdptr;
564 BOOL nointernal = FALSE;
565 INT ret;
566
567 TRACE ("DoCommand: (\'%s\' \'%s\')\n", debugstr_aw(first), debugstr_aw(rest));
568
569 /* Full command line */
570 com = cmd_alloc((_tcslen(first) + _tcslen(rest) + 2) * sizeof(TCHAR));
571 if (com == NULL)
572 {
574 return 1;
575 }
576
577 /* If present in the first word, these characters end the name of an
578 * internal command and become the beginning of its parameters. */
579 cp = first + _tcscspn(first, _T("\t +,/;=[]"));
580
581 for (cl = 0; cl < (cp - first); cl++)
582 {
583 /* These characters do it too, but if one of them is present,
584 * then we check to see if the word is a file name and skip
585 * checking for internal commands if so.
586 * This allows running programs with names like "echo.exe" */
587 if (_tcschr(_T(".:\\"), first[cl]))
588 {
589 TCHAR tmp = *cp;
590 *cp = _T('\0');
591 nointernal = IsExistingFile(first);
592 *cp = tmp;
593 break;
594 }
595 }
596
597 /* Scan internal command table */
598 for (cmdptr = cmds; !nointernal && cmdptr->name; cmdptr++)
599 {
600 if (!_tcsnicmp(first, cmdptr->name, cl) && cmdptr->name[cl] == _T('\0'))
601 {
602 _tcscpy(com, first);
603 _tcscat(com, rest);
604 param = &com[cl];
605
606 /* Skip over whitespace to rest of line, exclude 'echo' command */
607 if (_tcsicmp(cmdptr->name, _T("echo")) != 0)
608 {
609 while (_istspace(*param))
610 param++;
611 }
612
613 /* Set the new console title */
614 SetConTitle(com);
615
616 ret = cmdptr->func(param);
617
618 /* Restore the original console title */
620
621 cmd_free(com);
622 return ret;
623 }
624 }
625
626 ret = Execute(com, first, rest, Cmd);
627 cmd_free(com);
628 return ret;
629}
COMMAND cmds[]
Definition: main.c:21
static INT Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
Definition: cmd.c:347
static VOID SetConTitle(LPCTSTR pszTitle)
Definition: cmd.c:309
static VOID ResetConTitle(VOID)
Definition: cmd.c:329
VOID error_out_of_memory(VOID)
Definition: error.c:138
#define debugstr_aw
Definition: precomp.h:43
#define cmd_alloc(size)
Definition: cmddbg.h:29
unsigned int BOOL
Definition: ntddk_ex.h:94
const GLint * first
Definition: glext.h:5794
GLfloat param
Definition: glext.h:5796
#define _istspace
Definition: tchar.h:1504
#define _tcscat
Definition: tchar.h:622
#define _tcscpy
Definition: tchar.h:623
#define _tcscspn
Definition: tchar.h:1407
#define _tcschr
Definition: tchar.h:1406
POINT cp
Definition: magnifier.c:59
@ Cmd
Definition: sacdrv.h:278
#define TRACE(s)
Definition: solgame.cpp:4
INT(* func)(PCONSOLE_STATE, LPSTR)
Definition: cmdcons.c:29
LPSTR name
Definition: cmdcons.c:27
int ret
#define _tcsnicmp
Definition: xmlstorage.h:207
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define _tcslen
Definition: xmlstorage.h:198
#define _tcsicmp
Definition: xmlstorage.h:205

Referenced by ExecuteCommand().

◆ DoDelayedExpansion()

PTSTR DoDelayedExpansion ( IN PCTSTR  Line)

Definition at line 1642 of file cmd.c.

1644{
1645 TCHAR Buf1[CMDLINE_LENGTH];
1646 TCHAR Buf2[CMDLINE_LENGTH];
1647 PTCHAR Src, Dst;
1648 PTCHAR DestEnd = Buf2 + CMDLINE_LENGTH - 1;
1649 size_t SrcIncLen, DestIncLen;
1650
1651 /* First, substitute FOR variables */
1652 if (!SubstituteForVars(Line, Buf1))
1653 return NULL;
1654
1655 if (!bDelayedExpansion || !_tcschr(Buf1, _T('!')))
1656 return cmd_dup(Buf1);
1657
1658 /*
1659 * Delayed substitutions are not actually completely the same as
1660 * immediate substitutions. In particular, it is possible to escape
1661 * the exclamation point using the escape caret.
1662 */
1663
1664 /*
1665 * Perform delayed expansion: expand variables around '!',
1666 * and reparse escape carets.
1667 */
1668
1669#define APPEND1(Char) \
1670do { \
1671 if (Dst >= DestEnd) \
1672 goto too_long; \
1673 *Dst++ = (Char); \
1674} while (0)
1675
1676 Src = Buf1;
1677 Dst = Buf2;
1678 while (*Src && (Src < &Buf1[CMDLINE_LENGTH]))
1679 {
1680 if (*Src == _T('^'))
1681 {
1682 ++Src;
1683 if (!*Src || !(Src < &Buf1[CMDLINE_LENGTH]))
1684 break;
1685
1686 APPEND1(*Src++);
1687 }
1688 else if (*Src == _T('!'))
1689 {
1690 if (!SubstituteVar(Src, &SrcIncLen, Dst, DestEnd, &DestIncLen, _T('!')))
1691 {
1692 return NULL; // Got an error during parsing.
1693 }
1694 else
1695 {
1696 Src += SrcIncLen;
1697 Dst += DestIncLen;
1698 }
1699 }
1700 else
1701 {
1702 APPEND1(*Src++);
1703 }
1704 continue;
1705 }
1706 APPEND1(_T('\0'));
1707
1708 return cmd_dup(Buf2);
1709
1710too_long:
1712 nErrorLevel = 9023;
1713 return NULL;
1714
1715#undef APPEND1
1716}
BOOL bDelayedExpansion
Definition: cmd.c:162
BOOL SubstituteForVars(IN PCTSTR Src, OUT PTSTR Dest)
Definition: cmd.c:1598
#define APPEND1(Char)
BOOL SubstituteVar(IN PCTSTR Src, OUT size_t *SrcIncLen, OUT PTCHAR Dest, IN PTCHAR DestEnd, OUT size_t *DestIncLen, IN TCHAR Delim)
Definition: cmd.c:1328
#define ConOutResPrintf(uID,...)
Definition: console.h:48
#define STRING_ALIAS_ERROR
Definition: resource.h:22
#define cmd_dup(str)
Definition: cmddbg.h:32
char * PTCHAR
Definition: ntbasedef.h:476
Definition: ncftp.h:79

Referenced by Batch(), ExecuteCommand(), ExecuteFor(), ExecuteIf(), and PerformRedirection().

◆ Execute()

static INT Execute ( LPTSTR  Full,
LPTSTR  First,
LPTSTR  Rest,
PARSED_COMMAND Cmd 
)
static

Definition at line 347 of file cmd.c.

348{
349 TCHAR *first, *rest, *dot;
350 DWORD dwExitCode = 0;
351 TCHAR *FirstEnd;
352 TCHAR szFullName[MAX_PATH];
353 TCHAR szFullCmdLine[CMDLINE_LENGTH];
354
355 TRACE ("Execute: \'%s\' \'%s\'\n", debugstr_aw(First), debugstr_aw(Rest));
356
357 /* Though it was already parsed once, we have a different set of rules
358 for parsing before we pass to CreateProcess */
359 if (First[0] == _T('/') || (First[0] && First[1] == _T(':')))
360 {
361 /* Use the entire first word as the program name (no change) */
362 FirstEnd = First + _tcslen(First);
363 }
364 else
365 {
366 /* If present in the first word, spaces and ,;=/ end the program
367 * name and become the beginning of its parameters. */
368 BOOL bInside = FALSE;
369 for (FirstEnd = First; *FirstEnd; FirstEnd++)
370 {
371 if (!bInside && (_istspace(*FirstEnd) || _tcschr(_T(",;=/"), *FirstEnd)))
372 break;
373 bInside ^= *FirstEnd == _T('"');
374 }
375 }
376
377 /* Copy the new first/rest into the buffer */
378 rest = &Full[FirstEnd - First + 1];
379 _tcscpy(rest, FirstEnd);
380 _tcscat(rest, Rest);
381 first = Full;
382 *FirstEnd = _T('\0');
384
385 /* check for a drive change */
386 if ((_istalpha (first[0])) && (!_tcscmp (first + 1, _T(":"))))
387 {
388 BOOL working = TRUE;
390 {
391 /* Guess they changed disc or something, handle that gracefully and get to root */
392 TCHAR str[4];
393 str[0]=first[0];
394 str[1]=_T(':');
395 str[2]=_T('\\');
396 str[3]=0;
397 working = SetCurrentDirectory(str);
398 }
399
400 if (!working) ConErrResPuts (STRING_FREE_ERROR1);
401 return !working;
402 }
403
404 /* get the PATH environment variable and parse it */
405 /* search the PATH environment variable for the binary */
407 if (!SearchForExecutable(First, szFullName))
408 {
410 return 1;
411 }
412
413 /* Set the new console title */
414 FirstEnd = first + (FirstEnd - First); /* Point to the separating NULL in the full built string */
415 *FirstEnd = _T(' ');
417
418 /* check if this is a .BAT or .CMD file */
419 dot = _tcsrchr (szFullName, _T('.'));
420 if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot, _T(".cmd"))))
421 {
422 while (*rest == _T(' '))
423 rest++;
424
425 *FirstEnd = _T('\0');
426 TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
427 dwExitCode = Batch(szFullName, first, rest, Cmd);
428 }
429 else
430 {
431 /* exec the program */
433 STARTUPINFO stui;
434
435 /* build command line for CreateProcess(): FullName + " " + rest */
436 BOOL quoted = !!_tcschr(First, _T(' '));
437 _tcscpy(szFullCmdLine, quoted ? _T("\"") : _T(""));
438 _tcsncat(szFullCmdLine, First, CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
439 _tcsncat(szFullCmdLine, quoted ? _T("\"") : _T(""), CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
440
441 if (*rest)
442 {
443 _tcsncat(szFullCmdLine, _T(" "), CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
444 _tcsncat(szFullCmdLine, rest, CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
445 }
446
447 TRACE ("[EXEC: %s]\n", debugstr_aw(szFullCmdLine));
448
449 /* fill startup info */
450 memset(&stui, 0, sizeof(stui));
451 stui.cb = sizeof(stui);
452 stui.lpTitle = Full;
455
456 /* Set the console to standard mode */
459
460 if (CreateProcess(szFullName,
461 szFullCmdLine,
462 NULL,
463 NULL,
464 TRUE,
465 0,
466 NULL,
467 NULL,
468 &stui,
469 &prci))
470 {
471 CloseHandle(prci.hThread);
472 }
473 else
474 {
475 // See if we can run this with ShellExecute() ie myfile.xls
477 szFullName,
478 rest,
479 NULL,
481 }
482
483 *FirstEnd = _T('\0');
484
485 if (prci.hProcess != NULL)
486 {
487 if (bc != NULL || fSingleCommand != 0 || IsConsoleProcess(prci.hProcess))
488 {
489 /* when processing a batch file or starting console processes: execute synchronously */
492
494
496
497 GetExitCodeProcess(prci.hProcess, &dwExitCode);
498 nErrorLevel = (INT)dwExitCode;
499 }
500 CloseHandle(prci.hProcess);
501 }
502 else
503 {
504 TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full));
506 dwExitCode = 1;
507 }
508
509 /* Restore the default console mode */
514 }
515
516 /* Update the local code page cache */
517 {
518 UINT uNewInputCodePage = GetConsoleCP();
519 UINT uNewOutputCodePage = GetConsoleOutputCP();
520
521 if ((InputCodePage != uNewInputCodePage) ||
522 (OutputCodePage != uNewOutputCodePage))
523 {
524 InputCodePage = uNewInputCodePage;
525 OutputCodePage = uNewOutputCodePage;
526
527 /* Reset the current thread UI language */
530 {
532 }
533 /* Update the streams cached code page */
535
536 /* Update the locale as well */
537 InitLocale();
538 }
539 }
540
541 /* Restore the original console title */
543
544 return dwExitCode;
545}
WCHAR First[]
Definition: FormatMessage.c:11
PBATCH_CONTEXT bc
Definition: batch.c:67
DWORD dwChildProcessId
Definition: cmd.c:163
HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params, LPTSTR directory, INT show)
Definition: cmd.c:266
static BOOL IsConsoleProcess(HANDLE Process)
Definition: cmd.c:224
VOID error_bad_command(PCTSTR s)
Definition: error.c:124
BOOL SearchForExecutable(LPCTSTR, LPTSTR)
Definition: where.c:142
VOID InitLocale(VOID)
Definition: locale.c:25
#define STRING_FREE_ERROR1
Definition: resource.h:49
static VOID StripQuotes(LPSTR in)
Definition: cmdcons.c:116
#define CloseHandle
Definition: compat.h:739
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1168
#define INFINITE
Definition: serial.h:102
#define _tcscmp
Definition: tchar.h:1424
#define _istalpha
Definition: tchar.h:1492
#define _tcsncat
Definition: tchar.h:1408
#define _tcsrchr
Definition: utility.h:116
@ Batch
Definition: ntsecapi.h:291
static BOOL Full
Definition: pageheap.c:12
#define INT
Definition: polytest.cpp:20
const WCHAR * str
#define ConStdStreamsSetCacheCodePage(InputCodePage, OutputCodePage)
Definition: stream.h:152
#define memset(x, y, z)
Definition: compat.h:39
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
#define SEE_MASK_NO_CONSOLE
Definition: shellapi.h:38
LPSTR lpTitle
Definition: winbase.h:834
DWORD dwFlags
Definition: winbase.h:842
DWORD cb
Definition: winbase.h:831
WORD wShowWindow
Definition: winbase.h:843
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define CreateProcess
Definition: winbase.h:3629
#define STARTF_USESHOWWINDOW
Definition: winbase.h:491
#define SetCurrentDirectory
Definition: winbase.h:3774
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define SW_SHOWNORMAL
Definition: winuser.h:764
#define SW_SHOWDEFAULT
Definition: winuser.h:774

Referenced by DECLARE_INTERFACE_(), DoCommand(), and MiIsAccessAllowed().

◆ ExecuteAsync()

static HANDLE ExecuteAsync ( PARSED_COMMAND Cmd)
static

Definition at line 659 of file cmd.c.

660{
661 TCHAR CmdPath[MAX_PATH];
662 TCHAR CmdParams[CMDLINE_LENGTH], *ParamsEnd;
663 STARTUPINFO stui;
665
666 /* Get the path to cmd.exe */
667 GetModuleFileName(NULL, CmdPath, ARRAYSIZE(CmdPath));
668
669 /* Build the parameter string to pass to cmd.exe */
670 ParamsEnd = _stpcpy(CmdParams, _T("/S/D/C\""));
671 ParamsEnd = UnparseCommand(Cmd, ParamsEnd, &CmdParams[CMDLINE_LENGTH - 2]);
672 if (!ParamsEnd)
673 {
675 return NULL;
676 }
677 _tcscpy(ParamsEnd, _T("\""));
678
679 memset(&stui, 0, sizeof stui);
680 stui.cb = sizeof(STARTUPINFO);
681 if (!CreateProcess(CmdPath, CmdParams, NULL, NULL, TRUE, 0,
682 NULL, NULL, &stui, &prci))
683 {
685 return NULL;
686 }
687
688 CloseHandle(prci.hThread);
689 return prci.hProcess;
690}
static VOID ErrorMessage(_In_ DWORD dwErrorCode, _In_opt_ PCWSTR pszMsg,...)
Definition: attrib.c:51
PTCHAR UnparseCommand(IN PARSED_COMMAND *Cmd, OUT PTCHAR Out, IN PTCHAR OutEnd)
Definition: parser.c:1965
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:460
DWORD WINAPI GetLastError(void)
Definition: except.c:1040
STARTUPINFOA STARTUPINFO
Definition: winbase.h:3590
#define GetModuleFileName
Definition: winbase.h:3702

Referenced by ExecutePipeline().

◆ ExecuteAutoRunFile()

static VOID ExecuteAutoRunFile ( HKEY  hKeyRoot)
static

Definition at line 2042 of file cmd.c.

2043{
2044 LONG lRet;
2045 HKEY hKey;
2046 DWORD dwType, len;
2047 TCHAR AutoRun[2048];
2048
2049 lRet = RegOpenKeyEx(hKeyRoot,
2050 _T("Software\\Microsoft\\Command Processor"),
2051 0,
2053 &hKey);
2054 if (lRet != ERROR_SUCCESS)
2055 return;
2056
2057 len = sizeof(AutoRun);
2058 lRet = RegQueryValueEx(hKey,
2059 _T("AutoRun"),
2060 NULL,
2061 &dwType,
2062 (LPBYTE)&AutoRun,
2063 &len);
2064 if ((lRet == ERROR_SUCCESS) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ))
2065 {
2066 if (*AutoRun)
2067 ParseCommandLine(AutoRun);
2068 }
2069
2071}
#define RegCloseKey(hKey)
Definition: registry.h:47
#define ERROR_SUCCESS
Definition: deptool.c:10
FxAutoRegKey hKey
#define REG_SZ
Definition: layer.c:22
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
long LONG
Definition: pedump.c:60
unsigned char * LPBYTE
Definition: typedefs.h:53
#define RegOpenKeyEx
Definition: winreg.h:520
#define RegQueryValueEx
Definition: winreg.h:524

Referenced by Initialize().

◆ ExecuteCommand()

INT ExecuteCommand ( IN PARSED_COMMAND Cmd)

Definition at line 782 of file cmd.c.

784{
785#define SeenGoto() \
786 (bc && bc->current == NULL)
787
788 PARSED_COMMAND *Sub;
789 LPTSTR First, Rest;
790 INT Ret = 0;
791
792 /* If we don't have any command, or if this is REM, ignore it */
793 if (!Cmd || (Cmd->Type == C_REM))
794 return 0;
795 /*
796 * Do not execute any command if we are about to exit CMD, or about to
797 * change batch execution context, e.g. in case of a CALL / GOTO / EXIT.
798 */
799 if (bExit || SeenGoto())
800 return 0;
801
802 if (!PerformRedirection(Cmd->Redirections))
803 return 1;
804
805 switch (Cmd->Type)
806 {
807 case C_COMMAND:
808 Ret = 1;
809 First = DoDelayedExpansion(Cmd->Command.First);
810 if (First)
811 {
812 Rest = DoDelayedExpansion(Cmd->Command.Rest);
813 if (Rest)
814 {
815 Ret = DoCommand(First, Rest, Cmd);
816 cmd_free(Rest);
817 }
819 }
820 /* Fall through */
821 case C_REM:
822 break;
823
824 case C_QUIET:
825 case C_BLOCK:
826 case C_MULTI:
827 for (Sub = Cmd->Subcommands; Sub && !SeenGoto(); Sub = Sub->Next)
828 Ret = ExecuteCommand(Sub);
829 break;
830
831 case C_OR:
832 Sub = Cmd->Subcommands;
833 Ret = ExecuteCommand(Sub);
834 if ((Ret != 0) && !SeenGoto())
835 {
836 nErrorLevel = Ret;
837 Ret = ExecuteCommand(Sub->Next);
838 }
839 break;
840
841 case C_AND:
842 Sub = Cmd->Subcommands;
843 Ret = ExecuteCommand(Sub);
844 if ((Ret == 0) && !SeenGoto())
845 Ret = ExecuteCommand(Sub->Next);
846 break;
847
848 case C_PIPE:
849 Ret = ExecutePipeline(Cmd);
850 break;
851
852 case C_FOR:
853 Ret = ExecuteFor(Cmd);
854 break;
855
856 case C_IF:
857 Ret = ExecuteIf(Cmd);
858 break;
859 }
860
861 UndoRedirection(Cmd->Redirections, NULL);
862 return Ret;
863
864#undef SeenGoto
865}
INT ExecuteCommand(IN PARSED_COMMAND *Cmd)
Definition: cmd.c:782
INT DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
Definition: cmd.c:557
PTSTR DoDelayedExpansion(IN PCTSTR Line)
Definition: cmd.c:1642
static INT ExecutePipeline(PARSED_COMMAND *Cmd)
Definition: cmd.c:693
#define SeenGoto()
INT ExecuteIf(struct _PARSED_COMMAND *Cmd)
Definition: if.c:66
BOOL PerformRedirection(REDIRECTION *)
Definition: redir.c:63
@ C_QUIET
Definition: cmd.h:355
@ C_OR
Definition: cmd.h:359
@ C_COMMAND
Definition: cmd.h:353
@ C_REM
Definition: cmd.h:361
@ C_AND
Definition: cmd.h:359
@ C_MULTI
Definition: cmd.h:359
@ C_IF
Definition: cmd.h:361
@ C_PIPE
Definition: cmd.h:359
@ C_FOR
Definition: cmd.h:361
INT ExecuteFor(struct _PARSED_COMMAND *Cmd)
Definition: for.c:604
VOID UndoRedirection(REDIRECTION *, REDIRECTION *End)
Definition: redir.c:142
#define C_BLOCK
Definition: rsym.h:130
struct _PARSED_COMMAND * Next
Definition: cmd.h:372

Referenced by ExecuteCommand(), ExecuteCommandWithEcho(), ExecuteIf(), ParseCommandLine(), and ProcessInput().

◆ ExecuteCommandWithEcho()

INT ExecuteCommandWithEcho ( IN PARSED_COMMAND Cmd)

Definition at line 868 of file cmd.c.

870{
871 /* Echo the reconstructed command line */
872 if (bEcho && !bDisableBatchEcho && Cmd && (Cmd->Type != C_QUIET))
873 {
874 if (!bIgnoreEcho)
875 ConOutChar(_T('\n'));
876 PrintPrompt();
878 ConOutChar(_T('\n'));
879 }
880
881 /* Run the command */
882 return ExecuteCommand(Cmd);
883}
BOOL bEcho
Definition: batch.c:73
BOOL bDisableBatchEcho
Definition: cmd.c:160
BOOL bIgnoreEcho
Definition: cmd.c:155
VOID EchoCommand(IN PARSED_COMMAND *Cmd)
Definition: parser.c:1808
VOID PrintPrompt(VOID)
Definition: prompt.c:109
VOID ConOutChar(TCHAR c)
Definition: console.c:123

Referenced by Batch().

◆ ExecutePipeline()

static INT ExecutePipeline ( PARSED_COMMAND Cmd)
static

Definition at line 693 of file cmd.c.

694{
695#ifdef FEATURE_REDIRECTION
696 HANDLE hInput = NULL;
700 INT nProcesses = 0;
701 DWORD dwExitCode;
702
703 /* Do all but the last pipe command */
704 do
705 {
706 HANDLE hPipeRead, hPipeWrite;
707 if (nProcesses > (MAXIMUM_WAIT_OBJECTS - 2))
708 {
710 goto failed;
711 }
712
713 /* Create the pipe that this process will write into.
714 * Make the handles non-inheritable initially, because this
715 * process shouldn't inherit the reading handle. */
716 if (!CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0))
717 {
719 goto failed;
720 }
721
722 /* The writing side of the pipe is STDOUT for this process */
724 SetStdHandle(STD_OUTPUT_HANDLE, hPipeWrite);
725
726 /* Execute it (error check is done later for easier cleanup) */
727 hProcess[nProcesses] = ExecuteAsync(Cmd->Subcommands);
728 CloseHandle(hPipeWrite);
729 if (hInput)
730 CloseHandle(hInput);
731
732 /* The reading side of the pipe will be STDIN for the next process */
734 SetStdHandle(STD_INPUT_HANDLE, hPipeRead);
735 hInput = hPipeRead;
736
737 if (!hProcess[nProcesses])
738 goto failed;
739 nProcesses++;
740
741 Cmd = Cmd->Subcommands->Next;
742 } while (Cmd->Type == C_PIPE);
743
744 /* The last process uses the original STDOUT */
745 SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
746 hProcess[nProcesses] = ExecuteAsync(Cmd);
747 if (!hProcess[nProcesses])
748 goto failed;
749 nProcesses++;
750 CloseHandle(hInput);
751 SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
752
753 /* Wait for all processes to complete */
757
758 /* Use the exit code of the last process in the pipeline */
759 GetExitCodeProcess(hProcess[nProcesses - 1], &dwExitCode);
760 nErrorLevel = (INT)dwExitCode;
761
762 while (--nProcesses >= 0)
763 CloseHandle(hProcess[nProcesses]);
764 return nErrorLevel;
765
766failed:
767 if (hInput)
768 CloseHandle(hInput);
769 while (--nProcesses >= 0)
770 {
771 TerminateProcess(hProcess[nProcesses], 0);
772 CloseHandle(hProcess[nProcesses]);
773 }
774 SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
775 SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
776#endif
777
778 return nErrorLevel;
779}
static HANDLE ExecuteAsync(PARSED_COMMAND *Cmd)
Definition: cmd.c:659
VOID error_too_many_parameters(PCTSTR s)
Definition: error.c:79
VOID error_no_pipe(VOID)
Definition: error.c:131
BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle(DWORD nStdHandle, HANDLE hHandle)
Definition: console.c:1213
BOOL WINAPI SetHandleInformation(IN HANDLE hObject, IN DWORD dwMask, IN DWORD dwFlags)
Definition: handle.c:78
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1532
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:71
BOOL WINAPI CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize)
Definition: npipe.c:117
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
#define MAXIMUM_WAIT_OBJECTS
Definition: winbase.h:404
#define HANDLE_FLAG_INHERIT
Definition: winbase.h:264

Referenced by ExecuteCommand().

◆ FindForVar()

static BOOL FindForVar ( IN TCHAR  Var,
OUT PCTSTR VarPtr,
OUT BOOL IsParam0 
)
static

Definition at line 1576 of file cmd.c.

1580{
1581 PFOR_CONTEXT Ctx;
1582
1583 *VarPtr = NULL;
1584 *IsParam0 = FALSE;
1585
1586 for (Ctx = fc; Ctx != NULL; Ctx = Ctx->prev)
1587 {
1588 if ((UINT)(Var - Ctx->firstvar) < Ctx->varcount)
1589 {
1590 *VarPtr = Ctx->values[Var - Ctx->firstvar];
1591 return TRUE;
1592 }
1593 }
1594 return FALSE;
1595}
PFOR_CONTEXT fc
Definition: for.c:57
LPTSTR * values
Definition: batch.h:50
UINT varcount
Definition: batch.h:49
TCHAR firstvar
Definition: batch.h:48
struct _FOR_CONTEXT * prev
Definition: batch.h:47

Referenced by SubstituteForVars().

◆ GetBatchVar()

static PCTSTR GetBatchVar ( IN PCTSTR  varName,
OUT PUINT  varNameLen 
)
static

Definition at line 1275 of file cmd.c.

1278{
1279 PCTSTR ret;
1280 PCTSTR varNameEnd;
1281
1282 *varNameLen = 1;
1283
1284 switch (*varName)
1285 {
1286 case _T('~'):
1287 {
1288 varNameEnd = varName + 1;
1289 ret = GetEnhancedVar(&varNameEnd, FindArg);
1290 if (!ret)
1291 {
1292 ParseErrorEx(varName);
1293 return NULL;
1294 }
1295 *varNameLen = varNameEnd - varName;
1296 return ret;
1297 }
1298
1299 case _T('0'):
1300 case _T('1'):
1301 case _T('2'):
1302 case _T('3'):
1303 case _T('4'):
1304 case _T('5'):
1305 case _T('6'):
1306 case _T('7'):
1307 case _T('8'):
1308 case _T('9'):
1309 {
1310 BOOL dummy;
1311 if (!FindArg(*varName, &ret, &dummy))
1312 return NULL;
1313 else
1314 return ret;
1315 }
1316
1317 case _T('*'):
1318 /* Copy over the raw params (not including the batch file name) */
1319 return bc->raw_params;
1320
1321 case _T('%'):
1322 return _T("%");
1323 }
1324 return NULL;
1325}
BOOL FindArg(IN TCHAR Char, OUT PCTSTR *ArgPtr, OUT BOOL *IsParam0)
Definition: batch.c:84
static PCTSTR GetEnhancedVar(IN OUT PCTSTR *pFormat, IN BOOL(*GetVar)(TCHAR, PCTSTR *, BOOL *))
Definition: cmd.c:975
VOID ParseErrorEx(IN PCTSTR s)
Definition: parser.c:227
return
Definition: dirsup.c:529
LPCSTR PCTSTR
Definition: ntbasedef.h:488

Referenced by SubstituteVar().

◆ GetCmdLineCommand()

static VOID GetCmdLineCommand ( OUT LPTSTR  commandline,
IN LPCTSTR  ptr,
IN BOOL  AlwaysStrip 
)
static

Definition at line 2075 of file cmd.c.

2079{
2080 TCHAR* LastQuote;
2081
2082 while (_istspace(*ptr))
2083 ++ptr;
2084
2085 /* Remove leading quote, find final quote */
2086 if (*ptr == _T('"') &&
2087 (LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
2088 {
2089 const TCHAR* Space;
2090 /* Under certain circumstances, all quotes are preserved.
2091 * CMD /? documents these conditions as follows:
2092 * 1. No /S switch
2093 * 2. Exactly two quotes
2094 * 3. No "special characters" between the quotes
2095 * (CMD /? says &<>()@^| but parentheses did not
2096 * trigger this rule when I tested them.)
2097 * 4. Whitespace exists between the quotes
2098 * 5. Enclosed string is an executable filename
2099 */
2100 *LastQuote = _T('\0');
2101 for (Space = ptr + 1; Space < LastQuote; ++Space)
2102 {
2103 if (_istspace(*Space)) /* Rule 4 */
2104 {
2105 if (!AlwaysStrip && /* Rule 1 */
2106 !_tcspbrk(ptr, _T("\"&<>@^|")) && /* Rules 2, 3 */
2107 SearchForExecutable(ptr, commandline)) /* Rule 5 */
2108 {
2109 /* All conditions met: preserve both the quotes */
2110 *LastQuote = _T('"');
2111 _tcscpy(commandline, ptr - 1);
2112 return;
2113 }
2114 break;
2115 }
2116 }
2117
2118 /* The conditions were not met: remove both the
2119 * leading quote and the last quote */
2120 _tcscpy(commandline, ptr);
2121 _tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
2122 return;
2123 }
2124
2125 /* No quotes; just copy */
2126 _tcscpy(commandline, ptr);
2127}
#define _tcspbrk
Definition: tchar.h:1412
static PVOID ptr
Definition: dispmode.c:27

Referenced by _tmain().

◆ GetEnhancedVar()

static PCTSTR GetEnhancedVar ( IN OUT PCTSTR pFormat,
IN BOOL(*)(TCHAR, PCTSTR *, BOOL *)  GetVar 
)
static

Definition at line 975 of file cmd.c.

978{
979 static const TCHAR ModifierTable[] = _T("dpnxfsatz");
980 enum {
981 M_DRIVE = 1, /* D: drive letter */
982 M_PATH = 2, /* P: path */
983 M_NAME = 4, /* N: filename */
984 M_EXT = 8, /* X: extension */
985 M_FULL = 16, /* F: full path (drive+path+name+ext) */
986 M_SHORT = 32, /* S: full path (drive+path+name+ext), use short names */
987 M_ATTR = 64, /* A: attributes */
988 M_TIME = 128, /* T: modification time */
989 M_SIZE = 256, /* Z: file size */
990 } Modifiers = 0;
991
992 PCTSTR Format, FormatEnd;
993 PCTSTR PathVarName = NULL;
994 PCTSTR Variable;
995 PCTSTR VarEnd;
996 BOOL VariableIsParam0;
997 TCHAR FullPath[MAX_PATH];
998 TCHAR FixedPath[MAX_PATH];
1000 HANDLE hFind;
1001 WIN32_FIND_DATA w32fd;
1002 PTCHAR In, Out;
1003
1004 static TCHAR Result[CMDLINE_LENGTH];
1005
1006 /* Check whether the current character is a recognized variable.
1007 * If it is not, then restore the previous one: there is indeed
1008 * ambiguity between modifier characters and FOR variables;
1009 * the rule that CMD uses is to pick the longest possible match.
1010 * This case can happen if we have a FOR-variable specification
1011 * of the following form:
1012 *
1013 * %~<modifiers><actual FOR variable character><other characters>
1014 *
1015 * where the FOR variable character is also a similar to a modifier,
1016 * but should not be interpreted as is, and the following other
1017 * characters are not part of the possible modifier characters, and
1018 * are unrelated to the FOR variable (they can be part of a command).
1019 * For example, if there is a %n variable, then out of %~anxnd,
1020 * %~anxn will be substituted rather than just %~an.
1021 *
1022 * In the following examples, all characters 'd','p','n','x' are valid modifiers.
1023 *
1024 * 1. In this example, the FOR variable character is 'x' and the actual
1025 * modifiers are 'dpn'. Parsing will first determine that 'dpnx'
1026 * are modifiers, with the possible (last) valid variable being 'x',
1027 * and will stop at the letter 'g'. Since 'g' is not a valid
1028 * variable, then the actual variable is the lattest one 'x',
1029 * and the modifiers are then actually 'dpn'.
1030 * The FOR-loop will then display the %x variable formatted with 'dpn'
1031 * and will append any other characters following, 'g'.
1032 *
1033 * C:\Temp>for %x in (foo.exe bar.txt) do @echo %~dpnxg
1034 * C:\Temp\foog
1035 * C:\Temp\barg
1036 *
1037 *
1038 * 2. In this second example, the FOR variable character is 'g' and
1039 * the actual modifiers are 'dpnx'. Parsing will determine also that
1040 * the possible (last) valid variable could be 'x', but since it's
1041 * not present in the FOR-variables list, it won't be the case.
1042 * This means that the actual FOR variable character must follow,
1043 * in this case, 'g'.
1044 *
1045 * C:\Temp>for %g in (foo.exe bar.txt) do @echo %~dpnxg
1046 * C:\Temp\foo.exe
1047 * C:\Temp\bar.txt
1048 */
1049
1050 /* First, go through as many modifier characters as possible */
1051 FormatEnd = Format = *pFormat;
1052 while (*FormatEnd && _tcschr(ModifierTable, _totlower(*FormatEnd)))
1053 ++FormatEnd;
1054
1055 if (*FormatEnd == _T('$'))
1056 {
1057 /* $PATH: syntax */
1058 PathVarName = FormatEnd + 1;
1059 FormatEnd = _tcschr(PathVarName, _T(':'));
1060 if (!FormatEnd)
1061 return NULL;
1062
1063 /* Must be immediately followed by the variable */
1064 if (!GetVar(*++FormatEnd, &Variable, &VariableIsParam0))
1065 return NULL;
1066 }
1067 else
1068 {
1069 /* Backtrack if necessary to get a variable name match */
1070 while (!GetVar(*FormatEnd, &Variable, &VariableIsParam0))
1071 {
1072 if (FormatEnd == Format)
1073 return NULL;
1074 --FormatEnd;
1075 }
1076 }
1077
1078 *pFormat = FormatEnd + 1;
1079
1080 /* If the variable is empty, return an empty string */
1081 if (!Variable || !*Variable)
1082 return _T("");
1083
1084 /* Exclude the leading and trailing quotes */
1085 VarEnd = &Variable[_tcslen(Variable)];
1086 if (*Variable == _T('"'))
1087 {
1088 ++Variable;
1089 if (VarEnd > Variable && VarEnd[-1] == _T('"'))
1090 --VarEnd;
1091 }
1092
1093 if ((ULONG_PTR)VarEnd - (ULONG_PTR)Variable >= sizeof(Result))
1094 return _T("");
1095 memcpy(Result, Variable, (ULONG_PTR)VarEnd - (ULONG_PTR)Variable);
1096 Result[VarEnd - Variable] = _T('\0');
1097
1098 /* Now determine the actual modifiers */
1099 for (; Format < FormatEnd && *Format != _T('$'); ++Format)
1100 Modifiers |= 1 << (_tcschr(ModifierTable, _totlower(*Format)) - ModifierTable);
1101
1102 if (PathVarName)
1103 {
1104 /* $PATH: syntax - search the directories listed in the
1105 * specified environment variable for the file */
1106 PTSTR PathVar;
1107 ((PTSTR)FormatEnd)[-1] = _T('\0'); // FIXME: HACK!
1108 PathVar = GetEnvVar(PathVarName);
1109 ((PTSTR)FormatEnd)[-1] = _T(':');
1110 if (!PathVar ||
1111 !SearchPath(PathVar, Result, NULL, ARRAYSIZE(FullPath), FullPath, NULL))
1112 {
1113 return _T("");
1114 }
1115 }
1116 else if (Modifiers == 0)
1117 {
1118 /* For plain %~var with no modifiers, just return the variable without quotes */
1119 return Result;
1120 }
1121 else if (VariableIsParam0)
1122 {
1123 /* Special case: If the variable is %0 and modifier characters are present,
1124 * use the batch file's path (which includes the .bat/.cmd extension)
1125 * rather than the actual %0 variable (which might not). */
1126 ASSERT(bc);
1127 _tcscpy(FullPath, bc->BatchFilePath);
1128 }
1129 else
1130 {
1131 /* Convert the variable, now without quotes, to a full path */
1132 if (!GetFullPathName(Result, ARRAYSIZE(FullPath), FullPath, NULL))
1133 return _T("");
1134 }
1135
1136 /* Next step is to change the path to fix letter case (e.g.
1137 * C:\ReAcToS -> C:\ReactOS) and, if requested with the S modifier,
1138 * replace long filenames with short. */
1139
1140 In = FullPath;
1141 Out = FixedPath;
1142
1143 /* Copy drive letter */
1144 *Out++ = *In++;
1145 *Out++ = *In++;
1146 *Out++ = *In++;
1147 /* Loop over each \-separated component in the path */
1148 do {
1149 TCHAR *Next = _tcschr(In, _T('\\'));
1150 if (Next)
1151 *Next++ = _T('\0');
1152 /* Use FindFirstFile to get the correct name */
1153 if (Out + _tcslen(In) + 1 >= &FixedPath[ARRAYSIZE(FixedPath)])
1154 return _T("");
1155 _tcscpy(Out, In);
1156 hFind = FindFirstFile(FixedPath, &w32fd);
1157 /* If it doesn't exist, just leave the name as it was given */
1158 if (hFind != INVALID_HANDLE_VALUE)
1159 {
1160 PTSTR FixedComponent = w32fd.cFileName;
1161 if (*w32fd.cAlternateFileName &&
1162 ((Modifiers & M_SHORT) || !_tcsicmp(In, w32fd.cAlternateFileName)))
1163 {
1164 FixedComponent = w32fd.cAlternateFileName;
1165 }
1166 FindClose(hFind);
1167
1168 if (Out + _tcslen(FixedComponent) + 1 >= &FixedPath[ARRAYSIZE(FixedPath)])
1169 return _T("");
1170 _tcscpy(Out, FixedComponent);
1171 }
1172 Filename = Out;
1173 Out += _tcslen(Out);
1174 *Out++ = _T('\\');
1175
1176 In = Next;
1177 } while (In != NULL);
1178 Out[-1] = _T('\0');
1179
1180 /* Build the result string. Start with attributes, modification time, and
1181 * file size. If the file didn't exist, these fields will all be empty. */
1182 Out = Result;
1183 if (hFind != INVALID_HANDLE_VALUE)
1184 {
1185 if (Modifiers & M_ATTR)
1186 {
1187 static const struct {
1188 TCHAR Character;
1189 WORD Value;
1190 } *Attrib, Table[] = {
1191 { _T('d'), FILE_ATTRIBUTE_DIRECTORY },
1192 { _T('r'), FILE_ATTRIBUTE_READONLY },
1193 { _T('a'), FILE_ATTRIBUTE_ARCHIVE },
1194 { _T('h'), FILE_ATTRIBUTE_HIDDEN },
1195 { _T('s'), FILE_ATTRIBUTE_SYSTEM },
1196 { _T('c'), FILE_ATTRIBUTE_COMPRESSED },
1197 { _T('o'), FILE_ATTRIBUTE_OFFLINE },
1198 { _T('t'), FILE_ATTRIBUTE_TEMPORARY },
1200#if (NTDDI_VERSION >= NTDDI_WIN8)
1202 { _T('x'), FILE_ATTRIBUTE_NO_SCRUB_DATA /* 0x20000 */ },
1203#endif
1204 };
1205 for (Attrib = Table; Attrib != &Table[ARRAYSIZE(Table)]; Attrib++)
1206 {
1207 *Out++ = w32fd.dwFileAttributes & Attrib->Value
1208 ? Attrib->Character
1209 : _T('-');
1210 }
1211 *Out++ = _T(' ');
1212 }
1213 if (Modifiers & M_TIME)
1214 {
1215 FILETIME ft;
1216 SYSTEMTIME st;
1217 FileTimeToLocalFileTime(&w32fd.ftLastWriteTime, &ft);
1218 FileTimeToSystemTime(&ft, &st);
1219
1220 Out += FormatDate(Out, &st, TRUE);
1221 *Out++ = _T(' ');
1222 Out += FormatTime(Out, &st);
1223 *Out++ = _T(' ');
1224 }
1225 if (Modifiers & M_SIZE)
1226 {
1228 Size.LowPart = w32fd.nFileSizeLow;
1229 Size.HighPart = w32fd.nFileSizeHigh;
1230 Out += _stprintf(Out, _T("%I64u "), Size.QuadPart);
1231 }
1232 }
1233
1234 /* When using the path-searching syntax or the S modifier,
1235 * at least part of the file path is always included.
1236 * If none of the DPNX modifiers are present, include the full path */
1237 if (PathVarName || (Modifiers & M_SHORT))
1238 if ((Modifiers & (M_DRIVE | M_PATH | M_NAME | M_EXT)) == 0)
1239 Modifiers |= M_FULL;
1240
1241 /* Now add the requested parts of the name.
1242 * With the F modifier, add all parts to form the full path. */
1243 Extension = _tcsrchr(Filename, _T('.'));
1244 if (Modifiers & (M_DRIVE | M_FULL))
1245 {
1246 *Out++ = FixedPath[0];
1247 *Out++ = FixedPath[1];
1248 }
1249 if (Modifiers & (M_PATH | M_FULL))
1250 {
1251 memcpy(Out, &FixedPath[2], (ULONG_PTR)Filename - (ULONG_PTR)&FixedPath[2]);
1252 Out += Filename - &FixedPath[2];
1253 }
1254 if (Modifiers & (M_NAME | M_FULL))
1255 {
1256 while (*Filename && Filename != Extension)
1257 *Out++ = *Filename++;
1258 }
1259 if (Modifiers & (M_EXT | M_FULL))
1260 {
1261 if (Extension)
1263 }
1264
1265 /* Trim trailing space which otherwise would appear as a
1266 * result of using the A/T/Z modifiers but no others. */
1267 while (Out != &Result[0] && Out[-1] == _T(' '))
1268 Out--;
1269 *Out = _T('\0');
1270
1271 return Result;
1272}
INT FormatDate(TCHAR *, LPSYSTEMTIME, BOOL)
Definition: dir.c:674
INT FormatTime(TCHAR *, LPSYSTEMTIME)
Definition: dir.c:703
@ Out
@ In
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WINAPI FileTimeToLocalFileTime(IN CONST FILETIME *lpFileTime, OUT LPFILETIME lpLocalFileTime)
Definition: time.c:221
IN PVCB IN PBCB OUT PDIRENT IN USHORT IN POEM_STRING Filename
Definition: fatprocs.h:939
unsigned short WORD
Definition: ntddk_ex.h:93
_Inout_opt_ PUNICODE_STRING Extension
Definition: fltkernel.h:1092
ASMGENDATA Table[]
Definition: genincdata.c:61
#define _totlower
Definition: tchar.h:1511
#define ASSERT(a)
Definition: mode.c:44
#define _stprintf
Definition: utility.h:124
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define FILE_ATTRIBUTE_COMPRESSED
Definition: nt_native.h:711
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define FILE_ATTRIBUTE_OFFLINE
Definition: nt_native.h:712
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define FILE_ATTRIBUTE_TEMPORARY
Definition: nt_native.h:708
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
VKNAME Modifiers[]
Definition: data.c:56
TCHAR BatchFilePath[MAX_PATH]
Definition: batch.h:33
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define SearchPath
Definition: winbase.h:3771
#define FindFirstFile
Definition: winbase.h:3653
#define GetFullPathName
Definition: winbase.h:3692
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define FILE_ATTRIBUTE_INTEGRITY_STREAM
CHAR * PTSTR
Definition: xmlstorage.h:191

Referenced by GetBatchVar(), and SubstituteForVars().

◆ GetEnvVar()

LPTSTR GetEnvVar ( LPCTSTR  varName)

Definition at line 886 of file cmd.c.

887{
888 static LPTSTR ret = NULL;
889 UINT size;
890
891 cmd_free(ret);
892 ret = NULL;
893 size = GetEnvironmentVariable(varName, NULL, 0);
894 if (size > 0)
895 {
896 ret = cmd_alloc(size * sizeof(TCHAR));
897 if (ret != NULL)
898 GetEnvironmentVariable(varName, ret, size + 1);
899 }
900 return ret;
901}
GLsizeiptr size
Definition: glext.h:5919
#define GetEnvironmentVariable
Definition: winbase.h:3685

Referenced by Cleanup(), GetEnhancedVar(), and GetEnvVarOrSpecial().

◆ GetEnvVarOrSpecial()

LPCTSTR GetEnvVarOrSpecial ( LPCTSTR  varName)

Definition at line 904 of file cmd.c.

905{
906 static TCHAR ret[MAX_PATH];
907
908 LPTSTR var = GetEnvVar(varName);
909 if (var)
910 return var;
911
912 /* The environment variable doesn't exist, look for
913 * a "special" one only if extensions are enabled. */
915 return NULL;
916
917 /* %CD% */
918 if (_tcsicmp(varName, _T("CD")) == 0)
919 {
921 return ret;
922 }
923 /* %DATE% */
924 else if (_tcsicmp(varName, _T("DATE")) == 0)
925 {
926 return GetDateString();
927 }
928 /* %TIME% */
929 else if (_tcsicmp(varName, _T("TIME")) == 0)
930 {
931 return GetTimeString();
932 }
933 /* %RANDOM% */
934 else if (_tcsicmp(varName, _T("RANDOM")) == 0)
935 {
936 /* Get random number */
937 _itot(rand(), ret, 10);
938 return ret;
939 }
940 /* %CMDCMDLINE% */
941 else if (_tcsicmp(varName, _T("CMDCMDLINE")) == 0)
942 {
943 return GetCommandLine();
944 }
945 /* %CMDEXTVERSION% */
946 else if (_tcsicmp(varName, _T("CMDEXTVERSION")) == 0)
947 {
948 /* Set Command Extensions version number to CMDEXTVERSION */
949 _itot(CMDEXTVERSION, ret, 10);
950 return ret;
951 }
952 /* %ERRORLEVEL% */
953 else if (_tcsicmp(varName, _T("ERRORLEVEL")) == 0)
954 {
955 _itot(nErrorLevel, ret, 10);
956 return ret;
957 }
958#if (NTDDI_VERSION >= NTDDI_WIN7)
959 /* Available in Win7+, even if the underlying API is available in Win2003+ */
960 /* %HIGHESTNUMANODENUMBER% */
961 else if (_tcsicmp(varName, _T("HIGHESTNUMANODENUMBER")) == 0)
962 {
963 ULONG NumaNodeNumber = 0;
964 GetNumaHighestNodeNumber(&NumaNodeNumber);
965 _itot(NumaNodeNumber, ret, 10);
966 return ret;
967 }
968#endif
969
970 return NULL;
971}
BOOL bEnableExtensions
Definition: cmd.c:161
LPTSTR GetTimeString(VOID)
Definition: locale.c:73
#define CMDEXTVERSION
Definition: cmd.h:32
LPTSTR GetDateString(VOID)
Definition: locale.c:58
BOOL WINAPI GetNumaHighestNodeNumber(OUT PULONG HighestNodeNumber)
Definition: sysinfo.c:264
_Check_return_ int __cdecl rand(void)
Definition: rand.c:10
#define _itot
Definition: tchar.h:608
const char * var
Definition: shader.c:5666
uint32_t ULONG
Definition: typedefs.h:59
#define GetCommandLine
Definition: winbase.h:3670

Referenced by ExecuteIf(), seta_identval(), and SubstituteVar().

◆ Initialize()

static LPCTSTR Initialize ( VOID  )
static

Definition at line 2135 of file cmd.c.

2136{
2137 HMODULE NtDllModule;
2138 HANDLE hIn, hOut;
2139 LPTSTR ptr, cmdLine;
2140 TCHAR option = 0;
2141 BOOL AutoRun = TRUE;
2143
2144 /* Get version information */
2145 InitOSVersion();
2146
2147 /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
2148 * build process. So don't link implicitly against ntdll.dll, load it
2149 * dynamically instead */
2150 NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
2151 if (NtDllModule != NULL)
2152 {
2153 NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)GetProcAddress(NtDllModule, "NtQueryInformationProcess");
2154 NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
2155 }
2156
2157 /* Load the registry settings */
2160
2161 /* Initialize our locale */
2162 InitLocale();
2163
2164 /* Initialize prompt support */
2165 InitPrompt();
2166
2167#ifdef FEATURE_DIRECTORY_STACK
2168 /* Initialize directory stack */
2170#endif
2171
2172#ifdef FEATURE_HISTORY
2173 /* Initialize history */
2174 InitHistory();
2175#endif
2176
2177 /* Set COMSPEC environment variable */
2179 {
2180 ModuleName[MAX_PATH] = _T('\0');
2181 SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
2182 }
2183
2184 /* Add ctrl break handler */
2186
2187 /* Set the default console mode */
2190 SetConsoleMode(hOut, 0); // Reinitialize the console output mode
2193
2194 cmdLine = GetCommandLine();
2195 TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
2196
2197 for (ptr = cmdLine; *ptr; ++ptr)
2198 {
2199 if (*ptr == _T('/'))
2200 {
2201 option = _totupper(ptr[1]);
2202 if (option == _T('?'))
2203 {
2205 nErrorLevel = 1;
2206 bExit = TRUE;
2207 return NULL;
2208 }
2209 else if (option == _T('P'))
2210 {
2211 if (!IsExistingFile(_T("\\autoexec.bat")))
2212 {
2213#ifdef INCLUDE_CMD_DATE
2214 cmd_date(_T(""));
2215#endif
2216#ifdef INCLUDE_CMD_TIME
2217 cmd_time(_T(""));
2218#endif
2219 }
2220 else
2221 {
2222 ParseCommandLine(_T("\\autoexec.bat"));
2223 }
2224 bCanExit = FALSE;
2225 }
2226 else if (option == _T('A'))
2227 {
2229 }
2230 else if (option == _T('C') || option == _T('K') || option == _T('R'))
2231 {
2232 /* Remainder of command line is a command to be run */
2233 fSingleCommand = ((option == _T('K')) << 1) | 1;
2234 break;
2235 }
2236 else if (option == _T('D'))
2237 {
2238 AutoRun = FALSE;
2239 }
2240 else if (option == _T('Q'))
2241 {
2243 }
2244 else if (option == _T('S'))
2245 {
2247 }
2248#ifdef INCLUDE_CMD_COLOR
2249 else if (!_tcsnicmp(ptr, _T("/T:"), 3))
2250 {
2251 /* Process /T (color) argument; overwrite any previous settings */
2252 wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
2253 }
2254#endif
2255 else if (option == _T('U'))
2256 {
2258 }
2259 else if (option == _T('V'))
2260 {
2261 // FIXME: Check validity of the parameter given to V !
2262 bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
2263 }
2264 else if (option == _T('E'))
2265 {
2266 // FIXME: Check validity of the parameter given to E !
2267 bEnableExtensions = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
2268 }
2269 else if (option == _T('X'))
2270 {
2271 /* '/X' is identical to '/E:ON' */
2273 }
2274 else if (option == _T('Y'))
2275 {
2276 /* '/Y' is identical to '/E:OFF' */
2278 }
2279 }
2280 }
2281
2282#ifdef INCLUDE_CMD_COLOR
2283 if (wDefColor == 0)
2284 {
2285 /*
2286 * If we still do not have the console colour attribute set,
2287 * retrieve the default one.
2288 */
2290 }
2291
2292 if (wDefColor != 0)
2294#endif
2295
2296 /* Reset the output Standard Streams translation modes and code page caches */
2297 // ConStreamSetMode(StdIn , OutputStreamMode, InputCodePage );
2300
2301 if (!*ptr)
2302 {
2303 /* If neither /C or /K was given, display a simple version string */
2304 ConOutChar(_T('\n'));
2306 _T(KERNEL_VERSION_STR),
2307 _T(KERNEL_VERSION_BUILD_STR));
2308 ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team.\n"));
2309 }
2310
2311 if (AutoRun)
2312 {
2315 }
2316
2317 /* Returns the rest of the command line */
2318 return ptr;
2319}
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char const char * ModuleName
Definition: acpixf.h:1280
NTSTATUS(WINAPI * NtReadVirtualMemoryProc)(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T)
Definition: cmd.c:150
BOOL bCanExit
Definition: cmd.c:153
static VOID LoadRegistrySettings(HKEY hKeyRoot)
Definition: cmd.c:1893
WORD wDefColor
Definition: cmd.c:180
VOID AddBreakHandler(VOID)
Definition: cmd.c:1846
static VOID ExecuteAutoRunFile(HKEY hKeyRoot)
Definition: cmd.c:2042
static NtReadVirtualMemoryProc NtReadVirtualMemoryPtr
Definition: cmd.c:171
static NtQueryInformationProcessProc NtQueryInformationProcessPtr
Definition: cmd.c:170
NTSTATUS(WINAPI * NtQueryInformationProcessProc)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG)
Definition: cmd.c:148
VOID InitOSVersion(VOID)
Definition: ver.c:32
INT cmd_date(LPTSTR)
Definition: date.c:176
VOID InitDirectoryStack(VOID)
Definition: dirstack.c:80
INT cmd_time(LPTSTR)
Definition: time.c:132
VOID InitPrompt(VOID)
Definition: prompt.c:57
BOOL ConSetScreenColor(HANDLE hOutput, WORD wColor, BOOL bFill)
Definition: console.c:302
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
BOOL ConGetDefaultAttributes(PWORD pwDefAttr)
Definition: console.c:255
#define ConOutPuts(szStr)
Definition: console.h:30
VOID InitHistory(VOID)
Definition: history.c:132
#define STRING_REACTOS_VERSION
Definition: resource.h:89
#define STRING_CMD_HELP8
Definition: resource.h:82
#define GetProcAddress(x, y)
Definition: compat.h:753
#define _tcstoul
Definition: tchar.h:595
#define _totupper
Definition: tchar.h:1509
#define TEXT(s)
Definition: k32.h:26
BOOL ConStreamSetMode(IN PCON_STREAM Stream, IN CON_STREAM_MODE Mode, IN UINT CacheCodePage OPTIONAL)
Definition: stream.c:195
@ UTF16Text
Definition: stream.h:49
Definition: getopt.h:109
#define SetEnvironmentVariable
Definition: winbase.h:3779
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11

◆ IsConsoleProcess()

static BOOL IsConsoleProcess ( HANDLE  Process)
static

Definition at line 224 of file cmd.c.

225{
228 PEB ProcessPeb;
230
232 {
233 return TRUE;
234 }
235
239 if (! NT_SUCCESS(Status))
240 {
241 WARN ("NtQueryInformationProcess failed with status %08x\n", Status);
242 return TRUE;
243 }
245 Process, Info.PebBaseAddress, &ProcessPeb,
246 sizeof(PEB), &BytesRead);
247 if (! NT_SUCCESS(Status) || sizeof(PEB) != BytesRead)
248 {
249 WARN ("Couldn't read virt mem status %08x bytes read %Iu\n", Status, BytesRead);
250 return TRUE;
251 }
252
253 return IMAGE_SUBSYSTEM_WINDOWS_CUI == ProcessPeb.ImageSubsystem;
254}
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: debug.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
@ ProcessBasicInformation
Definition: winternl.h:394
#define IMAGE_SUBSYSTEM_WINDOWS_CUI
Definition: ntimage.h:438
ULONG ImageSubsystem
Definition: ntddk_ex.h:304
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870

Referenced by Execute().

◆ LoadRegistrySettings()

static VOID LoadRegistrySettings ( HKEY  hKeyRoot)
static

Definition at line 1893 of file cmd.c.

1894{
1895 LONG lRet;
1896 HKEY hKey;
1897 DWORD dwType, len;
1898 /*
1899 * Buffer big enough to hold the string L"4294967295",
1900 * corresponding to the literal 0xFFFFFFFF (MAXULONG) in decimal.
1901 */
1902 DWORD Buffer[6];
1903
1904 lRet = RegOpenKeyEx(hKeyRoot,
1905 _T("Software\\Microsoft\\Command Processor"),
1906 0,
1908 &hKey);
1909 if (lRet != ERROR_SUCCESS)
1910 return;
1911
1912#ifdef INCLUDE_CMD_COLOR
1913 len = sizeof(Buffer);
1914 lRet = RegQueryValueEx(hKey,
1915 _T("DefaultColor"),
1916 NULL,
1917 &dwType,
1918 (LPBYTE)&Buffer,
1919 &len);
1920 if (lRet == ERROR_SUCCESS)
1921 {
1922 /* Overwrite the default attributes */
1923 if (dwType == REG_DWORD)
1925 else if (dwType == REG_SZ)
1927 }
1928 // else, use the default attributes retrieved before.
1929#endif
1930
1931#if 0
1932 len = sizeof(Buffer);
1933 lRet = RegQueryValueEx(hKey,
1934 _T("DisableUNCCheck"),
1935 NULL,
1936 &dwType,
1937 (LPBYTE)&Buffer,
1938 &len);
1939 if (lRet == ERROR_SUCCESS)
1940 {
1941 /* Overwrite the default setting */
1942 if (dwType == REG_DWORD)
1943 bDisableUNCCheck = !!*(PDWORD)Buffer;
1944 else if (dwType == REG_SZ)
1945 bDisableUNCCheck = (_ttol((PTSTR)Buffer) == 1);
1946 }
1947 // else, use the default setting set globally.
1948#endif
1949
1950 len = sizeof(Buffer);
1951 lRet = RegQueryValueEx(hKey,
1952 _T("DelayedExpansion"),
1953 NULL,
1954 &dwType,
1955 (LPBYTE)&Buffer,
1956 &len);
1957 if (lRet == ERROR_SUCCESS)
1958 {
1959 /* Overwrite the default setting */
1960 if (dwType == REG_DWORD)
1962 else if (dwType == REG_SZ)
1964 }
1965 // else, use the default setting set globally.
1966
1967 len = sizeof(Buffer);
1968 lRet = RegQueryValueEx(hKey,
1969 _T("EnableExtensions"),
1970 NULL,
1971 &dwType,
1972 (LPBYTE)&Buffer,
1973 &len);
1974 if (lRet == ERROR_SUCCESS)
1975 {
1976 /* Overwrite the default setting */
1977 if (dwType == REG_DWORD)
1979 else if (dwType == REG_SZ)
1981 }
1982 // else, use the default setting set globally.
1983
1984 len = sizeof(Buffer);
1985 lRet = RegQueryValueEx(hKey,
1986 _T("CompletionChar"),
1987 NULL,
1988 &dwType,
1989 (LPBYTE)&Buffer,
1990 &len);
1991 if (lRet == ERROR_SUCCESS)
1992 {
1993 /* Overwrite the default setting */
1994 if (dwType == REG_DWORD)
1996 else if (dwType == REG_SZ)
1998 }
1999 // else, use the default setting set globally.
2000
2001 /* Validity check */
2003 {
2004 /* Disable autocompletion */
2005 AutoCompletionChar = 0x20;
2006 }
2007
2008 len = sizeof(Buffer);
2009 lRet = RegQueryValueEx(hKey,
2010 _T("PathCompletionChar"),
2011 NULL,
2012 &dwType,
2013 (LPBYTE)&Buffer,
2014 &len);
2015 if (lRet == ERROR_SUCCESS)
2016 {
2017 /* Overwrite the default setting */
2018 if (dwType == REG_DWORD)
2020 else if (dwType == REG_SZ)
2022 }
2023 // else, use the default setting set globally.
2024
2025 /* Validity check */
2027 {
2028 /* Disable autocompletion */
2029 PathCompletionChar = 0x20;
2030 }
2031
2032 /* Adjust completion chars */
2033 if (PathCompletionChar >= 0x20 && AutoCompletionChar < 0x20)
2035 else if (AutoCompletionChar >= 0x20 && PathCompletionChar < 0x20)
2037
2039}
#define IS_COMPLETION_DISABLED(CompletionCtrl)
Definition: cmd.h:135
TCHAR AutoCompletionChar
Definition: cmdinput.c:111
TCHAR PathCompletionChar
Definition: cmdinput.c:112
Definition: bufpool.h:45
#define _ttol
Definition: tchar.h:612
#define _tcstol
Definition: tchar.h:594
DWORD * PDWORD
Definition: pedump.c:68
#define REG_DWORD
Definition: sdbapi.c:596

Referenced by Initialize().

◆ ParseCommandLine()

INT ParseCommandLine ( LPTSTR  cmd)

Definition at line 636 of file cmd.c.

637{
638 INT Ret = 0;
640
642 if (!Cmd)
643 {
644 /* Return an adequate error code */
645 return (!bParseError ? 0 : 1);
646 }
647
648 Ret = ExecuteCommand(Cmd);
650 return Ret;
651}
PARSED_COMMAND * ParseCommand(IN PCTSTR Line)
Definition: parser.c:1461
BOOL bParseError
Definition: parser.c:90
VOID FreeCommand(IN OUT PARSED_COMMAND *Cmd)
Definition: parser.c:527
Definition: ftp_var.h:139

Referenced by _tmain(), Cleanup(), ExecuteAutoRunFile(), and Initialize().

◆ ProcessInput()

static INT ProcessInput ( VOID  )
static

Definition at line 1774 of file cmd.c.

1775{
1776 INT Ret = 0;
1778
1779 while (!bCanExit || !bExit)
1780 {
1781 /* Reset the Ctrl-Break / Ctrl-C state */
1782 bCtrlBreak = FALSE;
1783
1785 if (!Cmd)
1786 continue;
1787
1788 Ret = ExecuteCommand(Cmd);
1790 }
1791
1792 return Ret;
1793}

Referenced by _tmain().

◆ ReadLine()

BOOL ReadLine ( TCHAR commandline,
BOOL  bMore 
)

Definition at line 1723 of file cmd.c.

1724{
1726 LPTSTR ip;
1727
1728 /* if no batch input then... */
1729 if (bc == NULL)
1730 {
1731 if (bMore)
1732 {
1734 }
1735 else
1736 {
1737 /* JPP 19980807 - if echo off, don't print prompt */
1738 if (bEcho)
1739 {
1740 if (!bIgnoreEcho)
1741 ConOutChar(_T('\n'));
1742 PrintPrompt();
1743 }
1744 }
1745
1747 {
1748 bExit = TRUE;
1749 return FALSE;
1750 }
1751
1752 if (readline[0] == _T('\0'))
1753 ConOutChar(_T('\n'));
1754
1756 return FALSE;
1757
1758 if (readline[0] == _T('\0'))
1759 return FALSE;
1760
1761 ip = readline;
1762 }
1763 else
1764 {
1765 ip = ReadBatchLine();
1766 if (!ip)
1767 return FALSE;
1768 }
1769
1770 return SubstituteVars(ip, commandline, _T('%'));
1771}
static logline * readline(FILE *inf, adns_state adns, int opts)
Definition: adnslogres.c:145
LPTSTR ReadBatchLine(VOID)
Definition: batch.c:564
BOOL SubstituteVars(IN PCTSTR Src, OUT PTSTR Dest, IN TCHAR Delim)
Definition: cmd.c:1516
BOOL CheckCtrlBreak(INT)
Definition: misc.c:132
#define BREAK_INPUT
Definition: cmd.h:36
#define STRING_MORE
Definition: resource.h:239
static BOOL ReadCommand(PCONSOLE_STATE State, LPSTR str, INT maxlen)
Definition: cmdcons.c:735
Definition: dhcpd.h:62

Referenced by ParseChar(), and ParseCommand().

◆ RemoveBreakHandler()

VOID RemoveBreakHandler ( VOID  )

Definition at line 1852 of file cmd.c.

Referenced by Cleanup(), FilePromptYN(), FilePromptYNA(), and PagePrompt().

◆ ResetConTitle()

static VOID ResetConTitle ( VOID  )
static

Definition at line 329 of file cmd.c.

330{
331 /* Restore the original console title */
332 if (!bc && bTitleSet)
333 {
336 }
337}
TCHAR szCurTitle[MAX_PATH]
Definition: cmd.c:168
BOOL bTitleSet
Definition: cmd.c:167
BOOL ConSetTitle(IN LPCTSTR lpConsoleTitle)
Definition: console.c:280

Referenced by DoCommand(), and Execute().

◆ RunFile()

HANDLE RunFile ( DWORD  flags,
LPTSTR  filename,
LPTSTR  params,
LPTSTR  directory,
INT  show 
)

Definition at line 266 of file cmd.c.

268{
271 MYEX hShExt;
272 BOOL ret;
273
274 TRACE ("RunFile(%s)\n", debugstr_aw(filename));
275 hShell32 = LoadLibrary(_T("SHELL32.DLL"));
276 if (!hShell32)
277 {
278 WARN ("RunFile: couldn't load SHELL32.DLL!\n");
279 return NULL;
280 }
281
283 if (!hShExt)
284 {
285 WARN ("RunFile: couldn't find ShellExecuteExA/W in SHELL32.DLL!\n");
287 return NULL;
288 }
289
290 TRACE ("RunFile: ShellExecuteExA/W is at %x\n", hShExt);
291
292 memset(&sei, 0, sizeof sei);
293 sei.cbSize = sizeof sei;
294 sei.fMask = flags;
295 sei.lpFile = filename;
296 sei.lpParameters = params;
298 sei.nShow = show;
299 ret = hShExt(&sei);
300
301 TRACE ("RunFile: ShellExecuteExA/W returned 0x%p\n", ret);
302
304 return ret ? sei.hProcess : NULL;
305}
BOOL(WINAPI * MYEX)(LPSHELLEXECUTEINFO lpExecInfo)
Definition: cmd.c:264
#define SHELLEXECUTETEXT
Definition: cmd.c:261
int(* FARPROC)()
Definition: compat.h:36
#define FreeLibrary(x)
Definition: compat.h:748
GLenum const GLfloat * params
Definition: glext.h:5645
GLbitfield flags
Definition: glext.h:7161
const char * filename
Definition: ioapi.h:137
static HMODULE hShell32
Definition: string.c:34
LPCSTR lpParameters
Definition: shellapi.h:313
LPCSTR lpDirectory
Definition: shellapi.h:314
#define LoadLibrary
Definition: winbase.h:3733

Referenced by cmd_start(), and Execute().

◆ SetConTitle()

static VOID SetConTitle ( LPCTSTR  pszTitle)
static

Definition at line 309 of file cmd.c.

310{
311 TCHAR szNewTitle[MAX_PATH];
312
313 if (!pszTitle)
314 return;
315
316 /* Don't do anything if we run inside a batch file, or we are just running a single command */
317 if (bc || (fSingleCommand == 1))
318 return;
319
320 /* Save the original console title and build a new one */
322 StringCchPrintf(szNewTitle, ARRAYSIZE(szNewTitle),
323 _T("%s - %s"), szCurTitle, pszTitle);
324 bTitleSet = TRUE;
325 ConSetTitle(szNewTitle);
326}
#define StringCchPrintf
Definition: strsafe.h:517
#define GetConsoleTitle
Definition: wincon.h:775

Referenced by DoCommand(), and Execute().

◆ SubstituteForVars()

BOOL SubstituteForVars ( IN PCTSTR  Src,
OUT PTSTR  Dest 
)

Definition at line 1598 of file cmd.c.

1601{
1602 PTCHAR DestEnd = &Dest[CMDLINE_LENGTH - 1];
1603 while (*Src)
1604 {
1605 if (Src[0] == _T('%'))
1606 {
1607 BOOL Dummy;
1608 PCTSTR End = &Src[2];
1609 PCTSTR Value = NULL;
1610
1611 if (Src[1] == _T('~'))
1613
1614 if (!Value && Src[1])
1615 {
1616 if (FindForVar(Src[1], &Value, &Dummy) && !Value)
1617 {
1618 /* The variable is empty, return an empty string */
1619 Value = _T("");
1620 }
1621 }
1622
1623 if (Value)
1624 {
1625 if (Dest + _tcslen(Value) > DestEnd)
1626 return FALSE;
1627 Dest = _stpcpy(Dest, Value);
1628 Src = End;
1629 continue;
1630 }
1631 }
1632 /* Not a variable; just copy the character */
1633 if (Dest >= DestEnd)
1634 return FALSE;
1635 *Dest++ = *Src++;
1636 }
1637 *Dest = _T('\0');
1638 return TRUE;
1639}
static BOOL FindForVar(IN TCHAR Var, OUT PCTSTR *VarPtr, OUT BOOL *IsParam0)
Definition: cmd.c:1576

Referenced by DoDelayedExpansion(), EchoCommand(), and UnparseCommand().

◆ SubstituteVar()

BOOL SubstituteVar ( IN PCTSTR  Src,
OUT size_t SrcIncLen,
OUT PTCHAR  Dest,
IN PTCHAR  DestEnd,
OUT size_t DestIncLen,
IN TCHAR  Delim 
)

Definition at line 1328 of file cmd.c.

1335{
1336#define APPEND(From, Length) \
1337do { \
1338 if (Dest + (Length) > DestEnd) \
1339 goto too_long; \
1340 memcpy(Dest, (From), (Length) * sizeof(TCHAR)); \
1341 Dest += (Length); \
1342} while (0)
1343
1344#define APPEND1(Char) \
1345do { \
1346 if (Dest >= DestEnd) \
1347 goto too_long; \
1348 *Dest++ = (Char); \
1349} while (0)
1350
1351 PCTSTR Var;
1352 PCTSTR Start, End, SubstStart;
1353 TCHAR EndChr;
1354 size_t VarLength;
1355
1356 Start = Src;
1357 End = Dest;
1358 *SrcIncLen = 0;
1359 *DestIncLen = 0;
1360
1361 if (!Delim)
1362 return FALSE;
1363 if (*Src != Delim)
1364 return FALSE;
1365
1366 ++Src;
1367
1368 /* If we are already at the end of the string, fail the substitution */
1369 SubstStart = Src;
1370 if (!*Src || *Src == _T('\r') || *Src == _T('\n'))
1371 goto bad_subst;
1372
1373 if (bc && Delim == _T('%'))
1374 {
1375 UINT NameLen;
1376 Var = GetBatchVar(Src, &NameLen);
1377 if (!Var && bParseError)
1378 {
1379 /* Return the partially-parsed command to be
1380 * echoed for error diagnostics purposes. */
1381 APPEND1(Delim);
1382 APPEND(Src, _tcslen(Src) + 1);
1383 return FALSE;
1384 }
1385 if (Var != NULL)
1386 {
1387 VarLength = _tcslen(Var);
1388 APPEND(Var, VarLength);
1389 Src += NameLen;
1390 goto success;
1391 }
1392 }
1393
1394 /* Find the end of the variable name. A colon (:) will usually
1395 * end the name and begin the optional modifier, but not if it
1396 * is immediately followed by the delimiter (%VAR:%). */
1397 SubstStart = Src;
1398 while (*Src && *Src != Delim && !(*Src == _T(':') && Src[1] != Delim))
1399 {
1400 ++Src;
1401 }
1402 /* If we are either at the end of the string, or the delimiter
1403 * has been repeated more than once, fail the substitution. */
1404 if (!*Src || Src == SubstStart)
1405 goto bad_subst;
1406
1407 EndChr = *Src;
1408 *(PTSTR)Src = _T('\0'); // FIXME: HACK!
1409 Var = GetEnvVarOrSpecial(SubstStart);
1410 *(PTSTR)Src++ = EndChr;
1411 if (Var == NULL)
1412 {
1413 /* In a batch context, %NONEXISTENT% "expands" to an
1414 * empty string, otherwise fail the substitution. */
1415 if (bc)
1416 goto success;
1417 goto bad_subst;
1418 }
1419 VarLength = _tcslen(Var);
1420
1421 if (EndChr == Delim)
1422 {
1423 /* %VAR% - use as-is */
1424 APPEND(Var, VarLength);
1425 }
1426 else if (*Src == _T('~'))
1427 {
1428 /* %VAR:~[start][,length]% - Substring.
1429 * Negative values are offsets from the end.
1430 */
1431 SSIZE_T Start = _tcstol(Src + 1, (PTSTR*)&Src, 0);
1432 SSIZE_T End = (SSIZE_T)VarLength;
1433 if (Start < 0)
1434 Start += VarLength;
1435 Start = min(max(Start, 0), VarLength);
1436 if (*Src == _T(','))
1437 {
1438 End = _tcstol(Src + 1, (PTSTR*)&Src, 0);
1439 End += (End < 0) ? VarLength : Start;
1440 End = min(max(End, Start), VarLength);
1441 }
1442 if (*Src++ != Delim)
1443 goto bad_subst;
1444 APPEND(&Var[Start], End - Start);
1445 }
1446 else
1447 {
1448 /* %VAR:old=new% - Replace all occurrences of old with new.
1449 * %VAR:*old=new% - Replace first occurrence only,
1450 * and remove everything before it.
1451 */
1452 PCTSTR Old, New;
1453 size_t OldLength, NewLength;
1454 BOOL Star = FALSE;
1455 size_t LastMatch = 0, i = 0;
1456
1457 if (*Src == _T('*'))
1458 {
1459 Star = TRUE;
1460 Src++;
1461 }
1462
1463 /* The string to replace may contain the delimiter */
1464 Src = _tcschr(Old = Src, _T('='));
1465 if (Src == NULL)
1466 goto bad_subst;
1467 OldLength = Src++ - Old;
1468 if (OldLength == 0)
1469 goto bad_subst;
1470
1471 Src = _tcschr(New = Src, Delim);
1472 if (Src == NULL)
1473 goto bad_subst;
1474 NewLength = Src++ - New;
1475
1476 while (i < VarLength)
1477 {
1478 if (_tcsnicmp(&Var[i], Old, OldLength) == 0)
1479 {
1480 if (!Star)
1481 APPEND(&Var[LastMatch], i - LastMatch);
1483 i += OldLength;
1484 LastMatch = i;
1485 if (Star)
1486 break;
1487 continue;
1488 }
1489 i++;
1490 }
1491 APPEND(&Var[LastMatch], VarLength - LastMatch);
1492 }
1493
1494success:
1495 *SrcIncLen = (Src - Start);
1496 *DestIncLen = (Dest - End);
1497 return TRUE;
1498
1499bad_subst:
1500 Src = SubstStart;
1501 /* Only if no batch context active do we echo the delimiter */
1502 if (!bc)
1503 APPEND1(Delim);
1504 goto success;
1505
1506too_long:
1508 nErrorLevel = 9023;
1509 return FALSE;
1510
1511#undef APPEND
1512#undef APPEND1
1513}
static USHORT USHORT * NewLength
#define APPEND(From, Length)
static PCTSTR GetBatchVar(IN PCTSTR varName, OUT PUINT varNameLen)
Definition: cmd.c:1275
LPCTSTR GetEnvVarOrSpecial(LPCTSTR varName)
Definition: cmd.c:904
LONG_PTR SSIZE_T
Definition: basetsd.h:183
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define min(a, b)
Definition: monoChain.cc:55
#define New(t)
Definition: rtf.h:1086
#define max(a, b)
Definition: svc.c:63
@ Start
Definition: partlist.h:33
#define success(from, fromstr, to, tostr)

Referenced by DoDelayedExpansion(), and SubstituteVars().

◆ SubstituteVars()

BOOL SubstituteVars ( IN PCTSTR  Src,
OUT PTSTR  Dest,
IN TCHAR  Delim 
)

Definition at line 1516 of file cmd.c.

1520{
1521#define APPEND(From, Length) \
1522do { \
1523 if (Dest + (Length) > DestEnd) \
1524 goto too_long; \
1525 memcpy(Dest, (From), (Length) * sizeof(TCHAR)); \
1526 Dest += (Length); \
1527} while (0)
1528
1529#define APPEND1(Char) \
1530do { \
1531 if (Dest >= DestEnd) \
1532 goto too_long; \
1533 *Dest++ = (Char); \
1534} while (0)
1535
1536 PTCHAR DestEnd = Dest + CMDLINE_LENGTH - 1;
1537 PCTSTR End;
1538 size_t SrcIncLen, DestIncLen;
1539
1540 while (*Src /* && (Dest < DestEnd) */)
1541 {
1542 if (*Src != Delim)
1543 {
1544 End = _tcschr(Src, Delim);
1545 if (End == NULL)
1546 End = Src + _tcslen(Src);
1547 APPEND(Src, End - Src);
1548 Src = End;
1549 continue;
1550 }
1551
1552 if (!SubstituteVar(Src, &SrcIncLen, Dest, DestEnd, &DestIncLen, Delim))
1553 {
1554 return FALSE;
1555 }
1556 else
1557 {
1558 Src += SrcIncLen;
1559 Dest += DestIncLen;
1560 }
1561 }
1562 APPEND1(_T('\0'));
1563 return TRUE;
1564
1565too_long:
1567 nErrorLevel = 9023;
1568 return FALSE;
1569
1570#undef APPEND
1571#undef APPEND1
1572}

Referenced by ParseCommand(), and ReadLine().

Variable Documentation

◆ bAlwaysStrip

BOOL bAlwaysStrip = FALSE
static

Definition at line 157 of file cmd.c.

Referenced by _tmain(), and Initialize().

◆ bCanExit

BOOL bCanExit = TRUE

Definition at line 153 of file cmd.c.

Referenced by Initialize(), and ProcessInput().

◆ bCtrlBreak

◆ bDelayedExpansion

BOOL bDelayedExpansion = FALSE

◆ bDisableBatchEcho

BOOL bDisableBatchEcho = FALSE

Definition at line 160 of file cmd.c.

Referenced by Batch(), ExecuteCommandWithEcho(), and Initialize().

◆ bEnableExtensions

BOOL bEnableExtensions = TRUE

Definition at line 161 of file cmd.c.

Referenced by GetEnvVarOrSpecial(), Initialize(), and LoadRegistrySettings().

◆ bExit

◆ bIgnoreEcho

BOOL bIgnoreEcho = FALSE

Definition at line 155 of file cmd.c.

Referenced by Batch(), CommandScreen(), ExecuteCommandWithEcho(), ParseCommand(), and ReadLine().

◆ bTitleSet

BOOL bTitleSet = FALSE

Definition at line 167 of file cmd.c.

Referenced by cmd_title(), ResetConTitle(), and SetConTitle().

◆ ChildProcessRunningLock

CRITICAL_SECTION ChildProcessRunningLock

Definition at line 159 of file cmd.c.

Referenced by _tmain(), BreakHandler(), Cleanup(), Execute(), and ExecutePipeline().

◆ CMD_ModuleHandle

◆ dwChildProcessId

DWORD dwChildProcessId = 0

Definition at line 163 of file cmd.c.

Referenced by Execute().

◆ fSingleCommand

BOOL fSingleCommand = 0
static

Definition at line 156 of file cmd.c.

Referenced by _tmain(), Execute(), Initialize(), and SetConTitle().

◆ lpOriginalEnvironment

LPTSTR lpOriginalEnvironment

Definition at line 164 of file cmd.c.

Referenced by _tmain(), and cmd_start().

◆ nErrorLevel

◆ NtQueryInformationProcessPtr

NtQueryInformationProcessProc NtQueryInformationProcessPtr = NULL
static

Definition at line 170 of file cmd.c.

Referenced by Initialize(), and IsConsoleProcess().

◆ NtReadVirtualMemoryPtr

NtReadVirtualMemoryProc NtReadVirtualMemoryPtr = NULL
static

Definition at line 171 of file cmd.c.

Referenced by Initialize(), and IsConsoleProcess().

◆ OutputStreamMode

CON_STREAM_MODE OutputStreamMode = UTF8Text

Definition at line 177 of file cmd.c.

Referenced by _tmain(), and Initialize().

◆ szCurTitle

TCHAR szCurTitle[MAX_PATH]

Definition at line 168 of file cmd.c.

Referenced by ResetConTitle(), and SetConTitle().

◆ wDefColor

WORD wDefColor = 0

Definition at line 180 of file cmd.c.

Referenced by CommandColor(), Initialize(), and LoadRegistrySettings().