ReactOS  0.4.15-dev-425-gc40b086
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 %Iu\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
774 {
775  PARSED_COMMAND *Sub;
776  LPTSTR First, Rest;
777  INT Ret = 0;
778 
779  if (!PerformRedirection(Cmd->Redirections))
780  return 1;
781 
782  switch (Cmd->Type)
783  {
784  case C_COMMAND:
785  Ret = 1;
786  First = DoDelayedExpansion(Cmd->Command.First);
787  if (First)
788  {
789  Rest = DoDelayedExpansion(Cmd->Command.Rest);
790  if (Rest)
791  {
792  Ret = DoCommand(First, Rest, Cmd);
793  cmd_free(Rest);
794  }
795  cmd_free(First);
796  }
797  break;
798  case C_QUIET:
799  case C_BLOCK:
800  case C_MULTI:
801  for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
802  Ret = ExecuteCommand(Sub);
803  break;
804  case C_IFFAILURE:
805  Sub = Cmd->Subcommands;
806  Ret = ExecuteCommand(Sub);
807  if (Ret != 0)
808  {
809  nErrorLevel = Ret;
810  Ret = ExecuteCommand(Sub->Next);
811  }
812  break;
813  case C_IFSUCCESS:
814  Sub = Cmd->Subcommands;
815  Ret = ExecuteCommand(Sub);
816  if (Ret == 0)
817  Ret = ExecuteCommand(Sub->Next);
818  break;
819  case C_PIPE:
820  Ret = ExecutePipeline(Cmd);
821  break;
822  case C_IF:
823  Ret = ExecuteIf(Cmd);
824  break;
825  case C_FOR:
826  Ret = ExecuteFor(Cmd);
827  break;
828  }
829 
830  UndoRedirection(Cmd->Redirections, NULL);
831  return Ret;
832 }
833 
834 INT
837 {
838  /* Echo the reconstructed command line */
839  if (bEcho && !bDisableBatchEcho && Cmd->Type != C_QUIET)
840  {
841  if (!bIgnoreEcho)
842  ConOutChar(_T('\n'));
843  PrintPrompt();
844  EchoCommand(Cmd);
845  ConOutChar(_T('\n'));
846  }
847 
848  /* Run the command */
849  return ExecuteCommand(Cmd);
850 }
851 
852 LPTSTR
854 {
855  static LPTSTR ret = NULL;
856  UINT size;
857 
858  cmd_free(ret);
859  ret = NULL;
860  size = GetEnvironmentVariable(varName, NULL, 0);
861  if (size > 0)
862  {
863  ret = cmd_alloc(size * sizeof(TCHAR));
864  if (ret != NULL)
865  GetEnvironmentVariable(varName, ret, size + 1);
866  }
867  return ret;
868 }
869 
870 LPCTSTR
872 {
873  static TCHAR ret[MAX_PATH];
874 
875  LPTSTR var = GetEnvVar(varName);
876  if (var)
877  return var;
878 
879  /* env var doesn't exist, look for a "special" one */
880  /* %CD% */
881  if (_tcsicmp(varName,_T("cd")) ==0)
882  {
884  return ret;
885  }
886  /* %TIME% */
887  else if (_tcsicmp(varName,_T("time")) ==0)
888  {
889  return GetTimeString();
890  }
891  /* %DATE% */
892  else if (_tcsicmp(varName,_T("date")) ==0)
893  {
894  return GetDateString();
895  }
896 
897  /* %RANDOM% */
898  else if (_tcsicmp(varName,_T("random")) ==0)
899  {
900  /* Get random number */
901  _itot(rand(),ret,10);
902  return ret;
903  }
904 
905  /* %CMDCMDLINE% */
906  else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
907  {
908  return GetCommandLine();
909  }
910 
911  /* %CMDEXTVERSION% */
912  else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
913  {
914  /* Set version number to 2 */
915  _itot(2,ret,10);
916  return ret;
917  }
918 
919  /* %ERRORLEVEL% */
920  else if (_tcsicmp(varName,_T("errorlevel")) ==0)
921  {
922  _itot(nErrorLevel,ret,10);
923  return ret;
924  }
925 
926  return NULL;
927 }
928 
929 /* Handle the %~var syntax */
930 static LPTSTR
931 GetEnhancedVar(TCHAR **pFormat, LPTSTR (*GetVar)(TCHAR, BOOL *))
932 {
933  static const TCHAR ModifierTable[] = _T("dpnxfsatz");
934  enum {
935  M_DRIVE = 1, /* D: drive letter */
936  M_PATH = 2, /* P: path */
937  M_NAME = 4, /* N: filename */
938  M_EXT = 8, /* X: extension */
939  M_FULL = 16, /* F: full path (drive+path+name+ext) */
940  M_SHORT = 32, /* S: full path (drive+path+name+ext), use short names */
941  M_ATTR = 64, /* A: attributes */
942  M_TIME = 128, /* T: modification time */
943  M_SIZE = 256, /* Z: file size */
944  } Modifiers = 0;
945 
946  TCHAR *Format, *FormatEnd;
947  TCHAR *PathVarName = NULL;
948  LPTSTR Variable;
949  TCHAR *VarEnd;
950  BOOL VariableIsParam0;
951  TCHAR FullPath[MAX_PATH];
952  TCHAR FixedPath[MAX_PATH], *Filename, *Extension;
953  HANDLE hFind;
954  WIN32_FIND_DATA w32fd;
955  TCHAR *In, *Out;
956 
957  static TCHAR Result[CMDLINE_LENGTH];
958 
959  /* There is ambiguity between modifier characters and FOR variables;
960  * the rule that cmd uses is to pick the longest possible match.
961  * For example, if there is a %n variable, then out of %~anxnd,
962  * %~anxn will be substituted rather than just %~an. */
963 
964  /* First, go through as many modifier characters as possible */
965  FormatEnd = Format = *pFormat;
966  while (*FormatEnd && _tcschr(ModifierTable, _totlower(*FormatEnd)))
967  FormatEnd++;
968 
969  if (*FormatEnd == _T('$'))
970  {
971  /* $PATH: syntax */
972  PathVarName = FormatEnd + 1;
973  FormatEnd = _tcschr(PathVarName, _T(':'));
974  if (!FormatEnd)
975  return NULL;
976 
977  /* Must be immediately followed by the variable */
978  Variable = GetVar(*++FormatEnd, &VariableIsParam0);
979  if (!Variable)
980  return NULL;
981  }
982  else
983  {
984  /* Backtrack if necessary to get a variable name match */
985  while (!(Variable = GetVar(*FormatEnd, &VariableIsParam0)))
986  {
987  if (FormatEnd == Format)
988  return NULL;
989  FormatEnd--;
990  }
991  }
992 
993  for (; Format < FormatEnd && *Format != _T('$'); Format++)
994  Modifiers |= 1 << (_tcschr(ModifierTable, _totlower(*Format)) - ModifierTable);
995 
996  *pFormat = FormatEnd + 1;
997 
998  /* Exclude the leading and trailing quotes */
999  VarEnd = &Variable[_tcslen(Variable)];
1000  if (*Variable == _T('"'))
1001  {
1002  Variable++;
1003  if (VarEnd > Variable && VarEnd[-1] == _T('"'))
1004  VarEnd--;
1005  }
1006 
1007  if ((char *)VarEnd - (char *)Variable >= sizeof Result)
1008  return _T("");
1009  memcpy(Result, Variable, (char *)VarEnd - (char *)Variable);
1010  Result[VarEnd - Variable] = _T('\0');
1011 
1012  if (PathVarName)
1013  {
1014  /* $PATH: syntax - search the directories listed in the
1015  * specified environment variable for the file */
1016  LPTSTR PathVar;
1017  FormatEnd[-1] = _T('\0');
1018  PathVar = GetEnvVar(PathVarName);
1019  FormatEnd[-1] = _T(':');
1020  if (!PathVar ||
1021  !SearchPath(PathVar, Result, NULL, MAX_PATH, FullPath, NULL))
1022  {
1023  return _T("");
1024  }
1025  }
1026  else if (Modifiers == 0)
1027  {
1028  /* For plain %~var with no modifiers, just return the variable without quotes */
1029  return Result;
1030  }
1031  else if (VariableIsParam0)
1032  {
1033  /* Special case: If the variable is %0 and modifier characters are present,
1034  * use the batch file's path (which includes the .bat/.cmd extension)
1035  * rather than the actual %0 variable (which might not). */
1036  _tcscpy(FullPath, bc->BatchFilePath);
1037  }
1038  else
1039  {
1040  /* Convert the variable, now without quotes, to a full path */
1041  if (!GetFullPathName(Result, MAX_PATH, FullPath, NULL))
1042  return _T("");
1043  }
1044 
1045  /* Next step is to change the path to fix letter case (e.g.
1046  * C:\ReAcToS -> C:\ReactOS) and, if requested with the S modifier,
1047  * replace long filenames with short. */
1048 
1049  In = FullPath;
1050  Out = FixedPath;
1051 
1052  /* Copy drive letter */
1053  *Out++ = *In++;
1054  *Out++ = *In++;
1055  *Out++ = *In++;
1056  /* Loop over each \-separated component in the path */
1057  do {
1058  TCHAR *Next = _tcschr(In, _T('\\'));
1059  if (Next)
1060  *Next++ = _T('\0');
1061  /* Use FindFirstFile to get the correct name */
1062  if (Out + _tcslen(In) + 1 >= &FixedPath[MAX_PATH])
1063  return _T("");
1064  _tcscpy(Out, In);
1065  hFind = FindFirstFile(FixedPath, &w32fd);
1066  /* If it doesn't exist, just leave the name as it was given */
1067  if (hFind != INVALID_HANDLE_VALUE)
1068  {
1069  LPTSTR FixedComponent = w32fd.cFileName;
1070  if (*w32fd.cAlternateFileName &&
1071  ((Modifiers & M_SHORT) || !_tcsicmp(In, w32fd.cAlternateFileName)))
1072  {
1073  FixedComponent = w32fd.cAlternateFileName;
1074  }
1075  FindClose(hFind);
1076 
1077  if (Out + _tcslen(FixedComponent) + 1 >= &FixedPath[MAX_PATH])
1078  return _T("");
1079  _tcscpy(Out, FixedComponent);
1080  }
1081  Filename = Out;
1082  Out += _tcslen(Out);
1083  *Out++ = _T('\\');
1084 
1085  In = Next;
1086  } while (In != NULL);
1087  Out[-1] = _T('\0');
1088 
1089  /* Build the result string. Start with attributes, modification time, and
1090  * file size. If the file didn't exist, these fields will all be empty. */
1091  Out = Result;
1092  if (hFind != INVALID_HANDLE_VALUE)
1093  {
1094  if (Modifiers & M_ATTR)
1095  {
1096  static const struct {
1097  TCHAR Character;
1098  WORD Value;
1099  } *Attrib, Table[] = {
1100  { _T('d'), FILE_ATTRIBUTE_DIRECTORY },
1101  { _T('r'), FILE_ATTRIBUTE_READONLY },
1102  { _T('a'), FILE_ATTRIBUTE_ARCHIVE },
1103  { _T('h'), FILE_ATTRIBUTE_HIDDEN },
1104  { _T('s'), FILE_ATTRIBUTE_SYSTEM },
1105  { _T('c'), FILE_ATTRIBUTE_COMPRESSED },
1106  { _T('o'), FILE_ATTRIBUTE_OFFLINE },
1107  { _T('t'), FILE_ATTRIBUTE_TEMPORARY },
1108  { _T('l'), FILE_ATTRIBUTE_REPARSE_POINT },
1109  };
1110  for (Attrib = Table; Attrib != &Table[9]; Attrib++)
1111  {
1112  *Out++ = w32fd.dwFileAttributes & Attrib->Value
1113  ? Attrib->Character
1114  : _T('-');
1115  }
1116  *Out++ = _T(' ');
1117  }
1118  if (Modifiers & M_TIME)
1119  {
1120  FILETIME ft;
1121  SYSTEMTIME st;
1122  FileTimeToLocalFileTime(&w32fd.ftLastWriteTime, &ft);
1123  FileTimeToSystemTime(&ft, &st);
1124 
1125  Out += FormatDate(Out, &st, TRUE);
1126  *Out++ = _T(' ');
1127  Out += FormatTime(Out, &st);
1128  *Out++ = _T(' ');
1129  }
1130  if (Modifiers & M_SIZE)
1131  {
1133  Size.LowPart = w32fd.nFileSizeLow;
1134  Size.HighPart = w32fd.nFileSizeHigh;
1135  Out += _stprintf(Out, _T("%I64u "), Size.QuadPart);
1136  }
1137  }
1138 
1139  /* When using the path-searching syntax or the S modifier,
1140  * at least part of the file path is always included.
1141  * If none of the DPNX modifiers are present, include the full path */
1142  if (PathVarName || (Modifiers & M_SHORT))
1143  if ((Modifiers & (M_DRIVE | M_PATH | M_NAME | M_EXT)) == 0)
1144  Modifiers |= M_FULL;
1145 
1146  /* Now add the requested parts of the name.
1147  * With the F modifier, add all parts to form the full path. */
1148  Extension = _tcsrchr(Filename, _T('.'));
1149  if (Modifiers & (M_DRIVE | M_FULL))
1150  {
1151  *Out++ = FixedPath[0];
1152  *Out++ = FixedPath[1];
1153  }
1154  if (Modifiers & (M_PATH | M_FULL))
1155  {
1156  memcpy(Out, &FixedPath[2], (char *)Filename - (char *)&FixedPath[2]);
1157  Out += Filename - &FixedPath[2];
1158  }
1159  if (Modifiers & (M_NAME | M_FULL))
1160  {
1161  while (*Filename && Filename != Extension)
1162  *Out++ = *Filename++;
1163  }
1164  if (Modifiers & (M_EXT | M_FULL))
1165  {
1166  if (Extension)
1167  Out = _stpcpy(Out, Extension);
1168  }
1169 
1170  /* Trim trailing space which otherwise would appear as a
1171  * result of using the A/T/Z modifiers but no others. */
1172  while (Out != &Result[0] && Out[-1] == _T(' '))
1173  Out--;
1174  *Out = _T('\0');
1175 
1176  return Result;
1177 }
1178 
1179 LPCTSTR
1180 GetBatchVar(TCHAR *varName, UINT *varNameLen)
1181 {
1182  LPCTSTR ret;
1183  TCHAR *varNameEnd;
1184  BOOL dummy;
1185 
1186  *varNameLen = 1;
1187 
1188  switch ( *varName )
1189  {
1190  case _T('~'):
1191  varNameEnd = varName + 1;
1192  ret = GetEnhancedVar(&varNameEnd, FindArg);
1193  if (!ret)
1194  {
1195  error_syntax(varName);
1196  return NULL;
1197  }
1198  *varNameLen = varNameEnd - varName;
1199  return ret;
1200  case _T('0'):
1201  case _T('1'):
1202  case _T('2'):
1203  case _T('3'):
1204  case _T('4'):
1205  case _T('5'):
1206  case _T('6'):
1207  case _T('7'):
1208  case _T('8'):
1209  case _T('9'):
1210  return FindArg(*varName, &dummy);
1211 
1212  case _T('*'):
1213  //
1214  // Copy over the raw params(not including the batch file name
1215  //
1216  return bc->raw_params;
1217 
1218  case _T('%'):
1219  return _T("%");
1220  }
1221  return NULL;
1222 }
1223 
1224 BOOL
1225 SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim)
1226 {
1227 #define APPEND(From, Length) { \
1228  if (Dest + (Length) > DestEnd) \
1229  goto too_long; \
1230  memcpy(Dest, From, (Length) * sizeof(TCHAR)); \
1231  Dest += Length; }
1232 #define APPEND1(Char) { \
1233  if (Dest >= DestEnd) \
1234  goto too_long; \
1235  *Dest++ = Char; }
1236 
1237  TCHAR *DestEnd = Dest + CMDLINE_LENGTH - 1;
1238  const TCHAR *Var;
1239  int VarLength;
1240  TCHAR *SubstStart;
1241  TCHAR EndChr;
1242  while (*Src)
1243  {
1244  if (*Src != Delim)
1245  {
1246  APPEND1(*Src++)
1247  continue;
1248  }
1249 
1250  Src++;
1251  if (bc && Delim == _T('%'))
1252  {
1253  UINT NameLen;
1254  Var = GetBatchVar(Src, &NameLen);
1255  if (Var != NULL)
1256  {
1257  VarLength = _tcslen(Var);
1258  APPEND(Var, VarLength)
1259  Src += NameLen;
1260  continue;
1261  }
1262  }
1263 
1264  /* Find the end of the variable name. A colon (:) will usually
1265  * end the name and begin the optional modifier, but not if it
1266  * is immediately followed by the delimiter (%VAR:%). */
1267  SubstStart = Src;
1268  while (*Src != Delim && !(*Src == _T(':') && Src[1] != Delim))
1269  {
1270  if (!*Src)
1271  goto bad_subst;
1272  Src++;
1273  }
1274 
1275  EndChr = *Src;
1276  *Src = _T('\0');
1277  Var = GetEnvVarOrSpecial(SubstStart);
1278  *Src++ = EndChr;
1279  if (Var == NULL)
1280  {
1281  /* In a batch file, %NONEXISTENT% "expands" to an empty string */
1282  if (bc)
1283  continue;
1284  goto bad_subst;
1285  }
1286  VarLength = _tcslen(Var);
1287 
1288  if (EndChr == Delim)
1289  {
1290  /* %VAR% - use as-is */
1291  APPEND(Var, VarLength)
1292  }
1293  else if (*Src == _T('~'))
1294  {
1295  /* %VAR:~[start][,length]% - substring
1296  * Negative values are offsets from the end */
1297  int Start = _tcstol(Src + 1, &Src, 0);
1298  int End = VarLength;
1299  if (Start < 0)
1300  Start += VarLength;
1301  Start = max(Start, 0);
1302  Start = min(Start, VarLength);
1303  if (*Src == _T(','))
1304  {
1305  End = _tcstol(Src + 1, &Src, 0);
1306  End += (End < 0) ? VarLength : Start;
1307  End = max(End, Start);
1308  End = min(End, VarLength);
1309  }
1310  if (*Src++ != Delim)
1311  goto bad_subst;
1312  APPEND(&Var[Start], End - Start);
1313  }
1314  else
1315  {
1316  /* %VAR:old=new% - replace all occurrences of old with new
1317  * %VAR:*old=new% - replace first occurrence only,
1318  * and remove everything before it */
1319  TCHAR *Old, *New;
1320  DWORD OldLength, NewLength;
1321  BOOL Star = FALSE;
1322  int LastMatch = 0, i = 0;
1323 
1324  if (*Src == _T('*'))
1325  {
1326  Star = TRUE;
1327  Src++;
1328  }
1329 
1330  /* the string to replace may contain the delimiter */
1331  Src = _tcschr(Old = Src, _T('='));
1332  if (Src == NULL)
1333  goto bad_subst;
1334  OldLength = Src++ - Old;
1335  if (OldLength == 0)
1336  goto bad_subst;
1337 
1338  Src = _tcschr(New = Src, Delim);
1339  if (Src == NULL)
1340  goto bad_subst;
1341  NewLength = Src++ - New;
1342 
1343  while (i < VarLength)
1344  {
1345  if (_tcsnicmp(&Var[i], Old, OldLength) == 0)
1346  {
1347  if (!Star)
1348  APPEND(&Var[LastMatch], i - LastMatch)
1349  APPEND(New, NewLength)
1350  i += OldLength;
1351  LastMatch = i;
1352  if (Star)
1353  break;
1354  continue;
1355  }
1356  i++;
1357  }
1358  APPEND(&Var[LastMatch], VarLength - LastMatch)
1359  }
1360  continue;
1361 
1362  bad_subst:
1363  Src = SubstStart;
1364  if (!bc)
1365  APPEND1(Delim)
1366  }
1367  *Dest = _T('\0');
1368  return TRUE;
1369 too_long:
1371  nErrorLevel = 9023;
1372  return FALSE;
1373 #undef APPEND
1374 #undef APPEND1
1375 }
1376 
1377 /* Search the list of FOR contexts for a variable */
1378 static LPTSTR FindForVar(TCHAR Var, BOOL *IsParam0)
1379 {
1380  FOR_CONTEXT *Ctx;
1381  *IsParam0 = FALSE;
1382  for (Ctx = fc; Ctx != NULL; Ctx = Ctx->prev)
1383  {
1384  if ((UINT)(Var - Ctx->firstvar) < Ctx->varcount)
1385  return Ctx->values[Var - Ctx->firstvar];
1386  }
1387  return NULL;
1388 }
1389 
1390 BOOL
1392 {
1393  TCHAR *DestEnd = &Dest[CMDLINE_LENGTH - 1];
1394  while (*Src)
1395  {
1396  if (Src[0] == _T('%'))
1397  {
1398  BOOL Dummy;
1399  LPTSTR End = &Src[2];
1400  LPTSTR Value = NULL;
1401 
1402  if (Src[1] == _T('~'))
1403  Value = GetEnhancedVar(&End, FindForVar);
1404 
1405  if (!Value)
1406  Value = FindForVar(Src[1], &Dummy);
1407 
1408  if (Value)
1409  {
1410  if (Dest + _tcslen(Value) > DestEnd)
1411  return FALSE;
1412  Dest = _stpcpy(Dest, Value);
1413  Src = End;
1414  continue;
1415  }
1416  }
1417  /* Not a variable; just copy the character */
1418  if (Dest >= DestEnd)
1419  return FALSE;
1420  *Dest++ = *Src++;
1421  }
1422  *Dest = _T('\0');
1423  return TRUE;
1424 }
1425 
1426 LPTSTR
1428 {
1429  TCHAR Buf1[CMDLINE_LENGTH];
1430  TCHAR Buf2[CMDLINE_LENGTH];
1431 
1432  /* First, substitute FOR variables */
1433  if (!SubstituteForVars(Line, Buf1))
1434  return NULL;
1435 
1436  if (!bDelayedExpansion || !_tcschr(Buf1, _T('!')))
1437  return cmd_dup(Buf1);
1438 
1439  /* FIXME: Delayed substitutions actually aren't quite the same as
1440  * immediate substitutions. In particular, it's possible to escape
1441  * the exclamation point using ^. */
1442  if (!SubstituteVars(Buf1, Buf2, _T('!')))
1443  return NULL;
1444  return cmd_dup(Buf2);
1445 }
1446 
1447 
1448 /*
1449  * do the prompt/input/process loop
1450  *
1451  */
1452 
1453 BOOL
1454 ReadLine(TCHAR *commandline, BOOL bMore)
1455 {
1457  LPTSTR ip;
1458 
1459  /* if no batch input then... */
1460  if (bc == NULL)
1461  {
1462  if (bMore)
1463  {
1465  }
1466  else
1467  {
1468  /* JPP 19980807 - if echo off, don't print prompt */
1469  if (bEcho)
1470  {
1471  if (!bIgnoreEcho)
1472  ConOutChar(_T('\n'));
1473  PrintPrompt();
1474  }
1475  }
1476 
1477  if (!ReadCommand(readline, CMDLINE_LENGTH - 1))
1478  {
1479  bExit = TRUE;
1480  return FALSE;
1481  }
1482 
1483  if (readline[0] == _T('\0'))
1484  ConOutChar(_T('\n'));
1485 
1487  return FALSE;
1488 
1489  if (readline[0] == _T('\0'))
1490  return FALSE;
1491 
1492  ip = readline;
1493  }
1494  else
1495  {
1496  ip = ReadBatchLine();
1497  if (!ip)
1498  return FALSE;
1499  }
1500 
1501  return SubstituteVars(ip, commandline, _T('%'));
1502 }
1503 
1504 static VOID
1506 {
1508 
1509  while (!bCanExit || !bExit)
1510  {
1511  /* Reset the Ctrl-Break / Ctrl-C state */
1512  bCtrlBreak = FALSE;
1513 
1514  Cmd = ParseCommand(NULL);
1515  if (!Cmd)
1516  continue;
1517 
1519  FreeCommand(Cmd);
1520  }
1521 }
1522 
1523 
1524 /*
1525  * control-break handler.
1526  */
1528 {
1529  DWORD dwWritten;
1530  INPUT_RECORD rec;
1531 
1532  if ((dwCtrlType != CTRL_C_EVENT) &&
1533  (dwCtrlType != CTRL_BREAK_EVENT))
1534  {
1535  return FALSE;
1536  }
1537 
1539  {
1540  /* Child process is running and will have received the control event */
1541  return TRUE;
1542  }
1543  else
1544  {
1546  }
1547 
1548  bCtrlBreak = TRUE;
1549 
1550  rec.EventType = KEY_EVENT;
1551  rec.Event.KeyEvent.bKeyDown = TRUE;
1552  rec.Event.KeyEvent.wRepeatCount = 1;
1553  rec.Event.KeyEvent.wVirtualKeyCode = _T('C');
1554  rec.Event.KeyEvent.wVirtualScanCode = _T('C') - 35;
1555  rec.Event.KeyEvent.uChar.AsciiChar = _T('C');
1556  rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
1558 
1560  &rec,
1561  1,
1562  &dwWritten);
1563 
1564  /* FIXME: Handle batch files */
1565 
1566  // ConOutPrintf(_T("^C"));
1567 
1568  return TRUE;
1569 }
1570 
1571 
1573 {
1575 }
1576 
1577 
1579 {
1581 }
1582 
1583 
1584 /*
1585  * show commands and options that are available.
1586  *
1587  */
1588 #if 0
1589 static VOID
1590 ShowCommands(VOID)
1591 {
1592  /* print command list */
1594  PrintCommandList();
1595 
1596  /* print feature list */
1598 
1599 #ifdef FEATURE_ALIASES
1601 #endif
1602 #ifdef FEATURE_HISTORY
1604 #endif
1605 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
1607 #endif
1608 #ifdef FEATURE_DIRECTORY_STACK
1610 #endif
1611 #ifdef FEATURE_REDIRECTION
1613 #endif
1614  ConOutChar(_T('\n'));
1615 }
1616 #endif
1617 
1618 
1619 static VOID
1621 {
1622  LONG lRet;
1623  HKEY hKey;
1624  DWORD dwType, len;
1625  /*
1626  * Buffer big enough to hold the string L"4294967295",
1627  * corresponding to the literal 0xFFFFFFFF (MAXULONG) in decimal.
1628  */
1629  DWORD Buffer[6];
1630 
1631  lRet = RegOpenKeyEx(hKeyRoot,
1632  _T("Software\\Microsoft\\Command Processor"),
1633  0,
1635  &hKey);
1636  if (lRet != ERROR_SUCCESS)
1637  return;
1638 
1639 #ifdef INCLUDE_CMD_COLOR
1640  len = sizeof(Buffer);
1641  lRet = RegQueryValueEx(hKey,
1642  _T("DefaultColor"),
1643  NULL,
1644  &dwType,
1645  (LPBYTE)&Buffer,
1646  &len);
1647  if (lRet == ERROR_SUCCESS)
1648  {
1649  /* Overwrite the default attributes */
1650  if (dwType == REG_DWORD)
1651  wDefColor = (WORD)*(PDWORD)Buffer;
1652  else if (dwType == REG_SZ)
1654  }
1655  // else, use the default attributes retrieved before.
1656 #endif
1657 
1658 #if 0
1659  len = sizeof(Buffer);
1660  lRet = RegQueryValueEx(hKey,
1661  _T("DisableUNCCheck"),
1662  NULL,
1663  &dwType,
1664  (LPBYTE)&Buffer,
1665  &len);
1666  if (lRet == ERROR_SUCCESS)
1667  {
1668  /* Overwrite the default setting */
1669  if (dwType == REG_DWORD)
1670  bDisableUNCCheck = !!*(PDWORD)Buffer;
1671  else if (dwType == REG_SZ)
1672  bDisableUNCCheck = (_ttol((PTSTR)Buffer) == 1);
1673  }
1674  // else, use the default setting set globally.
1675 #endif
1676 
1677  len = sizeof(Buffer);
1678  lRet = RegQueryValueEx(hKey,
1679  _T("DelayedExpansion"),
1680  NULL,
1681  &dwType,
1682  (LPBYTE)&Buffer,
1683  &len);
1684  if (lRet == ERROR_SUCCESS)
1685  {
1686  /* Overwrite the default setting */
1687  if (dwType == REG_DWORD)
1689  else if (dwType == REG_SZ)
1690  bDelayedExpansion = (_ttol((PTSTR)Buffer) == 1);
1691  }
1692  // else, use the default setting set globally.
1693 
1694  len = sizeof(Buffer);
1695  lRet = RegQueryValueEx(hKey,
1696  _T("EnableExtensions"),
1697  NULL,
1698  &dwType,
1699  (LPBYTE)&Buffer,
1700  &len);
1701  if (lRet == ERROR_SUCCESS)
1702  {
1703  /* Overwrite the default setting */
1704  if (dwType == REG_DWORD)
1706  else if (dwType == REG_SZ)
1707  bEnableExtensions = (_ttol((PTSTR)Buffer) == 1);
1708  }
1709  // else, use the default setting set globally.
1710 
1711  len = sizeof(Buffer);
1712  lRet = RegQueryValueEx(hKey,
1713  _T("CompletionChar"),
1714  NULL,
1715  &dwType,
1716  (LPBYTE)&Buffer,
1717  &len);
1718  if (lRet == ERROR_SUCCESS)
1719  {
1720  /* Overwrite the default setting */
1721  if (dwType == REG_DWORD)
1723  else if (dwType == REG_SZ)
1725  }
1726  // else, use the default setting set globally.
1727 
1728  /* Validity check */
1730  {
1731  /* Disable autocompletion */
1732  AutoCompletionChar = 0x20;
1733  }
1734 
1735  len = sizeof(Buffer);
1736  lRet = RegQueryValueEx(hKey,
1737  _T("PathCompletionChar"),
1738  NULL,
1739  &dwType,
1740  (LPBYTE)&Buffer,
1741  &len);
1742  if (lRet == ERROR_SUCCESS)
1743  {
1744  /* Overwrite the default setting */
1745  if (dwType == REG_DWORD)
1747  else if (dwType == REG_SZ)
1749  }
1750  // else, use the default setting set globally.
1751 
1752  /* Validity check */
1754  {
1755  /* Disable autocompletion */
1756  PathCompletionChar = 0x20;
1757  }
1758 
1759  /* Adjust completion chars */
1760  if (PathCompletionChar >= 0x20 && AutoCompletionChar < 0x20)
1762  else if (AutoCompletionChar >= 0x20 && PathCompletionChar < 0x20)
1764 
1765  RegCloseKey(hKey);
1766 }
1767 
1768 static VOID
1770 {
1771  LONG lRet;
1772  HKEY hKey;
1773  DWORD dwType, len;
1774  TCHAR AutoRun[2048];
1775 
1776  lRet = RegOpenKeyEx(hKeyRoot,
1777  _T("Software\\Microsoft\\Command Processor"),
1778  0,
1780  &hKey);
1781  if (lRet != ERROR_SUCCESS)
1782  return;
1783 
1784  len = sizeof(AutoRun);
1785  lRet = RegQueryValueEx(hKey,
1786  _T("AutoRun"),
1787  NULL,
1788  &dwType,
1789  (LPBYTE)&AutoRun,
1790  &len);
1791  if ((lRet == ERROR_SUCCESS) && (dwType == REG_EXPAND_SZ || dwType == REG_SZ))
1792  {
1793  if (*AutoRun)
1794  ParseCommandLine(AutoRun);
1795  }
1796 
1797  RegCloseKey(hKey);
1798 }
1799 
1800 /* Get the command that comes after a /C or /K switch */
1801 static VOID
1802 GetCmdLineCommand(TCHAR *commandline, TCHAR *ptr, BOOL AlwaysStrip)
1803 {
1804  TCHAR *LastQuote;
1805 
1806  while (_istspace(*ptr))
1807  ptr++;
1808 
1809  /* Remove leading quote, find final quote */
1810  if (*ptr == _T('"') &&
1811  (LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
1812  {
1813  TCHAR *Space;
1814  /* Under certain circumstances, all quotes are preserved.
1815  * CMD /? documents these conditions as follows:
1816  * 1. No /S switch
1817  * 2. Exactly two quotes
1818  * 3. No "special characters" between the quotes
1819  * (CMD /? says &<>()@^| but parentheses did not
1820  * trigger this rule when I tested them.)
1821  * 4. Whitespace exists between the quotes
1822  * 5. Enclosed string is an executable filename
1823  */
1824  *LastQuote = _T('\0');
1825  for (Space = ptr + 1; Space < LastQuote; Space++)
1826  {
1827  if (_istspace(*Space)) /* Rule 4 */
1828  {
1829  if (!AlwaysStrip && /* Rule 1 */
1830  !_tcspbrk(ptr, _T("\"&<>@^|")) && /* Rules 2, 3 */
1831  SearchForExecutable(ptr, commandline)) /* Rule 5 */
1832  {
1833  /* All conditions met: preserve both the quotes */
1834  *LastQuote = _T('"');
1835  _tcscpy(commandline, ptr - 1);
1836  return;
1837  }
1838  break;
1839  }
1840  }
1841 
1842  /* The conditions were not met: remove both the
1843  * leading quote and the last quote */
1844  _tcscpy(commandline, ptr);
1845  _tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
1846  return;
1847  }
1848 
1849  /* No quotes; just copy */
1850  _tcscpy(commandline, ptr);
1851 }
1852 
1853 
1854 /*
1855  * Set up global initializations and process parameters
1856  */
1857 static VOID
1859 {
1860  HMODULE NtDllModule;
1861  TCHAR commandline[CMDLINE_LENGTH];
1862  TCHAR ModuleName[_MAX_PATH + 1];
1863  // INT nExitCode;
1864 
1865  HANDLE hIn, hOut;
1866 
1867  TCHAR *ptr, *cmdLine, option = 0;
1868  BOOL AlwaysStrip = FALSE;
1869  BOOL AutoRun = TRUE;
1870 
1871  /* Get version information */
1872  InitOSVersion();
1873 
1874  /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
1875  * build process. So don't link implicitly against ntdll.dll, load it
1876  * dynamically instead */
1877  NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
1878  if (NtDllModule != NULL)
1879  {
1880  NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)GetProcAddress(NtDllModule, "NtQueryInformationProcess");
1881  NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
1882  }
1883 
1884  /* Load the registry settings */
1887 
1888  /* Initialize our locale */
1889  InitLocale();
1890 
1891  /* Initialize prompt support */
1892  InitPrompt();
1893 
1894 #ifdef FEATURE_DIRECTORY_STACK
1895  /* Initialize directory stack */
1897 #endif
1898 
1899 #ifdef FEATURE_HISTORY
1900  /* Initialize history */
1901  InitHistory();
1902 #endif
1903 
1904  /* Set COMSPEC environment variable */
1906  {
1907  ModuleName[_MAX_PATH] = _T('\0');
1908  SetEnvironmentVariable (_T("COMSPEC"), ModuleName);
1909  }
1910 
1911  /* Add ctrl break handler */
1912  AddBreakHandler();
1913 
1914  /* Set our default console mode */
1915  hOut = ConStreamGetOSHandle(StdOut);
1916  hIn = ConStreamGetOSHandle(StdIn);
1917  SetConsoleMode(hOut, 0); // Reinitialize the console output mode
1920 
1921  cmdLine = GetCommandLine();
1922  TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
1923 
1924  for (ptr = cmdLine; *ptr; ptr++)
1925  {
1926  if (*ptr == _T('/'))
1927  {
1928  option = _totupper(ptr[1]);
1929  if (option == _T('?'))
1930  {
1932  nErrorLevel = 1;
1933  bExit = TRUE;
1934  return;
1935  }
1936  else if (option == _T('P'))
1937  {
1938  if (!IsExistingFile (_T("\\autoexec.bat")))
1939  {
1940 #ifdef INCLUDE_CMD_DATE
1941  cmd_date (_T(""));
1942 #endif
1943 #ifdef INCLUDE_CMD_TIME
1944  cmd_time (_T(""));
1945 #endif
1946  }
1947  else
1948  {
1949  ParseCommandLine (_T("\\autoexec.bat"));
1950  }
1951  bCanExit = FALSE;
1952  }
1953  else if (option == _T('A'))
1954  {
1956  }
1957  else if (option == _T('C') || option == _T('K') || option == _T('R'))
1958  {
1959  /* Remainder of command line is a command to be run */
1960  fSingleCommand = ((option == _T('K')) << 1) | 1;
1961  break;
1962  }
1963  else if (option == _T('D'))
1964  {
1965  AutoRun = FALSE;
1966  }
1967  else if (option == _T('Q'))
1968  {
1970  }
1971  else if (option == _T('S'))
1972  {
1973  AlwaysStrip = TRUE;
1974  }
1975 #ifdef INCLUDE_CMD_COLOR
1976  else if (!_tcsnicmp(ptr, _T("/T:"), 3))
1977  {
1978  /* Process /T (color) argument; overwrite any previous settings */
1979  wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
1980  }
1981 #endif
1982  else if (option == _T('U'))
1983  {
1985  }
1986  else if (option == _T('V'))
1987  {
1988  // FIXME: Check validity of the parameter given to V !
1989  bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
1990  }
1991  else if (option == _T('E'))
1992  {
1993  // FIXME: Check validity of the parameter given to E !
1994  bEnableExtensions = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
1995  }
1996  else if (option == _T('X'))
1997  {
1998  /* '/X' is identical to '/E:ON' */
2000  }
2001  else if (option == _T('Y'))
2002  {
2003  /* '/Y' is identical to '/E:OFF' */
2005  }
2006  }
2007  }
2008 
2009 #ifdef INCLUDE_CMD_COLOR
2010  if (wDefColor == 0)
2011  {
2012  /*
2013  * If we still do not have the console colour attribute set,
2014  * retrieve the default one.
2015  */
2017  }
2018 
2019  if (wDefColor != 0)
2021 #endif
2022 
2023  /* Reset the output Standard Streams translation modes and codepage caches */
2024  // ConStreamSetMode(StdIn , OutputStreamMode, InputCodePage );
2027 
2028  if (!*ptr)
2029  {
2030  /* If neither /C or /K was given, display a simple version string */
2031  ConOutChar(_T('\n'));
2033  _T(KERNEL_VERSION_STR),
2034  _T(KERNEL_VERSION_BUILD_STR));
2035  ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team.\n"));
2036  }
2037 
2038  if (AutoRun)
2039  {
2042  }
2043 
2044  if (*ptr)
2045  {
2046  /* Do the /C or /K command */
2047  GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
2048  /* nExitCode = */ ParseCommandLine(commandline);
2049  if (fSingleCommand == 1)
2050  {
2051  // nErrorLevel = nExitCode;
2052  bExit = TRUE;
2053  }
2054  fSingleCommand = 0;
2055  }
2056 }
2057 
2058 
2060 {
2061  /* Run cmdexit.bat */
2062  if (IsExistingFile(_T("cmdexit.bat")))
2063  {
2065  ParseCommandLine(_T("cmdexit.bat"));
2066  }
2067  else if (IsExistingFile(_T("\\cmdexit.bat")))
2068  {
2070  ParseCommandLine(_T("\\cmdexit.bat"));
2071  }
2072 
2073 #ifdef FEATURE_DIRECTORY_STACK
2074  /* Destroy directory stack */
2076 #endif
2077 
2078 #ifdef FEATURE_HISTORY
2079  CleanHistory();
2080 #endif
2081 
2082  /* Free GetEnvVar's buffer */
2083  GetEnvVar(NULL);
2084 
2085  /* Remove ctrl break handler */
2087 
2088  /* Restore the default console mode */
2093 
2095 }
2096 
2097 /*
2098  * main function
2099  */
2100 int _tmain(int argc, const TCHAR *argv[])
2101 {
2102  TCHAR startPath[MAX_PATH];
2103 
2106 
2107  GetCurrentDirectory(ARRAYSIZE(startPath), startPath);
2108  _tchdir(startPath);
2109 
2110  SetFileApisToOEM();
2113 
2114  /* Initialize the Console Standard Streams */
2118 
2120 
2121  /* Perform general initialization, parse switches on command-line */
2122  Initialize();
2123 
2124  /* Call prompt routine */
2125  ProcessInput();
2126 
2127  /* Do the cleanup */
2128  Cleanup();
2129 
2131 
2133  return nErrorLevel;
2134 }
2135 
2136 /* 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:1505
const char * var
Definition: shader.c:5666
INT ExecuteCommand(IN PARSED_COMMAND *Cmd)
Definition: cmd.c:772
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2373
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
Definition: cmd.h:304
#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:304
#define TRUE
Definition: types.h:120
static LPTSTR GetEnhancedVar(TCHAR **pFormat, LPTSTR(*GetVar)(TCHAR, BOOL *))
Definition: cmd.c:931
const CHAR * LPCTSTR
Definition: xmlstorage.h:193
#define CloseHandle
Definition: compat.h:407
WCHAR UnicodeChar
Definition: wincon.h:245
#define CTRL_BREAK_EVENT
Definition: wincon.h:69
#define FILE_ATTRIBUTE_TEMPORARY
Definition: nt_native.h:708
int _tmain(int argc, const TCHAR *argv[])
Definition: cmd.c:2100
VOID InitHistory(VOID)
Definition: history.c:132
WORD wVirtualScanCode
Definition: wincon.h:243
LPSTR lpTitle
Definition: winbase.h:812
#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:3702
Definition: cmd.h:304
static VOID SetConTitle(LPCTSTR pszTitle)
Definition: cmd.c:308
#define _tcsicmp
Definition: xmlstorage.h:205
union _KEY_EVENT_RECORD::@3202 uChar
LPBATCH_CONTEXT bc
Definition: batch.c:66
LPCTSTR GetBatchVar(TCHAR *varName, UINT *varNameLen)
Definition: cmd.c:1180
Definition: ftp_var.h:139
static VOID ExecuteAutoRunFile(HKEY hKeyRoot)
Definition: cmd.c:1769
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
int _tcscmp(const _TCHAR *s1, const _TCHAR *s2)
Definition: tcscmp.h:8
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define STRING_REACTOS_VERSION
Definition: resource.h:89
VOID ConOutChar(TCHAR c)
Definition: console.c:123
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1168
#define _tcstol
Definition: tchar.h:594
#define MAXIMUM_WAIT_OBJECTS
Definition: winbase.h:385
#define SEE_MASK_NO_CONSOLE
Definition: shellapi.h:38
TCHAR szCurTitle[MAX_PATH]
Definition: cmd.c:167
#define HKEY_CURRENT_USER
Definition: winreg.h:11
INT ExecuteCommandWithEcho(IN PARSED_COMMAND *Cmd)
Definition: cmd.c:835
static VOID ErrorMessage(DWORD dwErrorCode, LPWSTR szFormat,...)
Definition: attrib.c:51
static VOID LoadRegistrySettings(HKEY hKeyRoot)
Definition: cmd.c:1620
#define STRING_MORE
Definition: resource.h:239
#define ConErrResPuts(uID)
Definition: console.h:39
const GLint * first
Definition: glext.h:5794
#define WARN(fmt,...)
Definition: debug.h:112
#define WriteConsoleInput
Definition: wincon.h:788
static BOOL ReadCommand(PCONSOLE_STATE State, LPSTR str, INT maxlen)
Definition: cmdcons.c:735
LONG NTSTATUS
Definition: precomp.h:26
INT cmd_date(LPTSTR)
Definition: date.c:176
#define INT
Definition: polytest.cpp:20
VOID DestroyDirectoryStack(VOID)
Definition: dirstack.c:91
#define debugstr_aw
Definition: precomp.h:43
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:68
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:400
_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:1802
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:200
_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:1225
INT FormatDate(TCHAR *, LPSYSTEMTIME, BOOL)
Definition: dir.c:674
Definition: cmd.h:304
DWORD dwFlags
Definition: winbase.h:820
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
#define IS_COMPLETION_DISABLED(CompletionCtrl)
Definition: cmd.h:110
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)
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: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: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:57
LPTSTR ReadBatchLine(VOID)
Definition: batch.c:444
struct _PARSED_COMMAND * Next
Definition: cmd.h:308
CHAR * LPTSTR
Definition: xmlstorage.h:192
struct TraceInfo Info
IN PVCB IN PBCB OUT PDIRENT IN USHORT IN POEM_STRING Filename
Definition: fatprocs.h:934
#define _itot
Definition: tchar.h:608
#define SearchPath
Definition: winbase.h:3740
WORD wVirtualKeyCode
Definition: wincon.h:242
static USHORT USHORT * NewLength
TCHAR firstvar
Definition: batch.h:27
#define ENABLE_ECHO_INPUT
Definition: wincon.h:80
WCHAR First[]
Definition: FormatMessage.c:11
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
INT(* func)(PCONSOLE_STATE, LPSTR)
Definition: cmdcons.c:29
#define ENABLE_WRAP_AT_EOL_OUTPUT
Definition: blue.h:54
LPTSTR GetTimeString(VOID)
Definition: locale.c:73
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
enum _PROCESSINFOCLASS PROCESSINFOCLASS
Definition: loader.c:63
LPTSTR _stpcpy(LPTSTR, LPCTSTR)
Definition: misc.c:460
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
WORD wRepeatCount
Definition: wincon.h:241
unsigned char * LPBYTE
Definition: typedefs.h:53
ULONG_PTR * PSIZE_T
Definition: typedefs.h:79
NTSTATUS(WINAPI * NtReadVirtualMemoryProc)(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T)
Definition: cmd.c:150
#define StringCchPrintf
Definition: strsafe.h:517
GLenum const GLfloat * params
Definition: glext.h:5645
union _INPUT_RECORD::@3203 Event
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:871
#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:128
static PVOID ptr
Definition: dispmode.c:27
int ip[4]
Definition: rtl.c:1176
#define GetCurrentDirectory
Definition: winbase.h:3645
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleOutputCP(VOID)
Definition: console.c:2453
BOOL ConStreamSetCacheCodePage(IN PCON_STREAM Stream, IN UINT CacheCodePage)
Definition: stream.c:215
const WCHAR * str
#define IMAGE_SUBSYSTEM_WINDOWS_CUI
Definition: ntimage.h:438
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
WORD wDefColor
Definition: cmd.c:179
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
Definition: getopt.h:108
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define GetConsoleTitle
Definition: wincon.h:778
VOID error_out_of_memory(VOID)
Definition: error.c:140
#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:3639
BOOL WINAPI BreakHandler(DWORD dwCtrlType)
Definition: cmd.c:1527
void * PVOID
Definition: retypes.h:9
#define FindFirstFile
Definition: winbase.h:3622
#define STARTF_USESHOWWINDOW
Definition: winbase.h:472
UINT InputCodePage
Definition: console.c:25
#define STD_INPUT_HANDLE
Definition: winbase.h:264
DWORD dwChildProcessId
Definition: cmd.c: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: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:414
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
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:809
#define STRING_CMD_HELP4
Definition: resource.h:78
VOID InitDirectoryStack(VOID)
Definition: dirstack.c:80
Definition: dhcpd.h:61
Definition: cmd.h:304
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:66
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:6
UINT OutputCodePage
Definition: console.c:26
BOOL bDisableBatchEcho
Definition: cmd.c:159
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:278
#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:1427
#define ConOutResPrintf(uID,...)
Definition: console.h:48
unsigned long DWORD
Definition: ntddk_ex.h:95
PVOID HANDLE
Definition: typedefs.h:72
GLuint GLuint num
Definition: glext.h:9618
#define ENABLE_LINE_INPUT
Definition: wincon.h:79
LPFOR_CONTEXT fc
Definition: for.c:53
#define GetModuleFileName
Definition: winbase.h:3671
#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:79
BOOL ReadLine(TCHAR *commandline, BOOL bMore)
Definition: cmd.c:1454
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:1378
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:3661
VOID UndoRedirection(REDIRECTION *, REDIRECTION *End)
Definition: redir.c:142
#define SetEnvironmentVariable
Definition: winbase.h:3748
BOOL ConStreamSetMode(IN PCON_STREAM Stream, IN CON_STREAM_MODE Mode, IN UINT CacheCodePage OPTIONAL)
Definition: stream.c:195
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
VOID FreeCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:1016
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define CreateProcess
Definition: winbase.h:3598
BOOL ConSetTitle(IN LPCTSTR lpConsoleTitle)
Definition: console.c:280
VOID AddBreakHandler(VOID)
Definition: cmd.c:1572
VOID EchoCommand(PARSED_COMMAND *Cmd)
Definition: parser.c:812
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:304
Status
Definition: gdiplustypes.h:24
VOID error_too_many_parameters(LPTSTR)
Definition: error.c:81
#define ENABLE_PROCESSED_OUTPUT
Definition: blue.h:53
#define STRING_CMD_HELP3
Definition: resource.h:77
TCHAR * Unparse(PARSED_COMMAND *Cmd, TCHAR *Out, TCHAR *OutEnd)
Definition: parser.c:906
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest)
Definition: cmd.c:1391
enum _CON_STREAM_MODE CON_STREAM_MODE
VOID WINAPI SetFileApisToOEM(VOID)
Definition: utils.c:829
static VOID Cleanup(VOID)
Definition: cmd.c:2059
#define _stprintf
Definition: utility.h:124
#define ENABLE_PROCESSED_INPUT
Definition: wincon.h:78
VOID error_syntax(LPTSTR)
Definition: error.c:154
ULONG_PTR SIZE_T
Definition: typedefs.h:79
#define cmd_alloc(size)
Definition: cmddbg.h:29
#define RegOpenKeyEx
Definition: winreg.h:520
#define SW_SHOWNORMAL
Definition: winuser.h:764
#define cmd_free(ptr)
Definition: cmddbg.h:31
#define TEXT(s)
Definition: k32.h:26
static const WCHAR des[]
Definition: oid.c:1212
#define GetModuleHandle
Definition: winbase.h:3667
STARTUPINFOA STARTUPINFO
Definition: winbase.h:3559
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:126
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:853
BOOL bDelayedExpansion
Definition: cmd.c:161
#define cmd_dup(str)
Definition: cmddbg.h:32
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
unsigned int * PULONG
Definition: retypes.h:1
#define STRING_CMD_HELP8
Definition: resource.h:82
#define min(a, b)
Definition: monoChain.cc:55
CRITICAL_SECTION ChildProcessRunningLock
Definition: cmd.c:158
unsigned int UINT
Definition: ndis.h:50
WORD wShowWindow
Definition: winbase.h:821
BOOL PerformRedirection(REDIRECTION *)
Definition: redir.c:63
DWORD * PDWORD
Definition: pedump.c:68
static INT ExecutePipeline(PARSED_COMMAND *Cmd)
Definition: cmd.c:683
HANDLE CMD_ModuleHandle
Definition: cmd.c:164
BOOL bExit
Definition: cmd.c:152
PARSED_COMMAND * ParseCommand(LPTSTR Line)
Definition: parser.c:767
#define STRING_FREE_ERROR1
Definition: resource.h:49
WORD EventType
Definition: wincon.h:276
#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:304
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
#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:133
INT ExecuteIf(struct _PARSED_COMMAND *Cmd)
Definition: if.c:66
LPSTR name
Definition: cmdcons.c:27
#define GetEnvironmentVariable
Definition: winbase.h:3654
static BOOL fSingleCommand
Definition: cmd.c:156
#define GetProcAddress(x, y)
Definition: compat.h:419
#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:453
#define RIGHT_CTRL_PRESSED
Definition: wincon.h:139
#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:499
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
#define StdIn
Definition: stream.h:75
#define SetCurrentDirectory
Definition: winbase.h:3743
#define STRING_CMD_HELP6
Definition: resource.h:80
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:1578
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
static VOID Initialize(VOID)
Definition: cmd.c:1858
#define REG_SZ
Definition: layer.c:22
BOOL bCtrlBreak
Definition: cmd.c:154
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502