ReactOS  0.4.15-dev-1197-g8081ba9
cmd.c
Go to the documentation of this file.
1 /*
2  * CMD.C - command-line interface.
3  *
4  *
5  * History:
6  *
7  * 17 Jun 1994 (Tim Norman)
8  * started.
9  *
10  * 08 Aug 1995 (Matt Rains)
11  * I have cleaned up the source code. changes now bring this source
12  * into guidelines for recommended programming practice.
13  *
14  * A added the the standard FreeDOS GNU licence test to the
15  * initialize() function.
16  *
17  * Started to replace puts() with printf(). this will help
18  * standardize output. please follow my lead.
19  *
20  * I have added some constants to help making changes easier.
21  *
22  * 15 Dec 1995 (Tim Norman)
23  * major rewrite of the code to make it more efficient and add
24  * redirection support (finally!)
25  *
26  * 06 Jan 1996 (Tim Norman)
27  * finished adding redirection support! Changed to use our own
28  * exec code (MUCH thanks to Svante Frey!!)
29  *
30  * 29 Jan 1996 (Tim Norman)
31  * added support for CHDIR, RMDIR, MKDIR, and ERASE, as per
32  * suggestion of Steffan Kaiser
33  *
34  * changed "file not found" error message to "bad command or
35  * filename" thanks to Dustin Norman for noticing that confusing
36  * message!
37  *
38  * changed the format to call internal commands (again) so that if
39  * they want to split their commands, they can do it themselves
40  * (none of the internal functions so far need that much power, anyway)
41  *
42  * 27 Aug 1996 (Tim Norman)
43  * added in support for Oliver Mueller's ALIAS command
44  *
45  * 14 Jun 1997 (Steffan Kaiser)
46  * added ctrl-break handling and error level
47  *
48  * 16 Jun 1998 (Rob Lake)
49  * Runs command.com if /P is specified in command line. Command.com
50  * also stays permanent. If /C is in the command line, starts the
51  * program next in the line.
52  *
53  * 21 Jun 1998 (Rob Lake)
54  * Fixed up /C so that arguments for the program
55  *
56  * 08-Jul-1998 (John P. Price)
57  * Now sets COMSPEC environment variable
58  * misc clean up and optimization
59  * added date and time commands
60  * changed to using spawnl instead of exec. exec does not copy the
61  * environment to the child process!
62  *
63  * 14 Jul 1998 (Hans B Pufal)
64  * Reorganised source to be more efficient and to more closely
65  * follow MS-DOS conventions. (eg %..% environment variable
66  * replacement works form command line as well as batch file.
67  *
68  * New organisation also properly support nested batch files.
69  *
70  * New command table structure is half way towards providing a
71  * system in which COMMAND will find out what internal commands
72  * are loaded
73  *
74  * 24 Jul 1998 (Hans B Pufal) [HBP_003]
75  * Fixed return value when called with /C option
76  *
77  * 27 Jul 1998 John P. Price
78  * added config.h include
79  *
80  * 28 Jul 1998 John P. Price
81  * added showcmds function to show commands and options available
82  *
83  * 07-Aug-1998 (John P Price <linux-guru@gcfl.net>)
84  * Fixed carriage return output to better match MSDOS with echo
85  * on or off. (marked with "JPP 19980708")
86  *
87  * 07-Dec-1998 (Eric Kohl)
88  * First ReactOS release.
89  * Extended length of commandline buffers to 512.
90  *
91  * 13-Dec-1998 (Eric Kohl)
92  * Added COMSPEC environment variable.
93  * Added "/t" support (color) on cmd command line.
94  *
95  * 07-Jan-1999 (Eric Kohl)
96  * Added help text ("cmd /?").
97  *
98  * 25-Jan-1999 (Eric Kohl)
99  * Unicode and redirection safe!
100  * Fixed redirections and piping.
101  * Piping is based on temporary files, but basic support
102  * for anonymous pipes already exists.
103  *
104  * 27-Jan-1999 (Eric Kohl)
105  * Replaced spawnl() by CreateProcess().
106  *
107  * 22-Oct-1999 (Eric Kohl)
108  * Added break handler.
109  *
110  * 15-Dec-1999 (Eric Kohl)
111  * Fixed current directory
112  *
113  * 28-Dec-1999 (Eric Kohl)
114  * Restore window title after program/batch execution
115  *
116  * 03-Feb-2001 (Eric Kohl)
117  * Workaround because argc[0] is NULL under ReactOS
118  *
119  * 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
120  * %envvar% replacement conflicted with for.
121  *
122  * 30-Apr-2004 (Filip Navara <xnavara@volny.cz>)
123  * Make MakeSureDirectoryPathExistsEx unicode safe.
124  *
125  * 28-Mai-2004
126  * Removed MakeSureDirectoryPathExistsEx.
127  * Use the current directory if GetTempPath fails.
128  *
129  * 12-Jul-2004 (Jens Collin <jens.collin@lakhei.com>)
130  * Added ShellExecute call when all else fails to be able to "launch" any file.
131  *
132  * 02-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
133  * Remove all hardcode string to En.rc
134  *
135  * 06-May-2005 (Klemens Friedl <frik85@gmail.com>)
136  * Add 'help' command (list all commands plus description)
137  *
138  * 06-jul-2005 (Magnus Olsen <magnus@greatlord.com>)
139  * translate '%errorlevel%' to the internal value.
140  * Add proper memory alloc ProcessInput, the error
141  * handling for memory handling need to be improve
142  */
143 
144 #include "precomp.h"
145 #include <reactos/buildno.h>
146 #include <reactos/version.h>
147 
149  PVOID, ULONG, PULONG);
151 
152 BOOL bExit = FALSE; /* Indicates EXIT was typed */
153 BOOL bCanExit = TRUE; /* Indicates if this shell is exitable */
154 BOOL bCtrlBreak = FALSE; /* Ctrl-Break or Ctrl-C hit */
155 BOOL bIgnoreEcho = FALSE; /* Set this to TRUE to prevent a newline, when executing a command */
156 static BOOL fSingleCommand = 0; /* When we are executing something passed on the command line after /C or /K */
158 INT nErrorLevel = 0; /* Errorlevel of last launched external program */
166 
167 BOOL bTitleSet = FALSE; /* Indicates whether the console title has been changed and needs to be restored later */
169 
172 
173 /*
174  * Default output file stream translation mode is UTF8, but CMD switches
175  * allow to change it to either UTF16 (/U) or ANSI (/A).
176  */
178 
179 #ifdef INCLUDE_CMD_COLOR
180 WORD wDefColor = 0; /* Default color */
181 #endif
182 
183 /*
184  * convert
185  *
186  * insert commas into a number
187  */
188 INT
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 }
220 
221 /*
222  * Is a process a console process?
223  */
225 {
228  PEB ProcessPeb;
230 
232  {
233  return TRUE;
234  }
235 
238  &Info, sizeof(PROCESS_BASIC_INFORMATION), NULL);
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 }
255 
256 
257 
258 #ifdef _UNICODE
259 #define SHELLEXECUTETEXT "ShellExecuteExW"
260 #else
261 #define SHELLEXECUTETEXT "ShellExecuteExA"
262 #endif
263 
264 typedef BOOL (WINAPI *MYEX)(LPSHELLEXECUTEINFO lpExecInfo);
265 
267  LPTSTR directory, INT show)
268 {
269  SHELLEXECUTEINFO sei;
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;
297  sei.lpDirectory = directory;
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 }
306 
307 
308 static VOID
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 }
327 
328 static VOID
330 {
331  /* Restore the original console title */
332  if (!bc && bTitleSet)
333  {
335  bTitleSet = FALSE;
336  }
337 }
338 
339 /*
340  * This command (in First) was not found in the command table
341  *
342  * Full - output buffer to hold whole command line
343  * First - first word on command line
344  * Rest - rest of command line
345  */
346 static INT
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');
383  _tcscpy(first, First);
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(' ');
416  SetConTitle(Full);
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 */
432  PROCESS_INFORMATION prci;
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,
480  SW_SHOWNORMAL);
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 our default console mode */
514  }
515 
516  /* Update our local codepage cache */
517  {
518  UINT uNewInputCodePage = GetConsoleCP();
519  UINT uNewOutputCodePage = GetConsoleOutputCP();
520 
521  if ((InputCodePage != uNewInputCodePage) ||
522  (OutputCodePage != uNewOutputCodePage))
523  {
524  /* Update the locale as well */
525  InitLocale();
526  }
527 
528  InputCodePage = uNewInputCodePage;
529  OutputCodePage = uNewOutputCodePage;
530 
531  /* Update the streams codepage cache as well */
535  }
536 
537  /* Restore the original console title */
538  ResetConTitle();
539 
540  return dwExitCode;
541 }
542 
543 
544 /*
545  * Look through the internal commands and determine whether or not this
546  * command is one of them. If it is, call the command. If not, call
547  * execute to run it as an external program.
548  *
549  * first - first word on command line
550  * rest - rest of command line
551  */
552 INT
554 {
555  TCHAR *com;
556  TCHAR *cp;
557  LPTSTR param; /* Pointer to command's parameters */
558  INT cl;
559  LPCOMMAND cmdptr;
560  BOOL nointernal = FALSE;
561  INT ret;
562 
563  TRACE ("DoCommand: (\'%s\' \'%s\')\n", debugstr_aw(first), debugstr_aw(rest));
564 
565  /* Full command line */
566  com = cmd_alloc((_tcslen(first) + _tcslen(rest) + 2) * sizeof(TCHAR));
567  if (com == NULL)
568  {
570  return 1;
571  }
572 
573  /* If present in the first word, these characters end the name of an
574  * internal command and become the beginning of its parameters. */
575  cp = first + _tcscspn(first, _T("\t +,/;=[]"));
576 
577  for (cl = 0; cl < (cp - first); cl++)
578  {
579  /* These characters do it too, but if one of them is present,
580  * then we check to see if the word is a file name and skip
581  * checking for internal commands if so.
582  * This allows running programs with names like "echo.exe" */
583  if (_tcschr(_T(".:\\"), first[cl]))
584  {
585  TCHAR tmp = *cp;
586  *cp = _T('\0');
587  nointernal = IsExistingFile(first);
588  *cp = tmp;
589  break;
590  }
591  }
592 
593  /* Scan internal command table */
594  for (cmdptr = cmds; !nointernal && cmdptr->name; cmdptr++)
595  {
596  if (!_tcsnicmp(first, cmdptr->name, cl) && cmdptr->name[cl] == _T('\0'))
597  {
598  _tcscpy(com, first);
599  _tcscat(com, rest);
600  param = &com[cl];
601 
602  /* Skip over whitespace to rest of line, exclude 'echo' command */
603  if (_tcsicmp(cmdptr->name, _T("echo")) != 0)
604  {
605  while (_istspace(*param))
606  param++;
607  }
608 
609  /* Set the new console title */
610  SetConTitle(com);
611 
612  ret = cmdptr->func(param);
613 
614  /* Restore the original console title */
615  ResetConTitle();
616 
617  cmd_free(com);
618  return ret;
619  }
620  }
621 
622  ret = Execute(com, first, rest, Cmd);
623  cmd_free(com);
624  return ret;
625 }
626 
627 
628 /*
629  * process the command line and execute the appropriate functions
630  * full input/output redirection and piping are supported
631  */
633 {
634  INT Ret = 0;
636 
637  Cmd = ParseCommand(cmd);
638  if (!Cmd)
639  {
640  /* Return an adequate error code */
641  return (!bParseError ? 0 : 1);
642  }
643 
644  Ret = ExecuteCommand(Cmd);
645  FreeCommand(Cmd);
646  return Ret;
647 }
648 
649 /* Execute a command without waiting for it to finish. If it's an internal
650  * command or batch file, we must create a new cmd.exe process to handle it.
651  * TODO: For now, this just always creates a cmd.exe process.
652  * This works, but is inefficient for running external programs,
653  * which could just be run directly. */
654 static HANDLE
656 {
657  TCHAR CmdPath[MAX_PATH];
658  TCHAR CmdParams[CMDLINE_LENGTH], *ParamsEnd;
659  STARTUPINFO stui;
660  PROCESS_INFORMATION prci;
661 
662  /* Get the path to cmd.exe */
663  GetModuleFileName(NULL, CmdPath, ARRAYSIZE(CmdPath));
664 
665  /* Build the parameter string to pass to cmd.exe */
666  ParamsEnd = _stpcpy(CmdParams, _T("/S/D/C\""));
667  ParamsEnd = UnparseCommand(Cmd, ParamsEnd, &CmdParams[CMDLINE_LENGTH - 2]);
668  if (!ParamsEnd)
669  {
671  return NULL;
672  }
673  _tcscpy(ParamsEnd, _T("\""));
674 
675  memset(&stui, 0, sizeof stui);
676  stui.cb = sizeof(STARTUPINFO);
677  if (!CreateProcess(CmdPath, CmdParams, NULL, NULL, TRUE, 0,
678  NULL, NULL, &stui, &prci))
679  {
681  return NULL;
682  }
683 
684  CloseHandle(prci.hThread);
685  return prci.hProcess;
686 }
687 
688 static INT
690 {
691 #ifdef FEATURE_REDIRECTION
692  HANDLE hInput = NULL;
693  HANDLE hOldConIn = GetStdHandle(STD_INPUT_HANDLE);
694  HANDLE hOldConOut = GetStdHandle(STD_OUTPUT_HANDLE);
696  INT nProcesses = 0;
697  DWORD dwExitCode;
698 
699  /* Do all but the last pipe command */
700  do
701  {
702  HANDLE hPipeRead, hPipeWrite;
703  if (nProcesses > (MAXIMUM_WAIT_OBJECTS - 2))
704  {
706  goto failed;
707  }
708 
709  /* Create the pipe that this process will write into.
710  * Make the handles non-inheritable initially, because this
711  * process shouldn't inherit the reading handle. */
712  if (!CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0))
713  {
714  error_no_pipe();
715  goto failed;
716  }
717 
718  /* The writing side of the pipe is STDOUT for this process */
720  SetStdHandle(STD_OUTPUT_HANDLE, hPipeWrite);
721 
722  /* Execute it (error check is done later for easier cleanup) */
723  hProcess[nProcesses] = ExecuteAsync(Cmd->Subcommands);
724  CloseHandle(hPipeWrite);
725  if (hInput)
726  CloseHandle(hInput);
727 
728  /* The reading side of the pipe will be STDIN for the next process */
730  SetStdHandle(STD_INPUT_HANDLE, hPipeRead);
731  hInput = hPipeRead;
732 
733  if (!hProcess[nProcesses])
734  goto failed;
735  nProcesses++;
736 
737  Cmd = Cmd->Subcommands->Next;
738  } while (Cmd->Type == C_PIPE);
739 
740  /* The last process uses the original STDOUT */
741  SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
742  hProcess[nProcesses] = ExecuteAsync(Cmd);
743  if (!hProcess[nProcesses])
744  goto failed;
745  nProcesses++;
746  CloseHandle(hInput);
747  SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
748 
749  /* Wait for all processes to complete */
753 
754  /* Use the exit code of the last process in the pipeline */
755  GetExitCodeProcess(hProcess[nProcesses - 1], &dwExitCode);
756  nErrorLevel = (INT)dwExitCode;
757 
758  while (--nProcesses >= 0)
759  CloseHandle(hProcess[nProcesses]);
760  return nErrorLevel;
761 
762 failed:
763  if (hInput)
764  CloseHandle(hInput);
765  while (--nProcesses >= 0)
766  {
767  TerminateProcess(hProcess[nProcesses], 0);
768  CloseHandle(hProcess[nProcesses]);
769  }
770  SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
771  SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
772 #endif
773 
774  return nErrorLevel;
775 }
776 
777 INT
780 {
781 #define SeenGoto() \
782  (bc && bc->current == NULL)
783 
784  PARSED_COMMAND *Sub;
785  LPTSTR First, Rest;
786  INT Ret = 0;
787 
788  /* If we don't have any command, or if this is REM, ignore it */
789  if (!Cmd || (Cmd->Type == C_REM))
790  return 0;
791  /*
792  * Do not execute any command if we are about to exit CMD, or about to
793  * change batch execution context, e.g. in case of a CALL / GOTO / EXIT.
794  */
795  if (bExit || SeenGoto())
796  return 0;
797 
798  if (!PerformRedirection(Cmd->Redirections))
799  return 1;
800 
801  switch (Cmd->Type)
802  {
803  case C_COMMAND:
804  Ret = 1;
805  First = DoDelayedExpansion(Cmd->Command.First);
806  if (First)
807  {
808  Rest = DoDelayedExpansion(Cmd->Command.Rest);
809  if (Rest)
810  {
811  Ret = DoCommand(First, Rest, Cmd);
812  cmd_free(Rest);
813  }
814  cmd_free(First);
815  }
816  /* Fall through */
817  case C_REM:
818  break;
819 
820  case C_QUIET:
821  case C_BLOCK:
822  case C_MULTI:
823  for (Sub = Cmd->Subcommands; Sub && !SeenGoto(); Sub = Sub->Next)
824  Ret = ExecuteCommand(Sub);
825  break;
826 
827  case C_OR:
828  Sub = Cmd->Subcommands;
829  Ret = ExecuteCommand(Sub);
830  if ((Ret != 0) && !SeenGoto())
831  {
832  nErrorLevel = Ret;
833  Ret = ExecuteCommand(Sub->Next);
834  }
835  break;
836 
837  case C_AND:
838  Sub = Cmd->Subcommands;
839  Ret = ExecuteCommand(Sub);
840  if ((Ret == 0) && !SeenGoto())
841  Ret = ExecuteCommand(Sub->Next);
842  break;
843 
844  case C_PIPE:
845  Ret = ExecutePipeline(Cmd);
846  break;
847 
848  case C_FOR:
849  Ret = ExecuteFor(Cmd);
850  break;
851 
852  case C_IF:
853  Ret = ExecuteIf(Cmd);
854  break;
855  }
856 
857  UndoRedirection(Cmd->Redirections, NULL);
858  return Ret;
859 
860 #undef SeenGoto
861 }
862 
863 INT
866 {
867  /* Echo the reconstructed command line */
868  if (bEcho && !bDisableBatchEcho && Cmd && (Cmd->Type != C_QUIET))
869  {
870  if (!bIgnoreEcho)
871  ConOutChar(_T('\n'));
872  PrintPrompt();
873  EchoCommand(Cmd);
874  ConOutChar(_T('\n'));
875  }
876 
877  /* Run the command */
878  return ExecuteCommand(Cmd);
879 }
880 
881 LPTSTR
883 {
884  static LPTSTR ret = NULL;
885  UINT size;
886 
887  cmd_free(ret);
888  ret = NULL;
889  size = GetEnvironmentVariable(varName, NULL, 0);
890  if (size > 0)
891  {
892  ret = cmd_alloc(size * sizeof(TCHAR));
893  if (ret != NULL)
894  GetEnvironmentVariable(varName, ret, size + 1);
895  }
896  return ret;
897 }
898 
899 LPCTSTR
901 {
902  static TCHAR ret[MAX_PATH];
903 
904  LPTSTR var = GetEnvVar(varName);
905  if (var)
906  return var;
907 
908  /* The environment variable doesn't exist, look for
909  * a "special" one only if extensions are enabled. */
910  if (!bEnableExtensions)
911  return NULL;
912 
913  /* %CD% */
914  if (_tcsicmp(varName, _T("CD")) == 0)
915  {
917  return ret;
918  }
919  /* %DATE% */
920  else if (_tcsicmp(varName, _T("DATE")) == 0)
921  {
922  return GetDateString();
923  }
924  /* %TIME% */
925  else if (_tcsicmp(varName, _T("TIME")) == 0)
926  {
927  return GetTimeString();
928  }
929  /* %RANDOM% */
930  else if (_tcsicmp(varName, _T("RANDOM")) == 0)
931  {
932  /* Get random number */
933  _itot(rand(), ret, 10);
934  return ret;
935  }
936  /* %CMDCMDLINE% */
937  else if (_tcsicmp(varName, _T("CMDCMDLINE")) == 0)
938  {
939  return GetCommandLine();
940  }
941  /* %CMDEXTVERSION% */
942  else if (_tcsicmp(varName, _T("CMDEXTVERSION")) == 0)
943  {
944  /* Set Command Extensions version number to CMDEXTVERSION */
945  _itot(CMDEXTVERSION, ret, 10);
946  return ret;
947  }
948  /* %ERRORLEVEL% */
949  else if (_tcsicmp(varName, _T("ERRORLEVEL")) == 0)
950  {
951  _itot(nErrorLevel, ret, 10);
952  return ret;
953  }
954 #if (NTDDI_VERSION >= NTDDI_WIN7)
955  /* Available in Win7+, even if the underlying API is available in Win2003+ */
956  /* %HIGHESTNUMANODENUMBER% */
957  else if (_tcsicmp(varName, _T("HIGHESTNUMANODENUMBER")) == 0)
958  {
959  ULONG NumaNodeNumber = 0;
960  GetNumaHighestNodeNumber(&NumaNodeNumber);
961  _itot(NumaNodeNumber, ret, 10);
962  return ret;
963  }
964 #endif
965 
966  return NULL;
967 }
968 
969 /* Handle the %~var syntax */
970 static PCTSTR
972  IN OUT PCTSTR* pFormat,
973  IN BOOL (*GetVar)(TCHAR, PCTSTR*, BOOL*))
974 {
975  static const TCHAR ModifierTable[] = _T("dpnxfsatz");
976  enum {
977  M_DRIVE = 1, /* D: drive letter */
978  M_PATH = 2, /* P: path */
979  M_NAME = 4, /* N: filename */
980  M_EXT = 8, /* X: extension */
981  M_FULL = 16, /* F: full path (drive+path+name+ext) */
982  M_SHORT = 32, /* S: full path (drive+path+name+ext), use short names */
983  M_ATTR = 64, /* A: attributes */
984  M_TIME = 128, /* T: modification time */
985  M_SIZE = 256, /* Z: file size */
986  } Modifiers = 0;
987 
988  PCTSTR Format, FormatEnd;
989  PCTSTR PathVarName = NULL;
990  PCTSTR Variable;
991  PCTSTR VarEnd;
992  BOOL VariableIsParam0;
993  TCHAR FullPath[MAX_PATH];
994  TCHAR FixedPath[MAX_PATH];
996  HANDLE hFind;
997  WIN32_FIND_DATA w32fd;
998  PTCHAR In, Out;
999 
1000  static TCHAR Result[CMDLINE_LENGTH];
1001 
1002  /* Check whether the current character is a recognized variable.
1003  * If it is not, then restore the previous one: there is indeed
1004  * ambiguity between modifier characters and FOR variables;
1005  * the rule that CMD uses is to pick the longest possible match.
1006  * This case can happen if we have a FOR-variable specification
1007  * of the following form:
1008  *
1009  * %~<modifiers><actual FOR variable character><other characters>
1010  *
1011  * where the FOR variable character is also a similar to a modifier,
1012  * but should not be interpreted as is, and the following other
1013  * characters are not part of the possible modifier characters, and
1014  * are unrelated to the FOR variable (they can be part of a command).
1015  * For example, if there is a %n variable, then out of %~anxnd,
1016  * %~anxn will be substituted rather than just %~an.
1017  *
1018  * In the following examples, all characters 'd','p','n','x' are valid modifiers.
1019  *
1020  * 1. In this example, the FOR variable character is 'x' and the actual
1021  * modifiers are 'dpn'. Parsing will first determine that 'dpnx'
1022  * are modifiers, with the possible (last) valid variable being 'x',
1023  * and will stop at the letter 'g'. Since 'g' is not a valid
1024  * variable, then the actual variable is the lattest one 'x',
1025  * and the modifiers are then actually 'dpn'.
1026  * The FOR-loop will then display the %x variable formatted with 'dpn'
1027  * and will append any other characters following, 'g'.
1028  *
1029  * C:\Temp>for %x in (foo.exe bar.txt) do @echo %~dpnxg
1030  * C:\Temp\foog
1031  * C:\Temp\barg
1032  *
1033  *
1034  * 2. In this second example, the FOR variable character is 'g' and
1035  * the actual modifiers are 'dpnx'. Parsing will determine also that
1036  * the possible (last) valid variable could be 'x', but since it's
1037  * not present in the FOR-variables list, it won't be the case.
1038  * This means that the actual FOR variable character must follow,
1039  * in this case, 'g'.
1040  *
1041  * C:\Temp>for %g in (foo.exe bar.txt) do @echo %~dpnxg
1042  * C:\Temp\foo.exe
1043  * C:\Temp\bar.txt
1044  */
1045 
1046  /* First, go through as many modifier characters as possible */
1047  FormatEnd = Format = *pFormat;
1048  while (*FormatEnd && _tcschr(ModifierTable, _totlower(*FormatEnd)))
1049  ++FormatEnd;
1050 
1051  if (*FormatEnd == _T('$'))
1052  {
1053  /* $PATH: syntax */
1054  PathVarName = FormatEnd + 1;
1055  FormatEnd = _tcschr(PathVarName, _T(':'));
1056  if (!FormatEnd)
1057  return NULL;
1058 
1059  /* Must be immediately followed by the variable */
1060  if (!GetVar(*++FormatEnd, &Variable, &VariableIsParam0))
1061  return NULL;
1062  }
1063  else
1064  {
1065  /* Backtrack if necessary to get a variable name match */
1066  while (!GetVar(*FormatEnd, &Variable, &VariableIsParam0))
1067  {
1068  if (FormatEnd == Format)
1069  return NULL;
1070  --FormatEnd;
1071  }
1072  }
1073 
1074  *pFormat = FormatEnd + 1;
1075 
1076  /* If the variable is empty, return an empty string */
1077  if (!Variable || !*Variable)
1078  return _T("");
1079 
1080  /* Exclude the leading and trailing quotes */
1081  VarEnd = &Variable[_tcslen(Variable)];
1082  if (*Variable == _T('"'))
1083  {
1084  ++Variable;
1085  if (VarEnd > Variable && VarEnd[-1] == _T('"'))
1086  --VarEnd;
1087  }
1088 
1089  if ((ULONG_PTR)VarEnd - (ULONG_PTR)Variable >= sizeof(Result))
1090  return _T("");
1091  memcpy(Result, Variable, (ULONG_PTR)VarEnd - (ULONG_PTR)Variable);
1092  Result[VarEnd - Variable] = _T('\0');
1093 
1094  /* Now determine the actual modifiers */
1095  for (; Format < FormatEnd && *Format != _T('$'); ++Format)
1096  Modifiers |= 1 << (_tcschr(ModifierTable, _totlower(*Format)) - ModifierTable);
1097 
1098  if (PathVarName)
1099  {
1100  /* $PATH: syntax - search the directories listed in the
1101  * specified environment variable for the file */
1102  PTSTR PathVar;
1103  ((PTSTR)FormatEnd)[-1] = _T('\0'); // FIXME: HACK!
1104  PathVar = GetEnvVar(PathVarName);
1105  ((PTSTR)FormatEnd)[-1] = _T(':');
1106  if (!PathVar ||
1107  !SearchPath(PathVar, Result, NULL, ARRAYSIZE(FullPath), FullPath, NULL))
1108  {
1109  return _T("");
1110  }
1111  }
1112  else if (Modifiers == 0)
1113  {
1114  /* For plain %~var with no modifiers, just return the variable without quotes */
1115  return Result;
1116  }
1117  else if (VariableIsParam0)
1118  {
1119  /* Special case: If the variable is %0 and modifier characters are present,
1120  * use the batch file's path (which includes the .bat/.cmd extension)
1121  * rather than the actual %0 variable (which might not). */
1122  ASSERT(bc);
1123  _tcscpy(FullPath, bc->BatchFilePath);
1124  }
1125  else
1126  {
1127  /* Convert the variable, now without quotes, to a full path */
1128  if (!GetFullPathName(Result, ARRAYSIZE(FullPath), FullPath, NULL))
1129  return _T("");
1130  }
1131 
1132  /* Next step is to change the path to fix letter case (e.g.
1133  * C:\ReAcToS -> C:\ReactOS) and, if requested with the S modifier,
1134  * replace long filenames with short. */
1135 
1136  In = FullPath;
1137  Out = FixedPath;
1138 
1139  /* Copy drive letter */
1140  *Out++ = *In++;
1141  *Out++ = *In++;
1142  *Out++ = *In++;
1143  /* Loop over each \-separated component in the path */
1144  do {
1145  TCHAR *Next = _tcschr(In, _T('\\'));
1146  if (Next)
1147  *Next++ = _T('\0');
1148  /* Use FindFirstFile to get the correct name */
1149  if (Out + _tcslen(In) + 1 >= &FixedPath[ARRAYSIZE(FixedPath)])
1150  return _T("");
1151  _tcscpy(Out, In);
1152  hFind = FindFirstFile(FixedPath, &w32fd);
1153  /* If it doesn't exist, just leave the name as it was given */
1154  if (hFind != INVALID_HANDLE_VALUE)
1155  {
1156  PTSTR FixedComponent = w32fd.cFileName;
1157  if (*w32fd.cAlternateFileName &&
1158  ((Modifiers & M_SHORT) || !_tcsicmp(In, w32fd.cAlternateFileName)))
1159  {
1160  FixedComponent = w32fd.cAlternateFileName;
1161  }
1162  FindClose(hFind);
1163 
1164  if (Out + _tcslen(FixedComponent) + 1 >= &FixedPath[ARRAYSIZE(FixedPath)])
1165  return _T("");
1166  _tcscpy(Out, FixedComponent);
1167  }
1168  Filename = Out;
1169  Out += _tcslen(Out);
1170  *Out++ = _T('\\');
1171 
1172  In = Next;
1173  } while (In != NULL);
1174  Out[-1] = _T('\0');
1175 
1176  /* Build the result string. Start with attributes, modification time, and
1177  * file size. If the file didn't exist, these fields will all be empty. */
1178  Out = Result;
1179  if (hFind != INVALID_HANDLE_VALUE)
1180  {
1181  if (Modifiers & M_ATTR)
1182  {
1183  static const struct {
1184  TCHAR Character;
1185  WORD Value;
1186  } *Attrib, Table[] = {
1187  { _T('d'), FILE_ATTRIBUTE_DIRECTORY },
1188  { _T('r'), FILE_ATTRIBUTE_READONLY },
1189  { _T('a'), FILE_ATTRIBUTE_ARCHIVE },
1190  { _T('h'), FILE_ATTRIBUTE_HIDDEN },
1191  { _T('s'), FILE_ATTRIBUTE_SYSTEM },
1192  { _T('c'), FILE_ATTRIBUTE_COMPRESSED },
1193  { _T('o'), FILE_ATTRIBUTE_OFFLINE },
1194  { _T('t'), FILE_ATTRIBUTE_TEMPORARY },
1195  { _T('l'), FILE_ATTRIBUTE_REPARSE_POINT },
1196 #if (NTDDI_VERSION >= NTDDI_WIN8)
1198  { _T('x'), FILE_ATTRIBUTE_NO_SCRUB_DATA /* 0x20000 */ },
1199 #endif
1200  };
1201  for (Attrib = Table; Attrib != &Table[ARRAYSIZE(Table)]; Attrib++)
1202  {
1203  *Out++ = w32fd.dwFileAttributes & Attrib->Value
1204  ? Attrib->Character
1205  : _T('-');
1206  }
1207  *Out++ = _T(' ');
1208  }
1209  if (Modifiers & M_TIME)
1210  {
1211  FILETIME ft;
1212  SYSTEMTIME st;
1213  FileTimeToLocalFileTime(&w32fd.ftLastWriteTime, &ft);
1214  FileTimeToSystemTime(&ft, &st);
1215 
1216  Out += FormatDate(Out, &st, TRUE);
1217  *Out++ = _T(' ');
1218  Out += FormatTime(Out, &st);
1219  *Out++ = _T(' ');
1220  }
1221  if (Modifiers & M_SIZE)
1222  {
1224  Size.LowPart = w32fd.nFileSizeLow;
1225  Size.HighPart = w32fd.nFileSizeHigh;
1226  Out += _stprintf(Out, _T("%I64u "), Size.QuadPart);
1227  }
1228  }
1229 
1230  /* When using the path-searching syntax or the S modifier,
1231  * at least part of the file path is always included.
1232  * If none of the DPNX modifiers are present, include the full path */
1233  if (PathVarName || (Modifiers & M_SHORT))
1234  if ((Modifiers & (M_DRIVE | M_PATH | M_NAME | M_EXT)) == 0)
1235  Modifiers |= M_FULL;
1236 
1237  /* Now add the requested parts of the name.
1238  * With the F modifier, add all parts to form the full path. */
1239  Extension = _tcsrchr(Filename, _T('.'));
1240  if (Modifiers & (M_DRIVE | M_FULL))
1241  {
1242  *Out++ = FixedPath[0];
1243  *Out++ = FixedPath[1];
1244  }
1245  if (Modifiers & (M_PATH | M_FULL))
1246  {
1247  memcpy(Out, &FixedPath[2], (ULONG_PTR)Filename - (ULONG_PTR)&FixedPath[2]);
1248  Out += Filename - &FixedPath[2];
1249  }
1250  if (Modifiers & (M_NAME | M_FULL))
1251  {
1252  while (*Filename && Filename != Extension)
1253  *Out++ = *Filename++;
1254  }
1255  if (Modifiers & (M_EXT | M_FULL))
1256  {
1257  if (Extension)
1258  Out = _stpcpy(Out, Extension);
1259  }
1260 
1261  /* Trim trailing space which otherwise would appear as a
1262  * result of using the A/T/Z modifiers but no others. */
1263  while (Out != &Result[0] && Out[-1] == _T(' '))
1264  Out--;
1265  *Out = _T('\0');
1266 
1267  return Result;
1268 }
1269 
1270 static PCTSTR
1272  IN PCTSTR varName,
1273  OUT PUINT varNameLen)
1274 {
1275  PCTSTR ret;
1276  PCTSTR varNameEnd;
1277 
1278  *varNameLen = 1;
1279 
1280  switch (*varName)
1281  {
1282  case _T('~'):
1283  {
1284  varNameEnd = varName + 1;
1285  ret = GetEnhancedVar(&varNameEnd, FindArg);
1286  if (!ret)
1287  {
1288  ParseErrorEx(varName);
1289  return NULL;
1290  }
1291  *varNameLen = varNameEnd - varName;
1292  return ret;
1293  }
1294 
1295  case _T('0'):
1296  case _T('1'):
1297  case _T('2'):
1298  case _T('3'):
1299  case _T('4'):
1300  case _T('5'):
1301  case _T('6'):
1302  case _T('7'):
1303  case _T('8'):
1304  case _T('9'):
1305  {
1306  BOOL dummy;
1307  if (!FindArg(*varName, &ret, &dummy))
1308  return NULL;
1309  else
1310  return ret;
1311  }
1312 
1313  case _T('*'):
1314  /* Copy over the raw params (not including the batch file name) */
1315  return bc->raw_params;
1316 
1317  case _T('%'):
1318  return _T("%");
1319  }
1320  return NULL;
1321 }
1322 
1323 BOOL
1325  IN PCTSTR Src,
1326  OUT size_t* SrcIncLen, // VarNameLen
1327  OUT PTCHAR Dest,
1328  IN PTCHAR DestEnd,
1329  OUT size_t* DestIncLen,
1330  IN TCHAR Delim)
1331 {
1332 #define APPEND(From, Length) \
1333 do { \
1334  if (Dest + (Length) > DestEnd) \
1335  goto too_long; \
1336  memcpy(Dest, (From), (Length) * sizeof(TCHAR)); \
1337  Dest += (Length); \
1338 } while (0)
1339 
1340 #define APPEND1(Char) \
1341 do { \
1342  if (Dest >= DestEnd) \
1343  goto too_long; \
1344  *Dest++ = (Char); \
1345 } while (0)
1346 
1347  PCTSTR Var;
1348  PCTSTR Start, End, SubstStart;
1349  TCHAR EndChr;
1350  size_t VarLength;
1351 
1352  Start = Src;
1353  End = Dest;
1354  *SrcIncLen = 0;
1355  *DestIncLen = 0;
1356 
1357  if (!Delim)
1358  return FALSE;
1359  if (*Src != Delim)
1360  return FALSE;
1361 
1362  ++Src;
1363 
1364  /* If we are already at the end of the string, fail the substitution */
1365  SubstStart = Src;
1366  if (!*Src || *Src == _T('\r') || *Src == _T('\n'))
1367  goto bad_subst;
1368 
1369  if (bc && Delim == _T('%'))
1370  {
1371  UINT NameLen;
1372  Var = GetBatchVar(Src, &NameLen);
1373  if (!Var && bParseError)
1374  {
1375  /* Return the partially-parsed command to be
1376  * echoed for error diagnostics purposes. */
1377  APPEND1(Delim);
1378  APPEND(Src, _tcslen(Src) + 1);
1379  return FALSE;
1380  }
1381  if (Var != NULL)
1382  {
1383  VarLength = _tcslen(Var);
1384  APPEND(Var, VarLength);
1385  Src += NameLen;
1386  goto success;
1387  }
1388  }
1389 
1390  /* Find the end of the variable name. A colon (:) will usually
1391  * end the name and begin the optional modifier, but not if it
1392  * is immediately followed by the delimiter (%VAR:%). */
1393  SubstStart = Src;
1394  while (*Src && *Src != Delim && !(*Src == _T(':') && Src[1] != Delim))
1395  {
1396  ++Src;
1397  }
1398  /* If we are either at the end of the string, or the delimiter
1399  * has been repeated more than once, fail the substitution. */
1400  if (!*Src || Src == SubstStart)
1401  goto bad_subst;
1402 
1403  EndChr = *Src;
1404  *(PTSTR)Src = _T('\0'); // FIXME: HACK!
1405  Var = GetEnvVarOrSpecial(SubstStart);
1406  *(PTSTR)Src++ = EndChr;
1407  if (Var == NULL)
1408  {
1409  /* In a batch context, %NONEXISTENT% "expands" to an
1410  * empty string, otherwise fail the substitution. */
1411  if (bc)
1412  goto success;
1413  goto bad_subst;
1414  }
1415  VarLength = _tcslen(Var);
1416 
1417  if (EndChr == Delim)
1418  {
1419  /* %VAR% - use as-is */
1420  APPEND(Var, VarLength);
1421  }
1422  else if (*Src == _T('~'))
1423  {
1424  /* %VAR:~[start][,length]% - Substring.
1425  * Negative values are offsets from the end.
1426  */
1427  SSIZE_T Start = _tcstol(Src + 1, (PTSTR*)&Src, 0);
1428  SSIZE_T End = (SSIZE_T)VarLength;
1429  if (Start < 0)
1430  Start += VarLength;
1431  Start = min(max(Start, 0), VarLength);
1432  if (*Src == _T(','))
1433  {
1434  End = _tcstol(Src + 1, (PTSTR*)&Src, 0);
1435  End += (End < 0) ? VarLength : Start;
1436  End = min(max(End, Start), VarLength);
1437  }
1438  if (*Src++ != Delim)
1439  goto bad_subst;
1440  APPEND(&Var[Start], End - Start);
1441  }
1442  else
1443  {
1444  /* %VAR:old=new% - Replace all occurrences of old with new.
1445  * %VAR:*old=new% - Replace first occurrence only,
1446  * and remove everything before it.
1447  */
1448  PCTSTR Old, New;
1449  size_t OldLength, NewLength;
1450  BOOL Star = FALSE;
1451  size_t LastMatch = 0, i = 0;
1452 
1453  if (*Src == _T('*'))
1454  {
1455  Star = TRUE;
1456  Src++;
1457  }
1458 
1459  /* The string to replace may contain the delimiter */
1460  Src = _tcschr(Old = Src, _T('='));
1461  if (Src == NULL)
1462  goto bad_subst;
1463  OldLength = Src++ - Old;
1464  if (OldLength == 0)
1465  goto bad_subst;
1466 
1467  Src = _tcschr(New = Src, Delim);
1468  if (Src == NULL)
1469  goto bad_subst;
1470  NewLength = Src++ - New;
1471 
1472  while (i < VarLength)
1473  {
1474  if (_tcsnicmp(&Var[i], Old, OldLength) == 0)
1475  {
1476  if (!Star)
1477  APPEND(&Var[LastMatch], i - LastMatch);
1478  APPEND(New, NewLength);
1479  i += OldLength;
1480  LastMatch = i;
1481  if (Star)
1482  break;
1483  continue;
1484  }
1485  i++;
1486  }
1487  APPEND(&Var[LastMatch], VarLength - LastMatch);
1488  }
1489 
1490 success:
1491  *SrcIncLen = (Src - Start);
1492  *DestIncLen = (Dest - End);
1493  return TRUE;
1494 
1495 bad_subst:
1496  Src = SubstStart;
1497  /* Only if no batch context active do we echo the delimiter */
1498  if (!bc)
1499  APPEND1(Delim);
1500  goto success;
1501 
1502 too_long:
1504  nErrorLevel = 9023;
1505  return FALSE;
1506 
1507 #undef APPEND
1508 #undef APPEND1
1509 }
1510 
1511 BOOL
1513  IN PCTSTR Src,
1514  OUT PTSTR Dest,
1515  IN TCHAR Delim)
1516 {
1517 #define APPEND(From, Length) \
1518 do { \
1519  if (Dest + (Length) > DestEnd) \
1520  goto too_long; \
1521  memcpy(Dest, (From), (Length) * sizeof(TCHAR)); \
1522  Dest += (Length); \
1523 } while (0)
1524 
1525 #define APPEND1(Char) \
1526 do { \
1527  if (Dest >= DestEnd) \
1528  goto too_long; \
1529  *Dest++ = (Char); \
1530 } while (0)
1531 
1532  PTCHAR DestEnd = Dest + CMDLINE_LENGTH - 1;
1533  PCTSTR End;
1534  size_t SrcIncLen, DestIncLen;
1535 
1536  while (*Src /* && (Dest < DestEnd) */)
1537  {
1538  if (*Src != Delim)
1539  {
1540  End = _tcschr(Src, Delim);
1541  if (End == NULL)
1542  End = Src + _tcslen(Src);
1543  APPEND(Src, End - Src);
1544  Src = End;
1545  continue;
1546  }
1547 
1548  if (!SubstituteVar(Src, &SrcIncLen, Dest, DestEnd, &DestIncLen, Delim))
1549  {
1550  return FALSE;
1551  }
1552  else
1553  {
1554  Src += SrcIncLen;
1555  Dest += DestIncLen;
1556  }
1557  }
1558  APPEND1(_T('\0'));
1559  return TRUE;
1560 
1561 too_long:
1563  nErrorLevel = 9023;
1564  return FALSE;
1565 
1566 #undef APPEND
1567 #undef APPEND1
1568 }
1569 
1570 /* Search the list of FOR contexts for a variable */
1571 static BOOL
1573  IN TCHAR Var,
1574  OUT PCTSTR* VarPtr,
1575  OUT BOOL* IsParam0)
1576 {
1577  PFOR_CONTEXT Ctx;
1578 
1579  *VarPtr = NULL;
1580  *IsParam0 = FALSE;
1581 
1582  for (Ctx = fc; Ctx != NULL; Ctx = Ctx->prev)
1583  {
1584  if ((UINT)(Var - Ctx->firstvar) < Ctx->varcount)
1585  {
1586  *VarPtr = Ctx->values[Var - Ctx->firstvar];
1587  return TRUE;
1588  }
1589  }
1590  return FALSE;
1591 }
1592 
1593 BOOL
1595  IN PCTSTR Src,
1596  OUT PTSTR Dest)
1597 {
1598  PTCHAR DestEnd = &Dest[CMDLINE_LENGTH - 1];
1599  while (*Src)
1600  {
1601  if (Src[0] == _T('%'))
1602  {
1603  BOOL Dummy;
1604  PCTSTR End = &Src[2];
1605  PCTSTR Value = NULL;
1606 
1607  if (Src[1] == _T('~'))
1608  Value = GetEnhancedVar(&End, FindForVar);
1609 
1610  if (!Value && Src[1])
1611  {
1612  if (FindForVar(Src[1], &Value, &Dummy) && !Value)
1613  {
1614  /* The variable is empty, return an empty string */
1615  Value = _T("");
1616  }
1617  }
1618 
1619  if (Value)
1620  {
1621  if (Dest + _tcslen(Value) > DestEnd)
1622  return FALSE;
1623  Dest = _stpcpy(Dest, Value);
1624  Src = End;
1625  continue;
1626  }
1627  }
1628  /* Not a variable; just copy the character */
1629  if (Dest >= DestEnd)
1630  return FALSE;
1631  *Dest++ = *Src++;
1632  }
1633  *Dest = _T('\0');
1634  return TRUE;
1635 }
1636 
1637 PTSTR
1639  IN PCTSTR Line)
1640 {
1641  TCHAR Buf1[CMDLINE_LENGTH];
1642  TCHAR Buf2[CMDLINE_LENGTH];
1643  PTCHAR Src, Dst;
1644  PTCHAR DestEnd = Buf2 + CMDLINE_LENGTH - 1;
1645  size_t SrcIncLen, DestIncLen;
1646 
1647  /* First, substitute FOR variables */
1648  if (!SubstituteForVars(Line, Buf1))
1649  return NULL;
1650 
1651  if (!bDelayedExpansion || !_tcschr(Buf1, _T('!')))
1652  return cmd_dup(Buf1);
1653 
1654  /*
1655  * Delayed substitutions are not actually completely the same as
1656  * immediate substitutions. In particular, it is possible to escape
1657  * the exclamation point using the escape caret.
1658  */
1659 
1660  /*
1661  * Perform delayed expansion: expand variables around '!',
1662  * and reparse escape carets.
1663  */
1664 
1665 #define APPEND1(Char) \
1666 do { \
1667  if (Dst >= DestEnd) \
1668  goto too_long; \
1669  *Dst++ = (Char); \
1670 } while (0)
1671 
1672  Src = Buf1;
1673  Dst = Buf2;
1674  while (*Src && (Src < &Buf1[CMDLINE_LENGTH]))
1675  {
1676  if (*Src == _T('^'))
1677  {
1678  ++Src;
1679  if (!*Src || !(Src < &Buf1[CMDLINE_LENGTH]))
1680  break;
1681 
1682  APPEND1(*Src++);
1683  }
1684  else if (*Src == _T('!'))
1685  {
1686  if (!SubstituteVar(Src, &SrcIncLen, Dst, DestEnd, &DestIncLen, _T('!')))
1687  {
1688  return NULL; // Got an error during parsing.
1689  }
1690  else
1691  {
1692  Src += SrcIncLen;
1693  Dst += DestIncLen;
1694  }
1695  }
1696  else
1697  {
1698  APPEND1(*Src++);
1699  }
1700  continue;
1701  }
1702  APPEND1(_T('\0'));
1703 
1704  return cmd_dup(Buf2);
1705 
1706 too_long:
1708  nErrorLevel = 9023;
1709  return NULL;
1710 
1711 #undef APPEND1
1712 }
1713 
1714 
1715 /*
1716  * Do the prompt/input/process loop.
1717  */
1718 BOOL
1719 ReadLine(TCHAR *commandline, BOOL bMore)
1720 {
1722  LPTSTR ip;
1723 
1724  /* if no batch input then... */
1725  if (bc == NULL)
1726  {
1727  if (bMore)
1728  {
1730  }
1731  else
1732  {
1733  /* JPP 19980807 - if echo off, don't print prompt */
1734  if (bEcho)
1735  {
1736  if (!bIgnoreEcho)
1737  ConOutChar(_T('\n'));
1738  PrintPrompt();
1739  }
1740  }
1741 
1742  if (!ReadCommand(readline, CMDLINE_LENGTH - 1))
1743  {
1744  bExit = TRUE;
1745  return FALSE;
1746  }
1747 
1748  if (readline[0] == _T('\0'))
1749  ConOutChar(_T('\n'));
1750 
1752  return FALSE;
1753 
1754  if (readline[0] == _T('\0'))
1755  return FALSE;
1756 
1757  ip = readline;
1758  }
1759  else
1760  {
1761  ip = ReadBatchLine();
1762  if (!ip)
1763  return FALSE;
1764  }
1765 
1766  return SubstituteVars(ip, commandline, _T('%'));
1767 }
1768 
1769 static INT
1771 {
1772  INT Ret = 0;
1774 
1775  while (!bCanExit || !bExit)
1776  {
1777  /* Reset the Ctrl-Break / Ctrl-C state */
1778  bCtrlBreak = FALSE;
1779 
1780  Cmd = ParseCommand(NULL);
1781  if (!Cmd)
1782  continue;
1783 
1784  Ret = ExecuteCommand(Cmd);
1785  FreeCommand(Cmd);
1786  }
1787 
1788  return Ret;
1789 }
1790 
1791 
1792 /*
1793  * Control-break handler.
1794  */
1795 static BOOL
1796 WINAPI
1797 BreakHandler(IN DWORD dwCtrlType)
1798 {
1799  DWORD dwWritten;
1800  INPUT_RECORD rec;
1801 
1802  if ((dwCtrlType != CTRL_C_EVENT) &&
1803  (dwCtrlType != CTRL_BREAK_EVENT))
1804  {
1805  return FALSE;
1806  }
1807 
1809  {
1810  /* Child process is running and will have received the control event */
1811  return TRUE;
1812  }
1813  else
1814  {
1816  }
1817 
1818  bCtrlBreak = TRUE;
1819 
1820  rec.EventType = KEY_EVENT;
1821  rec.Event.KeyEvent.bKeyDown = TRUE;
1822  rec.Event.KeyEvent.wRepeatCount = 1;
1823  rec.Event.KeyEvent.wVirtualKeyCode = _T('C');
1824  rec.Event.KeyEvent.wVirtualScanCode = _T('C') - 35;
1825  rec.Event.KeyEvent.uChar.AsciiChar = _T('C');
1826  rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
1828 
1830  &rec,
1831  1,
1832  &dwWritten);
1833 
1834  /* FIXME: Handle batch files */
1835 
1836  // ConOutPrintf(_T("^C"));
1837 
1838  return TRUE;
1839 }
1840 
1841 
1843 {
1845 }
1846 
1847 
1849 {
1851 }
1852 
1853 
1854 /*
1855  * Show commands and options that are available.
1856  */
1857 #if 0
1858 static VOID
1859 ShowCommands(VOID)
1860 {
1861  /* print command list */
1863  PrintCommandList();
1864 
1865  /* print feature list */
1867 
1868 #ifdef FEATURE_ALIASES
1870 #endif
1871 #ifdef FEATURE_HISTORY
1873 #endif
1874 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
1876 #endif
1877 #ifdef FEATURE_DIRECTORY_STACK
1879 #endif
1880 #ifdef FEATURE_REDIRECTION
1882 #endif
1883  ConOutChar(_T('\n'));
1884 }
1885 #endif
1886 
1887 
1888 static VOID
1890 {
1891  LONG lRet;
1892  HKEY hKey;
1893  DWORD dwType, len;
1894  /*
1895  * Buffer big enough to hold the string L"4294967295",
1896  * corresponding to the literal 0xFFFFFFFF (MAXULONG) in decimal.
1897  */
1898  DWORD Buffer[6];
1899 
1900  lRet = RegOpenKeyEx(hKeyRoot,
1901  _T("Software\\Microsoft\\Command Processor"),
1902  0,
1904  &hKey);
1905  if (lRet != ERROR_SUCCESS)
1906  return;
1907 
1908 #ifdef INCLUDE_CMD_COLOR
1909  len = sizeof(Buffer);
1910  lRet = RegQueryValueEx(hKey,
1911  _T("DefaultColor"),
1912  NULL,
1913  &dwType,
1914  (LPBYTE)&Buffer,
1915  &len);
1916  if (lRet == ERROR_SUCCESS)
1917  {
1918  /* Overwrite the default attributes */
1919  if (dwType == REG_DWORD)
1920  wDefColor = (WORD)*(PDWORD)Buffer;
1921  else if (dwType == REG_SZ)
1923  }
1924  // else, use the default attributes retrieved before.
1925 #endif
1926 
1927 #if 0
1928  len = sizeof(Buffer);
1929  lRet = RegQueryValueEx(hKey,
1930  _T("DisableUNCCheck"),
1931  NULL,
1932  &dwType,
1933  (LPBYTE)&Buffer,
1934  &len);
1935  if (lRet == ERROR_SUCCESS)
1936  {
1937  /* Overwrite the default setting */
1938  if (dwType == REG_DWORD)
1939  bDisableUNCCheck = !!*(PDWORD)Buffer;
1940  else if (dwType == REG_SZ)
1941  bDisableUNCCheck = (_ttol((PTSTR)Buffer) == 1);
1942  }
1943  // else, use the default setting set globally.
1944 #endif
1945 
1946  len = sizeof(Buffer);
1947  lRet = RegQueryValueEx(hKey,
1948  _T("DelayedExpansion"),
1949  NULL,
1950  &dwType,
1951  (LPBYTE)&Buffer,
1952  &len);
1953  if (lRet == ERROR_SUCCESS)
1954  {
1955  /* Overwrite the default setting */
1956  if (dwType == REG_DWORD)
1958  else if (dwType == REG_SZ)
1959  bDelayedExpansion = (_ttol((PTSTR)Buffer) == 1);
1960  }
1961  // else, use the default setting set globally.
1962 
1963  len = sizeof(Buffer);
1964  lRet = RegQueryValueEx(hKey,
1965  _T("EnableExtensions"),
1966  NULL,
1967  &dwType,
1968  (LPBYTE)&Buffer,
1969  &len);
1970  if (lRet == ERROR_SUCCESS)
1971  {
1972  /* Overwrite the default setting */
1973  if (dwType == REG_DWORD)
1975  else if (dwType == REG_SZ)
1976  bEnableExtensions = (_ttol((PTSTR)Buffer) == 1);
1977  }
1978  // else, use the default setting set globally.
1979 
1980  len = sizeof(Buffer);
1981  lRet = RegQueryValueEx(hKey,
1982  _T("CompletionChar"),
1983  NULL,
1984  &dwType,
1985  (LPBYTE)&Buffer,
1986  &len);
1987  if (lRet == ERROR_SUCCESS)
1988  {
1989  /* Overwrite the default setting */
1990  if (dwType == REG_DWORD)
1992  else if (dwType == REG_SZ)
1994  }
1995  // else, use the default setting set globally.
1996 
1997  /* Validity check */
1999  {
2000  /* Disable autocompletion */
2001  AutoCompletionChar = 0x20;
2002  }
2003 
2004  len = sizeof(Buffer);
2005  lRet = RegQueryValueEx(hKey,
2006  _T("PathCompletionChar"),
2007  NULL,
2008  &dwType,
2009  (LPBYTE)&Buffer,
2010  &len);
2011  if (lRet == ERROR_SUCCESS)
2012  {
2013  /* Overwrite the default setting */
2014  if (dwType == REG_DWORD)
2016  else if (dwType == REG_SZ)
2018  }
2019  // else, use the default setting set globally.
2020 
2021  /* Validity check */
2023  {
2024  /* Disable autocompletion */
2025  PathCompletionChar = 0x20;
2026  }
2027 
2028  /* Adjust completion chars */
2029  if (PathCompletionChar >= 0x20 && AutoCompletionChar < 0x20)
2031  else if (AutoCompletionChar >= 0x20 && PathCompletionChar < 0x20)
2033 
2034  RegCloseKey(hKey);
2035 }
2036 
2037 static VOID
2039 {
2040  LONG lRet;
2041  HKEY hKey;
2042  DWORD dwType, len;
2043  TCHAR AutoRun[2048];
2044 
2045  lRet = RegOpenKeyEx(hKeyRoot,
2046  _T("Software\\Microsoft\\Command Processor"),
2047  0,
2049  &hKey);
2050  if (lRet != ERROR_SUCCESS)
2051  return;
2052 
2053  len = sizeof(AutoRun);
2054  lRet = RegQueryValueEx(hKey,
2055  _T("AutoRun"),
2056  NULL,
2057  &dwType,
2058  (LPBYTE)&AutoRun,
2059  &len);
2060  if ((lRet == ERROR_SUCCESS) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ))
2061  {
2062  if (*AutoRun)
2063  ParseCommandLine(AutoRun);
2064  }
2065 
2066  RegCloseKey(hKey);
2067 }
2068 
2069 /* Get the command that comes after a /C or /K switch */
2070 static VOID
2072  OUT LPTSTR commandline,
2073  IN LPCTSTR ptr,
2074  IN BOOL AlwaysStrip)
2075 {
2076  TCHAR* LastQuote;
2077 
2078  while (_istspace(*ptr))
2079  ++ptr;
2080 
2081  /* Remove leading quote, find final quote */
2082  if (*ptr == _T('"') &&
2083  (LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
2084  {
2085  const TCHAR* Space;
2086  /* Under certain circumstances, all quotes are preserved.
2087  * CMD /? documents these conditions as follows:
2088  * 1. No /S switch
2089  * 2. Exactly two quotes
2090  * 3. No "special characters" between the quotes
2091  * (CMD /? says &<>()@^| but parentheses did not
2092  * trigger this rule when I tested them.)
2093  * 4. Whitespace exists between the quotes
2094  * 5. Enclosed string is an executable filename
2095  */
2096  *LastQuote = _T('\0');
2097  for (Space = ptr + 1; Space < LastQuote; ++Space)
2098  {
2099  if (_istspace(*Space)) /* Rule 4 */
2100  {
2101  if (!AlwaysStrip && /* Rule 1 */
2102  !_tcspbrk(ptr, _T("\"&<>@^|")) && /* Rules 2, 3 */
2103  SearchForExecutable(ptr, commandline)) /* Rule 5 */
2104  {
2105  /* All conditions met: preserve both the quotes */
2106  *LastQuote = _T('"');
2107  _tcscpy(commandline, ptr - 1);
2108  return;
2109  }
2110  break;
2111  }
2112  }
2113 
2114  /* The conditions were not met: remove both the
2115  * leading quote and the last quote */
2116  _tcscpy(commandline, ptr);
2117  _tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
2118  return;
2119  }
2120 
2121  /* No quotes; just copy */
2122  _tcscpy(commandline, ptr);
2123 }
2124 
2125 
2126 /*
2127  * Set up global initializations and process parameters.
2128  * Return a pointer to the command line if present.
2129  */
2130 static LPCTSTR
2132 {
2133  HMODULE NtDllModule;
2134  HANDLE hIn, hOut;
2135  LPTSTR ptr, cmdLine;
2136  TCHAR option = 0;
2137  BOOL AutoRun = TRUE;
2138  TCHAR ModuleName[MAX_PATH + 1];
2139 
2140  /* Get version information */
2141  InitOSVersion();
2142 
2143  /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
2144  * build process. So don't link implicitly against ntdll.dll, load it
2145  * dynamically instead */
2146  NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
2147  if (NtDllModule != NULL)
2148  {
2149  NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)GetProcAddress(NtDllModule, "NtQueryInformationProcess");
2150  NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
2151  }
2152 
2153  /* Load the registry settings */
2156 
2157  /* Initialize our locale */
2158  InitLocale();
2159 
2160  /* Initialize prompt support */
2161  InitPrompt();
2162 
2163 #ifdef FEATURE_DIRECTORY_STACK
2164  /* Initialize directory stack */
2166 #endif
2167 
2168 #ifdef FEATURE_HISTORY
2169  /* Initialize history */
2170  InitHistory();
2171 #endif
2172 
2173  /* Set COMSPEC environment variable */
2175  {
2176  ModuleName[MAX_PATH] = _T('\0');
2177  SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
2178  }
2179 
2180  /* Add ctrl break handler */
2181  AddBreakHandler();
2182 
2183  /* Set our default console mode */
2184  hOut = ConStreamGetOSHandle(StdOut);
2185  hIn = ConStreamGetOSHandle(StdIn);
2186  SetConsoleMode(hOut, 0); // Reinitialize the console output mode
2189 
2190  cmdLine = GetCommandLine();
2191  TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
2192 
2193  for (ptr = cmdLine; *ptr; ++ptr)
2194  {
2195  if (*ptr == _T('/'))
2196  {
2197  option = _totupper(ptr[1]);
2198  if (option == _T('?'))
2199  {
2201  nErrorLevel = 1;
2202  bExit = TRUE;
2203  return NULL;
2204  }
2205  else if (option == _T('P'))
2206  {
2207  if (!IsExistingFile(_T("\\autoexec.bat")))
2208  {
2209 #ifdef INCLUDE_CMD_DATE
2210  cmd_date(_T(""));
2211 #endif
2212 #ifdef INCLUDE_CMD_TIME
2213  cmd_time(_T(""));
2214 #endif
2215  }
2216  else
2217  {
2218  ParseCommandLine(_T("\\autoexec.bat"));
2219  }
2220  bCanExit = FALSE;
2221  }
2222  else if (option == _T('A'))
2223  {
2225  }
2226  else if (option == _T('C') || option == _T('K') || option == _T('R'))
2227  {
2228  /* Remainder of command line is a command to be run */
2229  fSingleCommand = ((option == _T('K')) << 1) | 1;
2230  break;
2231  }
2232  else if (option == _T('D'))
2233  {
2234  AutoRun = FALSE;
2235  }
2236  else if (option == _T('Q'))
2237  {
2239  }
2240  else if (option == _T('S'))
2241  {
2242  bAlwaysStrip = TRUE;
2243  }
2244 #ifdef INCLUDE_CMD_COLOR
2245  else if (!_tcsnicmp(ptr, _T("/T:"), 3))
2246  {
2247  /* Process /T (color) argument; overwrite any previous settings */
2248  wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
2249  }
2250 #endif
2251  else if (option == _T('U'))
2252  {
2254  }
2255  else if (option == _T('V'))
2256  {
2257  // FIXME: Check validity of the parameter given to V !
2258  bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
2259  }
2260  else if (option == _T('E'))
2261  {
2262  // FIXME: Check validity of the parameter given to E !
2263  bEnableExtensions = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
2264  }
2265  else if (option == _T('X'))
2266  {
2267  /* '/X' is identical to '/E:ON' */
2269  }
2270  else if (option == _T('Y'))
2271  {
2272  /* '/Y' is identical to '/E:OFF' */
2274  }
2275  }
2276  }
2277 
2278 #ifdef INCLUDE_CMD_COLOR
2279  if (wDefColor == 0)
2280  {
2281  /*
2282  * If we still do not have the console colour attribute set,
2283  * retrieve the default one.
2284  */
2286  }
2287 
2288  if (wDefColor != 0)
2290 #endif
2291 
2292  /* Reset the output Standard Streams translation modes and codepage caches */
2293  // ConStreamSetMode(StdIn , OutputStreamMode, InputCodePage );
2296 
2297  if (!*ptr)
2298  {
2299  /* If neither /C or /K was given, display a simple version string */
2300  ConOutChar(_T('\n'));
2302  _T(KERNEL_VERSION_STR),
2303  _T(KERNEL_VERSION_BUILD_STR));
2304  ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team.\n"));
2305  }
2306 
2307  if (AutoRun)
2308  {
2311  }
2312 
2313  /* Returns the rest of the command line */
2314  return ptr;
2315 }
2316 
2317 
2319 {
2320  /* Run cmdexit.bat */
2321  if (IsExistingFile(_T("cmdexit.bat")))
2322  {
2324  ParseCommandLine(_T("cmdexit.bat"));
2325  }
2326  else if (IsExistingFile(_T("\\cmdexit.bat")))
2327  {
2329  ParseCommandLine(_T("\\cmdexit.bat"));
2330  }
2331 
2332 #ifdef FEATURE_DIRECTORY_STACK
2333  /* Destroy directory stack */
2335 #endif
2336 
2337 #ifdef FEATURE_HISTORY
2338  CleanHistory();
2339 #endif
2340 
2341  /* Free GetEnvVar's buffer */
2342  GetEnvVar(NULL);
2343 
2344  /* Remove ctrl break handler */
2346 
2347  /* Restore the default console mode */
2352 
2354 }
2355 
2356 /*
2357  * main function
2358  */
2359 int _tmain(int argc, const TCHAR *argv[])
2360 {
2361  INT nExitCode;
2362  LPCTSTR pCmdLine;
2363  TCHAR startPath[MAX_PATH];
2364 
2367 
2368  GetCurrentDirectory(ARRAYSIZE(startPath), startPath);
2369  _tchdir(startPath);
2370 
2371  SetFileApisToOEM();
2374 
2375  /* Initialize the Console Standard Streams */
2379 
2381 
2382  /*
2383  * Perform general initialization, parse switches on command-line.
2384  * Initialize the exit code with the errorlevel as Initialize() can set it.
2385  */
2386  pCmdLine = Initialize();
2387  nExitCode = nErrorLevel;
2388 
2389  if (pCmdLine && *pCmdLine)
2390  {
2391  TCHAR commandline[CMDLINE_LENGTH];
2392 
2393  /* Do the /C or /K command */
2394  GetCmdLineCommand(commandline, &pCmdLine[2], bAlwaysStrip);
2395  nExitCode = ParseCommandLine(commandline);
2396  if (fSingleCommand == 1)
2397  {
2398  // nErrorLevel = nExitCode;
2399  bExit = TRUE;
2400  }
2401  fSingleCommand = 0;
2402  }
2403  if (!bExit)
2404  {
2405  /* Call prompt routine */
2406  nExitCode = ProcessInput();
2407  }
2408 
2409  /* Do the cleanup */
2410  Cleanup();
2412 
2413  cmd_exit(nExitCode);
2414  return nExitCode;
2415 }
2416 
2417 /* EOF */
VOID InitLocale(VOID)
Definition: locale.c:25
#define RegQueryValueEx
Definition: winreg.h:524
INT nErrorLevel
Definition: cmd.c:158
const char * var
Definition: shader.c:5666
INT ExecuteCommand(IN PARSED_COMMAND *Cmd)
Definition: cmd.c:778
VOID PrintCommandList(VOID)
Definition: cmdtable.c:234
INT FormatTime(TCHAR *, LPSYSTEMTIME)
Definition: dir.c:703
static int argc
Definition: ServiceArgs.c:12
#define SW_SHOWDEFAULT
Definition: winuser.h:774
#define IN
Definition: typedefs.h:39
#define STRING_CMD_HELP1
Definition: resource.h:75
#define max(a, b)
Definition: svc.c:63
Definition: cmd.h:359
BOOL CheckCtrlBreak(INT)
Definition: misc.c:132
ASMGENDATA Table[]
Definition: genincdata.c:61
#define cmd_exit(code)
Definition: cmddbg.h:34
const CHAR * LPCTSTR
Definition: xmlstorage.h:193
#define CloseHandle
Definition: compat.h:487
WCHAR UnicodeChar
Definition: wincon.h:245
#define CTRL_BREAK_EVENT
Definition: wincon.h:69
#define FILE_ATTRIBUTE_TEMPORARY
Definition: nt_native.h:708
TCHAR BatchFilePath[MAX_PATH]
Definition: batch.h:33
int _tmain(int argc, const TCHAR *argv[])
Definition: cmd.c:2359
VOID InitHistory(VOID)
Definition: history.c:132
WORD wVirtualScanCode
Definition: wincon.h:243
LPSTR lpTitle
Definition: winbase.h:812
BOOL SubstituteVars(IN PCTSTR Src, OUT PTSTR Dest, IN TCHAR Delim)
Definition: cmd.c:1512
#define SHELLEXECUTETEXT
Definition: cmd.c:261
#define ERROR_SUCCESS
Definition: deptool.c:10
NTSTATUS(WINAPI * NtQueryInformationProcessProc)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG)
Definition: cmd.c:148
VOID CleanHistory(VOID)
Definition: history.c:163
#define BREAK_INPUT
Definition: cmd.h:36
BOOL bIgnoreEcho
Definition: cmd.c:155
LPCSTR PCTSTR
Definition: ntbasedef.h:489
#define LoadLibrary
Definition: winbase.h:3702
BOOL FindArg(IN TCHAR Char, OUT PCTSTR *ArgPtr, OUT BOOL *IsParam0)
Definition: batch.c:85
static VOID SetConTitle(LPCTSTR pszTitle)
Definition: cmd.c:309
#define _tcsicmp
Definition: xmlstorage.h:205
PTSTR DoDelayedExpansion(IN PCTSTR Line)
Definition: cmd.c:1638
Definition: ftp_var.h:139
static VOID ExecuteAutoRunFile(HKEY hKeyRoot)
Definition: cmd.c:2038
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
int _tcscmp(const _TCHAR *s1, const _TCHAR *s2)
Definition: tcscmp.h:8
#define TRUE
Definition: types.h:120
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define STRING_REACTOS_VERSION
Definition: resource.h:89
VOID ConOutChar(TCHAR c)
Definition: console.c:123
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1168
#define _tcstol
Definition: tchar.h:594
#define MAXIMUM_WAIT_OBJECTS
Definition: winbase.h:385
#define SEE_MASK_NO_CONSOLE
Definition: shellapi.h:38
TCHAR szCurTitle[MAX_PATH]
Definition: cmd.c:168
#define HKEY_CURRENT_USER
Definition: winreg.h:11
INT ExecuteCommandWithEcho(IN PARSED_COMMAND *Cmd)
Definition: cmd.c:864
static VOID ErrorMessage(DWORD dwErrorCode, LPWSTR szFormat,...)
Definition: attrib.c:51
static VOID LoadRegistrySettings(HKEY hKeyRoot)
Definition: cmd.c:1889
#define STRING_MORE
Definition: resource.h:239
Definition: cmd.h:361
#define ConErrResPuts(uID)
Definition: console.h:39
const GLint * first
Definition: glext.h:5794
#define WARN(fmt,...)
Definition: debug.h:112
#define WriteConsoleInput
Definition: wincon.h:788
static BOOL ReadCommand(PCONSOLE_STATE State, LPSTR str, INT maxlen)
Definition: cmdcons.c:735
LONG NTSTATUS
Definition: precomp.h:26
INT cmd_date(LPTSTR)
Definition: date.c:176
#define INT
Definition: polytest.cpp:20
VOID DestroyDirectoryStack(VOID)
Definition: dirstack.c:91
#define debugstr_aw
Definition: precomp.h:43
BOOL IsExistingFile(IN LPCTSTR pszPath)
Definition: misc.c:498
COMMAND cmds[]
Definition: main.c:21
#define CMDLINE_LENGTH
Definition: help.h:12
DWORD dwControlKeyState
Definition: wincon.h:248
#define CTRL_C_EVENT
Definition: wincon.h:68
GLdouble n
Definition: glext.h:7729
#define New(t)
Definition: rtf.h:1086
VKNAME Modifiers[]
Definition: data.c:56
BOOL bEcho
Definition: batch.c:73
Definition: cmd.h:361
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:479
_TCHAR * _tcscpy(_TCHAR *to, const _TCHAR *from)
Definition: tcscpy.h:8
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:200
LONG_PTR SSIZE_T
Definition: basetsd.h:183
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
INT ParseCommandLine(LPTSTR cmd)
Definition: cmd.c:632
static VOID GetCmdLineCommand(OUT LPTSTR commandline, IN LPCTSTR ptr, IN BOOL AlwaysStrip)
Definition: cmd.c:2071
INT FormatDate(TCHAR *, LPSYSTEMTIME, BOOL)
Definition: dir.c:674
DWORD dwFlags
Definition: winbase.h:820
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
#define IS_COMPLETION_DISABLED(CompletionCtrl)
Definition: cmd.h:135
VOID InitPrompt(VOID)
Definition: prompt.c:57
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:1274
#define _totupper
Definition: tchar.h:1509
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
static logline * readline(FILE *inf, adns_state adns, int opts)
Definition: adnslogres.c:145
#define STRING_ALIAS_ERROR
Definition: resource.h:22
#define argv
Definition: mplay32.c:18
const char * filename
Definition: ioapi.h:135
HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params, LPTSTR directory, INT show)
Definition: cmd.c:266
BOOL WINAPI FileTimeToLocalFileTime(IN CONST FILETIME *lpFileTime, OUT LPFILETIME lpLocalFileTime)
Definition: time.c:221
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
static BOOL IsConsoleProcess(HANDLE Process)
Definition: cmd.c:224
#define BOOL
Definition: nt_native.h:43
BOOL(WINAPI * MYEX)(LPSHELLEXECUTEINFO lpExecInfo)
Definition: cmd.c:264
PARSED_COMMAND * ParseCommand(IN PCTSTR Line)
Definition: parser.c:1461
#define _istalpha
Definition: tchar.h:1492
static VOID StripQuotes(LPSTR in)
Definition: cmdcons.c:116
static NtQueryInformationProcessProc NtQueryInformationProcessPtr
Definition: cmd.c:170
int32_t INT
Definition: typedefs.h:58
LPTSTR ReadBatchLine(VOID)
Definition: batch.c:579
Definition: cmd.h:355
static BOOL bAlwaysStrip
Definition: cmd.c:157
struct _PARSED_COMMAND * Next
Definition: cmd.h:372
CHAR * LPTSTR
Definition: xmlstorage.h:192
struct TraceInfo Info
IN PVCB IN PBCB OUT PDIRENT IN USHORT IN POEM_STRING Filename
Definition: fatprocs.h:934
IN UCHAR Value
Definition: halp.h:394
#define _itot
Definition: tchar.h:608
#define SearchPath
Definition: winbase.h:3740
WORD wVirtualKeyCode
Definition: wincon.h:242
VOID FreeCommand(IN OUT PARSED_COMMAND *Cmd)
Definition: parser.c:527
static USHORT USHORT * NewLength
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define ENABLE_ECHO_INPUT
Definition: wincon.h:80
WCHAR First[]
Definition: FormatMessage.c:11
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
INT(* func)(PCONSOLE_STATE, LPSTR)
Definition: cmdcons.c:29
Definition: cmd.h:359
#define ENABLE_WRAP_AT_EOL_OUTPUT
Definition: blue.h:54
LPTSTR GetTimeString(VOID)
Definition: locale.c:73
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
enum _PROCESSINFOCLASS PROCESSINFOCLASS
Definition: loader.c:63
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:460
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
WORD wRepeatCount
Definition: wincon.h:241
Definition: cmd.h:353
unsigned char * LPBYTE
Definition: typedefs.h:53
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
NTSTATUS(WINAPI * NtReadVirtualMemoryProc)(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T)
Definition: cmd.c:150
#define StringCchPrintf
Definition: strsafe.h:517
#define FALSE
Definition: types.h:117
GLenum const GLfloat * params
Definition: glext.h:5645
unsigned int BOOL
Definition: ntddk_ex.h:94
INT nNumberGroups
Definition: locale.c:22
long LONG
Definition: pedump.c:60
#define _tcsnicmp
Definition: xmlstorage.h:207
_Check_return_ int __cdecl rand(void)
Definition: rand.c:10
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1608
LPCTSTR GetEnvVarOrSpecial(LPCTSTR varName)
Definition: cmd.c:900
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2111
#define KEY_EVENT
Definition: wincon.h:128
static PVOID ptr
Definition: dispmode.c:27
int ip[4]
Definition: rtl.c:1176
#define GetCurrentDirectory
Definition: winbase.h:3645
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2453
BOOL ConStreamSetCacheCodePage(IN PCON_STREAM Stream, IN UINT CacheCodePage)
Definition: stream.c:215
const WCHAR * str
#define IMAGE_SUBSYSTEM_WINDOWS_CUI
Definition: ntimage.h:438
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
WORD wDefColor
Definition: cmd.c:180
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
Definition: getopt.h:108
_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 GetConsoleTitle
Definition: wincon.h:778
VOID error_out_of_memory(VOID)
Definition: error.c:138
#define HANDLE_FLAG_INHERIT
Definition: winbase.h:261
BOOL SearchForExecutable(LPCTSTR, LPTSTR)
Definition: where.c:142
LPTSTR * values
Definition: batch.h:50
Definition: bufpool.h:45
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(VOID)
Definition: console.c:2393
#define GetCommandLine
Definition: winbase.h:3639
void * PVOID
Definition: retypes.h:9
#define FindFirstFile
Definition: winbase.h:3622
#define STARTF_USESHOWWINDOW
Definition: winbase.h:472
UINT InputCodePage
Definition: console.c:25
#define STD_INPUT_HANDLE
Definition: winbase.h:264
DWORD dwChildProcessId
Definition: cmd.c:163
INT cmd_time(LPTSTR)
Definition: time.c:132
CHAR * PTSTR
Definition: xmlstorage.h:191
_TCHAR * _tcschr(const _TCHAR *s, _XINT c)
Definition: tcschr.h:4
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
TCHAR cThousandSeparator
Definition: locale.c:18
INT DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
Definition: cmd.c:553
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
LPTSTR DuplicateEnvironment(VOID)
Definition: setlocal.c:25
static BOOL FindForVar(IN TCHAR Var, OUT PCTSTR *VarPtr, OUT BOOL *IsParam0)
Definition: cmd.c:1572
#define APPEND(From, Length)
HANDLE ConStreamGetOSHandle(IN PCON_STREAM Stream)
Definition: stream.c:240
#define CMDEXTVERSION
Definition: cmd.h:32
PTCHAR UnparseCommand(IN PARSED_COMMAND *Cmd, OUT PTCHAR Out, IN PTCHAR OutEnd)
Definition: parser.c:1965
static VOID ResetConTitle(VOID)
Definition: cmd.c:329
char TCHAR
Definition: xmlstorage.h:189
#define STRING_CMD_HELP2
Definition: resource.h:76
BOOL ConStreamInit(OUT PCON_STREAM Stream, IN PVOID Handle, IN CON_STREAM_MODE Mode, IN UINT CacheCodePage OPTIONAL)
Definition: stream.c:185
BOOL bCanExit
Definition: cmd.c:153
#define _T(x)
Definition: vfdio.h:22
_TCHAR * _tcsncat(_TCHAR *dst, const _TCHAR *src, size_t n)
Definition: tcsncat.h:5
#define TRACE(s)
Definition: solgame.cpp:4
#define FreeLibrary(x)
Definition: compat.h:496
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL SubstituteForVars(IN PCTSTR Src, OUT PTSTR Dest)
Definition: cmd.c:1594
INT ConvertULargeInteger(ULONGLONG num, LPTSTR des, UINT len, BOOL bPutSeparator)
Definition: cmd.c:189
GLsizeiptr size
Definition: glext.h:5919
DWORD cb
Definition: winbase.h:809
#define STRING_CMD_HELP4
Definition: resource.h:78
VOID InitDirectoryStack(VOID)
Definition: dirstack.c:80
VOID EchoCommand(IN PARSED_COMMAND *Cmd)
Definition: parser.c:1808
Definition: dhcpd.h:61
static NtReadVirtualMemoryProc NtReadVirtualMemoryPtr
Definition: cmd.c:171
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
LPCSTR lpParameters
Definition: shellapi.h:314
uint64_t ULONGLONG
Definition: typedefs.h:67
static BOOL Full
Definition: pageheap.c:12
Definition: cmd.h:359
#define STD_ERROR_HANDLE
Definition: winbase.h:266
GLfloat param
Definition: glext.h:5796
#define MAX_PATH
Definition: compat.h:34
LPTSTR lpOriginalEnvironment
Definition: cmd.c:164
#define WINAPI
Definition: msvc.h:6
BOOL WINAPI GetNumaHighestNodeNumber(OUT PULONG HighestNodeNumber)
Definition: sysinfo.c:264
UINT OutputCodePage
Definition: console.c:26
BOOL bDisableBatchEcho
Definition: cmd.c:160
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:278
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
static INT ProcessInput(VOID)
Definition: cmd.c:1770
unsigned short WORD
Definition: ntddk_ex.h:93
TCHAR PathCompletionChar
Definition: cmdinput.c:112
#define ConOutResPrintf(uID,...)
Definition: console.h:48
unsigned long DWORD
Definition: ntddk_ex.h:95
PVOID HANDLE
Definition: typedefs.h:73
GLuint GLuint num
Definition: glext.h:9618
#define ENABLE_LINE_INPUT
Definition: wincon.h:79
VOID ParseErrorEx(IN PCTSTR s)
Definition: parser.c:227
#define success(from, fromstr, to, tostr)
#define GetModuleFileName
Definition: winbase.h:3671
#define StdErr
Definition: stream.h:83
CON_STREAM_MODE OutputStreamMode
Definition: cmd.c:177
Definition: partlist.h:33
#define FILE_ATTRIBUTE_COMPRESSED
Definition: nt_native.h:711
GLbitfield flags
Definition: glext.h:7161
static BOOL WINAPI BreakHandler(IN DWORD dwCtrlType)
Definition: cmd.c:1797
#define STRING_CMD_HELP5
Definition: resource.h:79
union _KEY_EVENT_RECORD::@3241 uChar
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
BOOL ReadLine(TCHAR *commandline, BOOL bMore)
Definition: cmd.c:1719
Definition: ncftp.h:79
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
BOOL bEnableExtensions
Definition: cmd.c:161
#define _totlower
Definition: tchar.h:1511
BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle(DWORD nStdHandle, HANDLE hHandle)
Definition: console.c:1213
TCHAR firstvar
Definition: batch.h:48
PFOR_CONTEXT fc
Definition: for.c:57
int ret
LPTSTR GetDateString(VOID)
Definition: locale.c:58
VOID error_too_many_parameters(PCTSTR s)
Definition: error.c:79
Status
Definition: gdiplustypes.h:24
#define _tcstoul
Definition: tchar.h:595
BOOL WINAPI TryEnterCriticalSection(LPCRITICAL_SECTION)
struct _FOR_CONTEXT * prev
Definition: batch.h:47
Definition: sacdrv.h:277
#define NTSTATUS
Definition: precomp.h:20
static HANDLE ExecuteAsync(PARSED_COMMAND *Cmd)
Definition: cmd.c:655
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define GetFullPathName
Definition: winbase.h:3661
VOID UndoRedirection(REDIRECTION *, REDIRECTION *End)
Definition: redir.c:142
#define SetEnvironmentVariable
Definition: winbase.h:3748
BOOL ConStreamSetMode(IN PCON_STREAM Stream, IN CON_STREAM_MODE Mode, IN UINT CacheCodePage OPTIONAL)
Definition: stream.c:195
static PCTSTR GetBatchVar(IN PCTSTR varName, OUT PUINT varNameLen)
Definition: cmd.c:1271
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
UINT varcount
Definition: batch.h:49
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define CreateProcess
Definition: winbase.h:3598
BOOL ConSetTitle(IN LPCTSTR lpConsoleTitle)
Definition: console.c:280
VOID AddBreakHandler(VOID)
Definition: cmd.c:1842
BOOL WINAPI CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize)
Definition: npipe.c:117
LPCSTR lpDirectory
Definition: shellapi.h:315
TCHAR AutoCompletionChar
Definition: cmdinput.c:111
static LPCTSTR Initialize(VOID)
Definition: cmd.c:2131
#define ENABLE_PROCESSED_OUTPUT
Definition: blue.h:53
#define Dst
Definition: mesh.h:153
#define STRING_CMD_HELP3
Definition: resource.h:77
enum _CON_STREAM_MODE CON_STREAM_MODE
Definition: cmd.h:361
LPTSTR raw_params
Definition: batch.h:35
VOID WINAPI SetFileApisToOEM(VOID)
Definition: utils.c:829
static VOID Cleanup(VOID)
Definition: cmd.c:2318
#define _stprintf
Definition: utility.h:124
#define ENABLE_PROCESSED_INPUT
Definition: wincon.h:78
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define cmd_alloc(size)
Definition: cmddbg.h:29
#define RegOpenKeyEx
Definition: winreg.h:520
#define SW_SHOWNORMAL
Definition: winuser.h:764
#define cmd_free(ptr)
Definition: cmddbg.h:31
#define TEXT(s)
Definition: k32.h:26
static const WCHAR des[]
Definition: oid.c:1212
#define GetModuleHandle
Definition: winbase.h:3667
Definition: cmd.h:357
VOID error_bad_command(PCTSTR s)
Definition: error.c:124
STARTUPINFOA STARTUPINFO
Definition: winbase.h:3559
static INT Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
Definition: cmd.c:347
static calc_node_t temp
Definition: rpn_ieee.c:38
unsigned char dummy
Definition: maze.c:118
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1532
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
LPTSTR GetEnvVar(LPCTSTR varName)
Definition: cmd.c:882
BOOL bDelayedExpansion
Definition: cmd.c:162
#define cmd_dup(str)
Definition: cmddbg.h:32
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
unsigned int * PULONG
Definition: retypes.h:1
#define STRING_CMD_HELP8
Definition: resource.h:82
#define min(a, b)
Definition: monoChain.cc:55
CRITICAL_SECTION ChildProcessRunningLock
Definition: cmd.c:159
unsigned int UINT
Definition: ndis.h:50
WORD wShowWindow
Definition: winbase.h:821
BOOL PerformRedirection(REDIRECTION *)
Definition: redir.c:63
DWORD * PDWORD
Definition: pedump.c:68
static INT ExecutePipeline(PARSED_COMMAND *Cmd)
Definition: cmd.c:689
HANDLE CMD_ModuleHandle
Definition: cmd.c:165
BOOL bExit
Definition: cmd.c:152
#define STRING_FREE_ERROR1
Definition: resource.h:49
WORD EventType
Definition: wincon.h:276
union _INPUT_RECORD::@3242 Event
#define ConOutResPuts(uID)
Definition: console.h:36
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
POINT cp
Definition: magnifier.c:59
Definition: cmd.h:359
_TCHAR * _tcsrchr(const _TCHAR *s, _XINT c)
Definition: tcsrchr.h:4
_TCHAR * _tcscat(_TCHAR *s, const _TCHAR *append)
Definition: tcscat.h:8
#define OUT
Definition: typedefs.h:40
#define StdOut
Definition: stream.h:82
#define _istspace
Definition: tchar.h:1504
unsigned int ULONG
Definition: retypes.h:1
VOID error_no_pipe(VOID)
Definition: error.c:131
INT ExecuteIf(struct _PARSED_COMMAND *Cmd)
Definition: if.c:66
LPSTR name
Definition: cmdcons.c:27
#define GetEnvironmentVariable
Definition: winbase.h:3654
PBATCH_CONTEXT bc
Definition: batch.c:67
static BOOL fSingleCommand
Definition: cmd.c:156
#define GetProcAddress(x, y)
Definition: compat.h:501
#define STRING_CMD_ERROR5
Definition: resource.h:31
#define STRING_CMD_HELP7
Definition: resource.h:81
BOOL WINAPI SetHandleInformation(IN HANDLE hObject, IN DWORD dwMask, IN DWORD dwFlags)
Definition: handle.c:78
INT ExecuteFor(struct _PARSED_COMMAND *Cmd)
Definition: for.c:604
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:139
#define SeenGoto()
#define _tcspbrk
Definition: tchar.h:1412
BOOL bTitleSet
Definition: cmd.c:167
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define _ttol
Definition: tchar.h:612
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define INFINITE
Definition: serial.h:102
#define memset(x, y, z)
Definition: compat.h:39
#define REG_DWORD
Definition: sdbapi.c:596
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:1324
static HMODULE hShell32
Definition: string.c:34
_Inout_opt_ PUNICODE_STRING Extension
Definition: fltkernel.h:1092
#define _tcscspn
Definition: tchar.h:1407
BOOL ConSetScreenColor(HANDLE hOutput, WORD wColor, BOOL bFill)
Definition: console.c:302
#define APPEND1(Char)
VOID InitOSVersion(VOID)
Definition: ver.c:32
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ FLT_IO_OPERATION_FLAGS _Out_opt_ PULONG BytesRead
Definition: fltkernel.h:1255
int(* FARPROC)()
Definition: compat.h:36
int _tchdir(const _TCHAR *_path)
Definition: chdir.c:8
VOID PrintPrompt(VOID)
Definition: prompt.c:109
unsigned int * PUINT
Definition: ndis.h:50
#define StdIn
Definition: stream.h:81
#define SetCurrentDirectory
Definition: winbase.h:3743
#define STRING_CMD_HELP6
Definition: resource.h:80
char * PTCHAR
Definition: ntbasedef.h:477
BOOL bParseError
Definition: parser.c:90
static PCTSTR GetEnhancedVar(IN OUT PCTSTR *pFormat, IN BOOL(*GetVar)(TCHAR, PCTSTR *, BOOL *))
Definition: cmd.c:971
VOID ConOutPuts(LPTSTR szText)
Definition: tee.c:27
#define FILE_ATTRIBUTE_OFFLINE
Definition: nt_native.h:712
BOOL ConGetDefaultAttributes(PWORD pwDefAttr)
Definition: console.c:255
ULONG ImageSubsystem
Definition: ntddk_ex.h:304
#define FILE_ATTRIBUTE_INTEGRITY_STREAM
VOID RemoveBreakHandler(VOID)
Definition: cmd.c:1848
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 * Format
Definition: acpixf.h:1216
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define REG_SZ
Definition: layer.c:22
BOOL bCtrlBreak
Definition: cmd.c:154
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502