ReactOS 0.4.15-dev-8227-g32d615f
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 2368 of file cmd.c.

2369{
2370 INT nExitCode;
2371 LPCTSTR pCmdLine;
2372 TCHAR startPath[MAX_PATH];
2373
2376
2377 GetCurrentDirectory(ARRAYSIZE(startPath), startPath);
2378 _tchdir(startPath);
2379
2383
2384 /* Initialize the Console Standard Streams */
2388 /* Reset the current thread UI language */
2391 {
2393 }
2394
2396
2397 /*
2398 * Perform general initialization, parse switches on command-line.
2399 * Initialize the exit code with the errorlevel as Initialize() can set it.
2400 */
2401 pCmdLine = Initialize();
2402 nExitCode = nErrorLevel;
2403
2404 if (pCmdLine && *pCmdLine)
2405 {
2406 TCHAR commandline[CMDLINE_LENGTH];
2407
2408 /* Do the /C or /K command */
2409 GetCmdLineCommand(commandline, &pCmdLine[2], bAlwaysStrip);
2410 nExitCode = ParseCommandLine(commandline);
2411 if (fSingleCommand == 1)
2412 {
2413 // nErrorLevel = nExitCode;
2414 bExit = TRUE;
2415 }
2416 fSingleCommand = 0;
2417 }
2418 if (!bExit)
2419 {
2420 /* Call prompt routine */
2421 nExitCode = ProcessInput();
2422 }
2423
2424 /* Do the cleanup */
2425 Cleanup();
2427
2428 cmd_exit(nExitCode);
2429 return nExitCode;
2430}
#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:1772
static VOID GetCmdLineCommand(OUT LPTSTR commandline, IN LPCTSTR ptr, IN BOOL AlwaysStrip)
Definition: cmd.c:2073
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:3827
VOID WINAPI SetFileApisToOEM(void)
Definition: utils.c:831
#define GetCurrentDirectory
Definition: winbase.h:3805
static void Initialize()
Definition: xlate.c:212
const CHAR * LPCTSTR
Definition: xmlstorage.h:193

◆ AddBreakHandler()

VOID AddBreakHandler ( VOID  )

Definition at line 1844 of file cmd.c.

1845{
1847}
static BOOL WINAPI BreakHandler(IN DWORD dwCtrlType)
Definition: cmd.c:1799
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 1799 of file cmd.c.

1800{
1801 DWORD dwWritten;
1802 INPUT_RECORD rec;
1803
1804 if ((dwCtrlType != CTRL_C_EVENT) &&
1805 (dwCtrlType != CTRL_BREAK_EVENT))
1806 {
1807 return FALSE;
1808 }
1809
1811 {
1812 /* Child process is running and will have received the control event */
1813 return TRUE;
1814 }
1815 else
1816 {
1818 }
1819
1820 bCtrlBreak = TRUE;
1821
1822 rec.EventType = KEY_EVENT;
1824 rec.Event.KeyEvent.wRepeatCount = 1;
1825 rec.Event.KeyEvent.wVirtualKeyCode = _T('C');
1826 rec.Event.KeyEvent.wVirtualScanCode = _T('C') - 35;
1827 rec.Event.KeyEvent.uChar.AsciiChar = _T('C');
1828 rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
1830
1832 &rec,
1833 1,
1834 &dwWritten);
1835
1836 /* FIXME: Handle batch files */
1837
1838 // ConOutPrintf(_T("^C"));
1839
1840 return TRUE;
1841}
BOOL bCtrlBreak
Definition: cmd.c:154
#define FALSE
Definition: types.h:117
unsigned long DWORD
Definition: ntddk_ex.h:95
union _INPUT_RECORD::@3303 Event
WORD EventType
Definition: wincon.h:273
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:275
WORD wVirtualScanCode
Definition: wincon.h:243
DWORD dwControlKeyState
Definition: wincon.h:248
WORD wVirtualKeyCode
Definition: wincon.h:242
WORD wRepeatCount
Definition: wincon.h:241
WCHAR UnicodeChar
Definition: wincon.h:245
union _KEY_EVENT_RECORD::@3302 uChar
#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 2324 of file cmd.c.

2325{
2326 /* Run cmdexit.bat */
2327 if (IsExistingFile(_T("cmdexit.bat")))
2328 {
2330 ParseCommandLine(_T("cmdexit.bat"));
2331 }
2332 else if (IsExistingFile(_T("\\cmdexit.bat")))
2333 {
2335 ParseCommandLine(_T("\\cmdexit.bat"));
2336 }
2337
2338 /* Remove ctrl break handler */
2340
2341 /* Restore the default console mode */
2346
2347
2348#ifdef _DEBUG_MEM
2349#ifdef FEATURE_DIRECTORY_STACK
2350 /* Destroy directory stack */
2352#endif
2353
2354#ifdef FEATURE_HISTORY
2355 CleanHistory();
2356#endif
2357
2358 /* Free GetEnvVar's buffer */
2359 GetEnvVar(NULL);
2360#endif /* _DEBUG_MEM */
2361
2363}
LPTSTR GetEnvVar(LPCTSTR varName)
Definition: cmd.c:886
VOID RemoveBreakHandler(VOID)
Definition: cmd.c:1850
BOOL IsExistingFile(IN LPCTSTR pszPath)
Definition: misc.c:498
VOID DestroyDirectoryStack(VOID)
Definition: dirstack.c:91
#define ConErrResPuts(uID)
Definition: console.h:38
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 1640 of file cmd.c.

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

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:33
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:1042
STARTUPINFOA STARTUPINFO
Definition: winbase.h:3719
#define GetModuleFileName
Definition: winbase.h:3831

Referenced by ExecutePipeline().

◆ ExecuteAutoRunFile()

static VOID ExecuteAutoRunFile ( HKEY  hKeyRoot)
static

Definition at line 2040 of file cmd.c.

2041{
2042 LONG lRet;
2043 HKEY hKey;
2044 DWORD dwType, len;
2045 TCHAR AutoRun[2048];
2046
2047 lRet = RegOpenKeyEx(hKeyRoot,
2048 _T("Software\\Microsoft\\Command Processor"),
2049 0,
2051 &hKey);
2052 if (lRet != ERROR_SUCCESS)
2053 return;
2054
2055 len = sizeof(AutoRun);
2056 lRet = RegQueryValueEx(hKey,
2057 _T("AutoRun"),
2058 NULL,
2059 &dwType,
2060 (LPBYTE)&AutoRun,
2061 &len);
2062 if ((lRet == ERROR_SUCCESS) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ))
2063 {
2064 if (*AutoRun)
2065 ParseCommandLine(AutoRun);
2066 }
2067
2069}
#define RegCloseKey(hKey)
Definition: registry.h:49
#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:1640
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:134
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 1574 of file cmd.c.

1578{
1579 PFOR_CONTEXT Ctx;
1580
1581 *VarPtr = NULL;
1582 *IsParam0 = FALSE;
1583
1584 for (Ctx = fc; Ctx != NULL; Ctx = Ctx->prev)
1585 {
1586 if ((UINT)(Var - Ctx->firstvar) < Ctx->varcount)
1587 {
1588 *VarPtr = Ctx->values[Var - Ctx->firstvar];
1589 return TRUE;
1590 }
1591 }
1592 return FALSE;
1593}
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 1273 of file cmd.c.

1276{
1277 PCTSTR ret;
1278 PCTSTR varNameEnd;
1279
1280 *varNameLen = 1;
1281
1282 switch (*varName)
1283 {
1284 case _T('~'):
1285 {
1286 varNameEnd = varName + 1;
1287 ret = GetEnhancedVar(&varNameEnd, FindArg);
1288 if (!ret)
1289 {
1290 ParseErrorEx(varName);
1291 return NULL;
1292 }
1293 *varNameLen = varNameEnd - varName;
1294 return ret;
1295 }
1296
1297 case _T('0'):
1298 case _T('1'):
1299 case _T('2'):
1300 case _T('3'):
1301 case _T('4'):
1302 case _T('5'):
1303 case _T('6'):
1304 case _T('7'):
1305 case _T('8'):
1306 case _T('9'):
1307 {
1308 BOOL dummy;
1309 if (!FindArg(*varName, &ret, &dummy))
1310 return NULL;
1311 else
1312 return ret;
1313 }
1314
1315 case _T('*'):
1316 /* Copy over the raw params (not including the batch file name) */
1317 return bc->raw_params;
1318
1319 case _T('%'):
1320 return _T("%");
1321 }
1322 return NULL;
1323}
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 2073 of file cmd.c.

2077{
2078 TCHAR* LastQuote;
2079
2080 while (_istspace(*ptr))
2081 ++ptr;
2082
2083 /* Remove leading quote, find final quote */
2084 if (*ptr == _T('"') &&
2085 (LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
2086 {
2087 const TCHAR* Space;
2088 /* Under certain circumstances, all quotes are preserved.
2089 * CMD /? documents these conditions as follows:
2090 * 1. No /S switch
2091 * 2. Exactly two quotes
2092 * 3. No "special characters" between the quotes
2093 * (CMD /? says &<>()@^| but parentheses did not
2094 * trigger this rule when I tested them.)
2095 * 4. Whitespace exists between the quotes
2096 * 5. Enclosed string is an executable filename
2097 */
2098 *LastQuote = _T('\0');
2099 for (Space = ptr + 1; Space < LastQuote; ++Space)
2100 {
2101 if (_istspace(*Space)) /* Rule 4 */
2102 {
2103 if (!AlwaysStrip && /* Rule 1 */
2104 !_tcspbrk(ptr, _T("\"&<>@^|")) && /* Rules 2, 3 */
2105 SearchForExecutable(ptr, commandline)) /* Rule 5 */
2106 {
2107 /* All conditions met: preserve both the quotes */
2108 *LastQuote = _T('"');
2109 _tcscpy(commandline, ptr - 1);
2110 return;
2111 }
2112 break;
2113 }
2114 }
2115
2116 /* The conditions were not met: remove both the
2117 * leading quote and the last quote */
2118 _tcscpy(commandline, ptr);
2119 _tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
2120 return;
2121 }
2122
2123 /* No quotes; just copy */
2124 _tcscpy(commandline, ptr);
2125}
#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 ((Modifiers & M_SHORT) && *w32fd.cAlternateFileName)
1162 FixedComponent = w32fd.cAlternateFileName;
1163
1164 FindClose(hFind);
1165
1166 if (Out + _tcslen(FixedComponent) + 1 >= &FixedPath[ARRAYSIZE(FixedPath)])
1167 return _T("");
1168 _tcscpy(Out, FixedComponent);
1169 }
1170 Filename = Out;
1171 Out += _tcslen(Out);
1172 *Out++ = _T('\\');
1173
1174 In = Next;
1175 } while (In != NULL);
1176 Out[-1] = _T('\0');
1177
1178 /* Build the result string. Start with attributes, modification time, and
1179 * file size. If the file didn't exist, these fields will all be empty. */
1180 Out = Result;
1181 if (hFind != INVALID_HANDLE_VALUE)
1182 {
1183 if (Modifiers & M_ATTR)
1184 {
1185 static const struct {
1186 TCHAR Character;
1187 WORD Value;
1188 } *Attrib, Table[] = {
1189 { _T('d'), FILE_ATTRIBUTE_DIRECTORY },
1190 { _T('r'), FILE_ATTRIBUTE_READONLY },
1191 { _T('a'), FILE_ATTRIBUTE_ARCHIVE },
1192 { _T('h'), FILE_ATTRIBUTE_HIDDEN },
1193 { _T('s'), FILE_ATTRIBUTE_SYSTEM },
1194 { _T('c'), FILE_ATTRIBUTE_COMPRESSED },
1195 { _T('o'), FILE_ATTRIBUTE_OFFLINE },
1196 { _T('t'), FILE_ATTRIBUTE_TEMPORARY },
1198#if (NTDDI_VERSION >= NTDDI_WIN8)
1200 { _T('x'), FILE_ATTRIBUTE_NO_SCRUB_DATA /* 0x20000 */ },
1201#endif
1202 };
1203 for (Attrib = Table; Attrib != &Table[ARRAYSIZE(Table)]; Attrib++)
1204 {
1205 *Out++ = w32fd.dwFileAttributes & Attrib->Value
1206 ? Attrib->Character
1207 : _T('-');
1208 }
1209 *Out++ = _T(' ');
1210 }
1211 if (Modifiers & M_TIME)
1212 {
1213 FILETIME ft;
1214 SYSTEMTIME st;
1215 FileTimeToLocalFileTime(&w32fd.ftLastWriteTime, &ft);
1216 FileTimeToSystemTime(&ft, &st);
1217
1218 Out += FormatDate(Out, &st, TRUE);
1219 *Out++ = _T(' ');
1220 Out += FormatTime(Out, &st);
1221 *Out++ = _T(' ');
1222 }
1223 if (Modifiers & M_SIZE)
1224 {
1226 Size.LowPart = w32fd.nFileSizeLow;
1227 Size.HighPart = w32fd.nFileSizeHigh;
1228 Out += _stprintf(Out, _T("%I64u "), Size.QuadPart);
1229 }
1230 }
1231
1232 /* When using the path-searching syntax or the S modifier,
1233 * at least part of the file path is always included.
1234 * If none of the DPNX modifiers are present, include the full path */
1235 if (PathVarName || (Modifiers & M_SHORT))
1236 if ((Modifiers & (M_DRIVE | M_PATH | M_NAME | M_EXT)) == 0)
1237 Modifiers |= M_FULL;
1238
1239 /* Now add the requested parts of the name.
1240 * With the F modifier, add all parts to form the full path. */
1241 Extension = _tcsrchr(Filename, _T('.'));
1242 if (Modifiers & (M_DRIVE | M_FULL))
1243 {
1244 *Out++ = FixedPath[0];
1245 *Out++ = FixedPath[1];
1246 }
1247 if (Modifiers & (M_PATH | M_FULL))
1248 {
1249 memcpy(Out, &FixedPath[2], (ULONG_PTR)Filename - (ULONG_PTR)&FixedPath[2]);
1250 Out += Filename - &FixedPath[2];
1251 }
1252 if (Modifiers & (M_NAME | M_FULL))
1253 {
1254 while (*Filename && Filename != Extension)
1255 *Out++ = *Filename++;
1256 }
1257 if (Modifiers & (M_EXT | M_FULL))
1258 {
1259 if (Extension)
1261 }
1262
1263 /* Trim trailing space which otherwise would appear as a
1264 * result of using the A/T/Z modifiers but no others. */
1265 while (Out != &Result[0] && Out[-1] == _T(' '))
1266 Out--;
1267 *Out = _T('\0');
1268
1269 return Result;
1270}
INT FormatDate(TCHAR *, LPSYSTEMTIME, BOOL)
Definition: dir.c:675
INT FormatTime(TCHAR *, LPSYSTEMTIME)
Definition: dir.c:704
@ 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:3900
#define FindFirstFile
Definition: winbase.h:3782
#define GetFullPathName
Definition: winbase.h:3821
_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:409
#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:3814

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:265
_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:3799

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

◆ Initialize()

static LPCTSTR Initialize ( VOID  )
static

Definition at line 2133 of file cmd.c.

2134{
2135 HMODULE NtDllModule;
2136 HANDLE hIn, hOut;
2137 LPTSTR ptr, cmdLine;
2138 TCHAR option = 0;
2139 BOOL AutoRun = TRUE;
2141
2142 /* Get version information */
2143 InitOSVersion();
2144
2145 /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
2146 * build process. So don't link implicitly against ntdll.dll, load it
2147 * dynamically instead */
2148 NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
2149 if (NtDllModule != NULL)
2150 {
2151 NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)GetProcAddress(NtDllModule, "NtQueryInformationProcess");
2152 NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
2153 }
2154
2155 /* Load the registry settings */
2158
2159 /* Initialize our locale */
2160 InitLocale();
2161
2162 /* Initialize prompt support */
2163 InitPrompt();
2164
2165#ifdef FEATURE_DIRECTORY_STACK
2166 /* Initialize directory stack */
2168#endif
2169
2170#ifdef FEATURE_HISTORY
2171 /* Initialize history */
2172 InitHistory();
2173#endif
2174
2175 /* Set COMSPEC environment variable */
2177 {
2178 ModuleName[MAX_PATH] = _T('\0');
2179 SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
2180 }
2181
2182 /* Add ctrl break handler */
2184
2185 /* Set the default console mode */
2188 SetConsoleMode(hOut, 0); // Reinitialize the console output mode
2191
2192 cmdLine = GetCommandLine();
2193 TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
2194
2195 for (ptr = cmdLine; *ptr; ++ptr)
2196 {
2197 if (*ptr == _T('/'))
2198 {
2199 option = _totupper(ptr[1]);
2200 if (option == _T('?'))
2201 {
2203 nErrorLevel = 1;
2204 bExit = TRUE;
2205 return NULL;
2206 }
2207 else if (option == _T('P'))
2208 {
2209 if (!IsExistingFile(_T("\\autoexec.bat")))
2210 {
2211#ifdef INCLUDE_CMD_DATE
2212 cmd_date(_T(""));
2213#endif
2214#ifdef INCLUDE_CMD_TIME
2215 cmd_time(_T(""));
2216#endif
2217 }
2218 else
2219 {
2220 ParseCommandLine(_T("\\autoexec.bat"));
2221 }
2222 bCanExit = FALSE;
2223 }
2224 else if (option == _T('A'))
2225 {
2227 }
2228 else if (option == _T('C') || option == _T('K') || option == _T('R'))
2229 {
2230 /* Remainder of command line is a command to be run */
2231 fSingleCommand = ((option == _T('K')) << 1) | 1;
2232 break;
2233 }
2234 else if (option == _T('D'))
2235 {
2236 AutoRun = FALSE;
2237 }
2238 else if (option == _T('Q'))
2239 {
2241 }
2242 else if (option == _T('S'))
2243 {
2245 }
2246#ifdef INCLUDE_CMD_COLOR
2247 else if (!_tcsnicmp(ptr, _T("/T:"), 3))
2248 {
2249 /* Process /T (color) argument; overwrite any previous settings */
2250 wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
2251 }
2252#endif
2253 else if (option == _T('U'))
2254 {
2256 }
2257 else if (option == _T('V'))
2258 {
2259 // FIXME: Check validity of the parameter given to V !
2260 bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
2261 }
2262 else if (option == _T('E'))
2263 {
2264 // FIXME: Check validity of the parameter given to E !
2265 bEnableExtensions = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
2266 }
2267 else if (option == _T('X'))
2268 {
2269 /* '/X' is identical to '/E:ON' */
2271 }
2272 else if (option == _T('Y'))
2273 {
2274 /* '/Y' is identical to '/E:OFF' */
2276 }
2277 }
2278 }
2279
2280#ifdef INCLUDE_CMD_COLOR
2281 if (wDefColor == 0)
2282 {
2283 /*
2284 * If we still do not have the console colour attribute set,
2285 * retrieve the default one.
2286 */
2288 }
2289
2290 if (wDefColor != 0)
2292#endif
2293
2294 /* Reset the output Standard Streams translation modes and code page caches */
2295 // ConStreamSetMode(StdIn , OutputStreamMode, InputCodePage );
2298
2299 if (!*ptr)
2300 {
2301 /* If neither /C or /K was given, display a simple version string */
2302
2303 /* Insert a new line above the copyright notice if we are drawing the information line. */
2304 if (HasInfoLine())
2305 ConOutChar('\n');
2306
2308 _T(KERNEL_VERSION_STR),
2309 _T(KERNEL_VERSION_BUILD_STR));
2310 ConOutResPrintf(STRING_CMD_COPYRIGHT, _T(COPYRIGHT_YEAR));
2311 }
2312
2313 if (AutoRun)
2314 {
2317 }
2318
2319 /* Returns the rest of the command line */
2320 return ptr;
2321}
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:1891
WORD wDefColor
Definition: cmd.c:180
VOID AddBreakHandler(VOID)
Definition: cmd.c:1844
static VOID ExecuteAutoRunFile(HKEY hKeyRoot)
Definition: cmd.c:2040
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
BOOL HasInfoLine(VOID)
Definition: prompt.c:72
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
VOID InitHistory(VOID)
Definition: history.c:132
#define STRING_REACTOS_VERSION
Definition: resource.h:90
#define STRING_CMD_HELP8
Definition: resource.h:82
#define STRING_CMD_COPYRIGHT
Definition: resource.h:89
#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:3908
#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:115
#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 1891 of file cmd.c.

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

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

Referenced by _tmain().

◆ ReadLine()

BOOL ReadLine ( TCHAR commandline,
BOOL  bMore 
)

Definition at line 1721 of file cmd.c.

1722{
1724 LPTSTR ip;
1725
1726 /* if no batch input then... */
1727 if (bc == NULL)
1728 {
1729 if (bMore)
1730 {
1732 }
1733 else
1734 {
1735 /* JPP 19980807 - if echo off, don't print prompt */
1736 if (bEcho)
1737 {
1738 if (!bIgnoreEcho)
1739 ConOutChar(_T('\n'));
1740 PrintPrompt();
1741 }
1742 }
1743
1745 {
1746 bExit = TRUE;
1747 return FALSE;
1748 }
1749
1750 if (readline[0] == _T('\0'))
1751 ConOutChar(_T('\n'));
1752
1754 return FALSE;
1755
1756 if (readline[0] == _T('\0'))
1757 return FALSE;
1758
1759 ip = readline;
1760 }
1761 else
1762 {
1763 ip = ReadBatchLine();
1764 if (!ip)
1765 return FALSE;
1766 }
1767
1768 return SubstituteVars(ip, commandline, _T('%'));
1769}
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:1514
BOOL CheckCtrlBreak(INT)
Definition: misc.c:132
#define BREAK_INPUT
Definition: cmd.h:36
#define STRING_MORE
Definition: resource.h:240
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 1850 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:316
LPCSTR lpDirectory
Definition: shellapi.h:317
#define LoadLibrary
Definition: winbase.h:3862

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 1596 of file cmd.c.

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

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 1326 of file cmd.c.

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

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

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().