ReactOS  0.4.15-dev-3331-g8ebe441
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 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 */
542  ResetConTitle();
543 
544  return dwExitCode;
545 }
546 
547 
548 /*
549  * Look through the internal commands and determine whether or not this
550  * command is one of them. If it is, call the command. If not, call
551  * execute to run it as an external program.
552  *
553  * first - first word on command line
554  * rest - rest of command line
555  */
556 INT
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 */
619  ResetConTitle();
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 }
630 
631 
632 /*
633  * process the command line and execute the appropriate functions
634  * full input/output redirection and piping are supported
635  */
637 {
638  INT Ret = 0;
640 
641  Cmd = ParseCommand(cmd);
642  if (!Cmd)
643  {
644  /* Return an adequate error code */
645  return (!bParseError ? 0 : 1);
646  }
647 
648  Ret = ExecuteCommand(Cmd);
649  FreeCommand(Cmd);
650  return Ret;
651 }
652 
653 /* Execute a command without waiting for it to finish. If it's an internal
654  * command or batch file, we must create a new cmd.exe process to handle it.
655  * TODO: For now, this just always creates a cmd.exe process.
656  * This works, but is inefficient for running external programs,
657  * which could just be run directly. */
658 static HANDLE
660 {
661  TCHAR CmdPath[MAX_PATH];
662  TCHAR CmdParams[CMDLINE_LENGTH], *ParamsEnd;
663  STARTUPINFO stui;
664  PROCESS_INFORMATION prci;
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 }
691 
692 static INT
694 {
695 #ifdef FEATURE_REDIRECTION
696  HANDLE hInput = NULL;
697  HANDLE hOldConIn = GetStdHandle(STD_INPUT_HANDLE);
698  HANDLE hOldConOut = GetStdHandle(STD_OUTPUT_HANDLE);
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  {
718  error_no_pipe();
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 
766 failed:
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 }
780 
781 INT
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  }
818  cmd_free(First);
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 }
866 
867 INT
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();
877  EchoCommand(Cmd);
878  ConOutChar(_T('\n'));
879  }
880 
881  /* Run the command */
882  return ExecuteCommand(Cmd);
883 }
884 
885 LPTSTR
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 }
902 
903 LPCTSTR
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. */
914  if (!bEnableExtensions)
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 }
972 
973 /* Handle the %~var syntax */
974 static PCTSTR
976  IN OUT PCTSTR* pFormat,
977  IN BOOL (*GetVar)(TCHAR, PCTSTR*, BOOL*))
978 {
979  static const TCHAR ModifierTable[] = _T("dpnxfsatz");
980  enum {
981  M_DRIVE = 1, /* D: drive letter */
982  M_PATH = 2, /* P: path */
983  M_NAME = 4, /* N: filename */
984  M_EXT = 8, /* X: extension */
985  M_FULL = 16, /* F: full path (drive+path+name+ext) */
986  M_SHORT = 32, /* S: full path (drive+path+name+ext), use short names */
987  M_ATTR = 64, /* A: attributes */
988  M_TIME = 128, /* T: modification time */
989  M_SIZE = 256, /* Z: file size */
990  } Modifiers = 0;
991 
992  PCTSTR Format, FormatEnd;
993  PCTSTR PathVarName = NULL;
994  PCTSTR Variable;
995  PCTSTR VarEnd;
996  BOOL VariableIsParam0;
997  TCHAR FullPath[MAX_PATH];
998  TCHAR FixedPath[MAX_PATH];
1000  HANDLE hFind;
1001  WIN32_FIND_DATA w32fd;
1002  PTCHAR In, Out;
1003 
1004  static TCHAR Result[CMDLINE_LENGTH];
1005 
1006  /* Check whether the current character is a recognized variable.
1007  * If it is not, then restore the previous one: there is indeed
1008  * ambiguity between modifier characters and FOR variables;
1009  * the rule that CMD uses is to pick the longest possible match.
1010  * This case can happen if we have a FOR-variable specification
1011  * of the following form:
1012  *
1013  * %~<modifiers><actual FOR variable character><other characters>
1014  *
1015  * where the FOR variable character is also a similar to a modifier,
1016  * but should not be interpreted as is, and the following other
1017  * characters are not part of the possible modifier characters, and
1018  * are unrelated to the FOR variable (they can be part of a command).
1019  * For example, if there is a %n variable, then out of %~anxnd,
1020  * %~anxn will be substituted rather than just %~an.
1021  *
1022  * In the following examples, all characters 'd','p','n','x' are valid modifiers.
1023  *
1024  * 1. In this example, the FOR variable character is 'x' and the actual
1025  * modifiers are 'dpn'. Parsing will first determine that 'dpnx'
1026  * are modifiers, with the possible (last) valid variable being 'x',
1027  * and will stop at the letter 'g'. Since 'g' is not a valid
1028  * variable, then the actual variable is the lattest one 'x',
1029  * and the modifiers are then actually 'dpn'.
1030  * The FOR-loop will then display the %x variable formatted with 'dpn'
1031  * and will append any other characters following, 'g'.
1032  *
1033  * C:\Temp>for %x in (foo.exe bar.txt) do @echo %~dpnxg
1034  * C:\Temp\foog
1035  * C:\Temp\barg
1036  *
1037  *
1038  * 2. In this second example, the FOR variable character is 'g' and
1039  * the actual modifiers are 'dpnx'. Parsing will determine also that
1040  * the possible (last) valid variable could be 'x', but since it's
1041  * not present in the FOR-variables list, it won't be the case.
1042  * This means that the actual FOR variable character must follow,
1043  * in this case, 'g'.
1044  *
1045  * C:\Temp>for %g in (foo.exe bar.txt) do @echo %~dpnxg
1046  * C:\Temp\foo.exe
1047  * C:\Temp\bar.txt
1048  */
1049 
1050  /* First, go through as many modifier characters as possible */
1051  FormatEnd = Format = *pFormat;
1052  while (*FormatEnd && _tcschr(ModifierTable, _totlower(*FormatEnd)))
1053  ++FormatEnd;
1054 
1055  if (*FormatEnd == _T('$'))
1056  {
1057  /* $PATH: syntax */
1058  PathVarName = FormatEnd + 1;
1059  FormatEnd = _tcschr(PathVarName, _T(':'));
1060  if (!FormatEnd)
1061  return NULL;
1062 
1063  /* Must be immediately followed by the variable */
1064  if (!GetVar(*++FormatEnd, &Variable, &VariableIsParam0))
1065  return NULL;
1066  }
1067  else
1068  {
1069  /* Backtrack if necessary to get a variable name match */
1070  while (!GetVar(*FormatEnd, &Variable, &VariableIsParam0))
1071  {
1072  if (FormatEnd == Format)
1073  return NULL;
1074  --FormatEnd;
1075  }
1076  }
1077 
1078  *pFormat = FormatEnd + 1;
1079 
1080  /* If the variable is empty, return an empty string */
1081  if (!Variable || !*Variable)
1082  return _T("");
1083 
1084  /* Exclude the leading and trailing quotes */
1085  VarEnd = &Variable[_tcslen(Variable)];
1086  if (*Variable == _T('"'))
1087  {
1088  ++Variable;
1089  if (VarEnd > Variable && VarEnd[-1] == _T('"'))
1090  --VarEnd;
1091  }
1092 
1093  if ((ULONG_PTR)VarEnd - (ULONG_PTR)Variable >= sizeof(Result))
1094  return _T("");
1095  memcpy(Result, Variable, (ULONG_PTR)VarEnd - (ULONG_PTR)Variable);
1096  Result[VarEnd - Variable] = _T('\0');
1097 
1098  /* Now determine the actual modifiers */
1099  for (; Format < FormatEnd && *Format != _T('$'); ++Format)
1100  Modifiers |= 1 << (_tcschr(ModifierTable, _totlower(*Format)) - ModifierTable);
1101 
1102  if (PathVarName)
1103  {
1104  /* $PATH: syntax - search the directories listed in the
1105  * specified environment variable for the file */
1106  PTSTR PathVar;
1107  ((PTSTR)FormatEnd)[-1] = _T('\0'); // FIXME: HACK!
1108  PathVar = GetEnvVar(PathVarName);
1109  ((PTSTR)FormatEnd)[-1] = _T(':');
1110  if (!PathVar ||
1111  !SearchPath(PathVar, Result, NULL, ARRAYSIZE(FullPath), FullPath, NULL))
1112  {
1113  return _T("");
1114  }
1115  }
1116  else if (Modifiers == 0)
1117  {
1118  /* For plain %~var with no modifiers, just return the variable without quotes */
1119  return Result;
1120  }
1121  else if (VariableIsParam0)
1122  {
1123  /* Special case: If the variable is %0 and modifier characters are present,
1124  * use the batch file's path (which includes the .bat/.cmd extension)
1125  * rather than the actual %0 variable (which might not). */
1126  ASSERT(bc);
1127  _tcscpy(FullPath, bc->BatchFilePath);
1128  }
1129  else
1130  {
1131  /* Convert the variable, now without quotes, to a full path */
1132  if (!GetFullPathName(Result, ARRAYSIZE(FullPath), FullPath, NULL))
1133  return _T("");
1134  }
1135 
1136  /* Next step is to change the path to fix letter case (e.g.
1137  * C:\ReAcToS -> C:\ReactOS) and, if requested with the S modifier,
1138  * replace long filenames with short. */
1139 
1140  In = FullPath;
1141  Out = FixedPath;
1142 
1143  /* Copy drive letter */
1144  *Out++ = *In++;
1145  *Out++ = *In++;
1146  *Out++ = *In++;
1147  /* Loop over each \-separated component in the path */
1148  do {
1149  TCHAR *Next = _tcschr(In, _T('\\'));
1150  if (Next)
1151  *Next++ = _T('\0');
1152  /* Use FindFirstFile to get the correct name */
1153  if (Out + _tcslen(In) + 1 >= &FixedPath[ARRAYSIZE(FixedPath)])
1154  return _T("");
1155  _tcscpy(Out, In);
1156  hFind = FindFirstFile(FixedPath, &w32fd);
1157  /* If it doesn't exist, just leave the name as it was given */
1158  if (hFind != INVALID_HANDLE_VALUE)
1159  {
1160  PTSTR FixedComponent = w32fd.cFileName;
1161  if (*w32fd.cAlternateFileName &&
1162  ((Modifiers & M_SHORT) || !_tcsicmp(In, w32fd.cAlternateFileName)))
1163  {
1164  FixedComponent = w32fd.cAlternateFileName;
1165  }
1166  FindClose(hFind);
1167 
1168  if (Out + _tcslen(FixedComponent) + 1 >= &FixedPath[ARRAYSIZE(FixedPath)])
1169  return _T("");
1170  _tcscpy(Out, FixedComponent);
1171  }
1172  Filename = Out;
1173  Out += _tcslen(Out);
1174  *Out++ = _T('\\');
1175 
1176  In = Next;
1177  } while (In != NULL);
1178  Out[-1] = _T('\0');
1179 
1180  /* Build the result string. Start with attributes, modification time, and
1181  * file size. If the file didn't exist, these fields will all be empty. */
1182  Out = Result;
1183  if (hFind != INVALID_HANDLE_VALUE)
1184  {
1185  if (Modifiers & M_ATTR)
1186  {
1187  static const struct {
1188  TCHAR Character;
1189  WORD Value;
1190  } *Attrib, Table[] = {
1191  { _T('d'), FILE_ATTRIBUTE_DIRECTORY },
1192  { _T('r'), FILE_ATTRIBUTE_READONLY },
1193  { _T('a'), FILE_ATTRIBUTE_ARCHIVE },
1194  { _T('h'), FILE_ATTRIBUTE_HIDDEN },
1195  { _T('s'), FILE_ATTRIBUTE_SYSTEM },
1196  { _T('c'), FILE_ATTRIBUTE_COMPRESSED },
1197  { _T('o'), FILE_ATTRIBUTE_OFFLINE },
1198  { _T('t'), FILE_ATTRIBUTE_TEMPORARY },
1199  { _T('l'), FILE_ATTRIBUTE_REPARSE_POINT },
1200 #if (NTDDI_VERSION >= NTDDI_WIN8)
1202  { _T('x'), FILE_ATTRIBUTE_NO_SCRUB_DATA /* 0x20000 */ },
1203 #endif
1204  };
1205  for (Attrib = Table; Attrib != &Table[ARRAYSIZE(Table)]; Attrib++)
1206  {
1207  *Out++ = w32fd.dwFileAttributes & Attrib->Value
1208  ? Attrib->Character
1209  : _T('-');
1210  }
1211  *Out++ = _T(' ');
1212  }
1213  if (Modifiers & M_TIME)
1214  {
1215  FILETIME ft;
1216  SYSTEMTIME st;
1217  FileTimeToLocalFileTime(&w32fd.ftLastWriteTime, &ft);
1218  FileTimeToSystemTime(&ft, &st);
1219 
1220  Out += FormatDate(Out, &st, TRUE);
1221  *Out++ = _T(' ');
1222  Out += FormatTime(Out, &st);
1223  *Out++ = _T(' ');
1224  }
1225  if (Modifiers & M_SIZE)
1226  {
1228  Size.LowPart = w32fd.nFileSizeLow;
1229  Size.HighPart = w32fd.nFileSizeHigh;
1230  Out += _stprintf(Out, _T("%I64u "), Size.QuadPart);
1231  }
1232  }
1233 
1234  /* When using the path-searching syntax or the S modifier,
1235  * at least part of the file path is always included.
1236  * If none of the DPNX modifiers are present, include the full path */
1237  if (PathVarName || (Modifiers & M_SHORT))
1238  if ((Modifiers & (M_DRIVE | M_PATH | M_NAME | M_EXT)) == 0)
1239  Modifiers |= M_FULL;
1240 
1241  /* Now add the requested parts of the name.
1242  * With the F modifier, add all parts to form the full path. */
1243  Extension = _tcsrchr(Filename, _T('.'));
1244  if (Modifiers & (M_DRIVE | M_FULL))
1245  {
1246  *Out++ = FixedPath[0];
1247  *Out++ = FixedPath[1];
1248  }
1249  if (Modifiers & (M_PATH | M_FULL))
1250  {
1251  memcpy(Out, &FixedPath[2], (ULONG_PTR)Filename - (ULONG_PTR)&FixedPath[2]);
1252  Out += Filename - &FixedPath[2];
1253  }
1254  if (Modifiers & (M_NAME | M_FULL))
1255  {
1256  while (*Filename && Filename != Extension)
1257  *Out++ = *Filename++;
1258  }
1259  if (Modifiers & (M_EXT | M_FULL))
1260  {
1261  if (Extension)
1262  Out = _stpcpy(Out, Extension);
1263  }
1264 
1265  /* Trim trailing space which otherwise would appear as a
1266  * result of using the A/T/Z modifiers but no others. */
1267  while (Out != &Result[0] && Out[-1] == _T(' '))
1268  Out--;
1269  *Out = _T('\0');
1270 
1271  return Result;
1272 }
1273 
1274 static PCTSTR
1276  IN PCTSTR varName,
1277  OUT PUINT varNameLen)
1278 {
1279  PCTSTR ret;
1280  PCTSTR varNameEnd;
1281 
1282  *varNameLen = 1;
1283 
1284  switch (*varName)
1285  {
1286  case _T('~'):
1287  {
1288  varNameEnd = varName + 1;
1289  ret = GetEnhancedVar(&varNameEnd, FindArg);
1290  if (!ret)
1291  {
1292  ParseErrorEx(varName);
1293  return NULL;
1294  }
1295  *varNameLen = varNameEnd - varName;
1296  return ret;
1297  }
1298 
1299  case _T('0'):
1300  case _T('1'):
1301  case _T('2'):
1302  case _T('3'):
1303  case _T('4'):
1304  case _T('5'):
1305  case _T('6'):
1306  case _T('7'):
1307  case _T('8'):
1308  case _T('9'):
1309  {
1310  BOOL dummy;
1311  if (!FindArg(*varName, &ret, &dummy))
1312  return NULL;
1313  else
1314  return ret;
1315  }
1316 
1317  case _T('*'):
1318  /* Copy over the raw params (not including the batch file name) */
1319  return bc->raw_params;
1320 
1321  case _T('%'):
1322  return _T("%");
1323  }
1324  return NULL;
1325 }
1326 
1327 BOOL
1329  IN PCTSTR Src,
1330  OUT size_t* SrcIncLen, // VarNameLen
1331  OUT PTCHAR Dest,
1332  IN PTCHAR DestEnd,
1333  OUT size_t* DestIncLen,
1334  IN TCHAR Delim)
1335 {
1336 #define APPEND(From, Length) \
1337 do { \
1338  if (Dest + (Length) > DestEnd) \
1339  goto too_long; \
1340  memcpy(Dest, (From), (Length) * sizeof(TCHAR)); \
1341  Dest += (Length); \
1342 } while (0)
1343 
1344 #define APPEND1(Char) \
1345 do { \
1346  if (Dest >= DestEnd) \
1347  goto too_long; \
1348  *Dest++ = (Char); \
1349 } while (0)
1350 
1351  PCTSTR Var;
1352  PCTSTR Start, End, SubstStart;
1353  TCHAR EndChr;
1354  size_t VarLength;
1355 
1356  Start = Src;
1357  End = Dest;
1358  *SrcIncLen = 0;
1359  *DestIncLen = 0;
1360 
1361  if (!Delim)
1362  return FALSE;
1363  if (*Src != Delim)
1364  return FALSE;
1365 
1366  ++Src;
1367 
1368  /* If we are already at the end of the string, fail the substitution */
1369  SubstStart = Src;
1370  if (!*Src || *Src == _T('\r') || *Src == _T('\n'))
1371  goto bad_subst;
1372 
1373  if (bc && Delim == _T('%'))
1374  {
1375  UINT NameLen;
1376  Var = GetBatchVar(Src, &NameLen);
1377  if (!Var && bParseError)
1378  {
1379  /* Return the partially-parsed command to be
1380  * echoed for error diagnostics purposes. */
1381  APPEND1(Delim);
1382  APPEND(Src, _tcslen(Src) + 1);
1383  return FALSE;
1384  }
1385  if (Var != NULL)
1386  {
1387  VarLength = _tcslen(Var);
1388  APPEND(Var, VarLength);
1389  Src += NameLen;
1390  goto success;
1391  }
1392  }
1393 
1394  /* Find the end of the variable name. A colon (:) will usually
1395  * end the name and begin the optional modifier, but not if it
1396  * is immediately followed by the delimiter (%VAR:%). */
1397  SubstStart = Src;
1398  while (*Src && *Src != Delim && !(*Src == _T(':') && Src[1] != Delim))
1399  {
1400  ++Src;
1401  }
1402  /* If we are either at the end of the string, or the delimiter
1403  * has been repeated more than once, fail the substitution. */
1404  if (!*Src || Src == SubstStart)
1405  goto bad_subst;
1406 
1407  EndChr = *Src;
1408  *(PTSTR)Src = _T('\0'); // FIXME: HACK!
1409  Var = GetEnvVarOrSpecial(SubstStart);
1410  *(PTSTR)Src++ = EndChr;
1411  if (Var == NULL)
1412  {
1413  /* In a batch context, %NONEXISTENT% "expands" to an
1414  * empty string, otherwise fail the substitution. */
1415  if (bc)
1416  goto success;
1417  goto bad_subst;
1418  }
1419  VarLength = _tcslen(Var);
1420 
1421  if (EndChr == Delim)
1422  {
1423  /* %VAR% - use as-is */
1424  APPEND(Var, VarLength);
1425  }
1426  else if (*Src == _T('~'))
1427  {
1428  /* %VAR:~[start][,length]% - Substring.
1429  * Negative values are offsets from the end.
1430  */
1431  SSIZE_T Start = _tcstol(Src + 1, (PTSTR*)&Src, 0);
1432  SSIZE_T End = (SSIZE_T)VarLength;
1433  if (Start < 0)
1434  Start += VarLength;
1435  Start = min(max(Start, 0), VarLength);
1436  if (*Src == _T(','))
1437  {
1438  End = _tcstol(Src + 1, (PTSTR*)&Src, 0);
1439  End += (End < 0) ? VarLength : Start;
1440  End = min(max(End, Start), VarLength);
1441  }
1442  if (*Src++ != Delim)
1443  goto bad_subst;
1444  APPEND(&Var[Start], End - Start);
1445  }
1446  else
1447  {
1448  /* %VAR:old=new% - Replace all occurrences of old with new.
1449  * %VAR:*old=new% - Replace first occurrence only,
1450  * and remove everything before it.
1451  */
1452  PCTSTR Old, New;
1453  size_t OldLength, NewLength;
1454  BOOL Star = FALSE;
1455  size_t LastMatch = 0, i = 0;
1456 
1457  if (*Src == _T('*'))
1458  {
1459  Star = TRUE;
1460  Src++;
1461  }
1462 
1463  /* The string to replace may contain the delimiter */
1464  Src = _tcschr(Old = Src, _T('='));
1465  if (Src == NULL)
1466  goto bad_subst;
1467  OldLength = Src++ - Old;
1468  if (OldLength == 0)
1469  goto bad_subst;
1470 
1471  Src = _tcschr(New = Src, Delim);
1472  if (Src == NULL)
1473  goto bad_subst;
1474  NewLength = Src++ - New;
1475 
1476  while (i < VarLength)
1477  {
1478  if (_tcsnicmp(&Var[i], Old, OldLength) == 0)
1479  {
1480  if (!Star)
1481  APPEND(&Var[LastMatch], i - LastMatch);
1482  APPEND(New, NewLength);
1483  i += OldLength;
1484  LastMatch = i;
1485  if (Star)
1486  break;
1487  continue;
1488  }
1489  i++;
1490  }
1491  APPEND(&Var[LastMatch], VarLength - LastMatch);
1492  }
1493 
1494 success:
1495  *SrcIncLen = (Src - Start);
1496  *DestIncLen = (Dest - End);
1497  return TRUE;
1498 
1499 bad_subst:
1500  Src = SubstStart;
1501  /* Only if no batch context active do we echo the delimiter */
1502  if (!bc)
1503  APPEND1(Delim);
1504  goto success;
1505 
1506 too_long:
1508  nErrorLevel = 9023;
1509  return FALSE;
1510 
1511 #undef APPEND
1512 #undef APPEND1
1513 }
1514 
1515 BOOL
1517  IN PCTSTR Src,
1518  OUT PTSTR Dest,
1519  IN TCHAR Delim)
1520 {
1521 #define APPEND(From, Length) \
1522 do { \
1523  if (Dest + (Length) > DestEnd) \
1524  goto too_long; \
1525  memcpy(Dest, (From), (Length) * sizeof(TCHAR)); \
1526  Dest += (Length); \
1527 } while (0)
1528 
1529 #define APPEND1(Char) \
1530 do { \
1531  if (Dest >= DestEnd) \
1532  goto too_long; \
1533  *Dest++ = (Char); \
1534 } while (0)
1535 
1536  PTCHAR DestEnd = Dest + CMDLINE_LENGTH - 1;
1537  PCTSTR End;
1538  size_t SrcIncLen, DestIncLen;
1539 
1540  while (*Src /* && (Dest < DestEnd) */)
1541  {
1542  if (*Src != Delim)
1543  {
1544  End = _tcschr(Src, Delim);
1545  if (End == NULL)
1546  End = Src + _tcslen(Src);
1547  APPEND(Src, End - Src);
1548  Src = End;
1549  continue;
1550  }
1551 
1552  if (!SubstituteVar(Src, &SrcIncLen, Dest, DestEnd, &DestIncLen, Delim))
1553  {
1554  return FALSE;
1555  }
1556  else
1557  {
1558  Src += SrcIncLen;
1559  Dest += DestIncLen;
1560  }
1561  }
1562  APPEND1(_T('\0'));
1563  return TRUE;
1564 
1565 too_long:
1567  nErrorLevel = 9023;
1568  return FALSE;
1569 
1570 #undef APPEND
1571 #undef APPEND1
1572 }
1573 
1574 /* Search the list of FOR contexts for a variable */
1575 static BOOL
1577  IN TCHAR Var,
1578  OUT PCTSTR* VarPtr,
1579  OUT BOOL* IsParam0)
1580 {
1581  PFOR_CONTEXT Ctx;
1582 
1583  *VarPtr = NULL;
1584  *IsParam0 = FALSE;
1585 
1586  for (Ctx = fc; Ctx != NULL; Ctx = Ctx->prev)
1587  {
1588  if ((UINT)(Var - Ctx->firstvar) < Ctx->varcount)
1589  {
1590  *VarPtr = Ctx->values[Var - Ctx->firstvar];
1591  return TRUE;
1592  }
1593  }
1594  return FALSE;
1595 }
1596 
1597 BOOL
1599  IN PCTSTR Src,
1600  OUT PTSTR Dest)
1601 {
1602  PTCHAR DestEnd = &Dest[CMDLINE_LENGTH - 1];
1603  while (*Src)
1604  {
1605  if (Src[0] == _T('%'))
1606  {
1607  BOOL Dummy;
1608  PCTSTR End = &Src[2];
1609  PCTSTR Value = NULL;
1610 
1611  if (Src[1] == _T('~'))
1612  Value = GetEnhancedVar(&End, FindForVar);
1613 
1614  if (!Value && Src[1])
1615  {
1616  if (FindForVar(Src[1], &Value, &Dummy) && !Value)
1617  {
1618  /* The variable is empty, return an empty string */
1619  Value = _T("");
1620  }
1621  }
1622 
1623  if (Value)
1624  {
1625  if (Dest + _tcslen(Value) > DestEnd)
1626  return FALSE;
1627  Dest = _stpcpy(Dest, Value);
1628  Src = End;
1629  continue;
1630  }
1631  }
1632  /* Not a variable; just copy the character */
1633  if (Dest >= DestEnd)
1634  return FALSE;
1635  *Dest++ = *Src++;
1636  }
1637  *Dest = _T('\0');
1638  return TRUE;
1639 }
1640 
1641 PTSTR
1643  IN PCTSTR Line)
1644 {
1645  TCHAR Buf1[CMDLINE_LENGTH];
1646  TCHAR Buf2[CMDLINE_LENGTH];
1647  PTCHAR Src, Dst;
1648  PTCHAR DestEnd = Buf2 + CMDLINE_LENGTH - 1;
1649  size_t SrcIncLen, DestIncLen;
1650 
1651  /* First, substitute FOR variables */
1652  if (!SubstituteForVars(Line, Buf1))
1653  return NULL;
1654 
1655  if (!bDelayedExpansion || !_tcschr(Buf1, _T('!')))
1656  return cmd_dup(Buf1);
1657 
1658  /*
1659  * Delayed substitutions are not actually completely the same as
1660  * immediate substitutions. In particular, it is possible to escape
1661  * the exclamation point using the escape caret.
1662  */
1663 
1664  /*
1665  * Perform delayed expansion: expand variables around '!',
1666  * and reparse escape carets.
1667  */
1668 
1669 #define APPEND1(Char) \
1670 do { \
1671  if (Dst >= DestEnd) \
1672  goto too_long; \
1673  *Dst++ = (Char); \
1674 } while (0)
1675 
1676  Src = Buf1;
1677  Dst = Buf2;
1678  while (*Src && (Src < &Buf1[CMDLINE_LENGTH]))
1679  {
1680  if (*Src == _T('^'))
1681  {
1682  ++Src;
1683  if (!*Src || !(Src < &Buf1[CMDLINE_LENGTH]))
1684  break;
1685 
1686  APPEND1(*Src++);
1687  }
1688  else if (*Src == _T('!'))
1689  {
1690  if (!SubstituteVar(Src, &SrcIncLen, Dst, DestEnd, &DestIncLen, _T('!')))
1691  {
1692  return NULL; // Got an error during parsing.
1693  }
1694  else
1695  {
1696  Src += SrcIncLen;
1697  Dst += DestIncLen;
1698  }
1699  }
1700  else
1701  {
1702  APPEND1(*Src++);
1703  }
1704  continue;
1705  }
1706  APPEND1(_T('\0'));
1707 
1708  return cmd_dup(Buf2);
1709 
1710 too_long:
1712  nErrorLevel = 9023;
1713  return NULL;
1714 
1715 #undef APPEND1
1716 }
1717 
1718 
1719 /*
1720  * Do the prompt/input/process loop.
1721  */
1722 BOOL
1723 ReadLine(TCHAR *commandline, BOOL bMore)
1724 {
1726  LPTSTR ip;
1727 
1728  /* if no batch input then... */
1729  if (bc == NULL)
1730  {
1731  if (bMore)
1732  {
1734  }
1735  else
1736  {
1737  /* JPP 19980807 - if echo off, don't print prompt */
1738  if (bEcho)
1739  {
1740  if (!bIgnoreEcho)
1741  ConOutChar(_T('\n'));
1742  PrintPrompt();
1743  }
1744  }
1745 
1746  if (!ReadCommand(readline, CMDLINE_LENGTH - 1))
1747  {
1748  bExit = TRUE;
1749  return FALSE;
1750  }
1751 
1752  if (readline[0] == _T('\0'))
1753  ConOutChar(_T('\n'));
1754 
1756  return FALSE;
1757 
1758  if (readline[0] == _T('\0'))
1759  return FALSE;
1760 
1761  ip = readline;
1762  }
1763  else
1764  {
1765  ip = ReadBatchLine();
1766  if (!ip)
1767  return FALSE;
1768  }
1769 
1770  return SubstituteVars(ip, commandline, _T('%'));
1771 }
1772 
1773 static INT
1775 {
1776  INT Ret = 0;
1778 
1779  while (!bCanExit || !bExit)
1780  {
1781  /* Reset the Ctrl-Break / Ctrl-C state */
1782  bCtrlBreak = FALSE;
1783 
1784  Cmd = ParseCommand(NULL);
1785  if (!Cmd)
1786  continue;
1787 
1788  Ret = ExecuteCommand(Cmd);
1789  FreeCommand(Cmd);
1790  }
1791 
1792  return Ret;
1793 }
1794 
1795 
1796 /*
1797  * Control-break handler.
1798  */
1799 static BOOL
1800 WINAPI
1801 BreakHandler(IN DWORD dwCtrlType)
1802 {
1803  DWORD dwWritten;
1804  INPUT_RECORD rec;
1805 
1806  if ((dwCtrlType != CTRL_C_EVENT) &&
1807  (dwCtrlType != CTRL_BREAK_EVENT))
1808  {
1809  return FALSE;
1810  }
1811 
1813  {
1814  /* Child process is running and will have received the control event */
1815  return TRUE;
1816  }
1817  else
1818  {
1820  }
1821 
1822  bCtrlBreak = TRUE;
1823 
1824  rec.EventType = KEY_EVENT;
1825  rec.Event.KeyEvent.bKeyDown = TRUE;
1826  rec.Event.KeyEvent.wRepeatCount = 1;
1827  rec.Event.KeyEvent.wVirtualKeyCode = _T('C');
1828  rec.Event.KeyEvent.wVirtualScanCode = _T('C') - 35;
1829  rec.Event.KeyEvent.uChar.AsciiChar = _T('C');
1830  rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
1832 
1834  &rec,
1835  1,
1836  &dwWritten);
1837 
1838  /* FIXME: Handle batch files */
1839 
1840  // ConOutPrintf(_T("^C"));
1841 
1842  return TRUE;
1843 }
1844 
1845 
1847 {
1849 }
1850 
1851 
1853 {
1855 }
1856 
1857 
1858 /*
1859  * Show commands and options that are available.
1860  */
1861 #if 0
1862 static VOID
1863 ShowCommands(VOID)
1864 {
1865  /* print command list */
1867  PrintCommandList();
1868 
1869  /* print feature list */
1871 
1872 #ifdef FEATURE_ALIASES
1874 #endif
1875 #ifdef FEATURE_HISTORY
1877 #endif
1878 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
1880 #endif
1881 #ifdef FEATURE_DIRECTORY_STACK
1883 #endif
1884 #ifdef FEATURE_REDIRECTION
1886 #endif
1887  ConOutChar(_T('\n'));
1888 }
1889 #endif
1890 
1891 
1892 static VOID
1894 {
1895  LONG lRet;
1896  HKEY hKey;
1897  DWORD dwType, len;
1898  /*
1899  * Buffer big enough to hold the string L"4294967295",
1900  * corresponding to the literal 0xFFFFFFFF (MAXULONG) in decimal.
1901  */
1902  DWORD Buffer[6];
1903 
1904  lRet = RegOpenKeyEx(hKeyRoot,
1905  _T("Software\\Microsoft\\Command Processor"),
1906  0,
1908  &hKey);
1909  if (lRet != ERROR_SUCCESS)
1910  return;
1911 
1912 #ifdef INCLUDE_CMD_COLOR
1913  len = sizeof(Buffer);
1914  lRet = RegQueryValueEx(hKey,
1915  _T("DefaultColor"),
1916  NULL,
1917  &dwType,
1918  (LPBYTE)&Buffer,
1919  &len);
1920  if (lRet == ERROR_SUCCESS)
1921  {
1922  /* Overwrite the default attributes */
1923  if (dwType == REG_DWORD)
1924  wDefColor = (WORD)*(PDWORD)Buffer;
1925  else if (dwType == REG_SZ)
1927  }
1928  // else, use the default attributes retrieved before.
1929 #endif
1930 
1931 #if 0
1932  len = sizeof(Buffer);
1933  lRet = RegQueryValueEx(hKey,
1934  _T("DisableUNCCheck"),
1935  NULL,
1936  &dwType,
1937  (LPBYTE)&Buffer,
1938  &len);
1939  if (lRet == ERROR_SUCCESS)
1940  {
1941  /* Overwrite the default setting */
1942  if (dwType == REG_DWORD)
1943  bDisableUNCCheck = !!*(PDWORD)Buffer;
1944  else if (dwType == REG_SZ)
1945  bDisableUNCCheck = (_ttol((PTSTR)Buffer) == 1);
1946  }
1947  // else, use the default setting set globally.
1948 #endif
1949 
1950  len = sizeof(Buffer);
1951  lRet = RegQueryValueEx(hKey,
1952  _T("DelayedExpansion"),
1953  NULL,
1954  &dwType,
1955  (LPBYTE)&Buffer,
1956  &len);
1957  if (lRet == ERROR_SUCCESS)
1958  {
1959  /* Overwrite the default setting */
1960  if (dwType == REG_DWORD)
1962  else if (dwType == REG_SZ)
1963  bDelayedExpansion = (_ttol((PTSTR)Buffer) == 1);
1964  }
1965  // else, use the default setting set globally.
1966 
1967  len = sizeof(Buffer);
1968  lRet = RegQueryValueEx(hKey,
1969  _T("EnableExtensions"),
1970  NULL,
1971  &dwType,
1972  (LPBYTE)&Buffer,
1973  &len);
1974  if (lRet == ERROR_SUCCESS)
1975  {
1976  /* Overwrite the default setting */
1977  if (dwType == REG_DWORD)
1979  else if (dwType == REG_SZ)
1980  bEnableExtensions = (_ttol((PTSTR)Buffer) == 1);
1981  }
1982  // else, use the default setting set globally.
1983 
1984  len = sizeof(Buffer);
1985  lRet = RegQueryValueEx(hKey,
1986  _T("CompletionChar"),
1987  NULL,
1988  &dwType,
1989  (LPBYTE)&Buffer,
1990  &len);
1991  if (lRet == ERROR_SUCCESS)
1992  {
1993  /* Overwrite the default setting */
1994  if (dwType == REG_DWORD)
1996  else if (dwType == REG_SZ)
1998  }
1999  // else, use the default setting set globally.
2000 
2001  /* Validity check */
2003  {
2004  /* Disable autocompletion */
2005  AutoCompletionChar = 0x20;
2006  }
2007 
2008  len = sizeof(Buffer);
2009  lRet = RegQueryValueEx(hKey,
2010  _T("PathCompletionChar"),
2011  NULL,
2012  &dwType,
2013  (LPBYTE)&Buffer,
2014  &len);
2015  if (lRet == ERROR_SUCCESS)
2016  {
2017  /* Overwrite the default setting */
2018  if (dwType == REG_DWORD)
2020  else if (dwType == REG_SZ)
2022  }
2023  // else, use the default setting set globally.
2024 
2025  /* Validity check */
2027  {
2028  /* Disable autocompletion */
2029  PathCompletionChar = 0x20;
2030  }
2031 
2032  /* Adjust completion chars */
2033  if (PathCompletionChar >= 0x20 && AutoCompletionChar < 0x20)
2035  else if (AutoCompletionChar >= 0x20 && PathCompletionChar < 0x20)
2037 
2038  RegCloseKey(hKey);
2039 }
2040 
2041 static VOID
2043 {
2044  LONG lRet;
2045  HKEY hKey;
2046  DWORD dwType, len;
2047  TCHAR AutoRun[2048];
2048 
2049  lRet = RegOpenKeyEx(hKeyRoot,
2050  _T("Software\\Microsoft\\Command Processor"),
2051  0,
2053  &hKey);
2054  if (lRet != ERROR_SUCCESS)
2055  return;
2056 
2057  len = sizeof(AutoRun);
2058  lRet = RegQueryValueEx(hKey,
2059  _T("AutoRun"),
2060  NULL,
2061  &dwType,
2062  (LPBYTE)&AutoRun,
2063  &len);
2064  if ((lRet == ERROR_SUCCESS) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ))
2065  {
2066  if (*AutoRun)
2067  ParseCommandLine(AutoRun);
2068  }
2069 
2070  RegCloseKey(hKey);
2071 }
2072 
2073 /* Get the command that comes after a /C or /K switch */
2074 static VOID
2076  OUT LPTSTR commandline,
2077  IN LPCTSTR ptr,
2078  IN BOOL AlwaysStrip)
2079 {
2080  TCHAR* LastQuote;
2081 
2082  while (_istspace(*ptr))
2083  ++ptr;
2084 
2085  /* Remove leading quote, find final quote */
2086  if (*ptr == _T('"') &&
2087  (LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
2088  {
2089  const TCHAR* Space;
2090  /* Under certain circumstances, all quotes are preserved.
2091  * CMD /? documents these conditions as follows:
2092  * 1. No /S switch
2093  * 2. Exactly two quotes
2094  * 3. No "special characters" between the quotes
2095  * (CMD /? says &<>()@^| but parentheses did not
2096  * trigger this rule when I tested them.)
2097  * 4. Whitespace exists between the quotes
2098  * 5. Enclosed string is an executable filename
2099  */
2100  *LastQuote = _T('\0');
2101  for (Space = ptr + 1; Space < LastQuote; ++Space)
2102  {
2103  if (_istspace(*Space)) /* Rule 4 */
2104  {
2105  if (!AlwaysStrip && /* Rule 1 */
2106  !_tcspbrk(ptr, _T("\"&<>@^|")) && /* Rules 2, 3 */
2107  SearchForExecutable(ptr, commandline)) /* Rule 5 */
2108  {
2109  /* All conditions met: preserve both the quotes */
2110  *LastQuote = _T('"');
2111  _tcscpy(commandline, ptr - 1);
2112  return;
2113  }
2114  break;
2115  }
2116  }
2117 
2118  /* The conditions were not met: remove both the
2119  * leading quote and the last quote */
2120  _tcscpy(commandline, ptr);
2121  _tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
2122  return;
2123  }
2124 
2125  /* No quotes; just copy */
2126  _tcscpy(commandline, ptr);
2127 }
2128 
2129 
2130 /*
2131  * Set up global initializations and process parameters.
2132  * Return a pointer to the command line if present.
2133  */
2134 static LPCTSTR
2136 {
2137  HMODULE NtDllModule;
2138  HANDLE hIn, hOut;
2139  LPTSTR ptr, cmdLine;
2140  TCHAR option = 0;
2141  BOOL AutoRun = TRUE;
2142  TCHAR ModuleName[MAX_PATH + 1];
2143 
2144  /* Get version information */
2145  InitOSVersion();
2146 
2147  /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
2148  * build process. So don't link implicitly against ntdll.dll, load it
2149  * dynamically instead */
2150  NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
2151  if (NtDllModule != NULL)
2152  {
2153  NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)GetProcAddress(NtDllModule, "NtQueryInformationProcess");
2154  NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
2155  }
2156 
2157  /* Load the registry settings */
2160 
2161  /* Initialize our locale */
2162  InitLocale();
2163 
2164  /* Initialize prompt support */
2165  InitPrompt();
2166 
2167 #ifdef FEATURE_DIRECTORY_STACK
2168  /* Initialize directory stack */
2170 #endif
2171 
2172 #ifdef FEATURE_HISTORY
2173  /* Initialize history */
2174  InitHistory();
2175 #endif
2176 
2177  /* Set COMSPEC environment variable */
2179  {
2180  ModuleName[MAX_PATH] = _T('\0');
2181  SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
2182  }
2183 
2184  /* Add ctrl break handler */
2185  AddBreakHandler();
2186 
2187  /* Set the default console mode */
2188  hOut = ConStreamGetOSHandle(StdOut);
2189  hIn = ConStreamGetOSHandle(StdIn);
2190  SetConsoleMode(hOut, 0); // Reinitialize the console output mode
2193 
2194  cmdLine = GetCommandLine();
2195  TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
2196 
2197  for (ptr = cmdLine; *ptr; ++ptr)
2198  {
2199  if (*ptr == _T('/'))
2200  {
2201  option = _totupper(ptr[1]);
2202  if (option == _T('?'))
2203  {
2205  nErrorLevel = 1;
2206  bExit = TRUE;
2207  return NULL;
2208  }
2209  else if (option == _T('P'))
2210  {
2211  if (!IsExistingFile(_T("\\autoexec.bat")))
2212  {
2213 #ifdef INCLUDE_CMD_DATE
2214  cmd_date(_T(""));
2215 #endif
2216 #ifdef INCLUDE_CMD_TIME
2217  cmd_time(_T(""));
2218 #endif
2219  }
2220  else
2221  {
2222  ParseCommandLine(_T("\\autoexec.bat"));
2223  }
2224  bCanExit = FALSE;
2225  }
2226  else if (option == _T('A'))
2227  {
2229  }
2230  else if (option == _T('C') || option == _T('K') || option == _T('R'))
2231  {
2232  /* Remainder of command line is a command to be run */
2233  fSingleCommand = ((option == _T('K')) << 1) | 1;
2234  break;
2235  }
2236  else if (option == _T('D'))
2237  {
2238  AutoRun = FALSE;
2239  }
2240  else if (option == _T('Q'))
2241  {
2243  }
2244  else if (option == _T('S'))
2245  {
2246  bAlwaysStrip = TRUE;
2247  }
2248 #ifdef INCLUDE_CMD_COLOR
2249  else if (!_tcsnicmp(ptr, _T("/T:"), 3))
2250  {
2251  /* Process /T (color) argument; overwrite any previous settings */
2252  wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
2253  }
2254 #endif
2255  else if (option == _T('U'))
2256  {
2258  }
2259  else if (option == _T('V'))
2260  {
2261  // FIXME: Check validity of the parameter given to V !
2262  bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
2263  }
2264  else if (option == _T('E'))
2265  {
2266  // FIXME: Check validity of the parameter given to E !
2267  bEnableExtensions = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
2268  }
2269  else if (option == _T('X'))
2270  {
2271  /* '/X' is identical to '/E:ON' */
2273  }
2274  else if (option == _T('Y'))
2275  {
2276  /* '/Y' is identical to '/E:OFF' */
2278  }
2279  }
2280  }
2281 
2282 #ifdef INCLUDE_CMD_COLOR
2283  if (wDefColor == 0)
2284  {
2285  /*
2286  * If we still do not have the console colour attribute set,
2287  * retrieve the default one.
2288  */
2290  }
2291 
2292  if (wDefColor != 0)
2294 #endif
2295 
2296  /* Reset the output Standard Streams translation modes and code page caches */
2297  // ConStreamSetMode(StdIn , OutputStreamMode, InputCodePage );
2300 
2301  if (!*ptr)
2302  {
2303  /* If neither /C or /K was given, display a simple version string */
2304  ConOutChar(_T('\n'));
2306  _T(KERNEL_VERSION_STR),
2307  _T(KERNEL_VERSION_BUILD_STR));
2308  ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team.\n"));
2309  }
2310 
2311  if (AutoRun)
2312  {
2315  }
2316 
2317  /* Returns the rest of the command line */
2318  return ptr;
2319 }
2320 
2321 
2323 {
2324  /* Run cmdexit.bat */
2325  if (IsExistingFile(_T("cmdexit.bat")))
2326  {
2328  ParseCommandLine(_T("cmdexit.bat"));
2329  }
2330  else if (IsExistingFile(_T("\\cmdexit.bat")))
2331  {
2333  ParseCommandLine(_T("\\cmdexit.bat"));
2334  }
2335 
2336  /* Remove ctrl break handler */
2338 
2339  /* Restore the default console mode */
2344 
2345 
2346 #ifdef _DEBUG_MEM
2347 #ifdef FEATURE_DIRECTORY_STACK
2348  /* Destroy directory stack */
2350 #endif
2351 
2352 #ifdef FEATURE_HISTORY
2353  CleanHistory();
2354 #endif
2355 
2356  /* Free GetEnvVar's buffer */
2357  GetEnvVar(NULL);
2358 #endif /* _DEBUG_MEM */
2359 
2361 }
2362 
2363 /*
2364  * main function
2365  */
2366 int _tmain(int argc, const TCHAR *argv[])
2367 {
2368  INT nExitCode;
2369  LPCTSTR pCmdLine;
2370  TCHAR startPath[MAX_PATH];
2371 
2374 
2375  GetCurrentDirectory(ARRAYSIZE(startPath), startPath);
2376  _tchdir(startPath);
2377 
2378  SetFileApisToOEM();
2381 
2382  /* Initialize the Console Standard Streams */
2386  /* Reset the current thread UI language */
2389  {
2391  }
2392 
2394 
2395  /*
2396  * Perform general initialization, parse switches on command-line.
2397  * Initialize the exit code with the errorlevel as Initialize() can set it.
2398  */
2399  pCmdLine = Initialize();
2400  nExitCode = nErrorLevel;
2401 
2402  if (pCmdLine && *pCmdLine)
2403  {
2404  TCHAR commandline[CMDLINE_LENGTH];
2405 
2406  /* Do the /C or /K command */
2407  GetCmdLineCommand(commandline, &pCmdLine[2], bAlwaysStrip);
2408  nExitCode = ParseCommandLine(commandline);
2409  if (fSingleCommand == 1)
2410  {
2411  // nErrorLevel = nExitCode;
2412  bExit = TRUE;
2413  }
2414  fSingleCommand = 0;
2415  }
2416  if (!bExit)
2417  {
2418  /* Call prompt routine */
2419  nExitCode = ProcessInput();
2420  }
2421 
2422  /* Do the cleanup */
2423  Cleanup();
2425 
2426  cmd_exit(nExitCode);
2427  return nExitCode;
2428 }
2429 
2430 /* 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:782
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:598
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:2366
VOID InitHistory(VOID)
Definition: history.c:132
WORD wVirtualScanCode
Definition: wincon.h:243
LPSTR lpTitle
Definition: winbase.h:828
BOOL SubstituteVars(IN PCTSTR Src, OUT PTSTR Dest, IN TCHAR Delim)
Definition: cmd.c:1516
#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:488
#define LoadLibrary
Definition: winbase.h:3718
BOOL FindArg(IN TCHAR Char, OUT PCTSTR *ArgPtr, OUT BOOL *IsParam0)
Definition: batch.c:84
static VOID SetConTitle(LPCTSTR pszTitle)
Definition: cmd.c:309
#define _tcsicmp
Definition: xmlstorage.h:205
PTSTR DoDelayedExpansion(IN PCTSTR Line)
Definition: cmd.c:1642
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
Definition: ftp_var.h:139
static VOID ExecuteAutoRunFile(HKEY hKeyRoot)
Definition: cmd.c:2042
#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:401
#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:868
static VOID ErrorMessage(DWORD dwErrorCode, LPWSTR szFormat,...)
Definition: attrib.c:51
static VOID LoadRegistrySettings(HKEY hKeyRoot)
Definition: cmd.c:1893
#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:785
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:590
_TCHAR * _tcscpy(_TCHAR *to, const _TCHAR *from)
Definition: tcscpy.h:8
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
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:636
static VOID GetCmdLineCommand(OUT LPTSTR commandline, IN LPCTSTR ptr, IN BOOL AlwaysStrip)
Definition: cmd.c:2075
INT FormatDate(TCHAR *, LPSYSTEMTIME, BOOL)
Definition: dir.c:674
DWORD dwFlags
Definition: winbase.h:836
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:564
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
IN PVCB IN PBCB OUT PDIRENT IN USHORT IN POEM_STRING Filename
Definition: fatprocs.h:934
_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:859
#define _itot
Definition: tchar.h:608
#define SearchPath
Definition: winbase.h:3756
WORD wVirtualKeyCode
Definition: wincon.h:242
union _KEY_EVENT_RECORD::@3205 uChar
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
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:683
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
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:904
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:3661
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2453
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
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:775
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:3655
void * PVOID
Definition: retypes.h:9
#define FindFirstFile
Definition: winbase.h:3638
#define STARTF_USESHOWWINDOW
Definition: winbase.h:488
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:557
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
LPTSTR DuplicateEnvironment(VOID)
Definition: setlocal.c:25
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
static BOOL FindForVar(IN TCHAR Var, OUT PCTSTR *VarPtr, OUT BOOL *IsParam0)
Definition: cmd.c:1576
#define APPEND(From, Length)
Status
Definition: gdiplustypes.h:24
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:607
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:1598
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:825
#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
#define ASSERT(a)
Definition: mode.c:44
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:275
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
static INT ProcessInput(VOID)
Definition: cmd.c:1774
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:3687
#define IsConsoleHandle(h)
Definition: console.h:14
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:1801
#define STRING_CMD_HELP5
Definition: resource.h:79
BOOL ReadLine(TCHAR *commandline, BOOL bMore)
Definition: cmd.c:1723
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
#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:659
LANGID ConSetThreadUILanguage(IN LANGID LangId OPTIONAL)
Definition: utils.c:352
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define GetFullPathName
Definition: winbase.h:3677
VOID UndoRedirection(REDIRECTION *, REDIRECTION *End)
Definition: redir.c:142
#define SetEnvironmentVariable
Definition: winbase.h:3764
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:1275
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
UINT varcount
Definition: batch.h:49
#define CreateProcess
Definition: winbase.h:3614
BOOL ConSetTitle(IN LPCTSTR lpConsoleTitle)
Definition: console.c:280
VOID AddBreakHandler(VOID)
Definition: cmd.c:1846
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:2135
#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:828
static VOID Cleanup(VOID)
Definition: cmd.c:2322
#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:3683
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
Definition: cmd.h:357
VOID error_bad_command(PCTSTR s)
Definition: error.c:124
STARTUPINFOA STARTUPINFO
Definition: winbase.h:3575
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
FxAutoRegKey hKey
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:886
BOOL bDelayedExpansion
Definition: cmd.c:162
#define cmd_dup(str)
Definition: cmddbg.h:32
union _INPUT_RECORD::@3206 Event
#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
#define NULL
Definition: types.h:112
WORD wShowWindow
Definition: winbase.h:837
BOOL PerformRedirection(REDIRECTION *)
Definition: redir.c:63
DWORD * PDWORD
Definition: pedump.c:68
static INT ExecutePipeline(PARSED_COMMAND *Cmd)
Definition: cmd.c:693
HANDLE CMD_ModuleHandle
Definition: cmd.c:165
BOOL bExit
Definition: cmd.c:152
#define ConStdStreamsSetCacheCodePage(InputCodePage, OutputCodePage)
Definition: stream.h:152
#define STRING_FREE_ERROR1
Definition: resource.h:49
WORD EventType
Definition: wincon.h:273
#define ConOutResPuts(uID)
Definition: console.h:36
#define StdOut
Definition: fc.c:14
_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 _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:3670
PBATCH_CONTEXT bc
Definition: batch.c:67
static BOOL fSingleCommand
Definition: cmd.c:156
#define GetProcAddress(x, y)
Definition: compat.h:612
#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
#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:1328
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
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:3759
#define STRING_CMD_HELP6
Definition: resource.h:80
char * PTCHAR
Definition: ntbasedef.h:476
BOOL bParseError
Definition: parser.c:90
static PCTSTR GetEnhancedVar(IN OUT PCTSTR *pFormat, IN BOOL(*GetVar)(TCHAR, PCTSTR *, BOOL *))
Definition: cmd.c:975
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:1852
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 StdErr
Definition: fc.c:15
#define REG_SZ
Definition: layer.c:22
BOOL bCtrlBreak
Definition: cmd.c:154
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502