ReactOS  0.4.13-dev-482-ge57f103
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 */
157 INT nErrorLevel = 0; /* Errorlevel of last launched external program */
165 
166 BOOL bTitleSet = FALSE; /* Indicates whether the console title has been changed and needs to be restored later */
168 
171 
172 /*
173  * Default output file stream translation mode is UTF8, but CMD switches
174  * allow to change it to either UTF16 (/U) or ANSI (/A).
175  */
177 
178 #ifdef INCLUDE_CMD_COLOR
179 WORD wDefColor = 0; /* Default color */
180 #endif
181 
182 /*
183  * convert
184  *
185  * insert commas into a number
186  */
187 INT
189 {
190  TCHAR temp[39]; /* maximum length with nNumberGroups == 1 */
191  UINT n, iTarget;
192 
193  if (len <= 1)
194  return 0;
195 
196  n = 0;
197  iTarget = nNumberGroups;
198  if (!nNumberGroups)
199  bPutSeparator = FALSE;
200 
201  do
202  {
203  if (iTarget == n && bPutSeparator)
204  {
205  iTarget += nNumberGroups + 1;
206  temp[38 - n++] = cThousandSeparator;
207  }
208  temp[38 - n++] = (TCHAR)(num % 10) + _T('0');
209  num /= 10;
210  } while (num > 0);
211  if (n > len-1)
212  n = len-1;
213 
214  memcpy(des, temp + 39 - n, n * sizeof(TCHAR));
215  des[n] = _T('\0');
216 
217  return n;
218 }
219 
220 /*
221  * Is a process a console process?
222  */
224 {
227  PEB ProcessPeb;
229 
231  {
232  return TRUE;
233  }
234 
237  &Info, sizeof(PROCESS_BASIC_INFORMATION), NULL);
238  if (! NT_SUCCESS(Status))
239  {
240  WARN ("NtQueryInformationProcess failed with status %08x\n", Status);
241  return TRUE;
242  }
244  Process, Info.PebBaseAddress, &ProcessPeb,
245  sizeof(PEB), &BytesRead);
246  if (! NT_SUCCESS(Status) || sizeof(PEB) != BytesRead)
247  {
248  WARN ("Couldn't read virt mem status %08x bytes read %lu\n", Status, BytesRead);
249  return TRUE;
250  }
251 
252  return IMAGE_SUBSYSTEM_WINDOWS_CUI == ProcessPeb.ImageSubsystem;
253 }
254 
255 
256 
257 #ifdef _UNICODE
258 #define SHELLEXECUTETEXT "ShellExecuteExW"
259 #else
260 #define SHELLEXECUTETEXT "ShellExecuteExA"
261 #endif
262 
263 typedef BOOL (WINAPI *MYEX)(LPSHELLEXECUTEINFO lpExecInfo);
264 
266  LPTSTR directory, INT show)
267 {
268  SHELLEXECUTEINFO sei;
270  MYEX hShExt;
271  BOOL ret;
272 
273  TRACE ("RunFile(%s)\n", debugstr_aw(filename));
274  hShell32 = LoadLibrary(_T("SHELL32.DLL"));
275  if (!hShell32)
276  {
277  WARN ("RunFile: couldn't load SHELL32.DLL!\n");
278  return NULL;
279  }
280 
282  if (!hShExt)
283  {
284  WARN ("RunFile: couldn't find ShellExecuteExA/W in SHELL32.DLL!\n");
286  return NULL;
287  }
288 
289  TRACE ("RunFile: ShellExecuteExA/W is at %x\n", hShExt);
290 
291  memset(&sei, 0, sizeof sei);
292  sei.cbSize = sizeof sei;
293  sei.fMask = flags;
294  sei.lpFile = filename;
295  sei.lpParameters = params;
296  sei.lpDirectory = directory;
297  sei.nShow = show;
298  ret = hShExt(&sei);
299 
300  TRACE ("RunFile: ShellExecuteExA/W returned 0x%p\n", ret);
301 
303  return ret ? sei.hProcess : NULL;
304 }
305 
306 
307 static VOID
309 {
310  TCHAR szNewTitle[MAX_PATH];
311 
312  if (!pszTitle)
313  return;
314 
315  /* Don't do anything if we run inside a batch file, or we are just running a single command */
316  if (bc || (fSingleCommand == 1))
317  return;
318 
319  /* Save the original console title and build a new one */
321  StringCchPrintf(szNewTitle, ARRAYSIZE(szNewTitle),
322  _T("%s - %s"), szCurTitle, pszTitle);
323  bTitleSet = TRUE;
324  ConSetTitle(szNewTitle);
325 }
326 
327 static VOID
329 {
330  /* Restore the original console title */
331  if (!bc && bTitleSet)
332  {
334  bTitleSet = FALSE;
335  }
336 }
337 
338 /*
339  * This command (in First) was not found in the command table
340  *
341  * Full - output buffer to hold whole command line
342  * First - first word on command line
343  * Rest - rest of command line
344  */
345 static INT
347 {
348  TCHAR *first, *rest, *dot;
349  DWORD dwExitCode = 0;
350  TCHAR *FirstEnd;
351  TCHAR szFullName[MAX_PATH];
352  TCHAR szFullCmdLine[CMDLINE_LENGTH];
353 
354  TRACE ("Execute: \'%s\' \'%s\'\n", debugstr_aw(First), debugstr_aw(Rest));
355 
356  /* Though it was already parsed once, we have a different set of rules
357  for parsing before we pass to CreateProcess */
358  if (First[0] == _T('/') || (First[0] && First[1] == _T(':')))
359  {
360  /* Use the entire first word as the program name (no change) */
361  FirstEnd = First + _tcslen(First);
362  }
363  else
364  {
365  /* If present in the first word, spaces and ,;=/ end the program
366  * name and become the beginning of its parameters. */
367  BOOL bInside = FALSE;
368  for (FirstEnd = First; *FirstEnd; FirstEnd++)
369  {
370  if (!bInside && (_istspace(*FirstEnd) || _tcschr(_T(",;=/"), *FirstEnd)))
371  break;
372  bInside ^= *FirstEnd == _T('"');
373  }
374  }
375 
376  /* Copy the new first/rest into the buffer */
377  rest = &Full[FirstEnd - First + 1];
378  _tcscpy(rest, FirstEnd);
379  _tcscat(rest, Rest);
380  first = Full;
381  *FirstEnd = _T('\0');
382  _tcscpy(first, First);
383 
384  /* check for a drive change */
385  if ((_istalpha (first[0])) && (!_tcscmp (first + 1, _T(":"))))
386  {
387  BOOL working = TRUE;
389  {
390  /* Guess they changed disc or something, handle that gracefully and get to root */
391  TCHAR str[4];
392  str[0]=first[0];
393  str[1]=_T(':');
394  str[2]=_T('\\');
395  str[3]=0;
396  working = SetCurrentDirectory(str);
397  }
398 
399  if (!working) ConErrResPuts (STRING_FREE_ERROR1);
400  return !working;
401  }
402 
403  /* get the PATH environment variable and parse it */
404  /* search the PATH environment variable for the binary */
406  if (!SearchForExecutable(First, szFullName))
407  {
409  return 1;
410  }
411 
412  /* Set the new console title */
413  FirstEnd = first + (FirstEnd - First); /* Point to the separating NULL in the full built string */
414  *FirstEnd = _T(' ');
415  SetConTitle(Full);
416 
417  /* check if this is a .BAT or .CMD file */
418  dot = _tcsrchr (szFullName, _T('.'));
419  if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot, _T(".cmd"))))
420  {
421  while (*rest == _T(' '))
422  rest++;
423 
424  *FirstEnd = _T('\0');
425  TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
426  dwExitCode = Batch(szFullName, first, rest, Cmd);
427  }
428  else
429  {
430  /* exec the program */
431  PROCESS_INFORMATION prci;
432  STARTUPINFO stui;
433 
434  /* build command line for CreateProcess(): FullName + " " + rest */
435  BOOL quoted = !!_tcschr(First, _T(' '));
436  _tcscpy(szFullCmdLine, quoted ? _T("\"") : _T(""));
437  _tcsncat(szFullCmdLine, First, CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
438  _tcsncat(szFullCmdLine, quoted ? _T("\"") : _T(""), CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
439 
440  if (*rest)
441  {
442  _tcsncat(szFullCmdLine, _T(" "), CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
443  _tcsncat(szFullCmdLine, rest, CMDLINE_LENGTH - _tcslen(szFullCmdLine) - 1);
444  }
445 
446  TRACE ("[EXEC: %s]\n", debugstr_aw(szFullCmdLine));
447 
448  /* fill startup info */
449  memset(&stui, 0, sizeof(stui));
450  stui.cb = sizeof(stui);
451  stui.lpTitle = Full;
454 
455  /* Set the console to standard mode */
458 
459  if (CreateProcess(szFullName,
460  szFullCmdLine,
461  NULL,
462  NULL,
463  TRUE,
464  0,
465  NULL,
466  NULL,
467  &stui,
468  &prci))
469  {
470  CloseHandle(prci.hThread);
471  }
472  else
473  {
474  // See if we can run this with ShellExecute() ie myfile.xls
476  szFullName,
477  rest,
478  NULL,
479  SW_SHOWNORMAL);
480  }
481 
482  *FirstEnd = _T('\0');
483 
484  if (prci.hProcess != NULL)
485  {
486  if (bc != NULL || fSingleCommand != 0 || IsConsoleProcess(prci.hProcess))
487  {
488  /* when processing a batch file or starting console processes: execute synchronously */
491 
493 
495 
496  GetExitCodeProcess(prci.hProcess, &dwExitCode);
497  nErrorLevel = (INT)dwExitCode;
498  }
499  CloseHandle(prci.hProcess);
500  }
501  else
502  {
503  TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full));
505  dwExitCode = 1;
506  }
507 
508  /* Restore our default console mode */
513  }
514 
515  /* Update our local codepage cache */
516  {
517  UINT uNewInputCodePage = GetConsoleCP();
518  UINT uNewOutputCodePage = GetConsoleOutputCP();
519 
520  if ((InputCodePage != uNewInputCodePage) ||
521  (OutputCodePage != uNewOutputCodePage))
522  {
523  /* Update the locale as well */
524  InitLocale();
525  }
526 
527  InputCodePage = uNewInputCodePage;
528  OutputCodePage = uNewOutputCodePage;
529 
530  /* Update the streams codepage cache as well */
534  }
535 
536  /* Restore the original console title */
537  ResetConTitle();
538 
539  return dwExitCode;
540 }
541 
542 
543 /*
544  * look through the internal commands and determine whether or not this
545  * command is one of them. If it is, call the command. If not, call
546  * execute to run it as an external program.
547  *
548  * first - first word on command line
549  * rest - rest of command line
550  */
551 INT
553 {
554  TCHAR *com;
555  TCHAR *cp;
556  LPTSTR param; /* pointer to command's parameters */
557  INT cl;
558  LPCOMMAND cmdptr;
559  BOOL nointernal = FALSE;
560  INT ret;
561 
562  TRACE ("DoCommand: (\'%s\' \'%s\')\n", debugstr_aw(first), debugstr_aw(rest));
563 
564  /* full command line */
565  com = cmd_alloc((_tcslen(first) + _tcslen(rest) + 2) * sizeof(TCHAR));
566  if (com == NULL)
567  {
569  return 1;
570  }
571 
572  /* If present in the first word, these characters end the name of an
573  * internal command and become the beginning of its parameters. */
574  cp = first + _tcscspn(first, _T("\t +,/;=[]"));
575 
576  for (cl = 0; cl < (cp - first); cl++)
577  {
578  /* These characters do it too, but if one of them is present,
579  * then we check to see if the word is a file name and skip
580  * checking for internal commands if so.
581  * This allows running programs with names like "echo.exe" */
582  if (_tcschr(_T(".:\\"), first[cl]))
583  {
584  TCHAR tmp = *cp;
585  *cp = _T('\0');
586  nointernal = IsExistingFile(first);
587  *cp = tmp;
588  break;
589  }
590  }
591 
592  /* Scan internal command table */
593  for (cmdptr = cmds; !nointernal && cmdptr->name; cmdptr++)
594  {
595  if (!_tcsnicmp(first, cmdptr->name, cl) && cmdptr->name[cl] == _T('\0'))
596  {
597  _tcscpy(com, first);
598  _tcscat(com, rest);
599  param = &com[cl];
600 
601  /* Skip over whitespace to rest of line, exclude 'echo' command */
602  if (_tcsicmp(cmdptr->name, _T("echo")) != 0)
603  {
604  while (_istspace(*param))
605  param++;
606  }
607 
608  /* Set the new console title */
609  SetConTitle(com);
610 
611  ret = cmdptr->func(param);
612 
613  /* Restore the original console title */
614  ResetConTitle();
615 
616  cmd_free(com);
617  return ret;
618  }
619  }
620 
621  ret = Execute(com, first, rest, Cmd);
622  cmd_free(com);
623  return ret;
624 }
625 
626 
627 /*
628  * process the command line and execute the appropriate functions
629  * full input/output redirection and piping are supported
630  */
632 {
633  INT Ret = 0;
635  if (Cmd)
636  {
637  Ret = ExecuteCommand(Cmd);
638  FreeCommand(Cmd);
639  }
640  return Ret;
641 }
642 
643 /* Execute a command without waiting for it to finish. If it's an internal
644  * command or batch file, we must create a new cmd.exe process to handle it.
645  * TODO: For now, this just always creates a cmd.exe process.
646  * This works, but is inefficient for running external programs,
647  * which could just be run directly. */
648 static HANDLE
650 {
651  TCHAR CmdPath[MAX_PATH];
652  TCHAR CmdParams[CMDLINE_LENGTH], *ParamsEnd;
653  STARTUPINFO stui;
654  PROCESS_INFORMATION prci;
655 
656  /* Get the path to cmd.exe */
657  GetModuleFileName(NULL, CmdPath, ARRAYSIZE(CmdPath));
658 
659  /* Build the parameter string to pass to cmd.exe */
660  ParamsEnd = _stpcpy(CmdParams, _T("/S/D/C\""));
661  ParamsEnd = Unparse(Cmd, ParamsEnd, &CmdParams[CMDLINE_LENGTH - 2]);
662  if (!ParamsEnd)
663  {
665  return NULL;
666  }
667  _tcscpy(ParamsEnd, _T("\""));
668 
669  memset(&stui, 0, sizeof stui);
670  stui.cb = sizeof(STARTUPINFO);
671  if (!CreateProcess(CmdPath, CmdParams, NULL, NULL, TRUE, 0,
672  NULL, NULL, &stui, &prci))
673  {
675  return NULL;
676  }
677 
678  CloseHandle(prci.hThread);
679  return prci.hProcess;
680 }
681 
682 static INT
684 {
685 #ifdef FEATURE_REDIRECTION
686  HANDLE hInput = NULL;
687  HANDLE hOldConIn = GetStdHandle(STD_INPUT_HANDLE);
688  HANDLE hOldConOut = GetStdHandle(STD_OUTPUT_HANDLE);
690  INT nProcesses = 0;
691  DWORD dwExitCode;
692 
693  /* Do all but the last pipe command */
694  do
695  {
696  HANDLE hPipeRead, hPipeWrite;
697  if (nProcesses > (MAXIMUM_WAIT_OBJECTS - 2))
698  {
700  goto failed;
701  }
702 
703  /* Create the pipe that this process will write into.
704  * Make the handles non-inheritable initially, because this
705  * process shouldn't inherit the reading handle. */
706  if (!CreatePipe(&hPipeRead, &hPipeWrite, NULL, 0))
707  {
708  error_no_pipe();
709  goto failed;
710  }
711 
712  /* The writing side of the pipe is STDOUT for this process */
714  SetStdHandle(STD_OUTPUT_HANDLE, hPipeWrite);
715 
716  /* Execute it (error check is done later for easier cleanup) */
717  hProcess[nProcesses] = ExecuteAsync(Cmd->Subcommands);
718  CloseHandle(hPipeWrite);
719  if (hInput)
720  CloseHandle(hInput);
721 
722  /* The reading side of the pipe will be STDIN for the next process */
724  SetStdHandle(STD_INPUT_HANDLE, hPipeRead);
725  hInput = hPipeRead;
726 
727  if (!hProcess[nProcesses])
728  goto failed;
729  nProcesses++;
730 
731  Cmd = Cmd->Subcommands->Next;
732  } while (Cmd->Type == C_PIPE);
733 
734  /* The last process uses the original STDOUT */
735  SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
736  hProcess[nProcesses] = ExecuteAsync(Cmd);
737  if (!hProcess[nProcesses])
738  goto failed;
739  nProcesses++;
740  CloseHandle(hInput);
741  SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
742 
743  /* Wait for all processes to complete */
747 
748  /* Use the exit code of the last process in the pipeline */
749  GetExitCodeProcess(hProcess[nProcesses - 1], &dwExitCode);
750  nErrorLevel = (INT)dwExitCode;
751 
752  while (--nProcesses >= 0)
753  CloseHandle(hProcess[nProcesses]);
754  return nErrorLevel;
755 
756 failed:
757  if (hInput)
758  CloseHandle(hInput);
759  while (--nProcesses >= 0)
760  {
761  TerminateProcess(hProcess[nProcesses], 0);
762  CloseHandle(hProcess[nProcesses]);
763  }
764  SetStdHandle(STD_INPUT_HANDLE, hOldConIn);
765  SetStdHandle(STD_OUTPUT_HANDLE, hOldConOut);
766 #endif
767 
768  return nErrorLevel;
769 }
770 
771 INT
773 {
774  PARSED_COMMAND *Sub;
775  LPTSTR First, Rest;
776  INT Ret = 0;
777 
778  if (!PerformRedirection(Cmd->Redirections))
779  return 1;
780 
781  switch (Cmd->Type)
782  {
783  case C_COMMAND:
784  Ret = 1;
785  First = DoDelayedExpansion(Cmd->Command.First);
786  if (First)
787  {
788  Rest = DoDelayedExpansion(Cmd->Command.Rest);
789  if (Rest)
790  {
791  Ret = DoCommand(First, Rest, Cmd);
792  cmd_free(Rest);
793  }
794  cmd_free(First);
795  }
796  break;
797  case C_QUIET:
798  case C_BLOCK:
799  case C_MULTI:
800  for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
801  Ret = ExecuteCommand(Sub);
802  break;
803  case C_IFFAILURE:
804  Sub = Cmd->Subcommands;
805  Ret = ExecuteCommand(Sub);
806  if (Ret != 0)
807  {
808  nErrorLevel = Ret;
809  Ret = ExecuteCommand(Sub->Next);
810  }
811  break;
812  case C_IFSUCCESS:
813  Sub = Cmd->Subcommands;
814  Ret = ExecuteCommand(Sub);
815  if (Ret == 0)
816  Ret = ExecuteCommand(Sub->Next);
817  break;
818  case C_PIPE:
819  Ret = ExecutePipeline(Cmd);
820  break;
821  case C_IF:
822  Ret = ExecuteIf(Cmd);
823  break;
824  case C_FOR:
825  Ret = ExecuteFor(Cmd);
826  break;
827  }
828 
829  UndoRedirection(Cmd->Redirections, NULL);
830  return Ret;
831 }
832 
833 LPTSTR
835 {
836  static LPTSTR ret = NULL;
837  UINT size;
838 
839  cmd_free(ret);
840  ret = NULL;
841  size = GetEnvironmentVariable(varName, NULL, 0);
842  if (size > 0)
843  {
844  ret = cmd_alloc(size * sizeof(TCHAR));
845  if (ret != NULL)
846  GetEnvironmentVariable(varName, ret, size + 1);
847  }
848  return ret;
849 }
850 
851 LPCTSTR
853 {
854  static TCHAR ret[MAX_PATH];
855 
856  LPTSTR var = GetEnvVar(varName);
857  if (var)
858  return var;
859 
860  /* env var doesn't exist, look for a "special" one */
861  /* %CD% */
862  if (_tcsicmp(varName,_T("cd")) ==0)
863  {
865  return ret;
866  }
867  /* %TIME% */
868  else if (_tcsicmp(varName,_T("time")) ==0)
869  {
870  return GetTimeString();
871  }
872  /* %DATE% */
873  else if (_tcsicmp(varName,_T("date")) ==0)
874  {
875  return GetDateString();
876  }
877 
878  /* %RANDOM% */
879  else if (_tcsicmp(varName,_T("random")) ==0)
880  {
881  /* Get random number */
882  _itot(rand(),ret,10);
883  return ret;
884  }
885 
886  /* %CMDCMDLINE% */
887  else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
888  {
889  return GetCommandLine();
890  }
891 
892  /* %CMDEXTVERSION% */
893  else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
894  {
895  /* Set version number to 2 */
896  _itot(2,ret,10);
897  return ret;
898  }
899 
900  /* %ERRORLEVEL% */
901  else if (_tcsicmp(varName,_T("errorlevel")) ==0)
902  {
903  _itot(nErrorLevel,ret,10);
904  return ret;
905  }
906 
907  return NULL;
908 }
909 
910 /* Handle the %~var syntax */
911 static LPTSTR
912 GetEnhancedVar(TCHAR **pFormat, LPTSTR (*GetVar)(TCHAR, BOOL *))
913 {
914  static const TCHAR ModifierTable[] = _T("dpnxfsatz");
915  enum {
916  M_DRIVE = 1, /* D: drive letter */
917  M_PATH = 2, /* P: path */
918  M_NAME = 4, /* N: filename */
919  M_EXT = 8, /* X: extension */
920  M_FULL = 16, /* F: full path (drive+path+name+ext) */
921  M_SHORT = 32, /* S: full path (drive+path+name+ext), use short names */
922  M_ATTR = 64, /* A: attributes */
923  M_TIME = 128, /* T: modification time */
924  M_SIZE = 256, /* Z: file size */
925  } Modifiers = 0;
926 
927  TCHAR *Format, *FormatEnd;
928  TCHAR *PathVarName = NULL;
929  LPTSTR Variable;
930  TCHAR *VarEnd;
931  BOOL VariableIsParam0;
932  TCHAR FullPath[MAX_PATH];
933  TCHAR FixedPath[MAX_PATH], *Filename, *Extension;
934  HANDLE hFind;
935  WIN32_FIND_DATA w32fd;
936  TCHAR *In, *Out;
937 
938  static TCHAR Result[CMDLINE_LENGTH];
939 
940  /* There is ambiguity between modifier characters and FOR variables;
941  * the rule that cmd uses is to pick the longest possible match.
942  * For example, if there is a %n variable, then out of %~anxnd,
943  * %~anxn will be substituted rather than just %~an. */
944 
945  /* First, go through as many modifier characters as possible */
946  FormatEnd = Format = *pFormat;
947  while (*FormatEnd && _tcschr(ModifierTable, _totlower(*FormatEnd)))
948  FormatEnd++;
949 
950  if (*FormatEnd == _T('$'))
951  {
952  /* $PATH: syntax */
953  PathVarName = FormatEnd + 1;
954  FormatEnd = _tcschr(PathVarName, _T(':'));
955  if (!FormatEnd)
956  return NULL;
957 
958  /* Must be immediately followed by the variable */
959  Variable = GetVar(*++FormatEnd, &VariableIsParam0);
960  if (!Variable)
961  return NULL;
962  }
963  else
964  {
965  /* Backtrack if necessary to get a variable name match */
966  while (!(Variable = GetVar(*FormatEnd, &VariableIsParam0)))
967  {
968  if (FormatEnd == Format)
969  return NULL;
970  FormatEnd--;
971  }
972  }
973 
974  for (; Format < FormatEnd && *Format != _T('$'); Format++)
975  Modifiers |= 1 << (_tcschr(ModifierTable, _totlower(*Format)) - ModifierTable);
976 
977  *pFormat = FormatEnd + 1;
978 
979  /* Exclude the leading and trailing quotes */
980  VarEnd = &Variable[_tcslen(Variable)];
981  if (*Variable == _T('"'))
982  {
983  Variable++;
984  if (VarEnd > Variable && VarEnd[-1] == _T('"'))
985  VarEnd--;
986  }
987 
988  if ((char *)VarEnd - (char *)Variable >= sizeof Result)
989  return _T("");
990  memcpy(Result, Variable, (char *)VarEnd - (char *)Variable);
991  Result[VarEnd - Variable] = _T('\0');
992 
993  if (PathVarName)
994  {
995  /* $PATH: syntax - search the directories listed in the
996  * specified environment variable for the file */
997  LPTSTR PathVar;
998  FormatEnd[-1] = _T('\0');
999  PathVar = GetEnvVar(PathVarName);
1000  FormatEnd[-1] = _T(':');
1001  if (!PathVar ||
1002  !SearchPath(PathVar, Result, NULL, MAX_PATH, FullPath, NULL))
1003  {
1004  return _T("");
1005  }
1006  }
1007  else if (Modifiers == 0)
1008  {
1009  /* For plain %~var with no modifiers, just return the variable without quotes */
1010  return Result;
1011  }
1012  else if (VariableIsParam0)
1013  {
1014  /* Special case: If the variable is %0 and modifier characters are present,
1015  * use the batch file's path (which includes the .bat/.cmd extension)
1016  * rather than the actual %0 variable (which might not). */
1017  _tcscpy(FullPath, bc->BatchFilePath);
1018  }
1019  else
1020  {
1021  /* Convert the variable, now without quotes, to a full path */
1022  if (!GetFullPathName(Result, MAX_PATH, FullPath, NULL))
1023  return _T("");
1024  }
1025 
1026  /* Next step is to change the path to fix letter case (e.g.
1027  * C:\ReAcToS -> C:\ReactOS) and, if requested with the S modifier,
1028  * replace long filenames with short. */
1029 
1030  In = FullPath;
1031  Out = FixedPath;
1032 
1033  /* Copy drive letter */
1034  *Out++ = *In++;
1035  *Out++ = *In++;
1036  *Out++ = *In++;
1037  /* Loop over each \-separated component in the path */
1038  do {
1039  TCHAR *Next = _tcschr(In, _T('\\'));
1040  if (Next)
1041  *Next++ = _T('\0');
1042  /* Use FindFirstFile to get the correct name */
1043  if (Out + _tcslen(In) + 1 >= &FixedPath[MAX_PATH])
1044  return _T("");
1045  _tcscpy(Out, In);
1046  hFind = FindFirstFile(FixedPath, &w32fd);
1047  /* If it doesn't exist, just leave the name as it was given */
1048  if (hFind != INVALID_HANDLE_VALUE)
1049  {
1050  LPTSTR FixedComponent = w32fd.cFileName;
1051  if (*w32fd.cAlternateFileName &&
1052  ((Modifiers & M_SHORT) || !_tcsicmp(In, w32fd.cAlternateFileName)))
1053  {
1054  FixedComponent = w32fd.cAlternateFileName;
1055  }
1056  FindClose(hFind);
1057 
1058  if (Out + _tcslen(FixedComponent) + 1 >= &FixedPath[MAX_PATH])
1059  return _T("");
1060  _tcscpy(Out, FixedComponent);
1061  }
1062  Filename = Out;
1063  Out += _tcslen(Out);
1064  *Out++ = _T('\\');
1065 
1066  In = Next;
1067  } while (In != NULL);
1068  Out[-1] = _T('\0');
1069 
1070  /* Build the result string. Start with attributes, modification time, and
1071  * file size. If the file didn't exist, these fields will all be empty. */
1072  Out = Result;
1073  if (hFind != INVALID_HANDLE_VALUE)
1074  {
1075  if (Modifiers & M_ATTR)
1076  {
1077  static const struct {
1078  TCHAR Character;
1079  WORD Value;
1080  } *Attrib, Table[] = {
1081  { _T('d'), FILE_ATTRIBUTE_DIRECTORY },
1082  { _T('r'), FILE_ATTRIBUTE_READONLY },
1083  { _T('a'), FILE_ATTRIBUTE_ARCHIVE },
1084  { _T('h'), FILE_ATTRIBUTE_HIDDEN },
1085  { _T('s'), FILE_ATTRIBUTE_SYSTEM },
1086  { _T('c'), FILE_ATTRIBUTE_COMPRESSED },
1087  { _T('o'), FILE_ATTRIBUTE_OFFLINE },
1088  { _T('t'), FILE_ATTRIBUTE_TEMPORARY },
1089  { _T('l'), FILE_ATTRIBUTE_REPARSE_POINT },
1090  };
1091  for (Attrib = Table; Attrib != &Table[9]; Attrib++)
1092  {
1093  *Out++ = w32fd.dwFileAttributes & Attrib->Value
1094  ? Attrib->Character
1095  : _T('-');
1096  }
1097  *Out++ = _T(' ');
1098  }
1099  if (Modifiers & M_TIME)
1100  {
1101  FILETIME ft;
1102  SYSTEMTIME st;
1103  FileTimeToLocalFileTime(&w32fd.ftLastWriteTime, &ft);
1104  FileTimeToSystemTime(&ft, &st);
1105 
1106  Out += FormatDate(Out, &st, TRUE);
1107  *Out++ = _T(' ');
1108  Out += FormatTime(Out, &st);
1109  *Out++ = _T(' ');
1110  }
1111  if (Modifiers & M_SIZE)
1112  {
1114  Size.LowPart = w32fd.nFileSizeLow;
1115  Size.HighPart = w32fd.nFileSizeHigh;
1116  Out += _stprintf(Out, _T("%I64u "), Size.QuadPart);
1117  }
1118  }
1119 
1120  /* When using the path-searching syntax or the S modifier,
1121  * at least part of the file path is always included.
1122  * If none of the DPNX modifiers are present, include the full path */
1123  if (PathVarName || (Modifiers & M_SHORT))
1124  if ((Modifiers & (M_DRIVE | M_PATH | M_NAME | M_EXT)) == 0)
1125  Modifiers |= M_FULL;
1126 
1127  /* Now add the requested parts of the name.
1128  * With the F modifier, add all parts to form the full path. */
1129  Extension = _tcsrchr(Filename, _T('.'));
1130  if (Modifiers & (M_DRIVE | M_FULL))
1131  {
1132  *Out++ = FixedPath[0];
1133  *Out++ = FixedPath[1];
1134  }
1135  if (Modifiers & (M_PATH | M_FULL))
1136  {
1137  memcpy(Out, &FixedPath[2], (char *)Filename - (char *)&FixedPath[2]);
1138  Out += Filename - &FixedPath[2];
1139  }
1140  if (Modifiers & (M_NAME | M_FULL))
1141  {
1142  while (*Filename && Filename != Extension)
1143  *Out++ = *Filename++;
1144  }
1145  if (Modifiers & (M_EXT | M_FULL))
1146  {
1147  if (Extension)
1148  Out = _stpcpy(Out, Extension);
1149  }
1150 
1151  /* Trim trailing space which otherwise would appear as a
1152  * result of using the A/T/Z modifiers but no others. */
1153  while (Out != &Result[0] && Out[-1] == _T(' '))
1154  Out--;
1155  *Out = _T('\0');
1156 
1157  return Result;
1158 }
1159 
1160 LPCTSTR
1161 GetBatchVar(TCHAR *varName, UINT *varNameLen)
1162 {
1163  LPCTSTR ret;
1164  TCHAR *varNameEnd;
1165  BOOL dummy;
1166 
1167  *varNameLen = 1;
1168 
1169  switch ( *varName )
1170  {
1171  case _T('~'):
1172  varNameEnd = varName + 1;
1173  ret = GetEnhancedVar(&varNameEnd, FindArg);
1174  if (!ret)
1175  {
1176  error_syntax(varName);
1177  return NULL;
1178  }
1179  *varNameLen = varNameEnd - varName;
1180  return ret;
1181  case _T('0'):
1182  case _T('1'):
1183  case _T('2'):
1184  case _T('3'):
1185  case _T('4'):
1186  case _T('5'):
1187  case _T('6'):
1188  case _T('7'):
1189  case _T('8'):
1190  case _T('9'):
1191  return FindArg(*varName, &dummy);
1192 
1193  case _T('*'):
1194  //
1195  // Copy over the raw params(not including the batch file name
1196  //
1197  return bc->raw_params;
1198 
1199  case _T('%'):
1200  return _T("%");
1201  }
1202  return NULL;
1203 }
1204 
1205 BOOL
1206 SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim)
1207 {
1208 #define APPEND(From, Length) { \
1209  if (Dest + (Length) > DestEnd) \
1210  goto too_long; \
1211  memcpy(Dest, From, (Length) * sizeof(TCHAR)); \
1212  Dest += Length; }
1213 #define APPEND1(Char) { \
1214  if (Dest >= DestEnd) \
1215  goto too_long; \
1216  *Dest++ = Char; }
1217 
1218  TCHAR *DestEnd = Dest + CMDLINE_LENGTH - 1;
1219  const TCHAR *Var;
1220  int VarLength;
1221  TCHAR *SubstStart;
1222  TCHAR EndChr;
1223  while (*Src)
1224  {
1225  if (*Src != Delim)
1226  {
1227  APPEND1(*Src++)
1228  continue;
1229  }
1230 
1231  Src++;
1232  if (bc && Delim == _T('%'))
1233  {
1234  UINT NameLen;
1235  Var = GetBatchVar(Src, &NameLen);
1236  if (Var != NULL)
1237  {
1238  VarLength = _tcslen(Var);
1239  APPEND(Var, VarLength)
1240  Src += NameLen;
1241  continue;
1242  }
1243  }
1244 
1245  /* Find the end of the variable name. A colon (:) will usually
1246  * end the name and begin the optional modifier, but not if it
1247  * is immediately followed by the delimiter (%VAR:%). */
1248  SubstStart = Src;
1249  while (*Src != Delim && !(*Src == _T(':') && Src[1] != Delim))
1250  {
1251  if (!*Src)
1252  goto bad_subst;
1253  Src++;
1254  }
1255 
1256  EndChr = *Src;
1257  *Src = _T('\0');
1258  Var = GetEnvVarOrSpecial(SubstStart);
1259  *Src++ = EndChr;
1260  if (Var == NULL)
1261  {
1262  /* In a batch file, %NONEXISTENT% "expands" to an empty string */
1263  if (bc)
1264  continue;
1265  goto bad_subst;
1266  }
1267  VarLength = _tcslen(Var);
1268 
1269  if (EndChr == Delim)
1270  {
1271  /* %VAR% - use as-is */
1272  APPEND(Var, VarLength)
1273  }
1274  else if (*Src == _T('~'))
1275  {
1276  /* %VAR:~[start][,length]% - substring
1277  * Negative values are offsets from the end */
1278  int Start = _tcstol(Src + 1, &Src, 0);
1279  int End = VarLength;
1280  if (Start < 0)
1281  Start += VarLength;
1282  Start = max(Start, 0);
1283  Start = min(Start, VarLength);
1284  if (*Src == _T(','))
1285  {
1286  End = _tcstol(Src + 1, &Src, 0);
1287  End += (End < 0) ? VarLength : Start;
1288  End = max(End, Start);
1289  End = min(End, VarLength);
1290  }
1291  if (*Src++ != Delim)
1292  goto bad_subst;
1293  APPEND(&Var[Start], End - Start);
1294  }
1295  else
1296  {
1297  /* %VAR:old=new% - replace all occurrences of old with new
1298  * %VAR:*old=new% - replace first occurrence only,
1299  * and remove everything before it */
1300  TCHAR *Old, *New;
1301  DWORD OldLength, NewLength;
1302  BOOL Star = FALSE;
1303  int LastMatch = 0, i = 0;
1304 
1305  if (*Src == _T('*'))
1306  {
1307  Star = TRUE;
1308  Src++;
1309  }
1310 
1311  /* the string to replace may contain the delimiter */
1312  Src = _tcschr(Old = Src, _T('='));
1313  if (Src == NULL)
1314  goto bad_subst;
1315  OldLength = Src++ - Old;
1316  if (OldLength == 0)
1317  goto bad_subst;
1318 
1319  Src = _tcschr(New = Src, Delim);
1320  if (Src == NULL)
1321  goto bad_subst;
1322  NewLength = Src++ - New;
1323 
1324  while (i < VarLength)
1325  {
1326  if (_tcsnicmp(&Var[i], Old, OldLength) == 0)
1327  {
1328  if (!Star)
1329  APPEND(&Var[LastMatch], i - LastMatch)
1330  APPEND(New, NewLength)
1331  i += OldLength;
1332  LastMatch = i;
1333  if (Star)
1334  break;
1335  continue;
1336  }
1337  i++;
1338  }
1339  APPEND(&Var[LastMatch], VarLength - LastMatch)
1340  }
1341  continue;
1342 
1343  bad_subst:
1344  Src = SubstStart;
1345  if (!bc)
1346  APPEND1(Delim)
1347  }
1348  *Dest = _T('\0');
1349  return TRUE;
1350 too_long:
1352  nErrorLevel = 9023;
1353  return FALSE;
1354 #undef APPEND
1355 #undef APPEND1
1356 }
1357 
1358 /* Search the list of FOR contexts for a variable */
1359 static LPTSTR FindForVar(TCHAR Var, BOOL *IsParam0)
1360 {
1361  FOR_CONTEXT *Ctx;
1362  *IsParam0 = FALSE;
1363  for (Ctx = fc; Ctx != NULL; Ctx = Ctx->prev)
1364  {
1365  if ((UINT)(Var - Ctx->firstvar) < Ctx->varcount)
1366  return Ctx->values[Var - Ctx->firstvar];
1367  }
1368  return NULL;
1369 }
1370 
1371 BOOL
1373 {
1374  TCHAR *DestEnd = &Dest[CMDLINE_LENGTH - 1];
1375  while (*Src)
1376  {
1377  if (Src[0] == _T('%'))
1378  {
1379  BOOL Dummy;
1380  LPTSTR End = &Src[2];
1381  LPTSTR Value = NULL;
1382 
1383  if (Src[1] == _T('~'))
1384  Value = GetEnhancedVar(&End, FindForVar);
1385 
1386  if (!Value)
1387  Value = FindForVar(Src[1], &Dummy);
1388 
1389  if (Value)
1390  {
1391  if (Dest + _tcslen(Value) > DestEnd)
1392  return FALSE;
1393  Dest = _stpcpy(Dest, Value);
1394  Src = End;
1395  continue;
1396  }
1397  }
1398  /* Not a variable; just copy the character */
1399  if (Dest >= DestEnd)
1400  return FALSE;
1401  *Dest++ = *Src++;
1402  }
1403  *Dest = _T('\0');
1404  return TRUE;
1405 }
1406 
1407 LPTSTR
1409 {
1410  TCHAR Buf1[CMDLINE_LENGTH];
1411  TCHAR Buf2[CMDLINE_LENGTH];
1412 
1413  /* First, substitute FOR variables */
1414  if (!SubstituteForVars(Line, Buf1))
1415  return NULL;
1416 
1417  if (!bDelayedExpansion || !_tcschr(Buf1, _T('!')))
1418  return cmd_dup(Buf1);
1419 
1420  /* FIXME: Delayed substitutions actually aren't quite the same as
1421  * immediate substitutions. In particular, it's possible to escape
1422  * the exclamation point using ^. */
1423  if (!SubstituteVars(Buf1, Buf2, _T('!')))
1424  return NULL;
1425  return cmd_dup(Buf2);
1426 }
1427 
1428 
1429 /*
1430  * do the prompt/input/process loop
1431  *
1432  */
1433 
1434 BOOL
1435 ReadLine(TCHAR *commandline, BOOL bMore)
1436 {
1438  LPTSTR ip;
1439 
1440  /* if no batch input then... */
1441  if (bc == NULL)
1442  {
1443  if (bMore)
1444  {
1446  }
1447  else
1448  {
1449  /* JPP 19980807 - if echo off, don't print prompt */
1450  if (bEcho)
1451  {
1452  if (!bIgnoreEcho)
1453  ConOutChar(_T('\n'));
1454  PrintPrompt();
1455  }
1456  }
1457 
1458  if (!ReadCommand(readline, CMDLINE_LENGTH - 1))
1459  {
1460  bExit = TRUE;
1461  return FALSE;
1462  }
1463 
1464  if (readline[0] == _T('\0'))
1465  ConOutChar(_T('\n'));
1466 
1468  return FALSE;
1469 
1470  if (readline[0] == _T('\0'))
1471  return FALSE;
1472 
1473  ip = readline;
1474  }
1475  else
1476  {
1477  ip = ReadBatchLine();
1478  if (!ip)
1479  return FALSE;
1480  }
1481 
1482  return SubstituteVars(ip, commandline, _T('%'));
1483 }
1484 
1485 static VOID
1487 {
1489 
1490  while (!bCanExit || !bExit)
1491  {
1492  /* Reset the Ctrl-Break / Ctrl-C state */
1493  bCtrlBreak = FALSE;
1494 
1495  Cmd = ParseCommand(NULL);
1496  if (!Cmd)
1497  continue;
1498 
1500  FreeCommand(Cmd);
1501  }
1502 }
1503 
1504 
1505 /*
1506  * control-break handler.
1507  */
1509 {
1510  DWORD dwWritten;
1511  INPUT_RECORD rec;
1512 
1513  if ((dwCtrlType != CTRL_C_EVENT) &&
1514  (dwCtrlType != CTRL_BREAK_EVENT))
1515  {
1516  return FALSE;
1517  }
1518 
1520  {
1521  /* Child process is running and will have received the control event */
1522  return TRUE;
1523  }
1524  else
1525  {
1527  }
1528 
1529  bCtrlBreak = TRUE;
1530 
1531  rec.EventType = KEY_EVENT;
1532  rec.Event.KeyEvent.bKeyDown = TRUE;
1533  rec.Event.KeyEvent.wRepeatCount = 1;
1534  rec.Event.KeyEvent.wVirtualKeyCode = _T('C');
1535  rec.Event.KeyEvent.wVirtualScanCode = _T('C') - 35;
1536  rec.Event.KeyEvent.uChar.AsciiChar = _T('C');
1537  rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
1539 
1541  &rec,
1542  1,
1543  &dwWritten);
1544 
1545  /* FIXME: Handle batch files */
1546 
1547  // ConOutPrintf(_T("^C"));
1548 
1549  return TRUE;
1550 }
1551 
1552 
1554 {
1556 }
1557 
1558 
1560 {
1562 }
1563 
1564 
1565 /*
1566  * show commands and options that are available.
1567  *
1568  */
1569 #if 0
1570 static VOID
1571 ShowCommands(VOID)
1572 {
1573  /* print command list */
1575  PrintCommandList();
1576 
1577  /* print feature list */
1579 
1580 #ifdef FEATURE_ALIASES
1582 #endif
1583 #ifdef FEATURE_HISTORY
1585 #endif
1586 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
1588 #endif
1589 #ifdef FEATURE_DIRECTORY_STACK
1591 #endif
1592 #ifdef FEATURE_REDIRECTION
1594 #endif
1595  ConOutChar(_T('\n'));
1596 }
1597 #endif
1598 
1599 
1600 static VOID
1602 {
1603  LONG lRet;
1604  HKEY hKey;
1605  DWORD dwType, len;
1606  /*
1607  * Buffer big enough to hold the string L"4294967295",
1608  * corresponding to the literal 0xFFFFFFFF (MAX_ULONG) in decimal.
1609  */
1610  DWORD Buffer[6];
1611 
1612  lRet = RegOpenKeyEx(hKeyRoot,
1613  _T("Software\\Microsoft\\Command Processor"),
1614  0,
1616  &hKey);
1617  if (lRet != ERROR_SUCCESS)
1618  return;
1619 
1620 #ifdef INCLUDE_CMD_COLOR
1621  len = sizeof(Buffer);
1622  lRet = RegQueryValueEx(hKey,
1623  _T("DefaultColor"),
1624  NULL,
1625  &dwType,
1626  (LPBYTE)&Buffer,
1627  &len);
1628  if (lRet == ERROR_SUCCESS)
1629  {
1630  /* Overwrite the default attributes */
1631  if (dwType == REG_DWORD)
1632  wDefColor = (WORD)*(PDWORD)Buffer;
1633  else if (dwType == REG_SZ)
1635  }
1636  // else, use the default attributes retrieved before.
1637 #endif
1638 
1639 #if 0
1640  len = sizeof(Buffer);
1641  lRet = RegQueryValueEx(hKey,
1642  _T("DisableUNCCheck"),
1643  NULL,
1644  &dwType,
1645  (LPBYTE)&Buffer,
1646  &len);
1647  if (lRet == ERROR_SUCCESS)
1648  {
1649  /* Overwrite the default setting */
1650  if (dwType == REG_DWORD)
1651  bDisableUNCCheck = !!*(PDWORD)Buffer;
1652  else if (dwType == REG_SZ)
1653  bDisableUNCCheck = (_ttol((PTSTR)Buffer) == 1);
1654  }
1655  // else, use the default setting set globally.
1656 #endif
1657 
1658  len = sizeof(Buffer);
1659  lRet = RegQueryValueEx(hKey,
1660  _T("DelayedExpansion"),
1661  NULL,
1662  &dwType,
1663  (LPBYTE)&Buffer,
1664  &len);
1665  if (lRet == ERROR_SUCCESS)
1666  {
1667  /* Overwrite the default setting */
1668  if (dwType == REG_DWORD)
1670  else if (dwType == REG_SZ)
1671  bDelayedExpansion = (_ttol((PTSTR)Buffer) == 1);
1672  }
1673  // else, use the default setting set globally.
1674 
1675  len = sizeof(Buffer);
1676  lRet = RegQueryValueEx(hKey,
1677  _T("EnableExtensions"),
1678  NULL,
1679  &dwType,
1680  (LPBYTE)&Buffer,
1681  &len);
1682  if (lRet == ERROR_SUCCESS)
1683  {
1684  /* Overwrite the default setting */
1685  if (dwType == REG_DWORD)
1687  else if (dwType == REG_SZ)
1688  bEnableExtensions = (_ttol((PTSTR)Buffer) == 1);
1689  }
1690  // else, use the default setting set globally.
1691 
1692  len = sizeof(Buffer);
1693  lRet = RegQueryValueEx(hKey,
1694  _T("CompletionChar"),
1695  NULL,
1696  &dwType,
1697  (LPBYTE)&Buffer,
1698  &len);
1699  if (lRet == ERROR_SUCCESS)
1700  {
1701  /* Overwrite the default setting */
1702  if (dwType == REG_DWORD)
1704  else if (dwType == REG_SZ)
1706  }
1707  // else, use the default setting set globally.
1708 
1709  /* Validity check */
1711  {
1712  /* Disable autocompletion */
1713  AutoCompletionChar = 0x20;
1714  }
1715 
1716  len = sizeof(Buffer);
1717  lRet = RegQueryValueEx(hKey,
1718  _T("PathCompletionChar"),
1719  NULL,
1720  &dwType,
1721  (LPBYTE)&Buffer,
1722  &len);
1723  if (lRet == ERROR_SUCCESS)
1724  {
1725  /* Overwrite the default setting */
1726  if (dwType == REG_DWORD)
1728  else if (dwType == REG_SZ)
1730  }
1731  // else, use the default setting set globally.
1732 
1733  /* Validity check */
1735  {
1736  /* Disable autocompletion */
1737  PathCompletionChar = 0x20;
1738  }
1739 
1740  /* Adjust completion chars */
1741  if (PathCompletionChar >= 0x20 && AutoCompletionChar < 0x20)
1743  else if (AutoCompletionChar >= 0x20 && PathCompletionChar < 0x20)
1745 
1746  RegCloseKey(hKey);
1747 }
1748 
1749 static VOID
1751 {
1752  LONG lRet;
1753  HKEY hKey;
1754  DWORD dwType, len;
1755  TCHAR AutoRun[2048];
1756 
1757  lRet = RegOpenKeyEx(hKeyRoot,
1758  _T("Software\\Microsoft\\Command Processor"),
1759  0,
1761  &hKey);
1762  if (lRet != ERROR_SUCCESS)
1763  return;
1764 
1765  len = sizeof(AutoRun);
1766  lRet = RegQueryValueEx(hKey,
1767  _T("AutoRun"),
1768  NULL,
1769  &dwType,
1770  (LPBYTE)&AutoRun,
1771  &len);
1772  if ((lRet == ERROR_SUCCESS) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ))
1773  {
1774  if (*AutoRun)
1775  ParseCommandLine(AutoRun);
1776  }
1777 
1778  RegCloseKey(hKey);
1779 }
1780 
1781 /* Get the command that comes after a /C or /K switch */
1782 static VOID
1783 GetCmdLineCommand(TCHAR *commandline, TCHAR *ptr, BOOL AlwaysStrip)
1784 {
1785  TCHAR *LastQuote;
1786 
1787  while (_istspace(*ptr))
1788  ptr++;
1789 
1790  /* Remove leading quote, find final quote */
1791  if (*ptr == _T('"') &&
1792  (LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
1793  {
1794  TCHAR *Space;
1795  /* Under certain circumstances, all quotes are preserved.
1796  * CMD /? documents these conditions as follows:
1797  * 1. No /S switch
1798  * 2. Exactly two quotes
1799  * 3. No "special characters" between the quotes
1800  * (CMD /? says &<>()@^| but parentheses did not
1801  * trigger this rule when I tested them.)
1802  * 4. Whitespace exists between the quotes
1803  * 5. Enclosed string is an executable filename
1804  */
1805  *LastQuote = _T('\0');
1806  for (Space = ptr + 1; Space < LastQuote; Space++)
1807  {
1808  if (_istspace(*Space)) /* Rule 4 */
1809  {
1810  if (!AlwaysStrip && /* Rule 1 */
1811  !_tcspbrk(ptr, _T("\"&<>@^|")) && /* Rules 2, 3 */
1812  SearchForExecutable(ptr, commandline)) /* Rule 5 */
1813  {
1814  /* All conditions met: preserve both the quotes */
1815  *LastQuote = _T('"');
1816  _tcscpy(commandline, ptr - 1);
1817  return;
1818  }
1819  break;
1820  }
1821  }
1822 
1823  /* The conditions were not met: remove both the
1824  * leading quote and the last quote */
1825  _tcscpy(commandline, ptr);
1826  _tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
1827  return;
1828  }
1829 
1830  /* No quotes; just copy */
1831  _tcscpy(commandline, ptr);
1832 }
1833 
1834 
1835 /*
1836  * Set up global initializations and process parameters
1837  */
1838 static VOID
1840 {
1841  HMODULE NtDllModule;
1842  TCHAR commandline[CMDLINE_LENGTH];
1843  TCHAR ModuleName[_MAX_PATH + 1];
1844  // INT nExitCode;
1845 
1846  HANDLE hIn, hOut;
1847 
1848  TCHAR *ptr, *cmdLine, option = 0;
1849  BOOL AlwaysStrip = FALSE;
1850  BOOL AutoRun = TRUE;
1851 
1852  /* Get version information */
1853  InitOSVersion();
1854 
1855  /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
1856  * build process. So don't link implicitly against ntdll.dll, load it
1857  * dynamically instead */
1858  NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
1859  if (NtDllModule != NULL)
1860  {
1861  NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)GetProcAddress(NtDllModule, "NtQueryInformationProcess");
1862  NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
1863  }
1864 
1865  /* Load the registry settings */
1868 
1869  /* Initialize our locale */
1870  InitLocale();
1871 
1872  /* Initialize prompt support */
1873  InitPrompt();
1874 
1875 #ifdef FEATURE_DIR_STACK
1876  /* Initialize directory stack */
1878 #endif
1879 
1880 #ifdef FEATURE_HISTORY
1881  /* Initialize history */
1882  InitHistory();
1883 #endif
1884 
1885  /* Set COMSPEC environment variable */
1887  {
1888  ModuleName[_MAX_PATH] = _T('\0');
1889  SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
1890  }
1891 
1892  /* Add ctrl break handler */
1893  AddBreakHandler();
1894 
1895  /* Set our default console mode */
1896  hOut = ConStreamGetOSHandle(StdOut);
1897  hIn = ConStreamGetOSHandle(StdIn);
1898  SetConsoleMode(hOut, 0); // Reinitialize the console output mode
1901 
1902  cmdLine = GetCommandLine();
1903  TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
1904 
1905  for (ptr = cmdLine; *ptr; ptr++)
1906  {
1907  if (*ptr == _T('/'))
1908  {
1909  option = _totupper(ptr[1]);
1910  if (option == _T('?'))
1911  {
1913  nErrorLevel = 1;
1914  bExit = TRUE;
1915  return;
1916  }
1917  else if (option == _T('P'))
1918  {
1919  if (!IsExistingFile (_T("\\autoexec.bat")))
1920  {
1921 #ifdef INCLUDE_CMD_DATE
1922  cmd_date (_T(""));
1923 #endif
1924 #ifdef INCLUDE_CMD_TIME
1925  cmd_time (_T(""));
1926 #endif
1927  }
1928  else
1929  {
1930  ParseCommandLine (_T("\\autoexec.bat"));
1931  }
1932  bCanExit = FALSE;
1933  }
1934  else if (option == _T('A'))
1935  {
1937  }
1938  else if (option == _T('C') || option == _T('K') || option == _T('R'))
1939  {
1940  /* Remainder of command line is a command to be run */
1941  fSingleCommand = ((option == _T('K')) << 1) | 1;
1942  break;
1943  }
1944  else if (option == _T('D'))
1945  {
1946  AutoRun = FALSE;
1947  }
1948  else if (option == _T('Q'))
1949  {
1951  }
1952  else if (option == _T('S'))
1953  {
1954  AlwaysStrip = TRUE;
1955  }
1956 #ifdef INCLUDE_CMD_COLOR
1957  else if (!_tcsnicmp(ptr, _T("/T:"), 3))
1958  {
1959  /* Process /T (color) argument; overwrite any previous settings */
1960  wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
1961  }
1962 #endif
1963  else if (option == _T('U'))
1964  {
1966  }
1967  else if (option == _T('V'))
1968  {
1969  // FIXME: Check validity of the parameter given to V !
1970  bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
1971  }
1972  else if (option == _T('E'))
1973  {
1974  // FIXME: Check validity of the parameter given to E !
1975  bEnableExtensions = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
1976  }
1977  else if (option == _T('X'))
1978  {
1979  /* '/X' is identical to '/E:ON' */
1981  }
1982  else if (option == _T('Y'))
1983  {
1984  /* '/Y' is identical to '/E:OFF' */
1986  }
1987  }
1988  }
1989 
1990 #ifdef INCLUDE_CMD_COLOR
1991  if (wDefColor == 0)
1992  {
1993  /*
1994  * If we still do not have the console colour attribute set,
1995  * retrieve the default one.
1996  */
1998  }
1999 
2000  if (wDefColor != 0)
2002 #endif
2003 
2004  /* Reset the output Standard Streams translation modes and codepage caches */
2005  // ConStreamSetMode(StdIn , OutputStreamMode, InputCodePage );
2008 
2009  if (!*ptr)
2010  {
2011  /* If neither /C or /K was given, display a simple version string */
2012  ConOutChar(_T('\n'));
2014  _T(KERNEL_VERSION_STR),
2015  _T(KERNEL_VERSION_BUILD_STR));
2016  ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team.\n"));
2017  }
2018 
2019  if (AutoRun)
2020  {
2023  }
2024 
2025  if (*ptr)
2026  {
2027  /* Do the /C or /K command */
2028  GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
2029  /* nExitCode = */ ParseCommandLine(commandline);
2030  if (fSingleCommand == 1)
2031  {
2032  // nErrorLevel = nExitCode;
2033  bExit = TRUE;
2034  }
2035  fSingleCommand = 0;
2036  }
2037 }
2038 
2039 
2041 {
2042  /* Run cmdexit.bat */
2043  if (IsExistingFile(_T("cmdexit.bat")))
2044  {
2046  ParseCommandLine(_T("cmdexit.bat"));
2047  }
2048  else if (IsExistingFile(_T("\\cmdexit.bat")))
2049  {
2051  ParseCommandLine(_T("\\cmdexit.bat"));
2052  }
2053 
2054 #ifdef FEATURE_DIRECTORY_STACK
2055  /* Destroy directory stack */
2057 #endif
2058 
2059 #ifdef FEATURE_HISTORY
2060  CleanHistory();
2061 #endif
2062 
2063  /* Free GetEnvVar's buffer */
2064  GetEnvVar(NULL);
2065 
2066  /* Remove ctrl break handler */
2068 
2069  /* Restore the default console mode */
2074 
2076 }
2077 
2078 /*
2079  * main function
2080  */
2081 int _tmain(int argc, const TCHAR *argv[])
2082 {
2083  TCHAR startPath[MAX_PATH];
2084 
2087 
2088  GetCurrentDirectory(ARRAYSIZE(startPath), startPath);
2089  _tchdir(startPath);
2090 
2091  SetFileApisToOEM();
2094 
2095  /* Initialize the Console Standard Streams */
2099 
2101 
2102  /* Perform general initialization, parse switches on command-line */
2103  Initialize();
2104 
2105  /* Call prompt routine */
2106  ProcessInput();
2107 
2108  /* Do the cleanup */
2109  Cleanup();
2110 
2112 
2114  return nErrorLevel;
2115 }
2116 
2117 /* EOF */
VOID InitLocale(VOID)
Definition: locale.c:25
#define RegQueryValueEx
Definition: winreg.h:524
INT nErrorLevel
Definition: cmd.c:157
static VOID ProcessInput(VOID)
Definition: cmd.c:1486
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2327
VOID PrintCommandList(VOID)
Definition: cmdtable.c:242
INT FormatTime(TCHAR *, LPSYSTEMTIME)
Definition: dir.c:703
static int argc
Definition: ServiceArgs.c:12
#define SW_SHOWDEFAULT
Definition: winuser.h:774
#define STRING_CMD_HELP1
Definition: resource.h:76
Definition: cmd.h:298
#define max(a, b)
Definition: svc.c:63
BOOL CheckCtrlBreak(INT)
Definition: misc.c:132
ASMGENDATA Table[]
Definition: genincdata.c:61
#define cmd_exit(code)
Definition: cmddbg.h:34
Definition: cmd.h:298
#define TRUE
Definition: types.h:120
static LPTSTR GetEnhancedVar(TCHAR **pFormat, LPTSTR(*GetVar)(TCHAR, BOOL *))
Definition: cmd.c:912
const CHAR * LPCTSTR
Definition: xmlstorage.h:193
#define CloseHandle
Definition: compat.h:398
WCHAR UnicodeChar
Definition: wincon.h:230
#define CTRL_BREAK_EVENT
Definition: wincon.h:66
#define FILE_ATTRIBUTE_TEMPORARY
Definition: nt_native.h:708
int _tmain(int argc, const TCHAR *argv[])
Definition: cmd.c:2081
VOID InitHistory(VOID)
Definition: history.c:132
WORD wVirtualScanCode
Definition: wincon.h:228
LPSTR lpTitle
Definition: winbase.h:799
#define SHELLEXECUTETEXT
Definition: cmd.c:260
#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:33
BOOL bIgnoreEcho
Definition: cmd.c:155
#define LoadLibrary
Definition: winbase.h:3676
Definition: cmd.h:298
static VOID SetConTitle(LPCTSTR pszTitle)
Definition: cmd.c:308
#define _tcsicmp
Definition: xmlstorage.h:205
LPBATCH_CONTEXT bc
Definition: batch.c:66
LPCTSTR GetBatchVar(TCHAR *varName, UINT *varNameLen)
Definition: cmd.c:1161
Definition: ftp_var.h:139
static VOID ExecuteAutoRunFile(HKEY hKeyRoot)
Definition: cmd.c:1750
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
int _tcscmp(const _TCHAR *s1, const _TCHAR *s2)
Definition: tcscmp.h:8
VOID ErrorMessage(DWORD, LPTSTR,...)
Definition: error.c:26
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define STRING_REACTOS_VERSION
Definition: resource.h:90
VOID ConOutChar(TCHAR c)
Definition: console.c:123
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1198
#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:167
#define HKEY_CURRENT_USER
Definition: winreg.h:11
static VOID LoadRegistrySettings(HKEY hKeyRoot)
Definition: cmd.c:1601
#define STRING_MORE
Definition: resource.h:246
#define ConErrResPuts(uID)
Definition: console.h:39
const GLint * first
Definition: glext.h:5794
#define WARN(fmt,...)
Definition: debug.h:111
#define WriteConsoleInput
Definition: wincon.h:773
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
COMMAND cmds[]
Definition: main.c:21
#define CMDLINE_LENGTH
Definition: help.h:12
DWORD dwControlKeyState
Definition: wincon.h:233
#define CTRL_C_EVENT
Definition: wincon.h:65
GLdouble n
Definition: glext.h:7729
#define New(t)
Definition: rtf.h:1086
VKNAME Modifiers[]
Definition: data.c:56
BOOL bEcho
Definition: batch.c:68
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
_TCHAR * _tcscpy(_TCHAR *to, const _TCHAR *from)
Definition: tcscpy.h:8
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static VOID GetCmdLineCommand(TCHAR *commandline, TCHAR *ptr, BOOL AlwaysStrip)
Definition: cmd.c:1783
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:152
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
INT ParseCommandLine(LPTSTR cmd)
Definition: cmd.c:631
BOOL SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim)
Definition: cmd.c:1206
INT FormatDate(TCHAR *, LPSYSTEMTIME, BOOL)
Definition: dir.c:674
Definition: cmd.h:298
DWORD dwFlags
Definition: winbase.h:807
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
#define IS_COMPLETION_DISABLED(CompletionCtrl)
Definition: cmd.h:105
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:1252
#define _totupper
Definition: tchar.h:1509
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
UINT varcount
Definition: batch.h:28
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:265
BOOL WINAPI FileTimeToLocalFileTime(IN CONST FILETIME *lpFileTime, OUT LPFILETIME lpLocalFileTime)
Definition: time.c:211
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:223
#define BOOL
Definition: nt_native.h:43
BOOL(WINAPI * MYEX)(LPSHELLEXECUTEINFO lpExecInfo)
Definition: cmd.c:263
#define _istalpha
Definition: tchar.h:1492
static VOID StripQuotes(LPSTR in)
Definition: cmdcons.c:116
static NtQueryInformationProcessProc NtQueryInformationProcessPtr
Definition: cmd.c:169
int32_t INT
Definition: typedefs.h:56
LPTSTR ReadBatchLine(VOID)
Definition: batch.c:453
struct _PARSED_COMMAND * Next
Definition: cmd.h:302
CHAR * LPTSTR
Definition: xmlstorage.h:192
struct TraceInfo Info
IN PVCB IN PBCB OUT PDIRENT IN USHORT IN POEM_STRING Filename
Definition: fatprocs.h:925
#define _itot
Definition: tchar.h:608
#define SearchPath
Definition: winbase.h:3714
WORD wVirtualKeyCode
Definition: wincon.h:227
static USHORT USHORT * NewLength
TCHAR firstvar
Definition: batch.h:27
#define ENABLE_ECHO_INPUT
Definition: wincon.h:77
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
#define ENABLE_WRAP_AT_EOL_OUTPUT
Definition: blue.h:45
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
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:461
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
WORD wRepeatCount
Definition: wincon.h:226
unsigned char * LPBYTE
Definition: typedefs.h:52
#define StringCchPrintf
Definition: strsafe.h:517
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
NTSTATUS(WINAPI * NtReadVirtualMemoryProc)(HANDLE, PVOID, PVOID, ULONG, PULONG)
Definition: cmd.c:150
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1608
LPCTSTR GetEnvVarOrSpecial(LPCTSTR varName)
Definition: cmd.c:852
#define _MAX_PATH
Definition: utility.h:77
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2111
LPTSTR FindArg(TCHAR Char, BOOL *IsParam0)
Definition: batch.c:83
#define KEY_EVENT
Definition: wincon.h:122
static PVOID ptr
Definition: dispmode.c:27
int ip[4]
Definition: rtl.c:1176
#define GetCurrentDirectory
Definition: winbase.h:3619
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:179
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
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:763
VOID error_out_of_memory(VOID)
Definition: error.c:136
#define HANDLE_FLAG_INHERIT
Definition: winbase.h:261
BOOL SearchForExecutable(LPCTSTR, LPTSTR)
Definition: where.c:142
Definition: bufpool.h:45
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(VOID)
Definition: console.c:2393
#define GetCommandLine
Definition: winbase.h:3613
BOOL WINAPI BreakHandler(DWORD dwCtrlType)
Definition: cmd.c:1508
void * PVOID
Definition: retypes.h:9
#define FindFirstFile
Definition: winbase.h:3596
#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:162
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:552
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
LPTSTR DuplicateEnvironment(VOID)
Definition: setlocal.c:22
#define APPEND(From, Length)
HANDLE ConStreamGetOSHandle(IN PCON_STREAM Stream)
Definition: stream.c:240
static VOID ResetConTitle(VOID)
Definition: cmd.c:328
char TCHAR
Definition: xmlstorage.h:189
#define STRING_CMD_HELP2
Definition: resource.h:77
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:405
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:178
INT ConvertULargeInteger(ULONGLONG num, LPTSTR des, UINT len, BOOL bPutSeparator)
Definition: cmd.c:188
GLsizeiptr size
Definition: glext.h:5919
DWORD cb
Definition: winbase.h:796
#define STRING_CMD_HELP4
Definition: resource.h:79
VOID InitDirectoryStack(VOID)
Definition: dirstack.c:80
Definition: dhcpd.h:61
Definition: cmd.h:298
TCHAR BatchFilePath[MAX_PATH]
Definition: batch.h:14
static NtReadVirtualMemoryProc NtReadVirtualMemoryPtr
Definition: cmd.c:170
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:65
static BOOL Full
Definition: pageheap.c:12
#define STD_ERROR_HANDLE
Definition: winbase.h:266
GLfloat param
Definition: glext.h:5796
#define MAX_PATH
Definition: compat.h:26
LPTSTR lpOriginalEnvironment
Definition: cmd.c:163
#define WINAPI
Definition: msvc.h:8
UINT OutputCodePage
Definition: console.c:26
BOOL bDisableBatchEcho
Definition: cmd.c:159
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:263
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
unsigned short WORD
Definition: ntddk_ex.h:93
TCHAR PathCompletionChar
Definition: cmdinput.c:112
LPTSTR DoDelayedExpansion(LPTSTR Line)
Definition: cmd.c:1408
#define ConOutResPrintf(uID,...)
Definition: console.h:48
unsigned long DWORD
Definition: ntddk_ex.h:95
PVOID HANDLE
Definition: typedefs.h:71
GLuint GLuint num
Definition: glext.h:9618
#define ENABLE_LINE_INPUT
Definition: wincon.h:76
LPFOR_CONTEXT fc
Definition: for.c:53
#define GetModuleFileName
Definition: winbase.h:3645
#define StdErr
Definition: stream.h:77
CON_STREAM_MODE OutputStreamMode
Definition: cmd.c:176
Definition: partlist.h:33
#define FILE_ATTRIBUTE_COMPRESSED
Definition: nt_native.h:711
GLbitfield flags
Definition: glext.h:7161
LPTSTR * values
Definition: batch.h:29
#define STRING_CMD_HELP5
Definition: resource.h:80
BOOL ReadLine(TCHAR *commandline, BOOL bMore)
Definition: cmd.c:1435
Definition: ncftp.h:79
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
BOOL bEnableExtensions
Definition: cmd.c:160
#define _totlower
Definition: tchar.h:1511
BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle(DWORD nStdHandle, HANDLE hHandle)
Definition: console.c:1213
static LPTSTR FindForVar(TCHAR Var, BOOL *IsParam0)
Definition: cmd.c:1359
int ret
LPTSTR GetDateString(VOID)
Definition: locale.c:58
#define _tcstoul
Definition: tchar.h:595
BOOL WINAPI TryEnterCriticalSection(LPCRITICAL_SECTION)
Definition: sacdrv.h:277
#define NTSTATUS
Definition: precomp.h:20
static HANDLE ExecuteAsync(PARSED_COMMAND *Cmd)
Definition: cmd.c:649
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define GetFullPathName
Definition: winbase.h:3635
VOID UndoRedirection(REDIRECTION *, REDIRECTION *End)
Definition: redir.c:142
#define SetEnvironmentVariable
Definition: winbase.h:3722
BOOL ConStreamSetMode(IN PCON_STREAM Stream, IN CON_STREAM_MODE Mode, IN UINT CacheCodePage OPTIONAL)
Definition: stream.c:195
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:1015
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
#define CreateProcess
Definition: winbase.h:3572
BOOL ConSetTitle(IN LPCTSTR lpConsoleTitle)
Definition: console.c:280
VOID AddBreakHandler(VOID)
Definition: cmd.c:1553
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
Definition: cmd.h:298
Status
Definition: gdiplustypes.h:24
VOID error_too_many_parameters(LPTSTR)
Definition: error.c:77
#define ENABLE_PROCESSED_OUTPUT
Definition: blue.h:44
#define STRING_CMD_HELP3
Definition: resource.h:78
TCHAR * Unparse(PARSED_COMMAND *Cmd, TCHAR *Out, TCHAR *OutEnd)
Definition: parser.c:905
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest)
Definition: cmd.c:1372
enum _CON_STREAM_MODE CON_STREAM_MODE
VOID WINAPI SetFileApisToOEM(VOID)
Definition: utils.c:819
static VOID Cleanup(VOID)
Definition: cmd.c:2040
#define _stprintf
Definition: utility.h:124
#define ENABLE_PROCESSED_INPUT
Definition: wincon.h:75
VOID error_syntax(LPTSTR)
Definition: error.c:150
#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:3641
STARTUPINFOA STARTUPINFO
Definition: winbase.h:3533
static INT Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
Definition: cmd.c:346
static calc_node_t temp
Definition: rpn_ieee.c:38
VOID error_bad_command(LPTSTR)
Definition: error.c:122
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:1562
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
LPTSTR GetEnvVar(LPCTSTR varName)
Definition: cmd.c:834
BOOL bDelayedExpansion
Definition: cmd.c:161
#define cmd_dup(str)
Definition: cmddbg.h:32
union _KEY_EVENT_RECORD::@3151 uChar
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
unsigned int * PULONG
Definition: retypes.h:1
#define STRING_CMD_HELP8
Definition: resource.h:83
#define min(a, b)
Definition: monoChain.cc:55
CRITICAL_SECTION ChildProcessRunningLock
Definition: cmd.c:158
unsigned int UINT
Definition: ndis.h:50
WORD wShowWindow
Definition: winbase.h:808
BOOL PerformRedirection(REDIRECTION *)
Definition: redir.c:63
DWORD * PDWORD
Definition: pedump.c:68
static INT ExecutePipeline(PARSED_COMMAND *Cmd)
Definition: cmd.c:683
HANDLE CMD_ModuleHandle
Definition: cmd.c:164
BOOL bExit
Definition: cmd.c:152
PARSED_COMMAND * ParseCommand(LPTSTR Line)
Definition: parser.c:766
#define STRING_FREE_ERROR1
Definition: resource.h:49
WORD EventType
Definition: wincon.h:261
INT ExecuteCommand(PARSED_COMMAND *Cmd)
Definition: cmd.c:772
#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:298
LPTSTR raw_params
Definition: batch.h:16
_TCHAR * _tcsrchr(const _TCHAR *s, _XINT c)
Definition: tcsrchr.h:4
_TCHAR * _tcscat(_TCHAR *s, const _TCHAR *append)
Definition: tcscat.h:8
enum _PROCESSINFOCLASS PROCESSINFOCLASS
Definition: loader.c:63
#define StdOut
Definition: stream.h:76
#define _istspace
Definition: tchar.h:1504
unsigned int ULONG
Definition: retypes.h:1
VOID error_no_pipe(VOID)
Definition: error.c:129
INT ExecuteIf(struct _PARSED_COMMAND *Cmd)
Definition: if.c:66
LPSTR name
Definition: cmdcons.c:27
#define GetEnvironmentVariable
Definition: winbase.h:3628
static BOOL fSingleCommand
Definition: cmd.c:156
#define GetProcAddress(x, y)
Definition: compat.h:410
#define STRING_CMD_ERROR5
Definition: resource.h:31
#define STRING_CMD_HELP7
Definition: resource.h:82
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:463
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:133
#define _tcspbrk
Definition: tchar.h:1412
BOOL bTitleSet
Definition: cmd.c:166
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 IsExistingFile(LPCTSTR)
Definition: misc.c:500
struct tagFORCONTEXT * prev
Definition: batch.h:26
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:28
int _tchdir(const _TCHAR *_path)
Definition: chdir.c:8
VOID PrintPrompt(VOID)
Definition: prompt.c:109
union _INPUT_RECORD::@3152 Event
#define StdIn
Definition: stream.h:75
#define SetCurrentDirectory
Definition: winbase.h:3717
#define STRING_CMD_HELP6
Definition: resource.h:81
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
VOID RemoveBreakHandler(VOID)
Definition: cmd.c:1559
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:1194
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
static VOID Initialize(VOID)
Definition: cmd.c:1839
#define REG_SZ
Definition: layer.c:22
BOOL bCtrlBreak
Definition: cmd.c:154
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502